Skip to content

Commit 40ed1b1

Browse files
altendkytheskumar
authored andcommitted
Fix empty self-referential variable issue (theskumar#135)
* Show empty self-referential variable issue theskumar#132 * Correct test names to use interpolation * Only use previously defined variables when handling interpolation * Recover original os.environ after tweaking it in a test
1 parent c5f5a8f commit 40ed1b1

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

dotenv/main.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ def _replacement(name):
187187
first search in environ, if not found,
188188
then look into the dotenv variables
189189
"""
190-
ret = os.getenv(name, values.get(name, ""))
190+
ret = os.getenv(name, new_values.get(name, ""))
191191
return ret
192192

193193
def _re_sub_callback(match_object):
@@ -197,10 +197,12 @@ def _re_sub_callback(match_object):
197197
"""
198198
return _replacement(match_object.group()[2:-1])
199199

200+
new_values = {}
201+
200202
for k, v in values.items():
201-
values[k] = __posix_variable.sub(_re_sub_callback, v)
203+
new_values[k] = __posix_variable.sub(_re_sub_callback, v)
202204

203-
return values
205+
return new_values
204206

205207

206208
def _walk_to_root(path):

tests/test_core.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
22
from __future__ import unicode_literals
33

4+
import contextlib
45
import os
56
import pytest
67
import tempfile
@@ -13,6 +14,16 @@
1314
from IPython.terminal.embed import InteractiveShellEmbed
1415

1516

17+
@contextlib.contextmanager
18+
def restore_os_environ():
19+
environ = dict(os.environ)
20+
21+
try:
22+
yield
23+
finally:
24+
os.environ.update(environ)
25+
26+
1627
@pytest.mark.parametrize("test_input,expected", [
1728
("a=b", ("a", "b")),
1829
(" a = b ", ("a", "b")),
@@ -161,3 +172,21 @@ def test_dotenv_values_export():
161172
load_dotenv(stream=stream)
162173
assert 'foo' in os.environ
163174
assert os.environ['foo'] == 'bar'
175+
176+
177+
def test_dotenv_empty_selfreferential_interpolation():
178+
stream = StringIO(u'some_path="${some_path}:a/b/c"\n')
179+
stream.seek(0)
180+
assert u'some_path' not in os.environ
181+
parsed_dict = dotenv_values(stream=stream)
182+
assert {u'some_path': u':a/b/c'} == parsed_dict
183+
184+
185+
def test_dotenv_nonempty_selfreferential_interpolation():
186+
stream = StringIO(u'some_path="${some_path}:a/b/c"\n')
187+
stream.seek(0)
188+
assert u'some_path' not in os.environ
189+
with restore_os_environ():
190+
os.environ[u'some_path'] = u'x/y/z'
191+
parsed_dict = dotenv_values(stream=stream)
192+
assert {u'some_path': u'x/y/z:a/b/c'} == parsed_dict

0 commit comments

Comments
 (0)