File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -110,6 +110,34 @@ Django
110110If you are using django you should add the above loader script at the
111111top of ``wsgi.py `` and ``manage.py ``.
112112
113+
114+ In-memory filelikes
115+ -------------------
116+
117+ Is possible to not rely on the filesystem to parse filelikes from other sources
118+ (e.g. from a network storage). ``parse_dotenv `` accepts a filelike `stream `.
119+ Just be sure to rewind it before passing.
120+
121+ .. code :: python
122+
123+ from io import StringIO # Python2: from StringIO import StringIO
124+ from dotenv.main import parse_dotenv
125+ filelike = StringIO(' SPAM=EGSS\n ' )
126+ filelike.seek(0 )
127+ parsed = parse_dotenv(stream = filelike)
128+
129+ The returned lazy generator yields ``(key,value) `` tuples.
130+ To ease the consumption, is suggested to unpack it into a dictionary.
131+
132+ .. code :: python
133+
134+ os_env_like = dict (iter (parsed))
135+ assert os_env_like[' SPAM' ] == ' EGGS'
136+
137+ This could be useful if you need to *consume * the envfile but not *apply * it
138+ directly into the system environment.
139+
140+
113141Installation
114142============
115143
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