Skip to content

Commit

Permalink
Fix parsing of lists with relativedelta objects.
Browse files Browse the repository at this point in the history
The relativedelta objects were rejected because we cannot compare them to
strings. Both `==` and `!=` results to `False`.

Instead we have to first test the type and then do the comparison.
  • Loading branch information
olii committed Mar 4, 2021
1 parent f26cc08 commit 84d12b2
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 8 deletions.
35 changes: 27 additions & 8 deletions pyhocon/config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ def glob(pathname, recursive=False):
else:
from glob import glob


try:
from dateutil.relativedelta import relativedelta as period_impl
except Exception:
from datetime import timedelta as period_impl


logger = logging.getLogger(__name__)

#
Expand All @@ -87,11 +94,6 @@ class STR_SUBSTITUTION(object):


def period(period_value, period_unit):
try:
from dateutil.relativedelta import relativedelta as period_impl
except Exception:
from datetime import timedelta as period_impl

if period_unit == 'nanoseconds':
period_unit = 'microseconds'
period_value = int(period_value / 1000)
Expand Down Expand Up @@ -749,9 +751,26 @@ def postParse(self, instring, loc, token_list):
:param token_list:
:return:
"""
cleaned_token_list = [token for tokens in (token.tokens if isinstance(token, ConfigInclude) else [token]
for token in token_list if token != '')
for token in tokens]
cleaned_token_list = []

# Note that:
# relativedelta.__eq__() raises NotImplemented if it is compared with
# a different object type so Python falls back to identity comparison.
# We cannot compare this object to a string.
# >>> relativedelta(hours = 1) == ''
# False
# >>> relativedelta(hours = 1) != ''
# False
for token in token_list:
# This is the case when there was a trailing comma in the list.
# The last token is just an empty string.
if isinstance(token, str) and token == '':
continue
if isinstance(token, ConfigInclude):
cleaned_token_list.extend(token.tokens)
else:
cleaned_token_list.append(token)

config_list = ConfigList(cleaned_token_list)
return [config_list]

Expand Down
10 changes: 10 additions & 0 deletions tests/test_config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,16 @@ def test_parse_string_with_duration_with_long_unit_name(self):
)
assert config['b'] == period(weeks=10)

def test_parse_with_list_mixed_types_with_durations_and_trailing_comma(self):
config = ConfigFactory.parse_string(
"""
a: foo
b: [a, 1, 10 weeks, 5 minutes,]
c: bar
"""
)
assert config['b'] == ['a', 1, period(weeks=10), period(minutes=5)]

def test_parse_with_enclosing_square_bracket(self):
config = ConfigFactory.parse_string("[1, 2, 3]")
assert config == [1, 2, 3]
Expand Down

0 comments on commit 84d12b2

Please sign in to comment.