Skip to content

Commit a1f92e9

Browse files
committed
File parsing: Option to raise exception instead of warning
1 parent 08937a1 commit a1f92e9

File tree

2 files changed

+43
-6
lines changed

2 files changed

+43
-6
lines changed

src/dotenv/main.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,24 @@
2222
logger = logging.getLogger(__name__)
2323

2424

25-
def with_warn_for_invalid_lines(mappings: Iterator[Binding]) -> Iterator[Binding]:
25+
class DotEnvParseError(Exception):
26+
def __init__(self, message):
27+
super().__init__(message)
28+
29+
30+
def with_warn_for_invalid_lines(mappings: Iterator[Binding], raise_on_error: bool = False) -> Iterator[Binding]:
2631
for mapping in mappings:
2732
if mapping.error:
28-
logger.warning(
29-
"Python-dotenv could not parse statement starting at line %s",
30-
mapping.original.line,
31-
)
33+
if raise_on_error:
34+
raise DotEnvParseError(
35+
"Python-dotenv could not parse statement starting at line %s" %
36+
mapping.original.line,
37+
)
38+
else:
39+
logger.warning(
40+
"Python-dotenv could not parse statement starting at line %s",
41+
mapping.original.line,
42+
)
3243
yield mapping
3344

3445

@@ -41,6 +52,7 @@ def __init__(
4152
encoding: Optional[str] = None,
4253
interpolate: bool = True,
4354
override: bool = True,
55+
raise_on_error: bool = False,
4456
) -> None:
4557
self.dotenv_path: Optional[StrPath] = dotenv_path
4658
self.stream: Optional[IO[str]] = stream
@@ -49,6 +61,7 @@ def __init__(
4961
self.encoding: Optional[str] = encoding
5062
self.interpolate: bool = interpolate
5163
self.override: bool = override
64+
self.raise_on_error: bool = raise_on_error
5265

5366
@contextmanager
5467
def _get_stream(self) -> Iterator[IO[str]]:
@@ -81,7 +94,7 @@ def dict(self) -> Dict[str, Optional[str]]:
8194

8295
def parse(self) -> Iterator[Tuple[str, Optional[str]]]:
8396
with self._get_stream() as stream:
84-
for mapping in with_warn_for_invalid_lines(parse_stream(stream)):
97+
for mapping in with_warn_for_invalid_lines(parse_stream(stream), self.raise_on_error):
8598
if mapping.key is not None:
8699
yield mapping.key, mapping.value
87100

@@ -325,6 +338,7 @@ def load_dotenv(
325338
override: bool = False,
326339
interpolate: bool = True,
327340
encoding: Optional[str] = "utf-8",
341+
raise_on_error: bool = False,
328342
) -> bool:
329343
"""Parse a .env file and then load all the variables found as environment variables.
330344
@@ -354,6 +368,7 @@ def load_dotenv(
354368
interpolate=interpolate,
355369
override=override,
356370
encoding=encoding,
371+
raise_on_error=raise_on_error,
357372
)
358373
return dotenv.set_as_environment_variables()
359374

@@ -364,6 +379,7 @@ def dotenv_values(
364379
verbose: bool = False,
365380
interpolate: bool = True,
366381
encoding: Optional[str] = "utf-8",
382+
raise_on_error: bool = False,
367383
) -> Dict[str, Optional[str]]:
368384
"""
369385
Parse a .env file and return its content as a dict.
@@ -391,4 +407,5 @@ def dotenv_values(
391407
interpolate=interpolate,
392408
override=True,
393409
encoding=encoding,
410+
raise_on_error=raise_on_error,
394411
).dict()

tests/test_main.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,26 @@ def test_dotenv_values_file(dotenv_path):
342342
assert result == {"a": "b"}
343343

344344

345+
def test_dotenv_parse_error_causes_warning(dotenv_path):
346+
logger = logging.getLogger("dotenv.main")
347+
dotenv_path.write_text("a='b\nc=d")
348+
349+
with mock.patch.object(logger, "warning") as mock_warning:
350+
result = dotenv.dotenv_values(dotenv_path)
351+
352+
mock_warning.assert_called_once_with("Python-dotenv could not parse statement starting at line %s", 1)
353+
assert result == {"c": "d"}
354+
355+
356+
def test_dotenv_parse_error_causes_exception(dotenv_path):
357+
dotenv_path.write_text("a='b")
358+
359+
with pytest.raises(dotenv.main.DotEnvParseError) as excinfo:
360+
dotenv.dotenv_values(dotenv_path, raise_on_error=True)
361+
362+
assert str(excinfo.value) == "Python-dotenv could not parse statement starting at line 1"
363+
364+
345365
@pytest.mark.parametrize(
346366
"env,string,interpolate,expected",
347367
[

0 commit comments

Comments
 (0)