Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle inline comments, and ignore spaces outside quotes #475

Merged
merged 7 commits into from Jul 6, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Expand Up @@ -15,11 +15,15 @@ Added
`#463 <https://github.com/joke2k/django-environ/pull/463>`_.
- Added variable expansion
`#468 <https://github.com/joke2k/django-environ/pull/468>`_.
- Added capability to handle comments after #, after quoted values, like ``KEY= 'part1 # part2' # comment``
`#475 <https://github.com/joke2k/django-environ/pull/475>`_.

Changed
+++++++
- Used ``mssql-django`` as engine for SQL Server
`#446 <https://github.com/joke2k/django-environ/pull/446>`_.
- Changed handling bool values, stripping whitespace around value
`#475 <https://github.com/joke2k/django-environ/pull/475>`_.

Removed
+++++++
Expand Down
12 changes: 10 additions & 2 deletions environ/environ.py
Expand Up @@ -473,7 +473,7 @@ def parse_value(cls, value, cast):
try:
value = int(value) != 0
except ValueError:
value = value.lower() in cls.BOOLEAN_TRUE_STRINGS
value = value.lower().strip() in cls.BOOLEAN_TRUE_STRINGS
elif isinstance(cast, list):
value = list(map(cast[0], [x for x in value.split(',') if x]))
elif isinstance(cast, tuple):
Expand Down Expand Up @@ -970,9 +970,17 @@ def _keep_escaped_format_characters(match):
m1 = re.match(r'\A(?:export )?([A-Za-z_0-9]+)=(.*)\Z', line)
if m1:
key, val = m1.group(1), m1.group(2)
m2 = re.match(r"\A'(.*)'\Z", val)
# Look for value in quotes, ignore post-# comments
# (outside quotes)
m2 = re.match(r"\A\s*'(?<!\\)(.*)'\s*(#.*\s*)?\Z", val)
if m2:
val = m2.group(1)
else:
# For no quotes, find value, ignore comments
# after the first #
m2a = re.match(r"\A(.*?)(#.*\s*)?\Z", val)
if m2a:
val = m2a.group(1)
m3 = re.match(r'\A"(.*)"\Z', val)
if m3:
val = re.sub(r'\\(.)', _keep_escaped_format_characters,
Expand Down
7 changes: 6 additions & 1 deletion tests/fixtures.py
Expand Up @@ -38,6 +38,8 @@ class FakeEnv:
@classmethod
def generate_data(cls):
return dict(STR_VAR='bar',
STR_QUOTED_IGNORE_COMMENT='foo',
STR_QUOTED_INCLUDE_HASH='foo # with hash',
MULTILINE_STR_VAR='foo\\nbar',
MULTILINE_QUOTED_STR_VAR='---BEGIN---\\r\\n---END---',
MULTILINE_ESCAPED_STR_VAR='---BEGIN---\\\\n---END---',
Expand All @@ -50,12 +52,14 @@ def generate_data(cls):
BOOL_TRUE_STRING_LIKE_INT='1',
BOOL_TRUE_INT=1,
BOOL_TRUE_STRING_LIKE_BOOL='True',
BOOL_TRUE_STRING_LIKE_BOOL_WITH_COMMENT='True',
BOOL_TRUE_STRING_1='on',
BOOL_TRUE_STRING_2='ok',
BOOL_TRUE_STRING_3='yes',
BOOL_TRUE_STRING_4='y',
BOOL_TRUE_STRING_5='true',
BOOL_TRUE_BOOL=True,
BOOL_TRUE_BOOL_WITH_COMMENT=True,
BOOL_FALSE_STRING_LIKE_INT='0',
BOOL_FALSE_INT=0,
BOOL_FALSE_STRING_LIKE_BOOL='False',
Expand All @@ -65,7 +69,8 @@ def generate_data(cls):
INT_LIST='42,33',
INT_TUPLE='(42,33)',
MIX_TUPLE='(42,Test)',
STR_LIST_WITH_SPACES=' foo, bar',
STR_LIST_WITH_SPACES=' foo, spaces',
STR_LIST_WITH_SPACES_QUOTED="' foo', ' quoted'",
EMPTY_LIST='',
DICT_VAR='foo=bar,test=on',
DICT_WITH_EQ_VAR='key1=sub_key1=sub_value1,key2=value2',
Expand Down
8 changes: 6 additions & 2 deletions tests/test_env.py
Expand Up @@ -112,8 +112,10 @@ def test_float(self, value, variable):
[
(True, 'BOOL_TRUE_STRING_LIKE_INT'),
(True, 'BOOL_TRUE_STRING_LIKE_BOOL'),
(True, 'BOOL_TRUE_STRING_LIKE_BOOL_WITH_COMMENT'),
(True, 'BOOL_TRUE_INT'),
(True, 'BOOL_TRUE_BOOL'),
(True, 'BOOL_TRUE_BOOL_WITH_COMMENT'),
(True, 'BOOL_TRUE_STRING_1'),
(True, 'BOOL_TRUE_STRING_2'),
(True, 'BOOL_TRUE_STRING_3'),
Expand Down Expand Up @@ -175,9 +177,9 @@ def test_mix_tuple_issue_387(self):
)

def test_str_list_with_spaces(self):
assert_type_and_value(list, [' foo', ' bar'],
assert_type_and_value(list, [' foo', ' spaces'],
self.env('STR_LIST_WITH_SPACES', cast=[str]))
assert_type_and_value(list, [' foo', ' bar'],
assert_type_and_value(list, [' foo', ' spaces'],
self.env.list('STR_LIST_WITH_SPACES'))

def test_empty_list(self):
Expand Down Expand Up @@ -339,6 +341,8 @@ def test_path(self):

def test_smart_cast(self):
assert self.env.get_value('STR_VAR', default='string') == 'bar'
assert self.env.get_value('STR_QUOTED_IGNORE_COMMENT', default='string') == 'foo'
assert self.env.get_value('STR_QUOTED_INCLUDE_HASH', default='string') == 'foo # with hash'
assert self.env.get_value('BOOL_TRUE_STRING_LIKE_INT', default=True)
assert not self.env.get_value(
'BOOL_FALSE_STRING_LIKE_INT',
Expand Down
7 changes: 6 additions & 1 deletion tests/test_env.txt
Expand Up @@ -25,6 +25,8 @@ BOOL_TRUE_STRING_3='yes'
BOOL_TRUE_STRING_4='y'
BOOL_TRUE_STRING_5='true'
BOOL_TRUE_BOOL=True
BOOL_TRUE_STRING_LIKE_BOOL_WITH_COMMENT='True' # comment
BOOL_TRUE_BOOL_WITH_COMMENT=True # comment
BOOL_FALSE_STRING_LIKE_INT='0'
BOOL_FALSE_INT=0
BOOL_FALSE_STRING_LIKE_BOOL='False'
Expand All @@ -42,8 +44,11 @@ ESCAPED_VAR=\$baz
EMPTY_LIST=
EMPTY_INT_VAR=
INT_VAR=42
STR_LIST_WITH_SPACES= foo, bar
STR_LIST_WITH_SPACES= foo, spaces
STR_LIST_WITH_SPACES_QUOTED=' foo',' quoted'
STR_VAR=bar
STR_QUOTED_IGNORE_COMMENT= 'foo' # comment
STR_QUOTED_INCLUDE_HASH='foo # with hash' # not comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String "ab#cd" does not work(

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #500

MULTILINE_STR_VAR=foo\nbar
MULTILINE_QUOTED_STR_VAR="---BEGIN---\r\n---END---"
MULTILINE_ESCAPED_STR_VAR=---BEGIN---\\n---END---
Expand Down