Repository: theskumar/python-dotenv
Pull request #222 (2020-01-17 21:30:36)

Fix handling of no-value and malformed lines
- Don't print warning when key has no value.
- Reject more malformed lines (e.g. "A: B").

bbc2: @ulyssessouza I released 0.10.4 but then realized that it was printing "malformed line" warnings in the Docker Compose use case (key without value) and would accept some really malformed lines.  Before I merge this and release 0.10.5, does this fix work for you?

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 93331a2..3b3a429 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,7 +19,9 @@ Changelog
 Latest
 -----
 
-- ...
+- Fix handling of malformed lines and lines without a value:
+  - Don't print warning when key has no value.
+  - Reject more malformed lines (e.g. "A: B").
 
 0.10.4
 -----
diff --git a/src/dotenv/main.py b/src/dotenv/main.py
index 5a1c325..7051cd3 100644
--- a/src/dotenv/main.py
+++ b/src/dotenv/main.py
@@ -37,7 +37,7 @@ __posix_variable = re.compile(r'\$\{[^\}]*\}')  # type: Pattern[Text]
 def with_warn_for_invalid_lines(mappings):
     # type: (Iterator[Binding]) -> Iterator[Binding]
     for mapping in mappings:
-        if mapping.key is None or mapping.value is None:
+        if mapping.key is None:
             logger.warning(
                 "Python-dotenv could not parse statement starting at line %s",
                 mapping.original.line,
diff --git a/src/dotenv/parser.py b/src/dotenv/parser.py
index bd60cab..516bacc 100644
--- a/src/dotenv/parser.py
+++ b/src/dotenv/parser.py
@@ -16,16 +16,17 @@ def make_regex(string, extra_flags=0):
 
 
 _newline = make_regex(r"(\r\n|\n|\r)")
-_whitespace = make_regex(r"\s*", extra_flags=re.MULTILINE)
+_multiline_whitespace = make_regex(r"\s*", extra_flags=re.MULTILINE)
+_whitespace = make_regex(r"[^\S\r\n]*")
 _export = make_regex(r"(?:export[^\S\r\n]+)?")
 _single_quoted_key = make_regex(r"'([^']+)'")
 _unquoted_key = make_regex(r"([^=\#\s]+)")
-_equal_sign = make_regex(r"([^\S\r\n]*=[^\S\r\n]*)?")
+_equal_sign = make_regex(r"(=[^\S\r\n]*)")
 _single_quoted_value = make_regex(r"'((?:\\'|[^'])*)'")
 _double_quoted_value = make_regex(r'"((?:\\"|[^"])*)"')
 _unquoted_value_part = make_regex(r"([^ \r\n]*)")
 _comment = make_regex(r"(?:\s*#[^\r\n]*)?")
-_end_of_line = make_regex(r"[^\S\r\n]*(?:\r\n|\n|\r)?")
+_end_of_line = make_regex(r"[^\S\r\n]*(?:\r\n|\n|\r|$)")
 _rest_of_line = make_regex(r"[^\r\n]*(?:\r|\n|\r\n)?")
 _double_quote_escapes = make_regex(r"\\[\\'\"abfnrtv]")
 _single_quote_escapes = make_regex(r"\\[\\']")
@@ -191,11 +192,15 @@ def parse_binding(reader):
     # type: (Reader) -> Binding
     reader.set_mark()
     try:
-        reader.read_regex(_whitespace)
+        reader.read_regex(_multiline_whitespace)
         reader.read_regex(_export)
         key = parse_key(reader)
-        (sign,) = reader.read_regex(_equal_sign)
-        value = parse_value(reader) if sign else None
+        reader.read_regex(_whitespace)
+        if reader.peek(1) == "=":
+            reader.read_regex(_equal_sign)
+            value = parse_value(reader)  # type: Optional[Text]
+        else:
+            value = None
         reader.read_regex(_comment)
         reader.read_regex(_end_of_line)
         return Binding(


Test patch:
diff --git a/tests/test_parser.py b/tests/test_parser.py
index c19ed50..837717d 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -36,6 +36,7 @@ from dotenv.parser import Binding, Original, parse_stream
     (u"a=à", [Binding(key=u"a", value=u"à", original=Original(string=u"a=à", line=1))]),
     (u'a="à"', [Binding(key=u"a", value=u"à", original=Original(string=u'a="à"', line=1))]),
     (u'no_value_var', [Binding(key=u'no_value_var', value=None, original=Original(string=u"no_value_var", line=1))]),
+    (u'a: b', [Binding(key=None, value=None, original=Original(string=u"a: b", line=1))]),
     (
         u"a=b\nc=d",
         [