Imported Upstream version 3.0.5 upstream/3.0.5
authorDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 18 Jul 2022 05:42:37 +0000 (14:42 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 18 Jul 2022 05:42:37 +0000 (14:42 +0900)
CHANGES
PKG-INFO
docs/HowToUsePyparsing.rst
pyparsing.egg-info/PKG-INFO
pyparsing/__init__.py
pyparsing/core.py
pyparsing/exceptions.py
pyparsing/helpers.py
pyparsing/results.py
pyparsing/util.py
tests/test_unit.py

diff --git a/CHANGES b/CHANGES
index 1c1396e85550a2e0c7a83c3ef98e782263b7d486..d1d6726c2add81ff4e0eeafa16d7be0b1460bbac 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,22 @@
 Change Log
 ==========
 
+Version 3.0.5 -
+---------------
+- Added return type annotations for `col`, `line`, and `lineno`.
+
+- Fixed bug when `warn_ungrouped_named_tokens_in_collection` warning was raised
+  when assigning a results name to an `original_text_for` expression.
+  (Issue #110, would raise warning in packaging.)
+
+- Fixed internal bug where ParserElement.streamline() would not return self if
+  already streamlined.
+
+- Changed run_tests() output to default to not showing line and column numbers.
+  If line numbering is desired, call with `with_line_numbers=True`. Also fixed
+  minor bug where separating line was not included after a test failure.
+
+
 Version 3.0.4 -
 ---------------
 - Fixed bug in which `Dict` classes did not correctly return tokens as nested
index 46c89b1f84a71fbf3d397d9fcf510e759720218b..7d121071fc554d0483f5dbd9b14253bc621299bd 100644 (file)
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: pyparsing
-Version: 3.0.4
+Version: 3.0.5
 Summary: Python parsing module
 Home-page: https://github.com/pyparsing/pyparsing/
 Author: Paul McGuire
index 59f994c65273f7dc794e60e36019749c7764a72d..4336e0c14fdc602316bcf4d5ec5f49fa272de852 100644 (file)
@@ -984,9 +984,10 @@ Exception classes and Troubleshooting
     >>> UserWarning: warn_name_set_on_empty_Forward: setting results name 'recursive_expr'
                      on Forward expression that has no contained expression
 
-  Warnings can also be enabled using the Python ``-W`` switch, or setting a non-empty
-  value to the environment variable ``PYPARSINGENABLEALLWARNINGS``. (If using `-Wd` for
-  testing, but wishing to disable pyparsing warnings, add `-Wi:::pyparsing`.)
+  Warnings can also be enabled using the Python ``-W`` switch (using ``-Wd`` or
+  ``-Wd:::pyparsing``) or setting a non-empty value to the environment variable
+  ``PYPARSINGENABLEALLWARNINGS``. (If using ``-Wd`` for testing, but wishing to
+  disable pyparsing warnings, add ``-Wi:::pyparsing``.)
 
 
 Miscellaneous attributes and methods
index 46c89b1f84a71fbf3d397d9fcf510e759720218b..7d121071fc554d0483f5dbd9b14253bc621299bd 100644 (file)
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: pyparsing
-Version: 3.0.4
+Version: 3.0.5
 Summary: Python parsing module
 Home-page: https://github.com/pyparsing/pyparsing/
 Author: Paul McGuire
index c8d40b564ee4dec37565083092aedebd09ddfa2d..a9643b86e84eae595ae25beb2f31286400cd6f27 100644 (file)
@@ -96,7 +96,7 @@ classes inherit from. Use the docstrings for examples of how to:
 from collections import namedtuple
 
 version_info = namedtuple("version_info", "major minor micro release_level serial")
-__version_info__ = version_info(3, 0, 4, "final", 0)
+__version_info__ = version_info(3, 0, 5, "final", 0)
 __version__ = "{}.{}.{}".format(*__version_info__[:3]) + (
     "{}{}{}".format(
         "r" if __version_info__.release_level[0] == "c" else "",
@@ -105,7 +105,7 @@ __version__ = "{}.{}.{}".format(*__version_info__[:3]) + (
     ),
     "",
 )[__version_info__.release_level == "final"]
-__version_time__ = "29 October 2021 05:11 UTC"
+__version_time__ = "5 November 2021 10:05 UTC"
 version_info.__str__ = lambda *args: "pyparsing {} - {}".format(
     __version__, __version_time__
 )
index fe7dbb4a0b178eaa8a413424ecbb565dd152396c..e2fbb6c2af79e668275687ffe3dc954db67dc354 100644 (file)
@@ -13,6 +13,7 @@ from typing import (
     List,
     TextIO,
     Set,
+    Dict as DictType,
 )
 from abc import ABC, abstractmethod
 from enum import Enum
@@ -34,8 +35,8 @@ from .util import (
     _FifoCache,
     _UnboundedCache,
     __config_flags,
-    _collapseStringToRanges,
-    _escapeRegexRangeChars,
+    _collapse_string_to_ranges,
+    _escape_regex_range_chars,
     _bslash,
     _flatten,
     LRUMemo as _LRUMemo,
@@ -47,7 +48,7 @@ from .results import ParseResults, _ParseResultsWithOffset
 from .unicode import pyparsing_unicode
 
 _MAX_INT = sys.maxsize
-str_type = (str, bytes)
+str_type: Tuple[type, ...] = (str, bytes)
 
 #
 # Copyright (c) 2003-2021  Paul T. McGuire
@@ -177,7 +178,7 @@ del __config_flags
 
 
 def _should_enable_warnings(
-    cmd_line_warn_options: List[str], warn_env_var: str
+    cmd_line_warn_options: List[str], warn_env_var: OptionalType[str]
 ) -> bool:
     enable = bool(warn_env_var)
     for warn_opt in cmd_line_warn_options:
@@ -412,7 +413,7 @@ class ParserElement(ABC):
         # update whitespace all parse expressions defined in this module
         for expr in _builtin_exprs:
             if expr.copyDefaultWhiteChars:
-                expr.whiteChars = chars
+                expr.whiteChars = set(chars)
 
     @staticmethod
     def inline_literals_using(cls: type):
@@ -747,7 +748,9 @@ class ParserElement(ABC):
         return tokenlist
 
     # @profile
-    def _parseNoCache(self, instring, loc, doActions=True, callPreParse=True):
+    def _parseNoCache(
+        self, instring, loc, doActions=True, callPreParse=True
+    ) -> Tuple[int, ParseResults]:
         TRY, MATCH, FAIL = 0, 1, 2
         debugging = self.debug  # and doActions)
         len_instring = len(instring)
@@ -756,43 +759,43 @@ class ParserElement(ABC):
             # print("Match {} at loc {}({}, {})".format(self, loc, lineno(loc, instring), col(loc, instring)))
             try:
                 if callPreParse and self.callPreparse:
-                    preloc = self.preParse(instring, loc)
+                    pre_loc = self.preParse(instring, loc)
                 else:
-                    preloc = loc
-                tokensStart = preloc
+                    pre_loc = loc
+                tokens_start = pre_loc
                 if self.debugActions[TRY]:
-                    self.debugActions[TRY](instring, tokensStart, self)
-                if self.mayIndexError or preloc >= len_instring:
+                    self.debugActions[TRY](instring, tokens_start, self)
+                if self.mayIndexError or pre_loc >= len_instring:
                     try:
-                        loc, tokens = self.parseImpl(instring, preloc, doActions)
+                        loc, tokens = self.parseImpl(instring, pre_loc, doActions)
                     except IndexError:
                         raise ParseException(instring, len_instring, self.errmsg, self)
                 else:
-                    loc, tokens = self.parseImpl(instring, preloc, doActions)
+                    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
             except Exception as err:
                 # print("Exception raised:", err)
                 if self.debugActions[FAIL]:
-                    self.debugActions[FAIL](instring, tokensStart, self, err)
+                    self.debugActions[FAIL](instring, tokens_start, self, err)
                 if self.failAction:
-                    self.failAction(instring, tokensStart, self, err)
+                    self.failAction(instring, tokens_start, self, err)
                 raise
         else:
             if callPreParse and self.callPreparse:
-                preloc = self.preParse(instring, loc)
+                pre_loc = self.preParse(instring, loc)
             else:
-                preloc = loc
-            tokensStart = preloc
-            if self.mayIndexError or preloc >= len_instring:
+                pre_loc = loc
+            tokens_start = pre_loc
+            if self.mayIndexError or pre_loc >= len_instring:
                 try:
-                    loc, tokens = self.parseImpl(instring, preloc, doActions)
+                    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
                 except IndexError:
                     raise ParseException(instring, len_instring, self.errmsg, self)
             else:
-                loc, tokens = self.parseImpl(instring, preloc, doActions)
+                loc, tokens = self.parseImpl(instring, pre_loc, doActions)
 
         tokens = self.postParse(instring, loc, tokens)
 
-        retTokens = ParseResults(
+        ret_tokens = ParseResults(
             tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults
         )
         if self.parseAction and (doActions or self.callDuringTry):
@@ -800,13 +803,13 @@ class ParserElement(ABC):
                 try:
                     for fn in self.parseAction:
                         try:
-                            tokens = fn(instring, tokensStart, retTokens)
+                            tokens = fn(instring, tokens_start, ret_tokens)
                         except IndexError as parse_action_exc:
                             exc = ParseException("exception raised in parse action")
                             raise exc from parse_action_exc
 
-                        if tokens is not None and tokens is not retTokens:
-                            retTokens = ParseResults(
+                        if tokens is not None and tokens is not ret_tokens:
+                            ret_tokens = ParseResults(
                                 tokens,
                                 self.resultsName,
                                 asList=self.saveAsList
@@ -816,18 +819,18 @@ class ParserElement(ABC):
                 except Exception as err:
                     # print "Exception raised in user parse action:", err
                     if self.debugActions[FAIL]:
-                        self.debugActions[FAIL](instring, tokensStart, self, err)
+                        self.debugActions[FAIL](instring, tokens_start, self, err)
                     raise
             else:
                 for fn in self.parseAction:
                     try:
-                        tokens = fn(instring, tokensStart, retTokens)
+                        tokens = fn(instring, tokens_start, ret_tokens)
                     except IndexError as parse_action_exc:
                         exc = ParseException("exception raised in parse action")
                         raise exc from parse_action_exc
 
-                    if tokens is not None and tokens is not retTokens:
-                        retTokens = ParseResults(
+                    if tokens is not None and tokens is not ret_tokens:
+                        ret_tokens = ParseResults(
                             tokens,
                             self.resultsName,
                             asList=self.saveAsList
@@ -835,11 +838,11 @@ class ParserElement(ABC):
                             modal=self.modalResults,
                         )
         if debugging:
-            # print("Matched", self, "->", retTokens.as_list())
+            # print("Matched", self, "->", ret_tokens.as_list())
             if self.debugActions[MATCH]:
-                self.debugActions[MATCH](instring, tokensStart, loc, self, retTokens)
+                self.debugActions[MATCH](instring, tokens_start, loc, self, ret_tokens)
 
-        return loc, retTokens
+        return loc, ret_tokens
 
     def try_parse(self, instring: str, loc: int, raise_fatal: bool = False) -> int:
         try:
@@ -859,9 +862,9 @@ class ParserElement(ABC):
 
     # cache for left-recursion in Forward references
     recursion_lock = RLock()
-    recursion_memos = (
-        {}
-    )  # type: dict[tuple[int, Forward, bool], tuple[int, ParseResults | Exception]]
+    recursion_memos: DictType[
+        Tuple[int, "Forward", bool], Tuple[int, Union[ParseResults, Exception]]
+    ] = {}
 
     # argument cache for optimizing repeated calls when backtracking through recursive expressions
     packrat_cache = (
@@ -1909,6 +1912,7 @@ class ParserElement(ABC):
         failure_tests: bool = False,
         post_parse: Callable[[str, ParseResults], str] = None,
         file: OptionalType[TextIO] = None,
+        with_line_numbers: bool = False,
         *,
         parseAll: bool = True,
         fullDump: bool = True,
@@ -1934,6 +1938,7 @@ class ParserElement(ABC):
           `fn(test_string, parse_results)` and returns a string to be added to the test output
         - ``file`` - (default= ``None``) optional file-like object to which test output will be written;
           if None, will default to ``sys.stdout``
+        - ``with_line_numbers`` - default= ``False``) show test strings with line and column numbers
 
         Returns: a (success, results) tuple, where success indicates that all tests succeeded
         (or failed if ``failure_tests`` is True), and the results contain a list of lines of each
@@ -2038,7 +2043,7 @@ class ParserElement(ABC):
                 continue
             out = [
                 "\n" + "\n".join(comments) if comments else "",
-                pyparsing_test.with_line_numbers(t),
+                pyparsing_test.with_line_numbers(t) if with_line_numbers else t,
             ]
             comments = []
             try:
@@ -2076,7 +2081,7 @@ class ParserElement(ABC):
                         )
                 else:
                     out.append(result.dump(full=fullDump))
-                out.append("")
+            out.append("")
 
             if printResults:
                 print_("\n".join(out))
@@ -2693,7 +2698,7 @@ class Word(Token):
                         self.minLen, "" if self.maxLen == _MAX_INT else self.maxLen
                     )
                 self.reString = "[{}]{}".format(
-                    _collapseStringToRanges(self.initChars),
+                    _collapse_string_to_ranges(self.initChars),
                     repeat,
                 )
             elif len(self.initChars) == 1:
@@ -2703,7 +2708,7 @@ class Word(Token):
                     repeat = "{{0,{}}}".format(max - 1)
                 self.reString = "{}[{}]{}".format(
                     re.escape(self.initCharsOrig),
-                    _collapseStringToRanges(self.bodyChars),
+                    _collapse_string_to_ranges(self.bodyChars),
                     repeat,
                 )
             else:
@@ -2714,8 +2719,8 @@ class Word(Token):
                 else:
                     repeat = "{{0,{}}}".format(max - 1)
                 self.reString = "[{}][{}]{}".format(
-                    _collapseStringToRanges(self.initChars),
-                    _collapseStringToRanges(self.bodyChars),
+                    _collapse_string_to_ranges(self.initChars),
+                    _collapse_string_to_ranges(self.bodyChars),
                     repeat,
                 )
             if self.asKeyword:
@@ -2732,7 +2737,7 @@ class Word(Token):
     def _generateDefaultName(self):
         def charsAsStr(s):
             max_repr_len = 16
-            s = _collapseStringToRanges(s, re_escape=False)
+            s = _collapse_string_to_ranges(s, re_escape=False)
             if len(s) > max_repr_len:
                 return s[: max_repr_len - 3] + "..."
             else:
@@ -2821,7 +2826,7 @@ class Char(_WordRegex):
         super().__init__(
             charset, exact=1, asKeyword=asKeyword, excludeChars=excludeChars
         )
-        self.reString = "[{}]".format(_collapseStringToRanges(self.initChars))
+        self.reString = "[{}]".format(_collapse_string_to_ranges(self.initChars))
         if asKeyword:
             self.reString = r"\b{}\b".format(self.reString)
         self.re = re.compile(self.reString)
@@ -3081,7 +3086,7 @@ class QuotedString(Token):
                 + "|".join(
                     "(?:{}(?!{}))".format(
                         re.escape(self.endQuoteChar[:i]),
-                        _escapeRegexRangeChars(self.endQuoteChar[i:]),
+                        _escape_regex_range_chars(self.endQuoteChar[i:]),
                     )
                     for i in range(len(self.endQuoteChar) - 1, 0, -1)
                 )
@@ -3093,15 +3098,15 @@ class QuotedString(Token):
             self.flags = re.MULTILINE | re.DOTALL
             inner_pattern += r"{}(?:[^{}{}])".format(
                 sep,
-                _escapeRegexRangeChars(self.endQuoteChar[0]),
-                (_escapeRegexRangeChars(escChar) if escChar is not None else ""),
+                _escape_regex_range_chars(self.endQuoteChar[0]),
+                (_escape_regex_range_chars(escChar) if escChar is not None else ""),
             )
         else:
             self.flags = 0
             inner_pattern += r"{}(?:[^{}\n\r{}])".format(
                 sep,
-                _escapeRegexRangeChars(self.endQuoteChar[0]),
-                (_escapeRegexRangeChars(escChar) if escChar is not None else ""),
+                _escape_regex_range_chars(self.endQuoteChar[0]),
+                (_escape_regex_range_chars(escChar) if escChar is not None else ""),
             )
 
         self.pattern = "".join(
@@ -3226,7 +3231,7 @@ class CharsNotIn(Token):
         self.mayIndexError = False
 
     def _generateDefaultName(self):
-        not_chars_str = _collapseStringToRanges(self.notChars)
+        not_chars_str = _collapse_string_to_ranges(self.notChars)
         if len(not_chars_str) > 16:
             return "!W:({}...)".format(self.notChars[: 16 - 3])
         else:
@@ -3532,7 +3537,6 @@ class ParseExpression(ParserElement):
     def __init__(self, exprs: IterableType[ParserElement], savelist: bool = False):
         super().__init__(savelist)
         self.exprs: List[ParserElement]
-        exprs: Iterable[ParserElement]
         if isinstance(exprs, _generatorType):
             exprs = list(exprs)
 
@@ -3606,7 +3610,7 @@ class ParseExpression(ParserElement):
 
     def streamline(self):
         if self.streamlined:
-            return
+            return self
 
         super().streamline()
 
@@ -3659,7 +3663,11 @@ class ParseExpression(ParserElement):
     def _setResultsName(self, name, listAllMatches=False):
         if __diag__.warn_ungrouped_named_tokens_in_collection:
             for e in self.exprs:
-                if isinstance(e, ParserElement) and e.resultsName:
+                if (
+                    isinstance(e, ParserElement)
+                    and e.resultsName
+                    and not e.resultsName.startswith("_NOWARN")
+                ):
                     warnings.warn(
                         "{}: setting results name {!r} on {} expression "
                         "collides with {!r} on contained expression".format(
@@ -3731,7 +3739,7 @@ class And(ParseExpression):
             self.mayReturnEmpty = True
         self.callPreparse = True
 
-    def streamline(self):
+    def streamline(self) -> ParserElement:
         # collapse any _PendingSkip's
         if self.exprs:
             if any(
@@ -3850,7 +3858,7 @@ class Or(ParseExpression):
         else:
             self.mayReturnEmpty = True
 
-    def streamline(self):
+    def streamline(self) -> ParserElement:
         super().streamline()
         if self.exprs:
             self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs)
@@ -3993,9 +4001,9 @@ class MatchFirst(ParseExpression):
         else:
             self.mayReturnEmpty = True
 
-    def streamline(self):
+    def streamline(self) -> ParserElement:
         if self.streamlined:
-            return
+            return self
 
         super().streamline()
         if self.exprs:
@@ -4134,7 +4142,7 @@ class Each(ParseExpression):
         self.initExprGroups = True
         self.saveAsList = True
 
-    def streamline(self):
+    def streamline(self) -> ParserElement:
         super().streamline()
         if self.exprs:
             self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs)
@@ -4700,7 +4708,11 @@ class _MultipleMatch(ParseElementEnhance):
     def _setResultsName(self, name, listAllMatches=False):
         if __diag__.warn_ungrouped_named_tokens_in_collection:
             for e in [self.expr] + self.expr.recurse():
-                if isinstance(e, ParserElement) and e.resultsName:
+                if (
+                    isinstance(e, ParserElement)
+                    and e.resultsName
+                    and not e.resultsName.startswith("_NOWARN")
+                ):
                     warnings.warn(
                         "{}: setting results name {!r} on {} expression "
                         "collides with {!r} on contained expression".format(
index 2fb9a25d807763523f625680f451543c058cd2c0..e06513eb00f723c3cb4efc4188141c2a6e303dd0 100644 (file)
@@ -4,7 +4,7 @@ import re
 import sys
 from typing import Optional
 
-from .util import col, line, lineno, _collapseStringToRanges
+from .util import col, line, lineno, _collapse_string_to_ranges
 from .unicode import pyparsing_unicode as ppu
 
 
@@ -12,7 +12,7 @@ class ExceptionWordUnicode(ppu.Latin1, ppu.LatinA, ppu.LatinB, ppu.Greek, ppu.Cy
     pass
 
 
-_extract_alphanums = _collapseStringToRanges(ExceptionWordUnicode.alphanums)
+_extract_alphanums = _collapse_string_to_ranges(ExceptionWordUnicode.alphanums)
 _exception_word_extractor = re.compile("([" + _extract_alphanums + "]{1,16})|.")
 
 
index b466075316f82fae588982be04cc3a8ff3af95fc..9b1e2e132df1211d36cf1cc62bfb69d562f4d9cb 100644 (file)
@@ -4,7 +4,7 @@ import re
 
 from . import __diag__
 from .core import *
-from .util import _bslash, _flatten, _escapeRegexRangeChars
+from .util import _bslash, _flatten, _escape_regex_range_chars
 
 
 #
@@ -35,7 +35,7 @@ def delimited_list(
         delimited_list(Word(hexnums), delim=':', combine=True).parse_string("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE']
     """
     dlName = "{expr} [{delim} {expr}]...{end}".format(
-        expr=str(expr),
+        expr=str(expr.streamline()),
         delim=str(delim),
         end=" [{}]".format(str(delim)) if allow_trailing_delim else "",
     )
@@ -278,7 +278,7 @@ def one_of(
             if all(len(sym) == 1 for sym in symbols):
                 # symbols are just single characters, create range regex pattern
                 patt = "[{}]".format(
-                    "".join(_escapeRegexRangeChars(sym) for sym in symbols)
+                    "".join(_escape_regex_range_chars(sym) for sym in symbols)
                 )
             else:
                 patt = "|".join(re.escape(sym) for sym in symbols)
@@ -387,13 +387,20 @@ def original_text_for(
     locMarker = Empty().set_parse_action(lambda s, loc, t: loc)
     endlocMarker = locMarker.copy()
     endlocMarker.callPreparse = False
-    matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end")
+    # prefix these transient names with _NOWARN to suppress ungrouped name warnings
+    matchExpr = (
+        locMarker("_NOWARN_original_start")
+        + expr
+        + endlocMarker("_NOWARN_original_end")
+    )
     if asString:
-        extractText = lambda s, l, t: s[t._original_start : t._original_end]
+        extractText = lambda s, l, t: s[
+            t._NOWARN_original_start : t._NOWARN_original_end
+        ]
     else:
 
         def extractText(s, l, t):
-            t[:] = [s[t.pop("_original_start") : t.pop("_original_end")]]
+            t[:] = [s[t.pop("_NOWARN_original_start") : t.pop("_NOWARN_original_end")]]
 
     matchExpr.set_parse_action(extractText)
     matchExpr.ignoreExprs = expr.ignoreExprs
index 194c3d91f38534e458d82f178ad71c849ba6d1d2..842d16b3c75fb452e89858932a738598965f9861 100644 (file)
@@ -4,7 +4,7 @@ import pprint
 from weakref import ref as wkref
 from typing import Tuple, Any
 
-str_type = (str, bytes)
+str_type: Tuple[type, ...] = (str, bytes)
 _generator_type = type((_ for _ in ()))
 
 
index 6bd52e103499503505fd9fbeb8b195a0bd447809..1309ad6effeb85ffbe49ca5736ddc402569eb45f 100644 (file)
@@ -4,8 +4,7 @@ import types
 import collections
 import itertools
 from functools import lru_cache
-from typing import List
-
+from typing import List, Union, Iterable
 
 _bslash = chr(92)
 
@@ -39,7 +38,7 @@ class __config_flags:
 
 
 @lru_cache(maxsize=128)
-def col(loc: int, strg: str):
+def col(loc: int, strg: str) -> int:
     """
     Returns current column within a string, counting newlines as line separators.
     The first column is number 1.
@@ -56,7 +55,7 @@ def col(loc: int, strg: str):
 
 
 @lru_cache(maxsize=128)
-def lineno(loc: int, strg: str):
+def lineno(loc: int, strg: str) -> int:
     """Returns current line number within a string, counting newlines as line separators.
     The first line is number 1.
 
@@ -70,13 +69,13 @@ def lineno(loc: int, strg: str):
 
 
 @lru_cache(maxsize=128)
-def line(loc: int, strg: str):
+def line(loc: int, strg: str) -> str:
     """
     Returns the line of text containing loc within a string, counting newlines as line separators.
     """
-    lastCR = strg.rfind("\n", 0, loc)
-    nextCR = strg.find("\n", loc)
-    return strg[lastCR + 1 : nextCR] if nextCR >= 0 else strg[lastCR + 1 :]
+    last_cr = strg.rfind("\n", 0, loc)
+    next_cr = strg.find("\n", loc)
+    return strg[last_cr + 1 : next_cr] if next_cr >= 0 else strg[last_cr + 1 :]
 
 
 class _UnboundedCache:
@@ -85,18 +84,18 @@ class _UnboundedCache:
         cache_get = cache.get
         self.not_in_cache = not_in_cache = object()
 
-        def get(self, key):
+        def get(_, key):
             return cache_get(key, not_in_cache)
 
-        def set(self, key, value):
+        def set_(_, key, value):
             cache[key] = value
 
-        def clear(self):
+        def clear(_):
             cache.clear()
 
         self.size = None
         self.get = types.MethodType(get, self)
-        self.set = types.MethodType(set, self)
+        self.set = types.MethodType(set_, self)
         self.clear = types.MethodType(clear, self)
 
 
@@ -106,20 +105,20 @@ class _FifoCache:
         cache = collections.OrderedDict()
         cache_get = cache.get
 
-        def get(self, key):
+        def get(_, key):
             return cache_get(key, not_in_cache)
 
-        def set(self, key, value):
+        def set_(_, key, value):
             cache[key] = value
             while len(cache) > size:
                 cache.popitem(last=False)
 
-        def clear(self):
+        def clear(_):
             cache.clear()
 
         self.size = size
         self.get = types.MethodType(get, self)
-        self.set = types.MethodType(set, self)
+        self.set = types.MethodType(set_, self)
         self.clear = types.MethodType(clear, self)
 
 
@@ -171,7 +170,7 @@ class UnboundedMemo(dict):
         pass
 
 
-def _escapeRegexRangeChars(s: str):
+def _escape_regex_range_chars(s: str) -> str:
     # escape these chars: ^-[]
     for c in r"\^-[]":
         s = s.replace(c, _bslash + c)
@@ -180,7 +179,9 @@ def _escapeRegexRangeChars(s: str):
     return str(s)
 
 
-def _collapseStringToRanges(s: str, re_escape: bool = True):
+def _collapse_string_to_ranges(
+    s: Union[str, Iterable[str]], re_escape: bool = True
+) -> str:
     def is_consecutive(c):
         c_int = ord(c)
         is_consecutive.prev, prev = c_int, is_consecutive.prev
@@ -223,7 +224,7 @@ def _collapseStringToRanges(s: str, re_escape: bool = True):
     return "".join(ret)
 
 
-def _flatten(ll: List):
+def _flatten(ll: list) -> list:
     ret = []
     for i in ll:
         if isinstance(i, list):
index b60e90b74760ef073966fcd64665caa5b632e2d7..db1c8e09b169e550d081e2df42c5acd25b0449ba 100644 (file)
@@ -7529,6 +7529,14 @@ class Test02_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase):
           name is defined on a containing expression with ungrouped subexpressions that also
           have results names (default=True)
         """
+        with self.assertDoesNotWarn(
+            msg="raised {} warning when not enabled".format(
+                pp.Diagnostics.warn_ungrouped_named_tokens_in_collection
+            )
+        ):
+            COMMA = pp.Suppress(",").setName("comma")
+            coord = ppc.integer("x") + COMMA + ppc.integer("y")
+            path = coord[...].setResultsName("path")
 
         with ppt.reset_pyparsing_context():
             pp.enable_diag(pp.Diagnostics.warn_ungrouped_named_tokens_in_collection)
@@ -7544,12 +7552,35 @@ class Test02_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase):
             ):
                 path = coord[...].setResultsName("path")
 
+    def testDontWarnUngroupedNamedTokensIfUngroupedNamesStartWithNOWARN(self):
+        """
+        - warn_ungrouped_named_tokens_in_collection - flag to enable warnings when a results
+          name is defined on a containing expression with ungrouped subexpressions that also
+          have results names (default=True)
+        """
+        with ppt.reset_pyparsing_context():
+            pp.enable_diag(pp.Diagnostics.warn_ungrouped_named_tokens_in_collection)
+
+            with self.assertDoesNotWarn(
+                msg="raised {} warning inner names start with '_NOWARN'".format(
+                    pp.Diagnostics.warn_ungrouped_named_tokens_in_collection
+                )
+            ):
+                pp.originalTextFor(pp.Word("ABC")[...])("words")
+
     def testWarnNameSetOnEmptyForward(self):
         """
         - warn_name_set_on_empty_Forward - flag to enable warnings when a Forward is defined
           with a results name, but has no contents defined (default=False)
         """
 
+        with self.assertDoesNotWarn(
+            msg="raised {} warning when not enabled".format(
+                pp.Diagnostics.warn_name_set_on_empty_Forward
+            )
+        ):
+            base = pp.Forward()("z")
+
         with ppt.reset_pyparsing_context():
             pp.enable_diag(pp.Diagnostics.warn_name_set_on_empty_Forward)
 
@@ -7567,6 +7598,17 @@ class Test02_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase):
           has no contents defined (default=False)
         """
 
+        with self.assertDoesNotWarn(
+            msg="raised {} warning when not enabled".format(
+                pp.Diagnostics.warn_on_parse_using_empty_Forward
+            )
+        ):
+            base = pp.Forward()
+            try:
+                print(base.parseString("x"))
+            except ParseException as pe:
+                pass
+
         with ppt.reset_pyparsing_context():
             pp.enable_diag(pp.Diagnostics.warn_on_parse_using_empty_Forward)
 
@@ -7590,13 +7632,20 @@ class Test02_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase):
             print("warn_on_assignment_to_Forward not supported on PyPy")
             return
 
+        def a_method():
+            base = pp.Forward()
+            base = pp.Word(pp.alphas)[...] | "(" + base + ")"
+
+        with self.assertDoesNotWarn(
+            msg="raised {} warning when not enabled".format(
+                pp.Diagnostics.warn_on_assignment_to_Forward
+            )
+        ):
+            a_method()
+
         with ppt.reset_pyparsing_context():
             pp.enable_diag(pp.Diagnostics.warn_on_assignment_to_Forward)
 
-            def a_method():
-                base = pp.Forward()
-                base = pp.Word(pp.alphas)[...] | "(" + base + ")"
-
             with self.assertWarns(
                 UserWarning,
                 msg="failed to warn when using '=' to assign expression to a Forward",
@@ -7609,7 +7658,9 @@ class Test02_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase):
           incorrectly called with multiple str arguments (default=True)
         """
         with self.assertDoesNotWarn(
-            "warn_on_multiple_string_args_to_oneof warning raised when not enabled"
+            msg="raised {} warning when not enabled".format(
+                pp.Diagnostics.warn_on_multiple_string_args_to_oneof
+            )
         ):
             a = pp.oneOf("A", "B")
 
@@ -7640,6 +7691,24 @@ class Test02_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase):
             self.assertEqual("a", a.name)
             self.assertEqual("bbb", b.name)
 
+    def testDelimitedListName(self):
+        bool_constant = pp.Literal("True") | "true" | "False" | "false"
+        bool_list = pp.delimitedList(bool_constant)
+        print(bool_list)
+        self.assertEqual(
+            "{'True' | 'true' | 'False' | 'false'} [, {'True' | 'true' | 'False' | 'false'}]...",
+            str(bool_list),
+        )
+
+        bool_constant.setName("bool")
+        print(bool_constant)
+        print(bool_constant.streamline())
+        bool_list2 = pp.delimitedList(bool_constant)
+        print(bool_constant)
+        print(bool_constant.streamline())
+        print(bool_list2)
+        self.assertEqual("bool [, bool]...", str(bool_list2))
+
     def testEnableDebugOnNamedExpressions(self):
         """
         - enable_debug_on_named_expressions - flag to auto-enable debug on all subsequent
@@ -8241,6 +8310,14 @@ class Test02_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase):
             len(results) > 0, "MatchFirst error - not iterating over all choices"
         )
 
+    def testStreamlineOfExpressionsAfterSetName(self):
+        bool_constant = pp.Literal("True") | "true" | "False" | "false"
+        self.assertEqual(
+            "{'True' | 'true' | 'False' | 'false'}", str(bool_constant.streamline())
+        )
+        bool_constant.setName("bool")
+        self.assertEqual("bool", str(bool_constant.streamline()))
+
     def testStreamlineOfSubexpressions(self):
         # verify streamline of subexpressions
         print("verify proper streamline logic")