Imported Upstream version 2.4.3 upstream/2.4.3
authorDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 18 Jul 2022 05:42:32 +0000 (14:42 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 18 Jul 2022 05:42:32 +0000 (14:42 +0900)
15 files changed:
CHANGES
PKG-INFO
docs/HowToUsePyparsing.rst
pyparsing.egg-info/PKG-INFO
pyparsing.egg-info/SOURCES.txt
pyparsing.py
setup.cfg
setup.py
test/__init__.pyc
test/__pycache__/__init__.cpython-35.pyc
test/__pycache__/__init__.cpython-38.pyc [new file with mode: 0644]
test/__pycache__/jsonParserTests.cpython-35.pyc
test/__pycache__/jsonParserTests.cpython-38.pyc [new file with mode: 0644]
test/jsonParserTests.pyc
unitTests.py

diff --git a/CHANGES b/CHANGES
index e1a94625785ce510a5fee63c80695ac7d2904698..fc9ff71c067e55fd71cd6b25e0d8e362ea600cb4 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,22 @@
 Change Log
 ==========
 
+Version 2.4.3 - November, 2019
+------------------------------
+- Fixed a bug in ParserElement.__eq__ that would for some parsers
+  create a recursion error at parser definition time. Thanks to
+  Michael Clerx for the assist. (Addresses issue #123)
+
+- Fixed bug in indentedBlock where a block that ended at the end
+  of the input string could cause pyaprsing to loop forever. Raised
+  as part of discussion on StackOverflow with geckos.
+
+- Backports from pyparsing 3.0.0:
+  . __diag__.enable_all_warnings()
+  . Fixed bug in PrecededBy which caused infinite recursion, issue #127
+  . support for using regex-compiled RE to construct Regex expressions
+
+
 Version 2.4.2 - July, 2019
 --------------------------
 - Updated the shorthand notation that has been added for repetition
index 8bfd5eb718cb64e3e2f40eac5d8e6bf12c8d3bda..4816c5e7588bb6c2fa343754df2fb526ef7a06bc 100644 (file)
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,13 +1,87 @@
 Metadata-Version: 1.2
 Name: pyparsing
-Version: 2.4.2
+Version: 2.4.3
 Summary: Python parsing module
 Home-page: https://github.com/pyparsing/pyparsing/
 Author: Paul McGuire
 Author-email: ptmcg@users.sourceforge.net
 License: MIT License
 Download-URL: https://pypi.org/project/pyparsing/
-Description: UNKNOWN
+Description: PyParsing -- A Python Parsing Module
+        ====================================
+        
+        |Build Status|
+        
+        Introduction
+        ============
+        
+        The pyparsing module is an alternative approach to creating and
+        executing simple grammars, vs. the traditional lex/yacc approach, or the
+        use of regular expressions. The pyparsing module provides a library of
+        classes that client code uses to construct the grammar directly in
+        Python code.
+        
+        *[Since first writing this description of pyparsing in late 2003, this
+        technique for developing parsers has become more widespread, under the
+        name Parsing Expression Grammars - PEGs. See more information on PEGs at*
+        https://en.wikipedia.org/wiki/Parsing_expression_grammar *.]*
+        
+        Here is a program to parse ``"Hello, World!"`` (or any greeting of the form
+        ``"salutation, addressee!"``):
+        
+        .. code:: python
+        
+            from pyparsing import Word, alphas
+            greet = Word(alphas) + "," + Word(alphas) + "!"
+            hello = "Hello, World!"
+            print(hello, "->", greet.parseString(hello))
+        
+        The program outputs the following::
+        
+            Hello, World! -> ['Hello', ',', 'World', '!']
+        
+        The Python representation of the grammar is quite readable, owing to the
+        self-explanatory class names, and the use of '+', '|' and '^' operator
+        definitions.
+        
+        The parsed results returned from ``parseString()`` can be accessed as a
+        nested list, a dictionary, or an object with named attributes.
+        
+        The pyparsing module handles some of the problems that are typically
+        vexing when writing text parsers:
+        
+        - extra or missing whitespace (the above program will also handle ``"Hello,World!"``, ``"Hello , World !"``, etc.)
+        - quoted strings
+        - embedded comments
+        
+        The examples directory includes a simple SQL parser, simple CORBA IDL
+        parser, a config file parser, a chemical formula parser, and a four-
+        function algebraic notation parser, among many others.
+        
+        Documentation
+        =============
+        
+        There are many examples in the online docstrings of the classes
+        and methods in pyparsing. You can find them compiled into online docs
+        at https://pyparsing-docs.readthedocs.io/en/latest/. Additional
+        documentation resources and project info are listed in the online
+        GitHub wiki, at https://github.com/pyparsing/pyparsing/wiki. An
+        entire directory of examples is at
+        https://github.com/pyparsing/pyparsing/tree/master/examples.
+        
+        License
+        =======
+        
+        MIT License. See header of pyparsing.py
+        
+        History
+        =======
+        
+        See CHANGES file.
+        
+        .. |Build Status| image:: https://travis-ci.org/pyparsing/pyparsing.svg?branch=master
+           :target: https://travis-ci.org/pyparsing/pyparsing
+        
 Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Intended Audience :: Developers
@@ -24,4 +98,5 @@ Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
 Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*
index dd75443b5b1e02aa229b2da1af619abbde75eb88..4a7cfb82cfed7cbd4c2b058784360e96987fbbcd 100644 (file)
@@ -821,7 +821,7 @@ Helper methods
 
   If an expression is not provided for the content argument, the nested
   expression will capture all whitespace-delimited content between delimiters
-vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv  as a list of separate values.
+  as a list of separate values.
 
   Use the ignoreExpr argument to define expressions that may contain
   opening or closing characters that should not be treated as opening
@@ -900,14 +900,14 @@ Helper parse actions
 - ``replaceWith(replString)`` - returns a parse action that simply returns the
   replString; useful when using transformString, or converting HTML entities, as in::
 
-      nbsp = Literal("&nbsp;").setParseAction(replaceWith("<BLANK>"))
+      nbsp = Literal("&nbsp;").setParseAction( replaceWith("<BLANK>") )
 
 - ``keepOriginalText``- (deprecated, use originalTextFor_ instead) restores any internal whitespace or suppressed
   text within the tokens for a matched parse
   expression.  This is especially useful when defining expressions
   for scanString or transformString applications.
 
-- ``withAttribute(*args, **kwargs)`` - helper to create a validating parse action to be used with start tags created
+- ``withAttribute( *args, **kwargs )`` - helper to create a validating parse action to be used with start tags created
   with ``makeXMLTags`` or ``makeHTMLTags``. Use ``withAttribute`` to qualify a starting tag
   with a required attribute value, to avoid false matches on common tags such as
   ``<TD>`` or ``<DIV>``.
index 8bfd5eb718cb64e3e2f40eac5d8e6bf12c8d3bda..4816c5e7588bb6c2fa343754df2fb526ef7a06bc 100644 (file)
@@ -1,13 +1,87 @@
 Metadata-Version: 1.2
 Name: pyparsing
-Version: 2.4.2
+Version: 2.4.3
 Summary: Python parsing module
 Home-page: https://github.com/pyparsing/pyparsing/
 Author: Paul McGuire
 Author-email: ptmcg@users.sourceforge.net
 License: MIT License
 Download-URL: https://pypi.org/project/pyparsing/
-Description: UNKNOWN
+Description: PyParsing -- A Python Parsing Module
+        ====================================
+        
+        |Build Status|
+        
+        Introduction
+        ============
+        
+        The pyparsing module is an alternative approach to creating and
+        executing simple grammars, vs. the traditional lex/yacc approach, or the
+        use of regular expressions. The pyparsing module provides a library of
+        classes that client code uses to construct the grammar directly in
+        Python code.
+        
+        *[Since first writing this description of pyparsing in late 2003, this
+        technique for developing parsers has become more widespread, under the
+        name Parsing Expression Grammars - PEGs. See more information on PEGs at*
+        https://en.wikipedia.org/wiki/Parsing_expression_grammar *.]*
+        
+        Here is a program to parse ``"Hello, World!"`` (or any greeting of the form
+        ``"salutation, addressee!"``):
+        
+        .. code:: python
+        
+            from pyparsing import Word, alphas
+            greet = Word(alphas) + "," + Word(alphas) + "!"
+            hello = "Hello, World!"
+            print(hello, "->", greet.parseString(hello))
+        
+        The program outputs the following::
+        
+            Hello, World! -> ['Hello', ',', 'World', '!']
+        
+        The Python representation of the grammar is quite readable, owing to the
+        self-explanatory class names, and the use of '+', '|' and '^' operator
+        definitions.
+        
+        The parsed results returned from ``parseString()`` can be accessed as a
+        nested list, a dictionary, or an object with named attributes.
+        
+        The pyparsing module handles some of the problems that are typically
+        vexing when writing text parsers:
+        
+        - extra or missing whitespace (the above program will also handle ``"Hello,World!"``, ``"Hello , World !"``, etc.)
+        - quoted strings
+        - embedded comments
+        
+        The examples directory includes a simple SQL parser, simple CORBA IDL
+        parser, a config file parser, a chemical formula parser, and a four-
+        function algebraic notation parser, among many others.
+        
+        Documentation
+        =============
+        
+        There are many examples in the online docstrings of the classes
+        and methods in pyparsing. You can find them compiled into online docs
+        at https://pyparsing-docs.readthedocs.io/en/latest/. Additional
+        documentation resources and project info are listed in the online
+        GitHub wiki, at https://github.com/pyparsing/pyparsing/wiki. An
+        entire directory of examples is at
+        https://github.com/pyparsing/pyparsing/tree/master/examples.
+        
+        License
+        =======
+        
+        MIT License. See header of pyparsing.py
+        
+        History
+        =======
+        
+        See CHANGES file.
+        
+        .. |Build Status| image:: https://travis-ci.org/pyparsing/pyparsing.svg?branch=master
+           :target: https://travis-ci.org/pyparsing/pyparsing
+        
 Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Intended Audience :: Developers
@@ -24,4 +98,5 @@ Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
 Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*
index 44e029d6722be1bc2add2ed0e473daed20f3c74f..34b85659dcfe2d96323ec78028e4aedc229c0eb4 100644 (file)
@@ -133,4 +133,6 @@ test/jsonParserTests.pyc
 test/karthik.ini
 test/parsefiletest_input_file.txt
 test/__pycache__/__init__.cpython-35.pyc
-test/__pycache__/jsonParserTests.cpython-35.pyc
\ No newline at end of file
+test/__pycache__/__init__.cpython-38.pyc
+test/__pycache__/jsonParserTests.cpython-35.pyc
+test/__pycache__/jsonParserTests.cpython-38.pyc
\ No newline at end of file
index 3854210da73eb2da03a3e0b0036dfde0ef766c08..7e35ed2f9b9f169c9ce7317ea162a790d8e1776f 100644 (file)
@@ -95,8 +95,8 @@ classes inherit from. Use the docstrings for examples of how to:
    namespace class
 """
 
-__version__ = "2.4.2"
-__versionTime__ = "29 Jul 2019 02:58 UTC"
+__version__ = "2.4.3"
+__versionTime__ = "21 Oct 2019 23:43 UTC"
 __author__ = "Paul McGuire <ptmcg@users.sourceforge.net>"
 
 import string
@@ -185,7 +185,13 @@ __diag__.warn_name_set_on_empty_Forward = False
 __diag__.warn_on_multiple_string_args_to_oneof = False
 __diag__.enable_debug_on_named_expressions = False
 
-# ~ sys.stderr.write("testing pyparsing module, version %s, %s\n" % (__version__, __versionTime__))
+def _enable_all_warnings():
+    __diag__.warn_multiple_tokens_in_named_alternation = True
+    __diag__.warn_ungrouped_named_tokens_in_collection = True
+    __diag__.warn_name_set_on_empty_Forward = True
+    __diag__.warn_on_multiple_string_args_to_oneof = True
+__diag__.enable_all_warnings = _enable_all_warnings
+
 
 __all__ = ['__version__', '__versionTime__', '__author__', '__compat__', '__diag__',
            'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty',
@@ -206,7 +212,7 @@ __all__ = ['__version__', '__versionTime__', '__author__', '__compat__', '__diag
            'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute',
            'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation', 'locatedExpr', 'withClass',
            'CloseMatch', 'tokenMap', 'pyparsing_common', 'pyparsing_unicode', 'unicode_set',
-           'conditionAsParseAction',
+           'conditionAsParseAction', 're',
            ]
 
 system_version = tuple(sys.version_info)[:3]
@@ -2561,15 +2567,13 @@ class ParserElement(object):
                 raise exc
 
     def __eq__(self, other):
-        if isinstance(other, ParserElement):
-            if PY_3:
-                self is other or super(ParserElement, self).__eq__(other)
-            else:
-                return self is other or vars(self) == vars(other)
+        if self is other:
+            return True
         elif isinstance(other, basestring):
             return self.matches(other)
-        else:
-            return super(ParserElement, self) == other
+        elif isinstance(other, ParserElement):
+            return vars(self) == vars(other)
+        return False
 
     def __ne__(self, other):
         return not (self == other)
@@ -3252,14 +3256,23 @@ class Regex(Token):
     If the given regex contains named groups (defined using ``(?P<name>...)``),
     these will be preserved as named parse results.
 
+    If instead of the Python stdlib re module you wish to use a different RE module
+    (such as the `regex` module), you can replace it by either building your
+    Regex object with a compiled RE that was compiled using regex:
+
     Example::
 
         realnum = Regex(r"[+-]?\d+\.\d*")
         date = Regex(r'(?P<year>\d{4})-(?P<month>\d\d?)-(?P<day>\d\d?)')
         # ref: https://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression
         roman = Regex(r"M{0,4}(CM|CD|D?{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})")
+
+        # use regex module instead of stdlib re module to construct a Regex using
+        # a compiled regular expression
+        import regex
+        parser = pp.Regex(regex.compile(r'[0-9]'))
+
     """
-    compiledREtype = type(re.compile("[A-Z]"))
     def __init__(self, pattern, flags=0, asGroupList=False, asMatch=False):
         """The parameters ``pattern`` and ``flags`` are passed
         to the ``re.compile()`` function as-is. See the Python
@@ -3284,13 +3297,13 @@ class Regex(Token):
                               SyntaxWarning, stacklevel=2)
                 raise
 
-        elif isinstance(pattern, Regex.compiledREtype):
+        elif hasattr(pattern, 'pattern') and hasattr(pattern, 'match'):
             self.re = pattern
-            self.pattern = self.reString = str(pattern)
+            self.pattern = self.reString = pattern.pattern
             self.flags = flags
 
         else:
-            raise ValueError("Regex may only be constructed with a string or a compiled RE object")
+            raise TypeError("Regex may only be constructed with a string or a compiled RE object")
 
         self.re_match = self.re.match
 
@@ -4566,6 +4579,7 @@ class PrecededBy(ParseElementEnhance):
         self.retreat = retreat
         self.errmsg = "not preceded by " + str(expr)
         self.skipWhitespace = False
+        self.parseAction.append(lambda s, l, t: t.__delitem__(slice(None, None)))
 
     def parseImpl(self, instring, loc=0, doActions=True):
         if self.exact:
@@ -4576,19 +4590,18 @@ class PrecededBy(ParseElementEnhance):
         else:
             # retreat specified a maximum lookbehind window, iterate
             test_expr = self.expr + StringEnd()
-            instring_slice = instring[:loc]
+            instring_slice = instring[max(0, loc - self.retreat):loc]
             last_expr = ParseException(instring, loc, self.errmsg)
-            for offset in range(1, min(loc, self.retreat + 1)):
+            for offset in range(1, min(loc, self.retreat + 1)+1):
                 try:
-                    _, ret = test_expr._parse(instring_slice, loc - offset)
+                    # print('trying', offset, instring_slice, repr(instring_slice[loc - offset:]))
+                    _, ret = test_expr._parse(instring_slice, len(instring_slice) - offset)
                 except ParseBaseException as pbe:
                     last_expr = pbe
                 else:
                     break
             else:
                 raise last_expr
-        # return empty list of tokens, but preserve any defined results names
-        del ret[:]
         return loc, ret
 
 
@@ -5504,7 +5517,7 @@ def oneOf(strs, caseless=False, useRegex=True, asKeyword=False):
         # ~ print (strs, "->", "|".join([_escapeRegexChars(sym) for sym in symbols]))
         try:
             if len(symbols) == len("".join(symbols)):
-                return Regex("[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols)).setName(' | '.join(symbols))
+                return Regex("[%s]" % "".join(_collapseAndEscapeRegexRangeChars(sym) for sym in symbols)).setName(' | '.join(symbols))
             else:
                 return Regex("|".join(re.escape(sym) for sym in symbols)).setName(' | '.join(symbols))
         except Exception:
@@ -6305,18 +6318,18 @@ def indentedBlock(blockStatementExpr, indentStack, indent=True):
         if curCol < indentStack[-1]:
             indentStack.pop()
 
-    NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress())
+    NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress(), stopOn=StringEnd())
     INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT')
     PEER   = Empty().setParseAction(checkPeerIndent).setName('')
     UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT')
     if indent:
         smExpr = Group(Optional(NL)
                        + INDENT
-                       + OneOrMore(PEER + Group(blockStatementExpr) + Optional(NL))
+                       + OneOrMore(PEER + Group(blockStatementExpr) + Optional(NL), stopOn=StringEnd())
                        + UNDENT)
     else:
         smExpr = Group(Optional(NL)
-                       + OneOrMore(PEER + Group(blockStatementExpr) + Optional(NL))
+                       + OneOrMore(PEER + Group(blockStatementExpr) + Optional(NL), stopOn=StringEnd())
                        + UNDENT)
     smExpr.setFailAction(lambda a, b, c, d: reset_stack())
     blockStatementExpr.ignore(_bslash + LineEnd())
index 51b5f83b3da1c73c4f95d2f3324918ad9de75958..163eba3165f1afa5161e7c1c1d77d4ad1c23763b 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -7,4 +7,5 @@ license_file = LICENSE
 [egg_info]
 tag_build = 
 tag_date = 0
+tag_svn_revision = 0
 
index 9de1761658390c235722eeec354b3758a13066be..27405215f01fe84566bfb2119fbe19fb478152bd 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -5,12 +5,20 @@
 from setuptools import setup
 from pyparsing import __version__ as pyparsing_version
 
+# The directory containing this file
+README_name = __file__.replace("setup.py", "README.rst")
+
+# The text of the README file
+with open(README_name) as README:
+    pyparsing_main_doc = README.read()
+
 modules = ["pyparsing",]
 
 setup(# Distribution meta-data
     name = "pyparsing",
     version = pyparsing_version,
     description = "Python parsing module",
+    long_description = pyparsing_main_doc,
     author = "Paul McGuire",
     author_email = "ptmcg@users.sourceforge.net",
     url = "https://github.com/pyparsing/pyparsing/",
@@ -35,5 +43,6 @@ setup(# Distribution meta-data
         'Programming Language :: Python :: 3.5',
         'Programming Language :: Python :: 3.6',
         'Programming Language :: Python :: 3.7',
+        'Programming Language :: Python :: 3.8',
         ]
     )
index 2bf2b940c15d3e68762495baeb870011bff3904f..4aac3ba957ab5f9df95f091c5be72c7f2ef4d7b7 100644 (file)
Binary files a/test/__init__.pyc and b/test/__init__.pyc differ
index d00969f1d90059b536cdfa37b617e8ece2bcd73f..1aeeae3a557489ac810a6a7794bd026e334a76aa 100644 (file)
Binary files a/test/__pycache__/__init__.cpython-35.pyc and b/test/__pycache__/__init__.cpython-35.pyc differ
diff --git a/test/__pycache__/__init__.cpython-38.pyc b/test/__pycache__/__init__.cpython-38.pyc
new file mode 100644 (file)
index 0000000..26336ff
Binary files /dev/null and b/test/__pycache__/__init__.cpython-38.pyc differ
index 8ebb2896d747bdf7fc56193b8c0d7f6d220aa16b..6dcd4b6e4b71d90111cea327d23b09512f9e9936 100644 (file)
Binary files a/test/__pycache__/jsonParserTests.cpython-35.pyc and b/test/__pycache__/jsonParserTests.cpython-35.pyc differ
diff --git a/test/__pycache__/jsonParserTests.cpython-38.pyc b/test/__pycache__/jsonParserTests.cpython-38.pyc
new file mode 100644 (file)
index 0000000..9968df6
Binary files /dev/null and b/test/__pycache__/jsonParserTests.cpython-38.pyc differ
index 7bb8c3438eaa9b3d1e7703981730af26422e1ed4..111928812ceaa7f96980e14c4acbd2214075af29 100644 (file)
Binary files a/test/jsonParserTests.pyc and b/test/jsonParserTests.pyc differ
index 90e33443314ba640dba27a24d712cbe705c87aaf..cfc4e90610a8c349a8b4307a1100f08f43a63630 100644 (file)
@@ -2046,6 +2046,21 @@ class PrecededByTest(ParseTestCase):
                              "Erroneous named results for {0}: expected {1}, got {2}".format(expr,
                                                                                           expected_dict,
                                                                                           result.asDict()))
+        # infinite loop test - from Issue #127
+        string_test = 'notworking'
+        # negs = pp.Or(['not', 'un'])('negs')
+        negs_pb = pp.PrecededBy('not', retreat=100)('negs_lb')
+        # negs_pb = pp.PrecededBy(negs, retreat=100)('negs_lb')
+        pattern = pp.Group(negs_pb + pp.Literal('working'))('main')
+
+        results = pattern.searchString(string_test)
+        try:
+            print_(results.dump())
+        except RecursionError:
+            self.assertTrue(False, "got maximum excursion limit exception")
+        else:
+            self.assertTrue(True, "got maximum excursion limit exception")
+
 
 class CountedArrayTest(ParseTestCase):
     def runTest(self):
@@ -4958,4 +4973,5 @@ if __name__ == '__main__':
         BUFFER_OUTPUT = False
         result = testRunner.run(makeTestSuiteTemp(testclasses))
 
+    sys.stdout.flush()
     exit(0 if result.wasSuccessful() else 1)