Skip to content

Commit 70d0c19

Browse files
committed
Fix handling of lines with just a comment
A .env file like the following would trigger a warning: # comment The problem is that with the previous `Binding` structure, it was impossible to distinguish the parsing of such a line and that of a malformed line. Therefore, this commit adds an `error` field so that error reporting works correctly in this case.
1 parent c68e78f commit 70d0c19

4 files changed

Lines changed: 88 additions & 46 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Latest
2222
- Fix handling of malformed lines and lines without a value:
2323
- Don't print warning when key has no value.
2424
- Reject more malformed lines (e.g. "A: B").
25+
- Fix handling of lines with just a comment.
2526

2627
0.10.4
2728
-----

src/dotenv/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
def with_warn_for_invalid_lines(mappings):
3838
# type: (Iterator[Binding]) -> Iterator[Binding]
3939
for mapping in mappings:
40-
if mapping.key is None:
40+
if mapping.error:
4141
logger.warning(
4242
"Python-dotenv could not parse statement starting at line %s",
4343
mapping.original.line,

src/dotenv/parser.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def make_regex(string, extra_flags=0):
2525
_single_quoted_value = make_regex(r"'((?:\\'|[^'])*)'")
2626
_double_quoted_value = make_regex(r'"((?:\\"|[^"])*)"')
2727
_unquoted_value_part = make_regex(r"([^ \r\n]*)")
28-
_comment = make_regex(r"(?:\s*#[^\r\n]*)?")
28+
_comment = make_regex(r"(?:[^\S\r\n]*#[^\r\n]*)?")
2929
_end_of_line = make_regex(r"[^\S\r\n]*(?:\r\n|\n|\r|$)")
3030
_rest_of_line = make_regex(r"[^\r\n]*(?:\r|\n|\r\n)?")
3131
_double_quote_escapes = make_regex(r"\\[\\'\"abfnrtv]")
@@ -52,6 +52,7 @@ def make_regex(string, extra_flags=0):
5252
("key", typing.Optional[typing.Text]),
5353
("value", typing.Optional[typing.Text]),
5454
("original", Original),
55+
("error", bool),
5556
],
5657
)
5758
except ImportError:
@@ -69,6 +70,7 @@ def make_regex(string, extra_flags=0):
6970
"key",
7071
"value",
7172
"original",
73+
"error",
7274
],
7375
)
7476

@@ -152,9 +154,11 @@ def decode_match(match):
152154

153155

154156
def parse_key(reader):
155-
# type: (Reader) -> Text
157+
# type: (Reader) -> Optional[Text]
156158
char = reader.peek(1)
157-
if char == "'":
159+
if char == "#":
160+
return None
161+
elif char == "'":
158162
(key,) = reader.read_regex(_single_quoted_key)
159163
else:
160164
(key,) = reader.read_regex(_unquoted_key)
@@ -207,13 +211,15 @@ def parse_binding(reader):
207211
key=key,
208212
value=value,
209213
original=reader.get_marked(),
214+
error=False,
210215
)
211216
except Error:
212217
reader.read_regex(_rest_of_line)
213218
return Binding(
214219
key=None,
215220
value=None,
216221
original=reader.get_marked(),
222+
error=True,
217223
)
218224

219225

tests/test_parser.py

Lines changed: 77 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,93 +7,128 @@
77

88
@pytest.mark.parametrize("test_input,expected", [
99
(u"", []),
10-
(u"a=b", [Binding(key=u"a", value=u"b", original=Original(string=u"a=b", line=1))]),
11-
(u"'a'=b", [Binding(key=u"a", value=u"b", original=Original(string=u"'a'=b", line=1))]),
12-
(u"[=b", [Binding(key=u"[", value=u"b", original=Original(string=u"[=b", line=1))]),
13-
(u" a = b ", [Binding(key=u"a", value=u"b", original=Original(string=u" a = b ", line=1))]),
14-
(u"export a=b", [Binding(key=u"a", value=u"b", original=Original(string=u"export a=b", line=1))]),
15-
(u" export 'a'=b", [Binding(key=u"a", value=u"b", original=Original(string=u" export 'a'=b", line=1))]),
16-
(u"# a=b", [Binding(key=None, value=None, original=Original(string=u"# a=b", line=1))]),
17-
(u"a=b#c", [Binding(key=u"a", value=u"b#c", original=Original(string=u"a=b#c", line=1))]),
18-
(u'a=b # comment', [Binding(key=u"a", value=u"b", original=Original(string=u"a=b # comment", line=1))]),
19-
(u"a=b space ", [Binding(key=u"a", value=u"b space", original=Original(string=u"a=b space ", line=1))]),
20-
(u"a='b space '", [Binding(key=u"a", value=u"b space ", original=Original(string=u"a='b space '", line=1))]),
21-
(u'a="b space "', [Binding(key=u"a", value=u"b space ", original=Original(string=u'a="b space "', line=1))]),
10+
(u"a=b", [Binding(key=u"a", value=u"b", original=Original(string=u"a=b", line=1), error=False)]),
11+
(u"'a'=b", [Binding(key=u"a", value=u"b", original=Original(string=u"'a'=b", line=1), error=False)]),
12+
(u"[=b", [Binding(key=u"[", value=u"b", original=Original(string=u"[=b", line=1), error=False)]),
13+
(u" a = b ", [Binding(key=u"a", value=u"b", original=Original(string=u" a = b ", line=1), error=False)]),
14+
(u"export a=b", [Binding(key=u"a", value=u"b", original=Original(string=u"export a=b", line=1), error=False)]),
15+
(
16+
u" export 'a'=b",
17+
[Binding(key=u"a", value=u"b", original=Original(string=u" export 'a'=b", line=1), error=False)],
18+
),
19+
(u"# a=b", [Binding(key=None, value=None, original=Original(string=u"# a=b", line=1), error=False)]),
20+
(u"a=b#c", [Binding(key=u"a", value=u"b#c", original=Original(string=u"a=b#c", line=1), error=False)]),
21+
(
22+
u'a=b # comment',
23+
[Binding(key=u"a", value=u"b", original=Original(string=u"a=b # comment", line=1), error=False)],
24+
),
25+
(
26+
u"a=b space ",
27+
[Binding(key=u"a", value=u"b space", original=Original(string=u"a=b space ", line=1), error=False)],
28+
),
29+
(
30+
u"a='b space '",
31+
[Binding(key=u"a", value=u"b space ", original=Original(string=u"a='b space '", line=1), error=False)],
32+
),
33+
(
34+
u'a="b space "',
35+
[Binding(key=u"a", value=u"b space ", original=Original(string=u'a="b space "', line=1), error=False)],
36+
),
2237
(
2338
u"export export_a=1",
2439
[
25-
Binding(key=u"export_a", value=u"1", original=Original(string=u"export export_a=1", line=1))
40+
Binding(key=u"export_a", value=u"1", original=Original(string=u"export export_a=1", line=1), error=False)
2641
],
2742
),
28-
(u"export port=8000", [Binding(key=u"port", value=u"8000", original=Original(string=u"export port=8000", line=1))]),
29-
(u'a="b\nc"', [Binding(key=u"a", value=u"b\nc", original=Original(string=u'a="b\nc"', line=1))]),
30-
(u"a='b\nc'", [Binding(key=u"a", value=u"b\nc", original=Original(string=u"a='b\nc'", line=1))]),
31-
(u'a="b\nc"', [Binding(key=u"a", value=u"b\nc", original=Original(string=u'a="b\nc"', line=1))]),
32-
(u'a="b\\nc"', [Binding(key=u"a", value=u'b\nc', original=Original(string=u'a="b\\nc"', line=1))]),
33-
(u"a='b\\nc'", [Binding(key=u"a", value=u'b\\nc', original=Original(string=u"a='b\\nc'", line=1))]),
34-
(u'a="b\\"c"', [Binding(key=u"a", value=u'b"c', original=Original(string=u'a="b\\"c"', line=1))]),
35-
(u"a='b\\'c'", [Binding(key=u"a", value=u"b'c", original=Original(string=u"a='b\\'c'", line=1))]),
36-
(u"a=à", [Binding(key=u"a", value=u"à", original=Original(string=u"a=à", line=1))]),
37-
(u'a="à"', [Binding(key=u"a", value=u"à", original=Original(string=u'a="à"', line=1))]),
38-
(u'no_value_var', [Binding(key=u'no_value_var', value=None, original=Original(string=u"no_value_var", line=1))]),
39-
(u'a: b', [Binding(key=None, value=None, original=Original(string=u"a: b", line=1))]),
43+
(
44+
u"export port=8000",
45+
[Binding(key=u"port", value=u"8000", original=Original(string=u"export port=8000", line=1), error=False)],
46+
),
47+
(u'a="b\nc"', [Binding(key=u"a", value=u"b\nc", original=Original(string=u'a="b\nc"', line=1), error=False)]),
48+
(u"a='b\nc'", [Binding(key=u"a", value=u"b\nc", original=Original(string=u"a='b\nc'", line=1), error=False)]),
49+
(u'a="b\nc"', [Binding(key=u"a", value=u"b\nc", original=Original(string=u'a="b\nc"', line=1), error=False)]),
50+
(u'a="b\\nc"', [Binding(key=u"a", value=u'b\nc', original=Original(string=u'a="b\\nc"', line=1), error=False)]),
51+
(u"a='b\\nc'", [Binding(key=u"a", value=u'b\\nc', original=Original(string=u"a='b\\nc'", line=1), error=False)]),
52+
(u'a="b\\"c"', [Binding(key=u"a", value=u'b"c', original=Original(string=u'a="b\\"c"', line=1), error=False)]),
53+
(u"a='b\\'c'", [Binding(key=u"a", value=u"b'c", original=Original(string=u"a='b\\'c'", line=1), error=False)]),
54+
(u"a=à", [Binding(key=u"a", value=u"à", original=Original(string=u"a=à", line=1), error=False)]),
55+
(u'a="à"', [Binding(key=u"a", value=u"à", original=Original(string=u'a="à"', line=1), error=False)]),
56+
(
57+
u'no_value_var',
58+
[Binding(key=u'no_value_var', value=None, original=Original(string=u"no_value_var", line=1), error=False)],
59+
),
60+
(u'a: b', [Binding(key=None, value=None, original=Original(string=u"a: b", line=1), error=True)]),
4061
(
4162
u"a=b\nc=d",
4263
[
43-
Binding(key=u"a", value=u"b", original=Original(string=u"a=b\n", line=1)),
44-
Binding(key=u"c", value=u"d", original=Original(string=u"c=d", line=2)),
64+
Binding(key=u"a", value=u"b", original=Original(string=u"a=b\n", line=1), error=False),
65+
Binding(key=u"c", value=u"d", original=Original(string=u"c=d", line=2), error=False),
4566
],
4667
),
4768
(
4869
u"a=b\rc=d",
4970
[
50-
Binding(key=u"a", value=u"b", original=Original(string=u"a=b\r", line=1)),
51-
Binding(key=u"c", value=u"d", original=Original(string=u"c=d", line=2)),
71+
Binding(key=u"a", value=u"b", original=Original(string=u"a=b\r", line=1), error=False),
72+
Binding(key=u"c", value=u"d", original=Original(string=u"c=d", line=2), error=False),
5273
],
5374
),
5475
(
5576
u"a=b\r\nc=d",
5677
[
57-
Binding(key=u"a", value=u"b", original=Original(string=u"a=b\r\n", line=1)),
58-
Binding(key=u"c", value=u"d", original=Original(string=u"c=d", line=2)),
78+
Binding(key=u"a", value=u"b", original=Original(string=u"a=b\r\n", line=1), error=False),
79+
Binding(key=u"c", value=u"d", original=Original(string=u"c=d", line=2), error=False),
5980
],
6081
),
6182
(
6283
u'a=\nb=c',
6384
[
64-
Binding(key=u"a", value=u'', original=Original(string=u'a=\n', line=1)),
65-
Binding(key=u"b", value=u'c', original=Original(string=u"b=c", line=2)),
85+
Binding(key=u"a", value=u'', original=Original(string=u'a=\n', line=1), error=False),
86+
Binding(key=u"b", value=u'c', original=Original(string=u"b=c", line=2), error=False),
6687
]
6788
),
6889
(
6990
u'a=b\n\nc=d',
7091
[
71-
Binding(key=u"a", value=u"b", original=Original(string=u"a=b\n", line=1)),
72-
Binding(key=u"c", value=u"d", original=Original(string=u"\nc=d", line=2)),
92+
Binding(key=u"a", value=u"b", original=Original(string=u"a=b\n", line=1), error=False),
93+
Binding(key=u"c", value=u"d", original=Original(string=u"\nc=d", line=2), error=False),
7394
]
7495
),
7596
(
7697
u'a="\nb=c',
7798
[
78-
Binding(key=None, value=None, original=Original(string=u'a="\n', line=1)),
79-
Binding(key=u"b", value=u"c", original=Original(string=u"b=c", line=2)),
99+
Binding(key=None, value=None, original=Original(string=u'a="\n', line=1), error=True),
100+
Binding(key=u"b", value=u"c", original=Original(string=u"b=c", line=2), error=False),
80101
]
81102
),
82103
(
83104
u'# comment\na="b\nc"\nd=e\n',
84105
[
85-
Binding(key=None, value=None, original=Original(string=u"# comment\n", line=1)),
86-
Binding(key=u"a", value=u"b\nc", original=Original(string=u'a="b\nc"\n', line=2)),
87-
Binding(key=u"d", value=u"e", original=Original(string=u"d=e\n", line=4)),
106+
Binding(key=None, value=None, original=Original(string=u"# comment\n", line=1), error=False),
107+
Binding(key=u"a", value=u"b\nc", original=Original(string=u'a="b\nc"\n', line=2), error=False),
108+
Binding(key=u"d", value=u"e", original=Original(string=u"d=e\n", line=4), error=False),
109+
],
110+
),
111+
(
112+
u'a=b\n# comment 1',
113+
[
114+
Binding(key="a", value="b", original=Original(string=u"a=b\n", line=1), error=False),
115+
Binding(key=None, value=None, original=Original(string=u"# comment 1", line=2), error=False),
116+
],
117+
),
118+
(
119+
u'# comment 1\n# comment 2',
120+
[
121+
Binding(key=None, value=None, original=Original(string=u"# comment 1\n", line=1), error=False),
122+
Binding(key=None, value=None, original=Original(string=u"# comment 2", line=2), error=False),
88123
],
89124
),
90125
(
91126
u'uglyKey[%$=\"S3cr3t_P4ssw#rD\" #\na=b',
92127
[
93128
Binding(key=u'uglyKey[%$',
94129
value=u'S3cr3t_P4ssw#rD',
95-
original=Original(string=u"uglyKey[%$=\"S3cr3t_P4ssw#rD\" #\n", line=1)),
96-
Binding(key=u"a", value=u"b", original=Original(string=u'a=b', line=2)),
130+
original=Original(string=u"uglyKey[%$=\"S3cr3t_P4ssw#rD\" #\n", line=1), error=False),
131+
Binding(key=u"a", value=u"b", original=Original(string=u'a=b', line=2), error=False),
97132
],
98133
),
99134
])

0 commit comments

Comments
 (0)