From 020ac3438931ca9db28559ac3417fedc308d6654 Mon Sep 17 00:00:00 2001 From: Lars Kellogg-Stedman Date: Mon, 14 Mar 2022 21:02:12 -0400 Subject: [PATCH] Return False when we do not discover any environment variables 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 --- src/dotenv/main.py | 3 +++ tests/test_main.py | 45 ++++++++++++++++++++++----------------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 4f626a0f..f705e898 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -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 diff --git a/tests/test_main.py b/tests/test_main.py index 364fc24d..559448ac 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -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"), @@ -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 @@ -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)], ) @@ -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() @@ -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) @@ -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): @@ -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"}),