diff --git a/CHANGELOG.md b/CHANGELOG.md index 116d97fa..a01d3dc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] -*No unreleased change at this time.* +### Fixed + +- Fix potentially empty expanded value for duplicate key (#260 by [@bbc]). ## [0.14.0] - 2020-07-03 diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 8f77e831..607299ae 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -18,7 +18,7 @@ if IS_TYPE_CHECKING: from typing import ( - Dict, Iterator, Match, Optional, Pattern, Union, Text, IO, Tuple + Dict, Iterable, Iterator, Match, Optional, Pattern, Union, Text, IO, Tuple ) if sys.version_info >= (3, 6): _PathLike = os.PathLike @@ -83,9 +83,13 @@ def dict(self): if self._dict: return self._dict - values = OrderedDict(self.parse()) - self._dict = resolve_nested_variables(values) if self.interpolate else values - return self._dict + if self.interpolate: + values = resolve_nested_variables(self.parse()) + else: + values = OrderedDict(self.parse()) + + self._dict = values + return values def parse(self): # type: () -> Iterator[Tuple[Text, Optional[Text]]] @@ -211,7 +215,7 @@ def unset_key(dotenv_path, key_to_unset, quote_mode="always"): def resolve_nested_variables(values): - # type: (Dict[Text, Optional[Text]]) -> Dict[Text, Optional[Text]] + # type: (Iterable[Tuple[Text, Optional[Text]]]) -> Dict[Text, Optional[Text]] def _replacement(name, default): # type: (Text, Optional[Text]) -> Text default = default if default is not None else "" @@ -229,7 +233,7 @@ def _re_sub_callback(match): new_values = {} - for k, v in values.items(): + for (k, v) in values: new_values[k] = __posix_variable.sub(_re_sub_callback, v) if v is not None else None return new_values diff --git a/tests/test_main.py b/tests/test_main.py index 3a3d059b..339d00bb 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -337,6 +337,8 @@ def test_dotenv_values_file(dotenv_file): # Re-defined and used in file ({"b": "c"}, "b=d\na=${b}", True, {"a": "d", "b": "d"}), + ({}, "a=b\na=c\nd=${a}", True, {"a": "c", "d": "c"}), + ({}, "a=b\nc=${a}\nd=e\nc=${d}", True, {"a": "b", "c": "e", "d": "e"}), ], ) def test_dotenv_values_stream(env, string, interpolate, expected):