From 1ecb57dd7dd516d3ecedf7e58ba84520281fbd00 Mon Sep 17 00:00:00 2001 From: Ben Li-Sauerwine Date: Wed, 27 Jul 2022 03:26:26 -0400 Subject: [PATCH] Fix out of scope error when "dest" variable is undefined Fixes #413 whereby the NamedTemporaryFile "dest" was out of scope in the error handling portion of rewrite. The problem was initially fixed in #414 but it got reverted because of a linter error. This new commit works around that linter error. --- src/dotenv/main.py | 20 +++++++++----------- tests/test_main.py | 7 +++++++ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 83ea3239..43248819 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -125,19 +125,17 @@ def rewrite( path: Union[str, os.PathLike], encoding: Optional[str], ) -> Iterator[Tuple[IO[str], IO[str]]]: - try: - if not os.path.isfile(path): - with open(path, "w+", encoding=encoding) as source: - source.write("") - with tempfile.NamedTemporaryFile(mode="w+", delete=False, encoding=encoding) as dest: + if not os.path.isfile(path): + with open(path, mode="w", encoding=encoding) as source: + source.write("") + with tempfile.NamedTemporaryFile(mode="w", encoding=encoding, delete=False) as dest: + try: with open(path, encoding=encoding) as source: - yield (source, dest) # type: ignore - except BaseException: - if os.path.isfile(dest.name): + yield (source, dest) + except BaseException: os.unlink(dest.name) - raise - else: - shutil.move(dest.name, path) + raise + shutil.move(dest.name, path) def set_key( diff --git a/tests/test_main.py b/tests/test_main.py index 82c73ba1..9c895851 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -178,6 +178,13 @@ def test_unset_encoding(dotenv_file): assert f.read() == "" +def test_set_key_unauthorized_file(dotenv_file): + os.chmod(dotenv_file, 0o000) + + with pytest.raises(PermissionError): + dotenv.set_key(dotenv_file, "a", "x") + + def test_unset_non_existent_file(tmp_path): nx_file = str(tmp_path / "nx") logger = logging.getLogger("dotenv.main")