From 447bb4abbc03a721284e42770ef23bddd72fc254 Mon Sep 17 00:00:00 2001 From: Peter Zaitcev Date: Mon, 26 Sep 2022 02:14:14 +0300 Subject: [PATCH 1/3] #281: Added tests covering broken `+=` operator behaviour --- tests/test_config_parser.py | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/test_config_parser.py b/tests/test_config_parser.py index 13a130fc..3426d007 100644 --- a/tests/test_config_parser.py +++ b/tests/test_config_parser.py @@ -816,6 +816,17 @@ def test_self_append_array(self): ) assert config.get("x") == [1, 2, 3, 4] + def test_self_append_array_inside_dict(self): + config = ConfigFactory.parse_string( + """ + d { + x = [1,2] + x += [3,4] + } + """ + ) + assert config.get("d.x") == [1, 2, 3, 4] + def test_self_append_string(self): ''' Should be equivalent to @@ -830,6 +841,22 @@ def test_self_append_string(self): ) assert config.get("x") == "abc def" + def test_self_append_string_inside_dict(self): + ''' + Should be equivalent to + x = abc + x = ${?x} def + ''' + config = ConfigFactory.parse_string( + """ + d { + x = abc + x += def + } + """ + ) + assert config.get("d.x") == "abc def" + def test_self_append_non_existent_string(self): ''' Should be equivalent to x = ${?x} def @@ -858,6 +885,17 @@ def test_self_append_object(self): ) assert config.get("x") == {'a': 1, 'b': 2} + def test_self_append_object_inside_dict(self): + config = ConfigFactory.parse_string( + """ + d { + x = {a: 1} + x += {b: 2} + } + """ + ) + assert config.get("d.x") == {'a': 1, 'b': 2} + def test_self_append_nonexistent_object(self): config = ConfigFactory.parse_string( """ From aa133cf9ca212dcea3f582f85f817448e692a70b Mon Sep 17 00:00:00 2001 From: Peter Zaitcev Date: Mon, 26 Sep 2022 02:17:43 +0300 Subject: [PATCH 2/3] #281: Fix broken `+=` operator behaviour --- pyhocon/config_parser.py | 9 ++++++--- pyhocon/config_tree.py | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pyhocon/config_parser.py b/pyhocon/config_parser.py index 6846589d..2ac789c6 100644 --- a/pyhocon/config_parser.py +++ b/pyhocon/config_parser.py @@ -535,7 +535,10 @@ def _resolve_variable(cls, config, substitution): """ variable = substitution.variable try: - return True, config.get(variable) + if substitution.self_ref: + return True, substitution.parent.overriden_value + else: + return True, config.get(variable) except ConfigMissingException: # default to environment variable value = os.environ.get(variable) @@ -859,10 +862,10 @@ def postParse(self, instring, loc, token_list): else: value = values[0] if isinstance(value, list) and operator == "+=": - value = ConfigValues([ConfigSubstitution(key, True, '', False, loc), value], False, loc) + value = ConfigValues([ConfigSubstitution(key, True, '', False, loc, self_ref=True), value], False, loc) config_tree.put(key, value, False) elif isinstance(value, unicode) and operator == "+=": - value = ConfigValues([ConfigSubstitution(key, True, '', True, loc), ' ' + value], True, loc) + value = ConfigValues([ConfigSubstitution(key, True, '', True, loc, self_ref=True), ' ' + value], True, loc) config_tree.put(key, value, False) elif isinstance(value, list): config_tree.put(key, value, False) diff --git a/pyhocon/config_tree.py b/pyhocon/config_tree.py index 9996df53..dab47968 100644 --- a/pyhocon/config_tree.py +++ b/pyhocon/config_tree.py @@ -602,7 +602,7 @@ def __repr__(self): # pragma: no cover class ConfigSubstitution(object): - def __init__(self, variable, optional, ws, instring, loc): + def __init__(self, variable, optional, ws, instring, loc, self_ref=False): self.variable = variable self.optional = optional self.ws = ws @@ -610,6 +610,7 @@ def __init__(self, variable, optional, ws, instring, loc): self.parent = None self.instring = instring self.loc = loc + self.self_ref = self_ref def raw_str(self): return self.variable From e213962f2e24c74a9daee8b8b6ba39ddb4e71956 Mon Sep 17 00:00:00 2001 From: Peter Zaitcev Date: Mon, 26 Sep 2022 02:42:14 +0300 Subject: [PATCH 3/3] #281: Add tests for *appending* elements to array rather than extending it --- tests/test_config_parser.py | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/tests/test_config_parser.py b/tests/test_config_parser.py index 3426d007..1c0942a8 100644 --- a/tests/test_config_parser.py +++ b/tests/test_config_parser.py @@ -807,7 +807,7 @@ def test_self_ref_substitution_array(self): ) assert config.get("x") == [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6] - def test_self_append_array(self): + def test_self_extend_array(self): config = ConfigFactory.parse_string( """ x = [1,2] @@ -816,7 +816,16 @@ def test_self_append_array(self): ) assert config.get("x") == [1, 2, 3, 4] - def test_self_append_array_inside_dict(self): + def test_self_append_array(self): + config = ConfigFactory.parse_string( + """ + x = [1,2] + x += 3 + """ + ) + assert config.get("x") == [1, 2, 3] + + def test_self_extend_array_inside_dict(self): config = ConfigFactory.parse_string( """ d { @@ -827,6 +836,17 @@ def test_self_append_array_inside_dict(self): ) assert config.get("d.x") == [1, 2, 3, 4] + def test_self_append_array_inside_dict(self): + config = ConfigFactory.parse_string( + """ + d { + x = [1,2] + x += 3 + } + """ + ) + assert config.get("d.x") == [1, 2, 3] + def test_self_append_string(self): ''' Should be equivalent to @@ -868,7 +888,7 @@ def test_self_append_non_existent_string(self): ) assert config.get("x") == " def" - def test_self_append_nonexistent_array(self): + def test_self_extend_nonexistent_array(self): config = ConfigFactory.parse_string( """ x += [1,2] @@ -876,6 +896,14 @@ def test_self_append_nonexistent_array(self): ) assert config.get("x") == [1, 2] + def test_self_append_nonexistent_array(self): + config = ConfigFactory.parse_string( + """ + x += 1 + """ + ) + assert config.get("x") == [1] + def test_self_append_object(self): config = ConfigFactory.parse_string( """