chimpler / pyhocon

HOCON parser for Python
Apache License 2.0
493 stars 117 forks source link

BUG/DEPS: tests fail for pyparsing>3 #305

Open fangchenli opened 1 year ago

fangchenli commented 1 year ago

ERROR tests/test_tool.py - pyparsing.exceptions.ParseException: Expected end of text, found '=' (at char 79), (line:5, col:15)

(pyhocon-dev) fangchenli@Fangchens-MacBook-Pro-2 pyhocon % pytest tests/test_config_parser.py
================================================== test session starts ===================================================
platform darwin -- Python 3.9.16, pytest-7.2.2, pluggy-1.0.0
rootdir: /Users/fangchenli/Workspace/pyhocon
collected 195 items                                                                                                      

tests/test_config_parser.py .............................................................F...F.................... [ 44%]
............................................F.x..............................................................      [100%]

======================================================== FAILURES ========================================================
____________________________________________ TestConfigParser.test_dict_merge ____________________________________________

self = <test_config_parser.TestConfigParser object at 0x106132a90>

    def test_dict_merge(self):
>       config = ConfigFactory.parse_string(
            """
            a {
                    d {
                            g.h.j.u: 5
                            g {
                                    h.d: 4
                            }
                            g.h.k: f d
                    }

                    h.i.m = 7
                    h.i {
                            d: 5
                    }

                    h.i {
                            e:65
                    }
            }
            """
        )

tests/test_config_parser.py:223: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
pyhocon/config_parser.py:221: in parse_string
    return ConfigParser().parse(content, basedir, resolve, unresolved_value)
pyhocon/config_parser.py:628: in parse
    config = config_expr.parseString(content, parseAll=True)[0]
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:1131: in parse_string
    loc, tokens = self._parse(instring, 0)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:3886: in parseImpl
    loc, exprtokens = e._parse(instring, loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4114: in parseImpl
    return e._parse(
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4375: in parseImpl
    return self.expr._parse(instring, loc, doActions, callPreParse=False)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4891: in parseImpl
    return super().parseImpl(instring, loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4790: in parseImpl
    loc, tokens = self_expr_parse(instring, loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4114: in parseImpl
    return e._parse(
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:5226: in parseImpl
    return super().parseImpl(instring, loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4375: in parseImpl
    return self.expr._parse(instring, loc, doActions, callPreParse=False)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4375: in parseImpl
    return self.expr._parse(instring, loc, doActions, callPreParse=False)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:3875: in parseImpl
    loc, exprtokens = e._parse(instring, loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4114: in parseImpl
    return e._parse(
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:5226: in parseImpl
    return super().parseImpl(instring, loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4375: in parseImpl
    return self.expr._parse(instring, loc, doActions, callPreParse=False)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:3875: in parseImpl
    loc, exprtokens = e._parse(instring, loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4375: in parseImpl
    return self.expr._parse(instring, loc, doActions, callPreParse=False)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4891: in parseImpl
    return super().parseImpl(instring, loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4800: in parseImpl
    loc, tmptokens = self_expr_parse(instring, preloc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4114: in parseImpl
    return e._parse(
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:5226: in parseImpl
    return super().parseImpl(instring, loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4375: in parseImpl
    return self.expr._parse(instring, loc, doActions, callPreParse=False)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4375: in parseImpl
    return self.expr._parse(instring, loc, doActions, callPreParse=False)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:3875: in parseImpl
    loc, exprtokens = e._parse(instring, loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:4114: in parseImpl
    return e._parse(
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:817: in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:3875: in parseImpl
    loc, exprtokens = e._parse(instring, loc, doActions)
/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:823: in _parseNoCache
    tokens = self.postParse(instring, loc, tokens)
pyhocon/config_parser.py:993: in postParse
    return [config_values.transform()]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = [ConfigValues: 7:00:00,.i ,ConfigTree([('d', 5)])]

    def transform(self):
        def determine_type(token):
            return (
                ConfigTree
                if isinstance(token, ConfigTree)
                else ConfigList
                if isinstance(token, list)
                else str
            )

        def format_str(v, last=False):
            if isinstance(v, ConfigQuotedString):
                return v.value + ("" if last else v.ws)
            else:
                return "" if v is None else str(v)

        if self.has_substitution():
            return self

        # remove None tokens
        tokens = [token for token in self.tokens if token is not None]

        if not tokens:
            return None

        # check if all tokens are compatible
        first_tok_type = determine_type(tokens[0])
        for index, token in enumerate(tokens[1:]):
            tok_type = determine_type(token)
            if first_tok_type is not tok_type:
>               raise ConfigWrongTypeException(
                    "Token '{token}' of type {tok_type} (index {index}) must be of type {req_tok_type} (line: {line}, col: {col})".format(
                        token=token,
                        index=index + 1,
                        tok_type=tok_type.__name__,
                        req_tok_type=first_tok_type.__name__,
                        line=lineno(self._loc, self._instring),
                        col=col(self._loc, self._instring),
                    )
                )
E               pyhocon.exceptions.ConfigWrongTypeException: Token 'ConfigTree([('d', 5)])' of type ConfigTree (index 2) must be of type str (line: 14, col: 22)

pyhocon/config_tree.py:592: ConfigWrongTypeException
__________________________________________ TestConfigParser.test_parse_override __________________________________________
pyparsing.exceptions.ParseException: Expected '}', found '='  (at char 201), (line:10, col:23)

During handling of the above exception, another exception occurred:

self = <test_config_parser.TestConfigParser object at 0x106132f10>

    def test_parse_override(self):
>       config = ConfigFactory.parse_string(
            """
            {
                a: {
                    b: {
                        c = 5
                    }
                }
                a.b {
                    c = 7
                    d = 8
                }
            }
            """
        )

tests/test_config_parser.py:303: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
pyhocon/config_parser.py:221: in parse_string
    return ConfigParser().parse(content, basedir, resolve, unresolved_value)
pyhocon/config_parser.py:628: in parse
    config = config_expr.parseString(content, parseAll=True)[0]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = {[{Suppress:({[Suppress:(W:(
,))] {'#' | '//'} - SkipTo:({Suppress:(W:(
)) | StringEnd})}) | Suppress:(W:(
))}]... ... [{Suppress:({[Suppress:(W:(
,))] {'#' | '//'} - SkipTo:({Suppress:(W:(
)) | StringEnd})}) | Suppress:(W:(
,))}]...}
instring = '\n            {\n                a: {\n                    b: {\n                        c = 5\n                    }...           a.b {\n                    c = 7\n                    d = 8\n                }\n            }\n            '
parse_all = False

    def parse_string(
        self, instring: str, parse_all: bool = False, *, parseAll: bool = False
    ) -> ParseResults:
        """
        Parse a string with respect to the parser definition. This function is intended as the primary interface to the
        client code.

        :param instring: The input string to be parsed.
        :param parse_all: If set, the entire input string must match the grammar.
        :param parseAll: retained for pre-PEP8 compatibility, will be removed in a future release.
        :raises ParseException: Raised if ``parse_all`` is set and the input string does not match the whole grammar.
        :returns: the parsed data as a :class:`ParseResults` object, which may be accessed as a `list`, a `dict`, or
          an object with attributes if the given parser includes results names.

        If the input string is required to match the entire grammar, ``parse_all`` flag must be set to ``True``. This
        is also equivalent to ending the grammar with :class:`StringEnd`().

        To report proper column numbers, ``parse_string`` operates on a copy of the input string where all tabs are
        converted to spaces (8 spaces per tab, as per the default in ``string.expandtabs``). If the input string
        contains tabs and the grammar uses parse actions that use the ``loc`` argument to index into the string
        being parsed, one can ensure a consistent view of the input string by doing one of the following:

        - calling ``parse_with_tabs`` on your grammar before calling ``parse_string`` (see :class:`parse_with_tabs`),
        - define your parse action using the full ``(s,loc,toks)`` signature, and reference the input string using the
          parse action's ``s`` argument, or
        - explicitly expand the tabs in your input string before calling ``parse_string``.

        Examples:

        By default, partial matches are OK.

        >>> res = Word('a').parse_string('aaaaabaaa')
        >>> print(res)
        ['aaaaa']

        The parsing behavior varies by the inheriting class of this abstract class. Please refer to the children
        directly to see more examples.

        It raises an exception if parse_all flag is set and instring does not match the whole grammar.

        >>> res = Word('a').parse_string('aaaaabaaa', parse_all=True)
        Traceback (most recent call last):
        ...
        pyparsing.ParseException: Expected end of text, found 'b'  (at char 5), (line:1, col:6)
        """
        parseAll = parse_all or parseAll

        ParserElement.reset_cache()
        if not self.streamlined:
            self.streamline()
        for e in self.ignoreExprs:
            e.streamline()
        if not self.keepTabs:
            instring = instring.expandtabs()
        try:
            loc, tokens = self._parse(instring, 0)
            if parseAll:
                loc = self.preParse(instring, loc)
                se = Empty() + StringEnd()
                se._parse(instring, loc)
        except ParseBaseException as exc:
            if ParserElement.verbose_stacktrace:
                raise
            else:
                # catch and re-raise exception from here, clearing out pyparsing internal stack trace
>               raise exc.with_traceback(None)
E               pyparsing.exceptions.ParseSyntaxException: Expected '}', found '='  (at char 201), (line:10, col:23)

/opt/homebrew/Caskroom/miniforge/base/envs/pyhocon-dev/lib/python3.9/site-packages/pyparsing/core.py:1141: ParseSyntaxException
___________________________________________ TestConfigParser.test_include_dict ___________________________________________

self = <test_config_parser.TestConfigParser object at 0x1061624f0>

    @pytest.mark.skipif(is_windows, reason="fails on windows")
    def test_include_dict(self):
        expected_res = {"a": 1, "b": 2, "c": 3, "d": 4}
        with tempfile.NamedTemporaryFile("w") as fdin:
            fdin.write("{a: 1, b: 2}")
            fdin.flush()

            config1 = ConfigFactory.parse_string(
                """
                a: {{
                    include "{tmp_file}"
                    c: 3
                    d: 4
                }}
                """.format(
                    tmp_file=fdin.name
                )
            )
>           assert config1["a"] == expected_res
E           AssertionError: assert ConfigTree([(...0:00:00: 4')]) == {'a': 1, 'b':...c': 3, 'd': 4}
E             Omitting 2 identical items, use -vv to show
E             Differing items:
E             {'c': '3 days, 0:00:00: 4'} != {'c': 3}
E             Right contains 1 more item:
E             {'d': 4}
E             Use -v to get more diff

tests/test_config_parser.py:1314: AssertionError
================================================ short test summary info =================================================
FAILED tests/test_config_parser.py::TestConfigParser::test_dict_merge - pyhocon.exceptions.ConfigWrongTypeException: Token 'ConfigTree([('d', 5)])' of type ConfigTree (index 2) must be of t...
FAILED tests/test_config_parser.py::TestConfigParser::test_parse_override - pyparsing.exceptions.ParseSyntaxException: Expected '}', found '='  (at char 201), (line:10, col:23)
FAILED tests/test_config_parser.py::TestConfigParser::test_include_dict - AssertionError: assert ConfigTree([(...0:00:00: 4')]) == {'a': 1, 'b':...c': 3, 'd': 4}
======================================= 3 failed, 191 passed, 1 xfailed in 12.03s ========================================