nebius/SWE-bench-extra huggingface dataset:
Repository: theskumar/python-dotenv

Issue:
Regression 0.9.1 -> 0.10.0: .env parsed incorrectly
Hello!

I have upgraded dotenv from 0.9.1 to 0.10 and now my config file is parsed incorrectly.

Example file:

```
$ cat .env
VAR_A=

VAR_B=123
```

Current behaviour on 0.10:
```
$ dotenv list

VAR_A=VAR_B=123
```

Previous (correct) behaviour on 0.9:

```
$ dotenv list

VAR_A=
VAR_B=123
```

Comments:

Patch:
diff --git a/dotenv/main.py b/dotenv/main.py
index 1a88238..98b22ec 100644
--- a/dotenv/main.py
+++ b/dotenv/main.py
@@ -21,14 +21,14 @@ _binding = re.compile(
     r"""
         (
             \s*                     # leading whitespace
-            (?:export\s+)?          # export
+            (?:export{0}+)?         # export
 
             ( '[^']+'               # single-quoted key
             | [^=\#\s]+             # or unquoted key
             )?
 
             (?:
-                (?:\s*=\s*)         # equal sign
+                (?:{0}*={0}*)       # equal sign
 
                 ( '(?:\\'|[^'])*'   # single-quoted value
                 | "(?:\\"|[^"])*"   # or double-quoted value
@@ -40,7 +40,7 @@ _binding = re.compile(
             (?:\#[^\r\n]*)?         # comment
             (?:\r|\n|\r\n)?         # newline
         )
-    """,
+    """.format(r'[^\S\r\n]'),
     re.MULTILINE | re.VERBOSE,
 )
 


Test patch:
diff --git a/tests/test_core.py b/tests/test_core.py
index bda2e3b..f797600 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -63,6 +63,13 @@ def restore_os_environ():
             Binding(key="c", value="d", original="c=d"),
         ],
     ),
+    (
+        'a=\nb=c',
+        [
+            Binding(key="a", value='', original='a=\n'),
+            Binding(key="b", value='c', original="b=c"),
+        ]
+    ),
     (
         'a="\nb=c',
         [
Repository: theskumar/python-dotenv

Issue:
set_key does not check if there is a carriage return before inserting new key
Example script :
```
import os
import dotenv

DOTENV_FILE = os.path.join(os.path.dirname(__file__), ".env")

def init_dotenv():
    with open(DOTENV_FILE, "w") as fp:
        fp.write("TEST=ABCD") 


def print_dotenv():
    with open(DOTENV_FILE) as fp:
        content = fp.read()
    print("-" * 30, "DOTENV", "-" * 30)
    print(content)
    print()

init_dotenv()
print_dotenv()
dotenv.set_key(DOTENV_FILE, "FOO", "1234")
print_dotenv()
```
Output
```
------------------------------ DOTENV ------------------------------
TEST=ABCD

------------------------------ DOTENV ------------------------------
TEST=ABCDFOO='1234'


```

Is this something you want to fix ?

Comments:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b2b2bb..811ed1a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this
 project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## Unreleased
+
+### Fixed
+
+- In `set_key`, add missing newline character before new entry if necessary. (#361 by
+  [@bbc2])
+
 ## [0.19.1] - 2021-08-09
 
 ### Added
diff --git a/src/dotenv/main.py b/src/dotenv/main.py
index b8d0a4e..d867f02 100644
--- a/src/dotenv/main.py
+++ b/src/dotenv/main.py
@@ -167,13 +167,17 @@ def set_key(
 
     with rewrite(dotenv_path) as (source, dest):
         replaced = False
+        missing_newline = False
         for mapping in with_warn_for_invalid_lines(parse_stream(source)):
             if mapping.key == key_to_set:
                 dest.write(line_out)
                 replaced = True
             else:
                 dest.write(mapping.original.string)
+                missing_newline = not mapping.original.string.endswith("\n")
         if not replaced:
+            if missing_newline:
+                dest.write("\n")
             dest.write(line_out)
 
     return True, key_to_set, value_to_set


Test patch:
diff --git a/tests/test_main.py b/tests/test_main.py
index 13e2791..541ac5e 100644
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -37,6 +37,7 @@ def test_set_key_no_file(tmp_path):
         ("a=b\nc=d", "a", "e", (True, "a", "e"), "a='e'\nc=d"),
         ("a=b\nc=d\ne=f", "c", "g", (True, "c", "g"), "a=b\nc='g'\ne=f"),
         ("a=b\n", "c", "d", (True, "c", "d"), "a=b\nc='d'\n"),
+        ("a=b", "c", "d", (True, "c", "d"), "a=b\nc='d'\n"),
     ],
 )
 def test_set_key(dotenv_file, before, key, value, expected, after):
Repository: theskumar/python-dotenv

Issue:
load_dotenv() returns True even if .env file is not found
This behaviour is not ideal since if the configuration file is not found in the filesystem it may be better to return False.
In this way the user can write something like:
```python
if load_dotenv():
    #do stuff
else
    print("No file .env found")
```

# Steps to reproduce
```
In [1]: import dotenv

In [2]: dotenv.load_dotenv()
Out[2]: True

In [3]: dotenv.find_dotenv()
Out[3]: ''
```

Comments:

Patch:
diff --git a/src/dotenv/main.py b/src/dotenv/main.py
index e7ad430..7841066 100644
--- a/src/dotenv/main.py
+++ b/src/dotenv/main.py
@@ -87,6 +87,9 @@ class DotEnv():
         """
         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
@@ -324,6 +327,8 @@ def load_dotenv(
         override: Whether to override the system environment variables with the variables
             from the `.env` file.
         encoding: Encoding to be used to read the file.
+    Returns:
+        Bool: True if atleast one environment variable is set elese False
 
     If both `dotenv_path` and `stream` are `None`, `find_dotenv()` is used to find the
     .env file.


Test patch:
diff --git a/tests/test_main.py b/tests/test_main.py
index ca14b1a..82c73ba 100644
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -259,8 +259,9 @@ 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)
 
+    assert result is False
     mock_info.assert_called_once_with("Python-dotenv could not find configuration file %s.", ".does_not_exist")
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.

Comments:

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",
     [
Repository: tinosulzer/PyBaMM

Issue:
Domains as strings
**Describe the bug**
The `Domain` class checks that `domain` is an iterable and raises a `TypeError` if it isn't.
However, a `str` domain is not caught by this as `iter("a string") == True`.
This isn't caught by the test in `TestIndependentVariable`; test should be
```python
with self.assertRaises(TypeError):
   pybamm.IndependentVariable("a", domain="test")
```

**Suggested fix**
If `domain` is a string, replace with `list(domain)`.



Comments:

Patch:
diff --git a/pybamm/expression_tree/domain.py b/pybamm/expression_tree/domain.py
index 5ca645b2..75be730f 100644
--- a/pybamm/expression_tree/domain.py
+++ b/pybamm/expression_tree/domain.py
@@ -13,17 +13,19 @@ class Domain(object):
 
     name: str
         the name of the node
-    domain : iterable of str
+    domain : iterable of str, or str
         the list of domains
 
     """
 
     def __init__(self, name, domain=[]):
         super().__init__(name)
+        if isinstance(domain, str):
+            domain = [domain]
         try:
             iter(domain)
         except TypeError:
-            raise TypeError('Domain: argument domain is not iterable')
+            raise TypeError("Domain: argument domain is not iterable")
         else:
             self.domain = domain
 


Test patch:
diff --git a/tests/test_expression_tree/test_independent_variable.py b/tests/test_expression_tree/test_independent_variable.py
index 7ce7b560..22db0db9 100644
--- a/tests/test_expression_tree/test_independent_variable.py
+++ b/tests/test_expression_tree/test_independent_variable.py
@@ -13,9 +13,12 @@ class TestIndependentVariable(unittest.TestCase):
         a = pybamm.IndependentVariable("a")
         self.assertEqual(a.name, "a")
         self.assertEqual(a.domain, [])
-        a = pybamm.IndependentVariable("a", domain=['test'])
-        self.assertEqual(a.domain[0], 'test')
-        self.assertRaises(TypeError, pybamm.IndependentVariable("a", domain='test'))
+        a = pybamm.IndependentVariable("a", domain=["test"])
+        self.assertEqual(a.domain[0], "test")
+        a = pybamm.IndependentVariable("a", domain="test")
+        self.assertEqual(a.domain[0], "test")
+        with self.assertRaises(TypeError):
+            pybamm.IndependentVariable("a", domain=1)
 
 
 if __name__ == "__main__":