Skip to content

Commit

Permalink
Return False when we do not discover any environment variables
Browse files Browse the repository at this point in the history
This modifies Dotenv.set_as_environment_variables to return False
if we have not discovered any environment variables via either
`dotenv_path` or `stream`.

The return value gets passed through to `load_dotenv`, so this can be
used to determine if `dotenv.load_dotenv` was able to set anything.

Closes #321
  • Loading branch information
larsks committed Mar 15, 2022
1 parent 9047c6a commit 020ac34
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 23 deletions.
3 changes: 3 additions & 0 deletions src/dotenv/main.py
Expand Up @@ -88,6 +88,9 @@ def set_as_environment_variables(self) -> bool:
"""
Load the current dotenv as system environment variable.
"""
if not self.dict():
return False

for k, v in self.dict().items():
if k in os.environ and not self.override:
continue
Expand Down
45 changes: 22 additions & 23 deletions tests/test_main.py
Expand Up @@ -28,9 +28,9 @@ def test_set_key_no_file(tmp_path):
("", "a", "", (True, "a", ""), "a=''\n"),
("", "a", "b", (True, "a", "b"), "a='b'\n"),
("", "a", "'b'", (True, "a", "'b'"), "a='\\'b\\''\n"),
("", "a", "\"b\"", (True, "a", '"b"'), "a='\"b\"'\n"),
("", "a", '"b"', (True, "a", '"b"'), "a='\"b\"'\n"),
("", "a", "b'c", (True, "a", "b'c"), "a='b\\'c'\n"),
("", "a", "b\"c", (True, "a", "b\"c"), "a='b\"c'\n"),
("", "a", 'b"c', (True, "a", 'b"c'), "a='b\"c'\n"),
("a=b", "a", "c", (True, "a", "c"), "a='c'\n"),
("a=b\n", "a", "c", (True, "a", "c"), "a='c'\n"),
("a=b\n\n", "a", "c", (True, "a", "c"), "a='c'\n\n"),
Expand Down Expand Up @@ -77,8 +77,9 @@ def test_get_key_no_file(tmp_path):
nx_file = str(tmp_path / "nx")
logger = logging.getLogger("dotenv.main")

with mock.patch.object(logger, "info") as mock_info, \
mock.patch.object(logger, "warning") as mock_warning:
with mock.patch.object(logger, "info") as mock_info, mock.patch.object(
logger, "warning"
) as mock_warning:
result = dotenv.get_key(nx_file, "foo")

assert result is None
Expand All @@ -88,9 +89,7 @@ def test_get_key_no_file(tmp_path):
],
)
mock_warning.assert_has_calls(
calls=[
mock.call("Key %s not found in %s.", "foo", nx_file)
],
calls=[mock.call("Key %s not found in %s.", "foo", nx_file)],
)


Expand Down Expand Up @@ -208,7 +207,7 @@ def prepare_file_hierarchy(path):

curr_dir = path
dirs = []
for f in ['child1', 'child2', 'child3', 'child4']:
for f in ["child1", "child2", "child3", "child4"]:
curr_dir /= f
dirs.append(curr_dir)
curr_dir.mkdir()
Expand Down Expand Up @@ -259,9 +258,12 @@ def test_load_dotenv_no_file_verbose():
logger = logging.getLogger("dotenv.main")

with mock.patch.object(logger, "info") as mock_info:
dotenv.load_dotenv('.does_not_exist', verbose=True)
result = dotenv.load_dotenv(".does_not_exist", verbose=True)

mock_info.assert_called_once_with("Python-dotenv could not find configuration file %s.", ".does_not_exist")
assert result is False
mock_info.assert_called_once_with(
"Python-dotenv could not find configuration file %s.", ".does_not_exist"
)


@mock.patch.dict(os.environ, {"a": "c"}, clear=True)
Expand Down Expand Up @@ -331,21 +333,25 @@ def test_load_dotenv_file_stream(dotenv_file):


def test_load_dotenv_in_current_dir(tmp_path):
dotenv_path = tmp_path / '.env'
dotenv_path.write_bytes(b'a=b')
code_path = tmp_path / 'code.py'
code_path.write_text(textwrap.dedent("""
dotenv_path = tmp_path / ".env"
dotenv_path.write_bytes(b"a=b")
code_path = tmp_path / "code.py"
code_path.write_text(
textwrap.dedent(
"""
import dotenv
import os
dotenv.load_dotenv(verbose=True)
print(os.environ['a'])
"""))
"""
)
)
os.chdir(str(tmp_path))

result = sh.Command(sys.executable)(code_path)

assert result == 'b\n'
assert result == "b\n"


def test_dotenv_values_file(dotenv_file):
Expand All @@ -367,30 +373,23 @@ def test_dotenv_values_file(dotenv_file):
({"b": "c"}, "a=${b}", True, {"a": "c"}),
({"b": "c"}, "a=${b:-d}", False, {"a": "${b:-d}"}),
({"b": "c"}, "a=${b:-d}", True, {"a": "c"}),
# Defined in file
({}, "b=c\na=${b}", True, {"a": "c", "b": "c"}),
# Undefined
({}, "a=${b}", True, {"a": ""}),
({}, "a=${b:-d}", True, {"a": "d"}),
# With quotes
({"b": "c"}, 'a="${b}"', True, {"a": "c"}),
({"b": "c"}, "a='${b}'", True, {"a": "c"}),
# With surrounding text
({"b": "c"}, "a=x${b}y", True, {"a": "xcy"}),
# Self-referential
({"a": "b"}, "a=${a}", True, {"a": "b"}),
({}, "a=${a}", True, {"a": ""}),
({"a": "b"}, "a=${a:-c}", True, {"a": "b"}),
({}, "a=${a:-c}", True, {"a": "c"}),
# Reused
({"b": "c"}, "a=${b}${b}", True, {"a": "cc"}),
# 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"}),
Expand Down

0 comments on commit 020ac34

Please sign in to comment.