Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from ._version import __version__, __version_tuple__ # noqa: F401
from .configuration import Configuration
from .configuration_set import ConfigurationSet
from .helpers import InterpolateEnumType, InterpolateType
from .helpers import InterpolateEnumType, InterpolateType, parse_env_line


def config(
Expand Down Expand Up @@ -586,9 +586,7 @@ def _reload(
data = data.read()
data = cast(str, data)
result: Dict[str, Any] = dict(
(y.strip() for y in x.split("=", 1)) # type: ignore
for x in data.splitlines()
if x
parse_env_line(x) for x in data.splitlines() if x and not x.startswith("#")
)

result = {
Expand All @@ -613,6 +611,8 @@ def config_from_dotenv(
) -> Configuration:
"""Create a [Configuration][config.configuration.Configuration] instance from a .env type file.

Lines starting with a # are ignored and treated as comments.

Params:
data: path to a .env type file or contents.
read_from_file: whether to read from a file path or to interpret.
Expand Down
9 changes: 9 additions & 0 deletions src/config/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,12 @@ def interpolate_object(
return [interpolate_object(attr, x, d, method) for x in obj]
else:
return obj


def parse_env_line(line: str) -> Tuple[str, str]:
"""Split an env line into variable and value."""
try:
key, value = tuple(y.strip() for y in line.split("=", 1))
except ValueError:
raise ValueError("Invalid line %s" % line) from None
return key.strip(), value.strip()
27 changes: 27 additions & 0 deletions tests/test_dotenv.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import pytest
from config import config_from_dotenv, config_from_dict
import tempfile

Expand All @@ -17,6 +18,14 @@
PREFIX__KEY4__C = 3
"""

DOTENV_WITH_COMMENTS = """
# key 1
KEY1 = abc
# key 2
KEY2 = def
# key 3
KEY3 = 1.1
"""

DICT = {
"key1": "abc",
Expand Down Expand Up @@ -83,3 +92,21 @@ def test_load_dotenv(): # type: ignore
cfg = config_from_dotenv(DOTENV_WITH_PREFIXES, lowercase_keys=True, prefix="PREFIX")
print(cfg.as_dict())
assert cfg == config_from_dict(DICT_WITH_PREFIXES)


def test_load_dotenv_comments(): # type: ignore
cfg = config_from_dotenv(DOTENV_WITH_COMMENTS, lowercase_keys=True)
assert cfg == config_from_dict(dict((k, str(v)) for k, v in DICT.items()))


def test_load_dotenv_comments_invalid(): # type: ignore
invalid = """
# key 1
VALID=1
## key2
INVALID
"""
with pytest.raises(ValueError) as err:
config_from_dotenv(invalid, lowercase_keys=True)
assert 'Invalid line INVALID' in str(err)

10 changes: 10 additions & 0 deletions tests/test_issues.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import pytest
from config import (
Configuration,
ConfigurationSet,
EnvConfiguration,
config,
config_from_dict,
config_from_dotenv,
)


Expand Down Expand Up @@ -78,3 +80,11 @@ def test_issue_79(): # type: ignore
conf.update(data)

assert conf["abc.def"] == "ghi"


def test_issue_100(): # type: ignore
invalid = """# key 1\nVALID=1\n## key2\nINVALID\n"""
with pytest.raises(ValueError) as err:
config_from_dotenv(invalid, lowercase_keys=True)
assert 'Invalid line INVALID' in str(err)