Repository: theskumar/python-dotenv

Issue:
Error Handling in rewrite is incorrect.
Look at:
https://github.com/theskumar/python-dotenv/blob/master/src/dotenv/main.py#L136

If lines 136, 137 or 140 there are ever hit, an error "local variable 'dest' referenced before assignment" will be thrown, because the `dest` variable only exists within the scope of the `with` block above.

Discussion:

Patch:
diff --git a/README.md b/README.md
index a9d19bf..983b7d1 100644
--- a/README.md
+++ b/README.md
@@ -163,7 +163,7 @@ The format is not formally specified and still improves over time.  That being s
 
 Keys can be unquoted or single-quoted. Values can be unquoted, single- or double-quoted.
 Spaces before and after keys, equal signs, and values are ignored. Values can be followed
-by a comment.  Lines can start with the `export` directive, which has no effect on their
+by a comment.  Lines can start with the `export` directive, which does not affect their
 interpretation.
 
 Allowed escape sequences:
diff --git a/src/dotenv/main.py b/src/dotenv/main.py
index 05d377a..3321788 100644
--- a/src/dotenv/main.py
+++ b/src/dotenv/main.py
@@ -125,15 +125,16 @@ def rewrite(
     path: Union[str, os.PathLike],
     encoding: Optional[str],
 ) -> Iterator[Tuple[IO[str], IO[str]]]:
+    dest = None
     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:
-            with open(path, encoding=encoding) as source:
-                yield (source, dest)  # type: ignore
+        dest = tempfile.NamedTemporaryFile(mode="w+", delete=False, encoding=encoding)
+        with open(path, encoding=encoding) as source:
+            yield (source, dest)  # type: ignore
     except BaseException:
-        if os.path.isfile(dest.name):
+        if dest and os.path.isfile(dest.name):
             os.unlink(dest.name)
         raise
     else:


Test patch:
diff --git a/tests/test_main.py b/tests/test_main.py
index 82c73ba..84a982f 100644
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -22,6 +22,11 @@ def test_set_key_no_file(tmp_path):
     assert os.path.exists(nx_file)
 
 
+def test_set_key_invalid_file():
+    with pytest.raises(TypeError):
+        result = dotenv.set_key(None, "foo", "bar")
+
+
 @pytest.mark.parametrize(
     "before,key,value,expected,after",
     [