File tree Expand file tree Collapse file tree 3 files changed +63
-14
lines changed
Expand file tree Collapse file tree 3 files changed +63
-14
lines changed Original file line number Diff line number Diff line change @@ -111,6 +111,34 @@ Django
111111If you are using django you should add the above loader script at the
112112top of ``wsgi.py `` and ``manage.py ``.
113113
114+
115+ In-memory filelikes
116+ -------------------
117+
118+ Is possible to not rely on the filesystem to parse filelikes from other sources
119+ (e.g. from a network storage). ``parse_dotenv `` accepts a filelike `stream `.
120+ Just be sure to rewind it before passing.
121+
122+ .. code :: python
123+
124+ from io import StringIO # Python2: from StringIO import StringIO
125+ from dotenv.main import parse_dotenv
126+ filelike = StringIO(' SPAM=EGSS\n ' )
127+ filelike.seek(0 )
128+ parsed = parse_dotenv(stream = filelike)
129+
130+ The returned lazy generator yields ``(key,value) `` tuples.
131+ To ease the consumption, is suggested to unpack it into a dictionary.
132+
133+ .. code :: python
134+
135+ os_env_like = dict (iter (parsed))
136+ assert os_env_like[' SPAM' ] == ' EGGS'
137+
138+ This could be useful if you need to *consume * the envfile but not *apply * it
139+ directly into the system environment.
140+
141+
114142Installation
115143============
116144
Original file line number Diff line number Diff line change @@ -95,24 +95,31 @@ def dotenv_values(dotenv_path):
9595 return values
9696
9797
98- def parse_dotenv (dotenv_path ):
99- with open (dotenv_path ) as f :
100- for line in f :
101- line = line .strip ()
102- if not line or line .startswith ('#' ) or '=' not in line :
103- continue
104- k , v = line .split ('=' , 1 )
98+ def parse_dotenv (dotenv_path = None , stream = None ):
99+ if dotenv_path :
100+ f = open (dotenv_path )
101+ elif stream :
102+ f = stream
105103
106- # Remove any leading and trailing spaces in key, value
107- k , v = k .strip (), v .strip ().encode ('unicode-escape' ).decode ('ascii' )
104+ for line in f :
105+ line = line .strip ()
106+ if not line or line .startswith ('#' ) or '=' not in line :
107+ continue
108+ k , v = line .split ('=' , 1 )
108109
109- if len ( v ) > 0 :
110- quoted = v [ 0 ] == v [ - 1 ] in [ '"' , "'" ]
110+ # Remove any leading and trailing spaces in key, value
111+ k , v = k . strip (), v . strip (). encode ( 'unicode-escape' ). decode ( 'ascii' )
111112
112- if quoted :
113- v = decode_escaped ( v [ 1 : - 1 ])
113+ if len ( v ) > 0 :
114+ quoted = v [ 0 ] == v [ - 1 ] in [ '"' , "'" ]
114115
115- yield k , v
116+ if quoted :
117+ v = decode_escaped (v [1 :- 1 ])
118+
119+ yield k , v
120+
121+ if dotenv_path :
122+ f .close ()
116123
117124
118125def resolve_nested_variables (values ):
Original file line number Diff line number Diff line change 44import tempfile
55import warnings
66import sh
7+ try :
8+ from StringIO import StringIO
9+ except ImportError :
10+ from io import StringIO
711
812from dotenv import load_dotenv , find_dotenv , set_key
13+ from dotenv .main import parse_dotenv
914from IPython .terminal .embed import InteractiveShellEmbed
1015
1116
@@ -110,3 +115,12 @@ def test_ipython_override():
110115 ipshell .magic ("load_ext dotenv" )
111116 ipshell .magic ("dotenv -o" )
112117 assert os .environ ["MYNEWVALUE" ] == 'q1w2e3'
118+
119+
120+ def test_parse_dotenv_stream ():
121+ stream = StringIO ('DOTENV=WORKS\n ' )
122+ stream .seek (0 )
123+ parsed_generator = parse_dotenv (stream = stream )
124+ parsed_dict = dict (iter (parsed_generator ))
125+ assert 'DOTENV' in parsed_dict
126+ assert parsed_dict ['DOTENV' ] == 'WORKS'
You can’t perform that action at this time.
0 commit comments