mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-06 21:21:15 -07:00
Bump pyparsing from 3.0.9 to 3.1.1 (#2131)
* Bump pyparsing from 3.0.9 to 3.1.1 Bumps [pyparsing](https://github.com/pyparsing/pyparsing) from 3.0.9 to 3.1.1. - [Release notes](https://github.com/pyparsing/pyparsing/releases) - [Changelog](https://github.com/pyparsing/pyparsing/blob/master/CHANGES) - [Commits](https://github.com/pyparsing/pyparsing/compare/pyparsing_3.0.9...3.1.1) --- updated-dependencies: - dependency-name: pyparsing dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Update pyparsing==3.1.1 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: JonnyWong16 <9099342+JonnyWong16@users.noreply.github.com> [skip ci]
This commit is contained in:
parent
d0c7f25a3f
commit
3debeada2a
12 changed files with 1306 additions and 797 deletions
|
@ -56,7 +56,7 @@ self-explanatory class names, and the use of :class:`'+'<And>`,
|
||||||
:class:`'|'<MatchFirst>`, :class:`'^'<Or>` and :class:`'&'<Each>` operators.
|
:class:`'|'<MatchFirst>`, :class:`'^'<Or>` and :class:`'&'<Each>` operators.
|
||||||
|
|
||||||
The :class:`ParseResults` object returned from
|
The :class:`ParseResults` object returned from
|
||||||
:class:`ParserElement.parseString` can be
|
:class:`ParserElement.parse_string` can be
|
||||||
accessed as a nested list, a dictionary, or an object with named
|
accessed as a nested list, a dictionary, or an object with named
|
||||||
attributes.
|
attributes.
|
||||||
|
|
||||||
|
@ -85,11 +85,11 @@ classes inherit from. Use the docstrings for examples of how to:
|
||||||
and :class:`'&'<Each>` operators to combine simple expressions into
|
and :class:`'&'<Each>` operators to combine simple expressions into
|
||||||
more complex ones
|
more complex ones
|
||||||
- associate names with your parsed results using
|
- associate names with your parsed results using
|
||||||
:class:`ParserElement.setResultsName`
|
:class:`ParserElement.set_results_name`
|
||||||
- access the parsed data, which is returned as a :class:`ParseResults`
|
- access the parsed data, which is returned as a :class:`ParseResults`
|
||||||
object
|
object
|
||||||
- find some helpful expression short-cuts like :class:`delimitedList`
|
- find some helpful expression short-cuts like :class:`DelimitedList`
|
||||||
and :class:`oneOf`
|
and :class:`one_of`
|
||||||
- find more useful common expressions in the :class:`pyparsing_common`
|
- find more useful common expressions in the :class:`pyparsing_common`
|
||||||
namespace class
|
namespace class
|
||||||
"""
|
"""
|
||||||
|
@ -106,30 +106,22 @@ class version_info(NamedTuple):
|
||||||
@property
|
@property
|
||||||
def __version__(self):
|
def __version__(self):
|
||||||
return (
|
return (
|
||||||
"{}.{}.{}".format(self.major, self.minor, self.micro)
|
f"{self.major}.{self.minor}.{self.micro}"
|
||||||
+ (
|
+ (
|
||||||
"{}{}{}".format(
|
f"{'r' if self.releaselevel[0] == 'c' else ''}{self.releaselevel[0]}{self.serial}",
|
||||||
"r" if self.releaselevel[0] == "c" else "",
|
|
||||||
self.releaselevel[0],
|
|
||||||
self.serial,
|
|
||||||
),
|
|
||||||
"",
|
"",
|
||||||
)[self.releaselevel == "final"]
|
)[self.releaselevel == "final"]
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "{} {} / {}".format(__name__, self.__version__, __version_time__)
|
return f"{__name__} {self.__version__} / {__version_time__}"
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "{}.{}({})".format(
|
return f"{__name__}.{type(self).__name__}({', '.join('{}={!r}'.format(*nv) for nv in zip(self._fields, self))})"
|
||||||
__name__,
|
|
||||||
type(self).__name__,
|
|
||||||
", ".join("{}={!r}".format(*nv) for nv in zip(self._fields, self)),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
__version_info__ = version_info(3, 0, 9, "final", 0)
|
__version_info__ = version_info(3, 1, 1, "final", 1)
|
||||||
__version_time__ = "05 May 2022 07:02 UTC"
|
__version_time__ = "29 Jul 2023 22:27 UTC"
|
||||||
__version__ = __version_info__.__version__
|
__version__ = __version_info__.__version__
|
||||||
__versionTime__ = __version_time__
|
__versionTime__ = __version_time__
|
||||||
__author__ = "Paul McGuire <ptmcg.gm+pyparsing@gmail.com>"
|
__author__ = "Paul McGuire <ptmcg.gm+pyparsing@gmail.com>"
|
||||||
|
@ -139,9 +131,9 @@ from .exceptions import *
|
||||||
from .actions import *
|
from .actions import *
|
||||||
from .core import __diag__, __compat__
|
from .core import __diag__, __compat__
|
||||||
from .results import *
|
from .results import *
|
||||||
from .core import *
|
from .core import * # type: ignore[misc, assignment]
|
||||||
from .core import _builtin_exprs as core_builtin_exprs
|
from .core import _builtin_exprs as core_builtin_exprs
|
||||||
from .helpers import *
|
from .helpers import * # type: ignore[misc, assignment]
|
||||||
from .helpers import _builtin_exprs as helper_builtin_exprs
|
from .helpers import _builtin_exprs as helper_builtin_exprs
|
||||||
|
|
||||||
from .unicode import unicode_set, UnicodeRangeList, pyparsing_unicode as unicode
|
from .unicode import unicode_set, UnicodeRangeList, pyparsing_unicode as unicode
|
||||||
|
@ -153,11 +145,11 @@ from .common import (
|
||||||
|
|
||||||
# define backward compat synonyms
|
# define backward compat synonyms
|
||||||
if "pyparsing_unicode" not in globals():
|
if "pyparsing_unicode" not in globals():
|
||||||
pyparsing_unicode = unicode
|
pyparsing_unicode = unicode # type: ignore[misc]
|
||||||
if "pyparsing_common" not in globals():
|
if "pyparsing_common" not in globals():
|
||||||
pyparsing_common = common
|
pyparsing_common = common # type: ignore[misc]
|
||||||
if "pyparsing_test" not in globals():
|
if "pyparsing_test" not in globals():
|
||||||
pyparsing_test = testing
|
pyparsing_test = testing # type: ignore[misc]
|
||||||
|
|
||||||
core_builtin_exprs += common_builtin_exprs + helper_builtin_exprs
|
core_builtin_exprs += common_builtin_exprs + helper_builtin_exprs
|
||||||
|
|
||||||
|
@ -174,7 +166,9 @@ __all__ = [
|
||||||
"CaselessKeyword",
|
"CaselessKeyword",
|
||||||
"CaselessLiteral",
|
"CaselessLiteral",
|
||||||
"CharsNotIn",
|
"CharsNotIn",
|
||||||
|
"CloseMatch",
|
||||||
"Combine",
|
"Combine",
|
||||||
|
"DelimitedList",
|
||||||
"Dict",
|
"Dict",
|
||||||
"Each",
|
"Each",
|
||||||
"Empty",
|
"Empty",
|
||||||
|
@ -227,9 +221,11 @@ __all__ = [
|
||||||
"alphas8bit",
|
"alphas8bit",
|
||||||
"any_close_tag",
|
"any_close_tag",
|
||||||
"any_open_tag",
|
"any_open_tag",
|
||||||
|
"autoname_elements",
|
||||||
"c_style_comment",
|
"c_style_comment",
|
||||||
"col",
|
"col",
|
||||||
"common_html_entity",
|
"common_html_entity",
|
||||||
|
"condition_as_parse_action",
|
||||||
"counted_array",
|
"counted_array",
|
||||||
"cpp_style_comment",
|
"cpp_style_comment",
|
||||||
"dbl_quoted_string",
|
"dbl_quoted_string",
|
||||||
|
@ -241,6 +237,7 @@ __all__ = [
|
||||||
"html_comment",
|
"html_comment",
|
||||||
"identchars",
|
"identchars",
|
||||||
"identbodychars",
|
"identbodychars",
|
||||||
|
"infix_notation",
|
||||||
"java_style_comment",
|
"java_style_comment",
|
||||||
"line",
|
"line",
|
||||||
"line_end",
|
"line_end",
|
||||||
|
@ -255,8 +252,12 @@ __all__ = [
|
||||||
"null_debug_action",
|
"null_debug_action",
|
||||||
"nums",
|
"nums",
|
||||||
"one_of",
|
"one_of",
|
||||||
|
"original_text_for",
|
||||||
"printables",
|
"printables",
|
||||||
"punc8bit",
|
"punc8bit",
|
||||||
|
"pyparsing_common",
|
||||||
|
"pyparsing_test",
|
||||||
|
"pyparsing_unicode",
|
||||||
"python_style_comment",
|
"python_style_comment",
|
||||||
"quoted_string",
|
"quoted_string",
|
||||||
"remove_quotes",
|
"remove_quotes",
|
||||||
|
@ -267,28 +268,20 @@ __all__ = [
|
||||||
"srange",
|
"srange",
|
||||||
"string_end",
|
"string_end",
|
||||||
"string_start",
|
"string_start",
|
||||||
|
"token_map",
|
||||||
"trace_parse_action",
|
"trace_parse_action",
|
||||||
|
"ungroup",
|
||||||
|
"unicode_set",
|
||||||
"unicode_string",
|
"unicode_string",
|
||||||
"with_attribute",
|
"with_attribute",
|
||||||
"indentedBlock",
|
|
||||||
"original_text_for",
|
|
||||||
"ungroup",
|
|
||||||
"infix_notation",
|
|
||||||
"locatedExpr",
|
|
||||||
"with_class",
|
"with_class",
|
||||||
"CloseMatch",
|
|
||||||
"token_map",
|
|
||||||
"pyparsing_common",
|
|
||||||
"pyparsing_unicode",
|
|
||||||
"unicode_set",
|
|
||||||
"condition_as_parse_action",
|
|
||||||
"pyparsing_test",
|
|
||||||
# pre-PEP8 compatibility names
|
# pre-PEP8 compatibility names
|
||||||
"__versionTime__",
|
"__versionTime__",
|
||||||
"anyCloseTag",
|
"anyCloseTag",
|
||||||
"anyOpenTag",
|
"anyOpenTag",
|
||||||
"cStyleComment",
|
"cStyleComment",
|
||||||
"commonHTMLEntity",
|
"commonHTMLEntity",
|
||||||
|
"conditionAsParseAction",
|
||||||
"countedArray",
|
"countedArray",
|
||||||
"cppStyleComment",
|
"cppStyleComment",
|
||||||
"dblQuotedString",
|
"dblQuotedString",
|
||||||
|
@ -296,9 +289,12 @@ __all__ = [
|
||||||
"delimitedList",
|
"delimitedList",
|
||||||
"dictOf",
|
"dictOf",
|
||||||
"htmlComment",
|
"htmlComment",
|
||||||
|
"indentedBlock",
|
||||||
|
"infixNotation",
|
||||||
"javaStyleComment",
|
"javaStyleComment",
|
||||||
"lineEnd",
|
"lineEnd",
|
||||||
"lineStart",
|
"lineStart",
|
||||||
|
"locatedExpr",
|
||||||
"makeHTMLTags",
|
"makeHTMLTags",
|
||||||
"makeXMLTags",
|
"makeXMLTags",
|
||||||
"matchOnlyAtCol",
|
"matchOnlyAtCol",
|
||||||
|
@ -308,6 +304,7 @@ __all__ = [
|
||||||
"nullDebugAction",
|
"nullDebugAction",
|
||||||
"oneOf",
|
"oneOf",
|
||||||
"opAssoc",
|
"opAssoc",
|
||||||
|
"originalTextFor",
|
||||||
"pythonStyleComment",
|
"pythonStyleComment",
|
||||||
"quotedString",
|
"quotedString",
|
||||||
"removeQuotes",
|
"removeQuotes",
|
||||||
|
@ -317,15 +314,12 @@ __all__ = [
|
||||||
"sglQuotedString",
|
"sglQuotedString",
|
||||||
"stringEnd",
|
"stringEnd",
|
||||||
"stringStart",
|
"stringStart",
|
||||||
|
"tokenMap",
|
||||||
"traceParseAction",
|
"traceParseAction",
|
||||||
"unicodeString",
|
"unicodeString",
|
||||||
"withAttribute",
|
"withAttribute",
|
||||||
"indentedBlock",
|
|
||||||
"originalTextFor",
|
|
||||||
"infixNotation",
|
|
||||||
"locatedExpr",
|
|
||||||
"withClass",
|
"withClass",
|
||||||
"tokenMap",
|
"common",
|
||||||
"conditionAsParseAction",
|
"unicode",
|
||||||
"autoname_elements",
|
"testing",
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# actions.py
|
# actions.py
|
||||||
|
|
||||||
from .exceptions import ParseException
|
from .exceptions import ParseException
|
||||||
from .util import col
|
from .util import col, replaced_by_pep8
|
||||||
|
|
||||||
|
|
||||||
class OnlyOnce:
|
class OnlyOnce:
|
||||||
|
@ -38,7 +38,7 @@ def match_only_at_col(n):
|
||||||
|
|
||||||
def verify_col(strg, locn, toks):
|
def verify_col(strg, locn, toks):
|
||||||
if col(locn, strg) != n:
|
if col(locn, strg) != n:
|
||||||
raise ParseException(strg, locn, "matched token not at column {}".format(n))
|
raise ParseException(strg, locn, f"matched token not at column {n}")
|
||||||
|
|
||||||
return verify_col
|
return verify_col
|
||||||
|
|
||||||
|
@ -148,15 +148,13 @@ def with_attribute(*args, **attr_dict):
|
||||||
raise ParseException(
|
raise ParseException(
|
||||||
s,
|
s,
|
||||||
l,
|
l,
|
||||||
"attribute {!r} has value {!r}, must be {!r}".format(
|
f"attribute {attrName!r} has value {tokens[attrName]!r}, must be {attrValue!r}",
|
||||||
attrName, tokens[attrName], attrValue
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return pa
|
return pa
|
||||||
|
|
||||||
|
|
||||||
with_attribute.ANY_VALUE = object()
|
with_attribute.ANY_VALUE = object() # type: ignore [attr-defined]
|
||||||
|
|
||||||
|
|
||||||
def with_class(classname, namespace=""):
|
def with_class(classname, namespace=""):
|
||||||
|
@ -195,13 +193,25 @@ def with_class(classname, namespace=""):
|
||||||
1 4 0 1 0
|
1 4 0 1 0
|
||||||
1,3 2,3 1,1
|
1,3 2,3 1,1
|
||||||
"""
|
"""
|
||||||
classattr = "{}:class".format(namespace) if namespace else "class"
|
classattr = f"{namespace}:class" if namespace else "class"
|
||||||
return with_attribute(**{classattr: classname})
|
return with_attribute(**{classattr: classname})
|
||||||
|
|
||||||
|
|
||||||
# pre-PEP8 compatibility symbols
|
# pre-PEP8 compatibility symbols
|
||||||
replaceWith = replace_with
|
# fmt: off
|
||||||
removeQuotes = remove_quotes
|
@replaced_by_pep8(replace_with)
|
||||||
withAttribute = with_attribute
|
def replaceWith(): ...
|
||||||
withClass = with_class
|
|
||||||
matchOnlyAtCol = match_only_at_col
|
@replaced_by_pep8(remove_quotes)
|
||||||
|
def removeQuotes(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(with_attribute)
|
||||||
|
def withAttribute(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(with_class)
|
||||||
|
def withClass(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(match_only_at_col)
|
||||||
|
def matchOnlyAtCol(): ...
|
||||||
|
|
||||||
|
# fmt: on
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# common.py
|
# common.py
|
||||||
from .core import *
|
from .core import *
|
||||||
from .helpers import delimited_list, any_open_tag, any_close_tag
|
from .helpers import DelimitedList, any_open_tag, any_close_tag
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,17 +22,17 @@ class pyparsing_common:
|
||||||
|
|
||||||
Parse actions:
|
Parse actions:
|
||||||
|
|
||||||
- :class:`convertToInteger`
|
- :class:`convert_to_integer`
|
||||||
- :class:`convertToFloat`
|
- :class:`convert_to_float`
|
||||||
- :class:`convertToDate`
|
- :class:`convert_to_date`
|
||||||
- :class:`convertToDatetime`
|
- :class:`convert_to_datetime`
|
||||||
- :class:`stripHTMLTags`
|
- :class:`strip_html_tags`
|
||||||
- :class:`upcaseTokens`
|
- :class:`upcase_tokens`
|
||||||
- :class:`downcaseTokens`
|
- :class:`downcase_tokens`
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
pyparsing_common.number.runTests('''
|
pyparsing_common.number.run_tests('''
|
||||||
# any int or real number, returned as the appropriate type
|
# any int or real number, returned as the appropriate type
|
||||||
100
|
100
|
||||||
-100
|
-100
|
||||||
|
@ -42,7 +42,7 @@ class pyparsing_common:
|
||||||
1e-12
|
1e-12
|
||||||
''')
|
''')
|
||||||
|
|
||||||
pyparsing_common.fnumber.runTests('''
|
pyparsing_common.fnumber.run_tests('''
|
||||||
# any int or real number, returned as float
|
# any int or real number, returned as float
|
||||||
100
|
100
|
||||||
-100
|
-100
|
||||||
|
@ -52,19 +52,19 @@ class pyparsing_common:
|
||||||
1e-12
|
1e-12
|
||||||
''')
|
''')
|
||||||
|
|
||||||
pyparsing_common.hex_integer.runTests('''
|
pyparsing_common.hex_integer.run_tests('''
|
||||||
# hex numbers
|
# hex numbers
|
||||||
100
|
100
|
||||||
FF
|
FF
|
||||||
''')
|
''')
|
||||||
|
|
||||||
pyparsing_common.fraction.runTests('''
|
pyparsing_common.fraction.run_tests('''
|
||||||
# fractions
|
# fractions
|
||||||
1/2
|
1/2
|
||||||
-3/4
|
-3/4
|
||||||
''')
|
''')
|
||||||
|
|
||||||
pyparsing_common.mixed_integer.runTests('''
|
pyparsing_common.mixed_integer.run_tests('''
|
||||||
# mixed fractions
|
# mixed fractions
|
||||||
1
|
1
|
||||||
1/2
|
1/2
|
||||||
|
@ -73,8 +73,8 @@ class pyparsing_common:
|
||||||
''')
|
''')
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID))
|
pyparsing_common.uuid.set_parse_action(token_map(uuid.UUID))
|
||||||
pyparsing_common.uuid.runTests('''
|
pyparsing_common.uuid.run_tests('''
|
||||||
# uuid
|
# uuid
|
||||||
12345678-1234-5678-1234-567812345678
|
12345678-1234-5678-1234-567812345678
|
||||||
''')
|
''')
|
||||||
|
@ -260,8 +260,8 @@ class pyparsing_common:
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
date_expr = pyparsing_common.iso8601_date.copy()
|
date_expr = pyparsing_common.iso8601_date.copy()
|
||||||
date_expr.setParseAction(pyparsing_common.convertToDate())
|
date_expr.set_parse_action(pyparsing_common.convert_to_date())
|
||||||
print(date_expr.parseString("1999-12-31"))
|
print(date_expr.parse_string("1999-12-31"))
|
||||||
|
|
||||||
prints::
|
prints::
|
||||||
|
|
||||||
|
@ -287,8 +287,8 @@ class pyparsing_common:
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
dt_expr = pyparsing_common.iso8601_datetime.copy()
|
dt_expr = pyparsing_common.iso8601_datetime.copy()
|
||||||
dt_expr.setParseAction(pyparsing_common.convertToDatetime())
|
dt_expr.set_parse_action(pyparsing_common.convert_to_datetime())
|
||||||
print(dt_expr.parseString("1999-12-31T23:59:59.999"))
|
print(dt_expr.parse_string("1999-12-31T23:59:59.999"))
|
||||||
|
|
||||||
prints::
|
prints::
|
||||||
|
|
||||||
|
@ -326,9 +326,9 @@ class pyparsing_common:
|
||||||
|
|
||||||
# strip HTML links from normal text
|
# strip HTML links from normal text
|
||||||
text = '<td>More info at the <a href="https://github.com/pyparsing/pyparsing/wiki">pyparsing</a> wiki page</td>'
|
text = '<td>More info at the <a href="https://github.com/pyparsing/pyparsing/wiki">pyparsing</a> wiki page</td>'
|
||||||
td, td_end = makeHTMLTags("TD")
|
td, td_end = make_html_tags("TD")
|
||||||
table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end
|
table_text = td + SkipTo(td_end).set_parse_action(pyparsing_common.strip_html_tags)("body") + td_end
|
||||||
print(table_text.parseString(text).body)
|
print(table_text.parse_string(text).body)
|
||||||
|
|
||||||
Prints::
|
Prints::
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ class pyparsing_common:
|
||||||
.streamline()
|
.streamline()
|
||||||
.set_name("commaItem")
|
.set_name("commaItem")
|
||||||
)
|
)
|
||||||
comma_separated_list = delimited_list(
|
comma_separated_list = DelimitedList(
|
||||||
Opt(quoted_string.copy() | _commasepitem, default="")
|
Opt(quoted_string.copy() | _commasepitem, default="")
|
||||||
).set_name("comma separated list")
|
).set_name("comma separated list")
|
||||||
"""Predefined expression of 1 or more printable words or quoted strings, separated by commas."""
|
"""Predefined expression of 1 or more printable words or quoted strings, separated by commas."""
|
||||||
|
@ -363,7 +363,7 @@ class pyparsing_common:
|
||||||
url = Regex(
|
url = Regex(
|
||||||
# https://mathiasbynens.be/demo/url-regex
|
# https://mathiasbynens.be/demo/url-regex
|
||||||
# https://gist.github.com/dperini/729294
|
# https://gist.github.com/dperini/729294
|
||||||
r"^" +
|
r"(?P<url>" +
|
||||||
# protocol identifier (optional)
|
# protocol identifier (optional)
|
||||||
# short syntax // still required
|
# short syntax // still required
|
||||||
r"(?:(?:(?P<scheme>https?|ftp):)?\/\/)" +
|
r"(?:(?:(?P<scheme>https?|ftp):)?\/\/)" +
|
||||||
|
@ -405,18 +405,26 @@ class pyparsing_common:
|
||||||
r"(\?(?P<query>[^#]*))?" +
|
r"(\?(?P<query>[^#]*))?" +
|
||||||
# fragment (optional)
|
# fragment (optional)
|
||||||
r"(#(?P<fragment>\S*))?" +
|
r"(#(?P<fragment>\S*))?" +
|
||||||
r"$"
|
r")"
|
||||||
).set_name("url")
|
).set_name("url")
|
||||||
|
"""URL (http/https/ftp scheme)"""
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
# pre-PEP8 compatibility names
|
# pre-PEP8 compatibility names
|
||||||
convertToInteger = convert_to_integer
|
convertToInteger = convert_to_integer
|
||||||
|
"""Deprecated - use :class:`convert_to_integer`"""
|
||||||
convertToFloat = convert_to_float
|
convertToFloat = convert_to_float
|
||||||
|
"""Deprecated - use :class:`convert_to_float`"""
|
||||||
convertToDate = convert_to_date
|
convertToDate = convert_to_date
|
||||||
|
"""Deprecated - use :class:`convert_to_date`"""
|
||||||
convertToDatetime = convert_to_datetime
|
convertToDatetime = convert_to_datetime
|
||||||
|
"""Deprecated - use :class:`convert_to_datetime`"""
|
||||||
stripHTMLTags = strip_html_tags
|
stripHTMLTags = strip_html_tags
|
||||||
|
"""Deprecated - use :class:`strip_html_tags`"""
|
||||||
upcaseTokens = upcase_tokens
|
upcaseTokens = upcase_tokens
|
||||||
|
"""Deprecated - use :class:`upcase_tokens`"""
|
||||||
downcaseTokens = downcase_tokens
|
downcaseTokens = downcase_tokens
|
||||||
|
"""Deprecated - use :class:`downcase_tokens`"""
|
||||||
|
|
||||||
|
|
||||||
_builtin_exprs = [
|
_builtin_exprs = [
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,4 @@
|
||||||
|
# mypy: ignore-errors
|
||||||
import railroad
|
import railroad
|
||||||
import pyparsing
|
import pyparsing
|
||||||
import typing
|
import typing
|
||||||
|
@ -17,11 +18,13 @@ import inspect
|
||||||
|
|
||||||
|
|
||||||
jinja2_template_source = """\
|
jinja2_template_source = """\
|
||||||
|
{% if not embed %}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
{% endif %}
|
||||||
{% if not head %}
|
{% if not head %}
|
||||||
<style type="text/css">
|
<style>
|
||||||
.railroad-heading {
|
.railroad-heading {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
@ -29,8 +32,10 @@ jinja2_template_source = """\
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ head | safe }}
|
{{ head | safe }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if not embed %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
{% endif %}
|
||||||
{{ body | safe }}
|
{{ body | safe }}
|
||||||
{% for diagram in diagrams %}
|
{% for diagram in diagrams %}
|
||||||
<div class="railroad-group">
|
<div class="railroad-group">
|
||||||
|
@ -41,8 +46,10 @@ jinja2_template_source = """\
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% if not embed %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
{% endif %}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
template = Template(jinja2_template_source)
|
template = Template(jinja2_template_source)
|
||||||
|
@ -127,7 +134,7 @@ class EditablePartial(Generic[T]):
|
||||||
return self.func(*args, **kwargs)
|
return self.func(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def railroad_to_html(diagrams: List[NamedDiagram], **kwargs) -> str:
|
def railroad_to_html(diagrams: List[NamedDiagram], embed=False, **kwargs) -> str:
|
||||||
"""
|
"""
|
||||||
Given a list of NamedDiagram, produce a single HTML string that visualises those diagrams
|
Given a list of NamedDiagram, produce a single HTML string that visualises those diagrams
|
||||||
:params kwargs: kwargs to be passed in to the template
|
:params kwargs: kwargs to be passed in to the template
|
||||||
|
@ -137,13 +144,17 @@ def railroad_to_html(diagrams: List[NamedDiagram], **kwargs) -> str:
|
||||||
if diagram.diagram is None:
|
if diagram.diagram is None:
|
||||||
continue
|
continue
|
||||||
io = StringIO()
|
io = StringIO()
|
||||||
|
try:
|
||||||
|
css = kwargs.get('css')
|
||||||
|
diagram.diagram.writeStandalone(io.write, css=css)
|
||||||
|
except AttributeError:
|
||||||
diagram.diagram.writeSvg(io.write)
|
diagram.diagram.writeSvg(io.write)
|
||||||
title = diagram.name
|
title = diagram.name
|
||||||
if diagram.index == 0:
|
if diagram.index == 0:
|
||||||
title += " (root)"
|
title += " (root)"
|
||||||
data.append({"title": title, "text": "", "svg": io.getvalue()})
|
data.append({"title": title, "text": "", "svg": io.getvalue()})
|
||||||
|
|
||||||
return template.render(diagrams=data, **kwargs)
|
return template.render(diagrams=data, embed=embed, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def resolve_partial(partial: "EditablePartial[T]") -> T:
|
def resolve_partial(partial: "EditablePartial[T]") -> T:
|
||||||
|
@ -398,7 +409,6 @@ def _apply_diagram_item_enhancements(fn):
|
||||||
show_results_names: bool = False,
|
show_results_names: bool = False,
|
||||||
show_groups: bool = False,
|
show_groups: bool = False,
|
||||||
) -> typing.Optional[EditablePartial]:
|
) -> typing.Optional[EditablePartial]:
|
||||||
|
|
||||||
ret = fn(
|
ret = fn(
|
||||||
element,
|
element,
|
||||||
parent,
|
parent,
|
||||||
|
@ -555,9 +565,11 @@ def _to_diagram_element(
|
||||||
else:
|
else:
|
||||||
ret = EditablePartial.from_call(railroad.Group, label="", item="")
|
ret = EditablePartial.from_call(railroad.Group, label="", item="")
|
||||||
elif isinstance(element, pyparsing.TokenConverter):
|
elif isinstance(element, pyparsing.TokenConverter):
|
||||||
ret = EditablePartial.from_call(
|
label = type(element).__name__.lower()
|
||||||
AnnotatedItem, label=type(element).__name__.lower(), item=""
|
if label == "tokenconverter":
|
||||||
)
|
ret = EditablePartial.from_call(railroad.Sequence, items=[])
|
||||||
|
else:
|
||||||
|
ret = EditablePartial.from_call(AnnotatedItem, label=label, item="")
|
||||||
elif isinstance(element, pyparsing.Opt):
|
elif isinstance(element, pyparsing.Opt):
|
||||||
ret = EditablePartial.from_call(railroad.Optional, item="")
|
ret = EditablePartial.from_call(railroad.Optional, item="")
|
||||||
elif isinstance(element, pyparsing.OneOrMore):
|
elif isinstance(element, pyparsing.OneOrMore):
|
||||||
|
@ -571,10 +583,12 @@ def _to_diagram_element(
|
||||||
elif isinstance(element, pyparsing.Empty) and not element.customName:
|
elif isinstance(element, pyparsing.Empty) and not element.customName:
|
||||||
# Skip unnamed "Empty" elements
|
# Skip unnamed "Empty" elements
|
||||||
ret = None
|
ret = None
|
||||||
elif len(exprs) > 1:
|
elif isinstance(element, pyparsing.ParseElementEnhance):
|
||||||
ret = EditablePartial.from_call(railroad.Sequence, items=[])
|
ret = EditablePartial.from_call(railroad.Sequence, items=[])
|
||||||
elif len(exprs) > 0 and not element_results_name:
|
elif len(exprs) > 0 and not element_results_name:
|
||||||
ret = EditablePartial.from_call(railroad.Group, item="", label=name)
|
ret = EditablePartial.from_call(railroad.Group, item="", label=name)
|
||||||
|
elif len(exprs) > 0:
|
||||||
|
ret = EditablePartial.from_call(railroad.Sequence, items=[])
|
||||||
else:
|
else:
|
||||||
terminal = EditablePartial.from_call(railroad.Terminal, element.defaultName)
|
terminal = EditablePartial.from_call(railroad.Terminal, element.defaultName)
|
||||||
ret = terminal
|
ret = terminal
|
||||||
|
|
|
@ -4,7 +4,13 @@ import re
|
||||||
import sys
|
import sys
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from .util import col, line, lineno, _collapse_string_to_ranges
|
from .util import (
|
||||||
|
col,
|
||||||
|
line,
|
||||||
|
lineno,
|
||||||
|
_collapse_string_to_ranges,
|
||||||
|
replaced_by_pep8,
|
||||||
|
)
|
||||||
from .unicode import pyparsing_unicode as ppu
|
from .unicode import pyparsing_unicode as ppu
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,6 +25,20 @@ _exception_word_extractor = re.compile("([" + _extract_alphanums + "]{1,16})|.")
|
||||||
class ParseBaseException(Exception):
|
class ParseBaseException(Exception):
|
||||||
"""base exception class for all parsing runtime exceptions"""
|
"""base exception class for all parsing runtime exceptions"""
|
||||||
|
|
||||||
|
loc: int
|
||||||
|
msg: str
|
||||||
|
pstr: str
|
||||||
|
parser_element: typing.Any # "ParserElement"
|
||||||
|
args: typing.Tuple[str, int, typing.Optional[str]]
|
||||||
|
|
||||||
|
__slots__ = (
|
||||||
|
"loc",
|
||||||
|
"msg",
|
||||||
|
"pstr",
|
||||||
|
"parser_element",
|
||||||
|
"args",
|
||||||
|
)
|
||||||
|
|
||||||
# Performance tuning: we construct a *lot* of these, so keep this
|
# Performance tuning: we construct a *lot* of these, so keep this
|
||||||
# constructor as small and fast as possible
|
# constructor as small and fast as possible
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -35,7 +55,7 @@ class ParseBaseException(Exception):
|
||||||
else:
|
else:
|
||||||
self.msg = msg
|
self.msg = msg
|
||||||
self.pstr = pstr
|
self.pstr = pstr
|
||||||
self.parser_element = self.parserElement = elem
|
self.parser_element = elem
|
||||||
self.args = (pstr, loc, msg)
|
self.args = (pstr, loc, msg)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -64,7 +84,7 @@ class ParseBaseException(Exception):
|
||||||
if isinstance(exc, ParseBaseException):
|
if isinstance(exc, ParseBaseException):
|
||||||
ret.append(exc.line)
|
ret.append(exc.line)
|
||||||
ret.append(" " * (exc.column - 1) + "^")
|
ret.append(" " * (exc.column - 1) + "^")
|
||||||
ret.append("{}: {}".format(type(exc).__name__, exc))
|
ret.append(f"{type(exc).__name__}: {exc}")
|
||||||
|
|
||||||
if depth > 0:
|
if depth > 0:
|
||||||
callers = inspect.getinnerframes(exc.__traceback__, context=depth)
|
callers = inspect.getinnerframes(exc.__traceback__, context=depth)
|
||||||
|
@ -74,7 +94,9 @@ class ParseBaseException(Exception):
|
||||||
|
|
||||||
f_self = frm.f_locals.get("self", None)
|
f_self = frm.f_locals.get("self", None)
|
||||||
if isinstance(f_self, ParserElement):
|
if isinstance(f_self, ParserElement):
|
||||||
if frm.f_code.co_name not in ("parseImpl", "_parseNoCache"):
|
if not frm.f_code.co_name.startswith(
|
||||||
|
("parseImpl", "_parseNoCache")
|
||||||
|
):
|
||||||
continue
|
continue
|
||||||
if id(f_self) in seen:
|
if id(f_self) in seen:
|
||||||
continue
|
continue
|
||||||
|
@ -82,21 +104,19 @@ class ParseBaseException(Exception):
|
||||||
|
|
||||||
self_type = type(f_self)
|
self_type = type(f_self)
|
||||||
ret.append(
|
ret.append(
|
||||||
"{}.{} - {}".format(
|
f"{self_type.__module__}.{self_type.__name__} - {f_self}"
|
||||||
self_type.__module__, self_type.__name__, f_self
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
elif f_self is not None:
|
elif f_self is not None:
|
||||||
self_type = type(f_self)
|
self_type = type(f_self)
|
||||||
ret.append("{}.{}".format(self_type.__module__, self_type.__name__))
|
ret.append(f"{self_type.__module__}.{self_type.__name__}")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
code = frm.f_code
|
code = frm.f_code
|
||||||
if code.co_name in ("wrapper", "<module>"):
|
if code.co_name in ("wrapper", "<module>"):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
ret.append("{}".format(code.co_name))
|
ret.append(code.co_name)
|
||||||
|
|
||||||
depth -= 1
|
depth -= 1
|
||||||
if not depth:
|
if not depth:
|
||||||
|
@ -110,7 +130,7 @@ class ParseBaseException(Exception):
|
||||||
internal factory method to simplify creating one type of ParseException
|
internal factory method to simplify creating one type of ParseException
|
||||||
from another - avoids having __init__ signature conflicts among subclasses
|
from another - avoids having __init__ signature conflicts among subclasses
|
||||||
"""
|
"""
|
||||||
return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement)
|
return cls(pe.pstr, pe.loc, pe.msg, pe.parser_element)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def line(self) -> str:
|
def line(self) -> str:
|
||||||
|
@ -140,6 +160,15 @@ class ParseBaseException(Exception):
|
||||||
"""
|
"""
|
||||||
return col(self.loc, self.pstr)
|
return col(self.loc, self.pstr)
|
||||||
|
|
||||||
|
# pre-PEP8 compatibility
|
||||||
|
@property
|
||||||
|
def parserElement(self):
|
||||||
|
return self.parser_element
|
||||||
|
|
||||||
|
@parserElement.setter
|
||||||
|
def parserElement(self, elem):
|
||||||
|
self.parser_element = elem
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
if self.pstr:
|
if self.pstr:
|
||||||
if self.loc >= len(self.pstr):
|
if self.loc >= len(self.pstr):
|
||||||
|
@ -154,14 +183,14 @@ class ParseBaseException(Exception):
|
||||||
foundstr = (", found %r" % found).replace(r"\\", "\\")
|
foundstr = (", found %r" % found).replace(r"\\", "\\")
|
||||||
else:
|
else:
|
||||||
foundstr = ""
|
foundstr = ""
|
||||||
return "{}{} (at char {}), (line:{}, col:{})".format(
|
return f"{self.msg}{foundstr} (at char {self.loc}), (line:{self.lineno}, col:{self.column})"
|
||||||
self.msg, foundstr, self.loc, self.lineno, self.column
|
|
||||||
)
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return str(self)
|
return str(self)
|
||||||
|
|
||||||
def mark_input_line(self, marker_string: str = None, *, markerString=">!<") -> str:
|
def mark_input_line(
|
||||||
|
self, marker_string: typing.Optional[str] = None, *, markerString: str = ">!<"
|
||||||
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Extracts the exception line from the input string, and marks
|
Extracts the exception line from the input string, and marks
|
||||||
the location of the exception with a special symbol.
|
the location of the exception with a special symbol.
|
||||||
|
@ -214,7 +243,10 @@ class ParseBaseException(Exception):
|
||||||
"""
|
"""
|
||||||
return self.explain_exception(self, depth)
|
return self.explain_exception(self, depth)
|
||||||
|
|
||||||
markInputline = mark_input_line
|
# fmt: off
|
||||||
|
@replaced_by_pep8(mark_input_line)
|
||||||
|
def markInputline(self): ...
|
||||||
|
# fmt: on
|
||||||
|
|
||||||
|
|
||||||
class ParseException(ParseBaseException):
|
class ParseException(ParseBaseException):
|
||||||
|
@ -264,4 +296,4 @@ class RecursiveGrammarException(Exception):
|
||||||
self.parseElementTrace = parseElementList
|
self.parseElementTrace = parseElementList
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return "RecursiveGrammarException: {}".format(self.parseElementTrace)
|
return f"RecursiveGrammarException: {self.parseElementTrace}"
|
||||||
|
|
|
@ -1,73 +1,22 @@
|
||||||
# helpers.py
|
# helpers.py
|
||||||
import html.entities
|
import html.entities
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from . import __diag__
|
from . import __diag__
|
||||||
from .core import *
|
from .core import *
|
||||||
from .util import _bslash, _flatten, _escape_regex_range_chars
|
from .util import (
|
||||||
|
_bslash,
|
||||||
|
_flatten,
|
||||||
|
_escape_regex_range_chars,
|
||||||
|
replaced_by_pep8,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# global helpers
|
# global helpers
|
||||||
#
|
#
|
||||||
def delimited_list(
|
|
||||||
expr: Union[str, ParserElement],
|
|
||||||
delim: Union[str, ParserElement] = ",",
|
|
||||||
combine: bool = False,
|
|
||||||
min: typing.Optional[int] = None,
|
|
||||||
max: typing.Optional[int] = None,
|
|
||||||
*,
|
|
||||||
allow_trailing_delim: bool = False,
|
|
||||||
) -> ParserElement:
|
|
||||||
"""Helper to define a delimited list of expressions - the delimiter
|
|
||||||
defaults to ','. By default, the list elements and delimiters can
|
|
||||||
have intervening whitespace, and comments, but this can be
|
|
||||||
overridden by passing ``combine=True`` in the constructor. If
|
|
||||||
``combine`` is set to ``True``, the matching tokens are
|
|
||||||
returned as a single token string, with the delimiters included;
|
|
||||||
otherwise, the matching tokens are returned as a list of tokens,
|
|
||||||
with the delimiters suppressed.
|
|
||||||
|
|
||||||
If ``allow_trailing_delim`` is set to True, then the list may end with
|
|
||||||
a delimiter.
|
|
||||||
|
|
||||||
Example::
|
|
||||||
|
|
||||||
delimited_list(Word(alphas)).parse_string("aa,bb,cc") # -> ['aa', 'bb', 'cc']
|
|
||||||
delimited_list(Word(hexnums), delim=':', combine=True).parse_string("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE']
|
|
||||||
"""
|
|
||||||
if isinstance(expr, str_type):
|
|
||||||
expr = ParserElement._literalStringClass(expr)
|
|
||||||
|
|
||||||
dlName = "{expr} [{delim} {expr}]...{end}".format(
|
|
||||||
expr=str(expr.copy().streamline()),
|
|
||||||
delim=str(delim),
|
|
||||||
end=" [{}]".format(str(delim)) if allow_trailing_delim else "",
|
|
||||||
)
|
|
||||||
|
|
||||||
if not combine:
|
|
||||||
delim = Suppress(delim)
|
|
||||||
|
|
||||||
if min is not None:
|
|
||||||
if min < 1:
|
|
||||||
raise ValueError("min must be greater than 0")
|
|
||||||
min -= 1
|
|
||||||
if max is not None:
|
|
||||||
if min is not None and max <= min:
|
|
||||||
raise ValueError("max must be greater than, or equal to min")
|
|
||||||
max -= 1
|
|
||||||
delimited_list_expr = expr + (delim + expr)[min, max]
|
|
||||||
|
|
||||||
if allow_trailing_delim:
|
|
||||||
delimited_list_expr += Opt(delim)
|
|
||||||
|
|
||||||
if combine:
|
|
||||||
return Combine(delimited_list_expr).set_name(dlName)
|
|
||||||
else:
|
|
||||||
return delimited_list_expr.set_name(dlName)
|
|
||||||
|
|
||||||
|
|
||||||
def counted_array(
|
def counted_array(
|
||||||
expr: ParserElement,
|
expr: ParserElement,
|
||||||
int_expr: typing.Optional[ParserElement] = None,
|
int_expr: typing.Optional[ParserElement] = None,
|
||||||
|
@ -187,7 +136,7 @@ def match_previous_expr(expr: ParserElement) -> ParserElement:
|
||||||
theseTokens = _flatten(t.as_list())
|
theseTokens = _flatten(t.as_list())
|
||||||
if theseTokens != matchTokens:
|
if theseTokens != matchTokens:
|
||||||
raise ParseException(
|
raise ParseException(
|
||||||
s, l, "Expected {}, found{}".format(matchTokens, theseTokens)
|
s, l, f"Expected {matchTokens}, found{theseTokens}"
|
||||||
)
|
)
|
||||||
|
|
||||||
rep.set_parse_action(must_match_these_tokens, callDuringTry=True)
|
rep.set_parse_action(must_match_these_tokens, callDuringTry=True)
|
||||||
|
@ -218,7 +167,7 @@ def one_of(
|
||||||
- ``caseless`` - treat all literals as caseless - (default= ``False``)
|
- ``caseless`` - treat all literals as caseless - (default= ``False``)
|
||||||
- ``use_regex`` - as an optimization, will
|
- ``use_regex`` - as an optimization, will
|
||||||
generate a :class:`Regex` object; otherwise, will generate
|
generate a :class:`Regex` object; otherwise, will generate
|
||||||
a :class:`MatchFirst` object (if ``caseless=True`` or ``asKeyword=True``, or if
|
a :class:`MatchFirst` object (if ``caseless=True`` or ``as_keyword=True``, or if
|
||||||
creating a :class:`Regex` raises an exception) - (default= ``True``)
|
creating a :class:`Regex` raises an exception) - (default= ``True``)
|
||||||
- ``as_keyword`` - enforce :class:`Keyword`-style matching on the
|
- ``as_keyword`` - enforce :class:`Keyword`-style matching on the
|
||||||
generated expressions - (default= ``False``)
|
generated expressions - (default= ``False``)
|
||||||
|
@ -262,6 +211,7 @@ def one_of(
|
||||||
|
|
||||||
symbols: List[str] = []
|
symbols: List[str] = []
|
||||||
if isinstance(strs, str_type):
|
if isinstance(strs, str_type):
|
||||||
|
strs = typing.cast(str, strs)
|
||||||
symbols = strs.split()
|
symbols = strs.split()
|
||||||
elif isinstance(strs, Iterable):
|
elif isinstance(strs, Iterable):
|
||||||
symbols = list(strs)
|
symbols = list(strs)
|
||||||
|
@ -293,15 +243,13 @@ def one_of(
|
||||||
try:
|
try:
|
||||||
if all(len(sym) == 1 for sym in symbols):
|
if all(len(sym) == 1 for sym in symbols):
|
||||||
# symbols are just single characters, create range regex pattern
|
# symbols are just single characters, create range regex pattern
|
||||||
patt = "[{}]".format(
|
patt = f"[{''.join(_escape_regex_range_chars(sym) for sym in symbols)}]"
|
||||||
"".join(_escape_regex_range_chars(sym) for sym in symbols)
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
patt = "|".join(re.escape(sym) for sym in symbols)
|
patt = "|".join(re.escape(sym) for sym in symbols)
|
||||||
|
|
||||||
# wrap with \b word break markers if defining as keywords
|
# wrap with \b word break markers if defining as keywords
|
||||||
if asKeyword:
|
if asKeyword:
|
||||||
patt = r"\b(?:{})\b".format(patt)
|
patt = rf"\b(?:{patt})\b"
|
||||||
|
|
||||||
ret = Regex(patt, flags=re_flags).set_name(" | ".join(symbols))
|
ret = Regex(patt, flags=re_flags).set_name(" | ".join(symbols))
|
||||||
|
|
||||||
|
@ -371,7 +319,7 @@ def original_text_for(
|
||||||
expression. Useful to restore the parsed fields of an HTML start
|
expression. Useful to restore the parsed fields of an HTML start
|
||||||
tag into the raw tag text itself, or to revert separate tokens with
|
tag into the raw tag text itself, or to revert separate tokens with
|
||||||
intervening whitespace back to the original matching input text. By
|
intervening whitespace back to the original matching input text. By
|
||||||
default, returns astring containing the original parsed text.
|
default, returns a string containing the original parsed text.
|
||||||
|
|
||||||
If the optional ``as_string`` argument is passed as
|
If the optional ``as_string`` argument is passed as
|
||||||
``False``, then the return value is
|
``False``, then the return value is
|
||||||
|
@ -390,7 +338,7 @@ def original_text_for(
|
||||||
src = "this is test <b> bold <i>text</i> </b> normal text "
|
src = "this is test <b> bold <i>text</i> </b> normal text "
|
||||||
for tag in ("b", "i"):
|
for tag in ("b", "i"):
|
||||||
opener, closer = make_html_tags(tag)
|
opener, closer = make_html_tags(tag)
|
||||||
patt = original_text_for(opener + SkipTo(closer) + closer)
|
patt = original_text_for(opener + ... + closer)
|
||||||
print(patt.search_string(src)[0])
|
print(patt.search_string(src)[0])
|
||||||
|
|
||||||
prints::
|
prints::
|
||||||
|
@ -426,7 +374,7 @@ def ungroup(expr: ParserElement) -> ParserElement:
|
||||||
|
|
||||||
def locatedExpr(expr: ParserElement) -> ParserElement:
|
def locatedExpr(expr: ParserElement) -> ParserElement:
|
||||||
"""
|
"""
|
||||||
(DEPRECATED - future code should use the Located class)
|
(DEPRECATED - future code should use the :class:`Located` class)
|
||||||
Helper to decorate a returned token with its starting and ending
|
Helper to decorate a returned token with its starting and ending
|
||||||
locations in the input string.
|
locations in the input string.
|
||||||
|
|
||||||
|
@ -437,12 +385,12 @@ def locatedExpr(expr: ParserElement) -> ParserElement:
|
||||||
- ``value`` - the actual parsed results
|
- ``value`` - the actual parsed results
|
||||||
|
|
||||||
Be careful if the input text contains ``<TAB>`` characters, you
|
Be careful if the input text contains ``<TAB>`` characters, you
|
||||||
may want to call :class:`ParserElement.parseWithTabs`
|
may want to call :class:`ParserElement.parse_with_tabs`
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
wd = Word(alphas)
|
wd = Word(alphas)
|
||||||
for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"):
|
for match in locatedExpr(wd).search_string("ljsdf123lksdjjf123lkkjj1222"):
|
||||||
print(match)
|
print(match)
|
||||||
|
|
||||||
prints::
|
prints::
|
||||||
|
@ -471,6 +419,7 @@ def nested_expr(
|
||||||
closing delimiters (``"("`` and ``")"`` are the default).
|
closing delimiters (``"("`` and ``")"`` are the default).
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
- ``opener`` - opening character for a nested list
|
- ``opener`` - opening character for a nested list
|
||||||
(default= ``"("``); can also be a pyparsing expression
|
(default= ``"("``); can also be a pyparsing expression
|
||||||
- ``closer`` - closing character for a nested list
|
- ``closer`` - closing character for a nested list
|
||||||
|
@ -507,7 +456,7 @@ def nested_expr(
|
||||||
|
|
||||||
c_function = (decl_data_type("type")
|
c_function = (decl_data_type("type")
|
||||||
+ ident("name")
|
+ ident("name")
|
||||||
+ LPAR + Opt(delimited_list(arg), [])("args") + RPAR
|
+ LPAR + Opt(DelimitedList(arg), [])("args") + RPAR
|
||||||
+ code_body("body"))
|
+ code_body("body"))
|
||||||
c_function.ignore(c_style_comment)
|
c_function.ignore(c_style_comment)
|
||||||
|
|
||||||
|
@ -539,6 +488,8 @@ def nested_expr(
|
||||||
raise ValueError("opening and closing strings cannot be the same")
|
raise ValueError("opening and closing strings cannot be the same")
|
||||||
if content is None:
|
if content is None:
|
||||||
if isinstance(opener, str_type) and isinstance(closer, str_type):
|
if isinstance(opener, str_type) and isinstance(closer, str_type):
|
||||||
|
opener = typing.cast(str, opener)
|
||||||
|
closer = typing.cast(str, closer)
|
||||||
if len(opener) == 1 and len(closer) == 1:
|
if len(opener) == 1 and len(closer) == 1:
|
||||||
if ignoreExpr is not None:
|
if ignoreExpr is not None:
|
||||||
content = Combine(
|
content = Combine(
|
||||||
|
@ -695,12 +646,15 @@ common_html_entity = Regex("&(?P<entity>" + "|".join(_htmlEntityMap) + ");").set
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def replace_html_entity(t):
|
def replace_html_entity(s, l, t):
|
||||||
"""Helper parser action to replace common HTML entities with their special characters"""
|
"""Helper parser action to replace common HTML entities with their special characters"""
|
||||||
return _htmlEntityMap.get(t.entity)
|
return _htmlEntityMap.get(t.entity)
|
||||||
|
|
||||||
|
|
||||||
class OpAssoc(Enum):
|
class OpAssoc(Enum):
|
||||||
|
"""Enumeration of operator associativity
|
||||||
|
- used in constructing InfixNotationOperatorSpec for :class:`infix_notation`"""
|
||||||
|
|
||||||
LEFT = 1
|
LEFT = 1
|
||||||
RIGHT = 2
|
RIGHT = 2
|
||||||
|
|
||||||
|
@ -742,6 +696,7 @@ def infix_notation(
|
||||||
improve your parser performance.
|
improve your parser performance.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
- ``base_expr`` - expression representing the most basic operand to
|
- ``base_expr`` - expression representing the most basic operand to
|
||||||
be used in the expression
|
be used in the expression
|
||||||
- ``op_list`` - list of tuples, one for each operator precedence level
|
- ``op_list`` - list of tuples, one for each operator precedence level
|
||||||
|
@ -764,11 +719,11 @@ def infix_notation(
|
||||||
``set_parse_action(*fn)``
|
``set_parse_action(*fn)``
|
||||||
(:class:`ParserElement.set_parse_action`)
|
(:class:`ParserElement.set_parse_action`)
|
||||||
- ``lpar`` - expression for matching left-parentheses; if passed as a
|
- ``lpar`` - expression for matching left-parentheses; if passed as a
|
||||||
str, then will be parsed as Suppress(lpar). If lpar is passed as
|
str, then will be parsed as ``Suppress(lpar)``. If lpar is passed as
|
||||||
an expression (such as ``Literal('(')``), then it will be kept in
|
an expression (such as ``Literal('(')``), then it will be kept in
|
||||||
the parsed results, and grouped with them. (default= ``Suppress('(')``)
|
the parsed results, and grouped with them. (default= ``Suppress('(')``)
|
||||||
- ``rpar`` - expression for matching right-parentheses; if passed as a
|
- ``rpar`` - expression for matching right-parentheses; if passed as a
|
||||||
str, then will be parsed as Suppress(rpar). If rpar is passed as
|
str, then will be parsed as ``Suppress(rpar)``. If rpar is passed as
|
||||||
an expression (such as ``Literal(')')``), then it will be kept in
|
an expression (such as ``Literal(')')``), then it will be kept in
|
||||||
the parsed results, and grouped with them. (default= ``Suppress(')')``)
|
the parsed results, and grouped with them. (default= ``Suppress(')')``)
|
||||||
|
|
||||||
|
@ -800,9 +755,13 @@ def infix_notation(
|
||||||
(5+3)*6
|
(5+3)*6
|
||||||
[[[5, '+', 3], '*', 6]]
|
[[[5, '+', 3], '*', 6]]
|
||||||
|
|
||||||
|
(5+x)*y
|
||||||
|
[[[5, '+', 'x'], '*', 'y']]
|
||||||
|
|
||||||
-2--11
|
-2--11
|
||||||
[[['-', 2], '-', ['-', 11]]]
|
[[['-', 2], '-', ['-', 11]]]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# captive version of FollowedBy that does not do parse actions or capture results names
|
# captive version of FollowedBy that does not do parse actions or capture results names
|
||||||
class _FB(FollowedBy):
|
class _FB(FollowedBy):
|
||||||
def parseImpl(self, instring, loc, doActions=True):
|
def parseImpl(self, instring, loc, doActions=True):
|
||||||
|
@ -823,19 +782,25 @@ def infix_notation(
|
||||||
else:
|
else:
|
||||||
lastExpr = base_expr | (lpar + ret + rpar)
|
lastExpr = base_expr | (lpar + ret + rpar)
|
||||||
|
|
||||||
|
arity: int
|
||||||
|
rightLeftAssoc: opAssoc
|
||||||
|
pa: typing.Optional[ParseAction]
|
||||||
|
opExpr1: ParserElement
|
||||||
|
opExpr2: ParserElement
|
||||||
for i, operDef in enumerate(op_list):
|
for i, operDef in enumerate(op_list):
|
||||||
opExpr, arity, rightLeftAssoc, pa = (operDef + (None,))[:4]
|
opExpr, arity, rightLeftAssoc, pa = (operDef + (None,))[:4] # type: ignore[assignment]
|
||||||
if isinstance(opExpr, str_type):
|
if isinstance(opExpr, str_type):
|
||||||
opExpr = ParserElement._literalStringClass(opExpr)
|
opExpr = ParserElement._literalStringClass(opExpr)
|
||||||
|
opExpr = typing.cast(ParserElement, opExpr)
|
||||||
if arity == 3:
|
if arity == 3:
|
||||||
if not isinstance(opExpr, (tuple, list)) or len(opExpr) != 2:
|
if not isinstance(opExpr, (tuple, list)) or len(opExpr) != 2:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"if numterms=3, opExpr must be a tuple or list of two expressions"
|
"if numterms=3, opExpr must be a tuple or list of two expressions"
|
||||||
)
|
)
|
||||||
opExpr1, opExpr2 = opExpr
|
opExpr1, opExpr2 = opExpr
|
||||||
term_name = "{}{} term".format(opExpr1, opExpr2)
|
term_name = f"{opExpr1}{opExpr2} term"
|
||||||
else:
|
else:
|
||||||
term_name = "{} term".format(opExpr)
|
term_name = f"{opExpr} term"
|
||||||
|
|
||||||
if not 1 <= arity <= 3:
|
if not 1 <= arity <= 3:
|
||||||
raise ValueError("operator must be unary (1), binary (2), or ternary (3)")
|
raise ValueError("operator must be unary (1), binary (2), or ternary (3)")
|
||||||
|
@ -843,7 +808,8 @@ def infix_notation(
|
||||||
if rightLeftAssoc not in (OpAssoc.LEFT, OpAssoc.RIGHT):
|
if rightLeftAssoc not in (OpAssoc.LEFT, OpAssoc.RIGHT):
|
||||||
raise ValueError("operator must indicate right or left associativity")
|
raise ValueError("operator must indicate right or left associativity")
|
||||||
|
|
||||||
thisExpr: Forward = Forward().set_name(term_name)
|
thisExpr: ParserElement = Forward().set_name(term_name)
|
||||||
|
thisExpr = typing.cast(Forward, thisExpr)
|
||||||
if rightLeftAssoc is OpAssoc.LEFT:
|
if rightLeftAssoc is OpAssoc.LEFT:
|
||||||
if arity == 1:
|
if arity == 1:
|
||||||
matchExpr = _FB(lastExpr + opExpr) + Group(lastExpr + opExpr[1, ...])
|
matchExpr = _FB(lastExpr + opExpr) + Group(lastExpr + opExpr[1, ...])
|
||||||
|
@ -890,7 +856,7 @@ def infix_notation(
|
||||||
|
|
||||||
def indentedBlock(blockStatementExpr, indentStack, indent=True, backup_stacks=[]):
|
def indentedBlock(blockStatementExpr, indentStack, indent=True, backup_stacks=[]):
|
||||||
"""
|
"""
|
||||||
(DEPRECATED - use IndentedBlock class instead)
|
(DEPRECATED - use :class:`IndentedBlock` class instead)
|
||||||
Helper method for defining space-delimited indentation blocks,
|
Helper method for defining space-delimited indentation blocks,
|
||||||
such as those used to define block statements in Python source code.
|
such as those used to define block statements in Python source code.
|
||||||
|
|
||||||
|
@ -1063,22 +1029,28 @@ _builtin_exprs: List[ParserElement] = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# compatibility function, superseded by DelimitedList class
|
||||||
|
def delimited_list(
|
||||||
|
expr: Union[str, ParserElement],
|
||||||
|
delim: Union[str, ParserElement] = ",",
|
||||||
|
combine: bool = False,
|
||||||
|
min: typing.Optional[int] = None,
|
||||||
|
max: typing.Optional[int] = None,
|
||||||
|
*,
|
||||||
|
allow_trailing_delim: bool = False,
|
||||||
|
) -> ParserElement:
|
||||||
|
"""(DEPRECATED - use :class:`DelimitedList` class)"""
|
||||||
|
return DelimitedList(
|
||||||
|
expr, delim, combine, min, max, allow_trailing_delim=allow_trailing_delim
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# pre-PEP8 compatible names
|
# pre-PEP8 compatible names
|
||||||
delimitedList = delimited_list
|
# fmt: off
|
||||||
countedArray = counted_array
|
|
||||||
matchPreviousLiteral = match_previous_literal
|
|
||||||
matchPreviousExpr = match_previous_expr
|
|
||||||
oneOf = one_of
|
|
||||||
dictOf = dict_of
|
|
||||||
originalTextFor = original_text_for
|
|
||||||
nestedExpr = nested_expr
|
|
||||||
makeHTMLTags = make_html_tags
|
|
||||||
makeXMLTags = make_xml_tags
|
|
||||||
anyOpenTag, anyCloseTag = any_open_tag, any_close_tag
|
|
||||||
commonHTMLEntity = common_html_entity
|
|
||||||
replaceHTMLEntity = replace_html_entity
|
|
||||||
opAssoc = OpAssoc
|
opAssoc = OpAssoc
|
||||||
infixNotation = infix_notation
|
anyOpenTag = any_open_tag
|
||||||
|
anyCloseTag = any_close_tag
|
||||||
|
commonHTMLEntity = common_html_entity
|
||||||
cStyleComment = c_style_comment
|
cStyleComment = c_style_comment
|
||||||
htmlComment = html_comment
|
htmlComment = html_comment
|
||||||
restOfLine = rest_of_line
|
restOfLine = rest_of_line
|
||||||
|
@ -1086,3 +1058,43 @@ dblSlashComment = dbl_slash_comment
|
||||||
cppStyleComment = cpp_style_comment
|
cppStyleComment = cpp_style_comment
|
||||||
javaStyleComment = java_style_comment
|
javaStyleComment = java_style_comment
|
||||||
pythonStyleComment = python_style_comment
|
pythonStyleComment = python_style_comment
|
||||||
|
|
||||||
|
@replaced_by_pep8(DelimitedList)
|
||||||
|
def delimitedList(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(DelimitedList)
|
||||||
|
def delimited_list(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(counted_array)
|
||||||
|
def countedArray(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(match_previous_literal)
|
||||||
|
def matchPreviousLiteral(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(match_previous_expr)
|
||||||
|
def matchPreviousExpr(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(one_of)
|
||||||
|
def oneOf(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(dict_of)
|
||||||
|
def dictOf(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(original_text_for)
|
||||||
|
def originalTextFor(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(nested_expr)
|
||||||
|
def nestedExpr(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(make_html_tags)
|
||||||
|
def makeHTMLTags(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(make_xml_tags)
|
||||||
|
def makeXMLTags(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(replace_html_entity)
|
||||||
|
def replaceHTMLEntity(): ...
|
||||||
|
|
||||||
|
@replaced_by_pep8(infix_notation)
|
||||||
|
def infixNotation(): ...
|
||||||
|
# fmt: on
|
||||||
|
|
|
@ -1,18 +1,25 @@
|
||||||
# results.py
|
# results.py
|
||||||
from collections.abc import MutableMapping, Mapping, MutableSequence, Iterator
|
from collections.abc import (
|
||||||
|
MutableMapping,
|
||||||
|
Mapping,
|
||||||
|
MutableSequence,
|
||||||
|
Iterator,
|
||||||
|
Sequence,
|
||||||
|
Container,
|
||||||
|
)
|
||||||
import pprint
|
import pprint
|
||||||
from weakref import ref as wkref
|
from typing import Tuple, Any, Dict, Set, List
|
||||||
from typing import Tuple, Any
|
|
||||||
|
|
||||||
str_type: Tuple[type, ...] = (str, bytes)
|
str_type: Tuple[type, ...] = (str, bytes)
|
||||||
_generator_type = type((_ for _ in ()))
|
_generator_type = type((_ for _ in ()))
|
||||||
|
|
||||||
|
|
||||||
class _ParseResultsWithOffset:
|
class _ParseResultsWithOffset:
|
||||||
|
tup: Tuple["ParseResults", int]
|
||||||
__slots__ = ["tup"]
|
__slots__ = ["tup"]
|
||||||
|
|
||||||
def __init__(self, p1, p2):
|
def __init__(self, p1: "ParseResults", p2: int):
|
||||||
self.tup = (p1, p2)
|
self.tup: Tuple[ParseResults, int] = (p1, p2)
|
||||||
|
|
||||||
def __getitem__(self, i):
|
def __getitem__(self, i):
|
||||||
return self.tup[i]
|
return self.tup[i]
|
||||||
|
@ -47,7 +54,7 @@ class ParseResults:
|
||||||
result = date_str.parse_string("1999/12/31")
|
result = date_str.parse_string("1999/12/31")
|
||||||
|
|
||||||
def test(s, fn=repr):
|
def test(s, fn=repr):
|
||||||
print("{} -> {}".format(s, fn(eval(s))))
|
print(f"{s} -> {fn(eval(s))}")
|
||||||
test("list(result)")
|
test("list(result)")
|
||||||
test("result[0]")
|
test("result[0]")
|
||||||
test("result['month']")
|
test("result['month']")
|
||||||
|
@ -70,27 +77,33 @@ class ParseResults:
|
||||||
- year: '1999'
|
- year: '1999'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_null_values: Tuple[Any, ...] = (None, [], "", ())
|
_null_values: Tuple[Any, ...] = (None, [], ())
|
||||||
|
|
||||||
__slots__ = [
|
_name: str
|
||||||
|
_parent: "ParseResults"
|
||||||
|
_all_names: Set[str]
|
||||||
|
_modal: bool
|
||||||
|
_toklist: List[Any]
|
||||||
|
_tokdict: Dict[str, Any]
|
||||||
|
|
||||||
|
__slots__ = (
|
||||||
"_name",
|
"_name",
|
||||||
"_parent",
|
"_parent",
|
||||||
"_all_names",
|
"_all_names",
|
||||||
"_modal",
|
"_modal",
|
||||||
"_toklist",
|
"_toklist",
|
||||||
"_tokdict",
|
"_tokdict",
|
||||||
"__weakref__",
|
)
|
||||||
]
|
|
||||||
|
|
||||||
class List(list):
|
class List(list):
|
||||||
"""
|
"""
|
||||||
Simple wrapper class to distinguish parsed list results that should be preserved
|
Simple wrapper class to distinguish parsed list results that should be preserved
|
||||||
as actual Python lists, instead of being converted to :class:`ParseResults`:
|
as actual Python lists, instead of being converted to :class:`ParseResults`::
|
||||||
|
|
||||||
LBRACK, RBRACK = map(pp.Suppress, "[]")
|
LBRACK, RBRACK = map(pp.Suppress, "[]")
|
||||||
element = pp.Forward()
|
element = pp.Forward()
|
||||||
item = ppc.integer
|
item = ppc.integer
|
||||||
element_list = LBRACK + pp.delimited_list(element) + RBRACK
|
element_list = LBRACK + pp.DelimitedList(element) + RBRACK
|
||||||
|
|
||||||
# add parse actions to convert from ParseResults to actual Python collection types
|
# add parse actions to convert from ParseResults to actual Python collection types
|
||||||
def as_python_list(t):
|
def as_python_list(t):
|
||||||
|
@ -107,7 +120,7 @@ class ParseResults:
|
||||||
(2,3,4)
|
(2,3,4)
|
||||||
''', post_parse=lambda s, r: (r[0], type(r[0])))
|
''', post_parse=lambda s, r: (r[0], type(r[0])))
|
||||||
|
|
||||||
prints:
|
prints::
|
||||||
|
|
||||||
100
|
100
|
||||||
(100, <class 'int'>)
|
(100, <class 'int'>)
|
||||||
|
@ -127,8 +140,7 @@ class ParseResults:
|
||||||
|
|
||||||
if not isinstance(contained, list):
|
if not isinstance(contained, list):
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
"{} may only be constructed with a list,"
|
f"{cls.__name__} may only be constructed with a list, not {type(contained).__name__}"
|
||||||
" not {}".format(cls.__name__, type(contained).__name__)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return list.__new__(cls)
|
return list.__new__(cls)
|
||||||
|
@ -159,6 +171,7 @@ class ParseResults:
|
||||||
def __init__(
|
def __init__(
|
||||||
self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance
|
self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance
|
||||||
):
|
):
|
||||||
|
self._tokdict: Dict[str, _ParseResultsWithOffset]
|
||||||
self._modal = modal
|
self._modal = modal
|
||||||
if name is not None and name != "":
|
if name is not None and name != "":
|
||||||
if isinstance(name, int):
|
if isinstance(name, int):
|
||||||
|
@ -210,7 +223,7 @@ class ParseResults:
|
||||||
]
|
]
|
||||||
sub = v
|
sub = v
|
||||||
if isinstance(sub, ParseResults):
|
if isinstance(sub, ParseResults):
|
||||||
sub._parent = wkref(self)
|
sub._parent = self
|
||||||
|
|
||||||
def __delitem__(self, i):
|
def __delitem__(self, i):
|
||||||
if isinstance(i, (int, slice)):
|
if isinstance(i, (int, slice)):
|
||||||
|
@ -263,7 +276,7 @@ class ParseResults:
|
||||||
"""
|
"""
|
||||||
Since ``keys()`` returns an iterator, this method is helpful in bypassing
|
Since ``keys()`` returns an iterator, this method is helpful in bypassing
|
||||||
code that looks for the existence of any defined results names."""
|
code that looks for the existence of any defined results names."""
|
||||||
return bool(self._tokdict)
|
return not not self._tokdict
|
||||||
|
|
||||||
def pop(self, *args, **kwargs):
|
def pop(self, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -311,9 +324,7 @@ class ParseResults:
|
||||||
if k == "default":
|
if k == "default":
|
||||||
args = (args[0], v)
|
args = (args[0], v)
|
||||||
else:
|
else:
|
||||||
raise TypeError(
|
raise TypeError(f"pop() got an unexpected keyword argument {k!r}")
|
||||||
"pop() got an unexpected keyword argument {!r}".format(k)
|
|
||||||
)
|
|
||||||
if isinstance(args[0], int) or len(args) == 1 or args[0] in self:
|
if isinstance(args[0], int) or len(args) == 1 or args[0] in self:
|
||||||
index = args[0]
|
index = args[0]
|
||||||
ret = self[index]
|
ret = self[index]
|
||||||
|
@ -423,12 +434,15 @@ class ParseResults:
|
||||||
raise AttributeError(name)
|
raise AttributeError(name)
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def __add__(self, other) -> "ParseResults":
|
def __add__(self, other: "ParseResults") -> "ParseResults":
|
||||||
ret = self.copy()
|
ret = self.copy()
|
||||||
ret += other
|
ret += other
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def __iadd__(self, other) -> "ParseResults":
|
def __iadd__(self, other: "ParseResults") -> "ParseResults":
|
||||||
|
if not other:
|
||||||
|
return self
|
||||||
|
|
||||||
if other._tokdict:
|
if other._tokdict:
|
||||||
offset = len(self._toklist)
|
offset = len(self._toklist)
|
||||||
addoffset = lambda a: offset if a < 0 else a + offset
|
addoffset = lambda a: offset if a < 0 else a + offset
|
||||||
|
@ -441,7 +455,7 @@ class ParseResults:
|
||||||
for k, v in otherdictitems:
|
for k, v in otherdictitems:
|
||||||
self[k] = v
|
self[k] = v
|
||||||
if isinstance(v[0], ParseResults):
|
if isinstance(v[0], ParseResults):
|
||||||
v[0]._parent = wkref(self)
|
v[0]._parent = self
|
||||||
|
|
||||||
self._toklist += other._toklist
|
self._toklist += other._toklist
|
||||||
self._all_names |= other._all_names
|
self._all_names |= other._all_names
|
||||||
|
@ -456,7 +470,7 @@ class ParseResults:
|
||||||
return other + self
|
return other + self
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "{}({!r}, {})".format(type(self).__name__, self._toklist, self.as_dict())
|
return f"{type(self).__name__}({self._toklist!r}, {self.as_dict()})"
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return (
|
return (
|
||||||
|
@ -532,7 +546,10 @@ class ParseResults:
|
||||||
|
|
||||||
def copy(self) -> "ParseResults":
|
def copy(self) -> "ParseResults":
|
||||||
"""
|
"""
|
||||||
Returns a new copy of a :class:`ParseResults` object.
|
Returns a new shallow copy of a :class:`ParseResults` object. `ParseResults`
|
||||||
|
items contained within the source are shared with the copy. Use
|
||||||
|
:class:`ParseResults.deepcopy()` to create a copy with its own separate
|
||||||
|
content values.
|
||||||
"""
|
"""
|
||||||
ret = ParseResults(self._toklist)
|
ret = ParseResults(self._toklist)
|
||||||
ret._tokdict = self._tokdict.copy()
|
ret._tokdict = self._tokdict.copy()
|
||||||
|
@ -541,6 +558,27 @@ class ParseResults:
|
||||||
ret._name = self._name
|
ret._name = self._name
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def deepcopy(self) -> "ParseResults":
|
||||||
|
"""
|
||||||
|
Returns a new deep copy of a :class:`ParseResults` object.
|
||||||
|
"""
|
||||||
|
ret = self.copy()
|
||||||
|
# replace values with copies if they are of known mutable types
|
||||||
|
for i, obj in enumerate(self._toklist):
|
||||||
|
if isinstance(obj, ParseResults):
|
||||||
|
self._toklist[i] = obj.deepcopy()
|
||||||
|
elif isinstance(obj, (str, bytes)):
|
||||||
|
pass
|
||||||
|
elif isinstance(obj, MutableMapping):
|
||||||
|
self._toklist[i] = dest = type(obj)()
|
||||||
|
for k, v in obj.items():
|
||||||
|
dest[k] = v.deepcopy() if isinstance(v, ParseResults) else v
|
||||||
|
elif isinstance(obj, Container):
|
||||||
|
self._toklist[i] = type(obj)(
|
||||||
|
v.deepcopy() if isinstance(v, ParseResults) else v for v in obj
|
||||||
|
)
|
||||||
|
return ret
|
||||||
|
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
r"""
|
r"""
|
||||||
Returns the results name for this token expression. Useful when several
|
Returns the results name for this token expression. Useful when several
|
||||||
|
@ -569,20 +607,17 @@ class ParseResults:
|
||||||
if self._name:
|
if self._name:
|
||||||
return self._name
|
return self._name
|
||||||
elif self._parent:
|
elif self._parent:
|
||||||
par = self._parent()
|
par: "ParseResults" = self._parent
|
||||||
|
parent_tokdict_items = par._tokdict.items()
|
||||||
def find_in_parent(sub):
|
|
||||||
return next(
|
return next(
|
||||||
(
|
(
|
||||||
k
|
k
|
||||||
for k, vlist in par._tokdict.items()
|
for k, vlist in parent_tokdict_items
|
||||||
for v, loc in vlist
|
for v, loc in vlist
|
||||||
if sub is v
|
if v is self
|
||||||
),
|
),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
|
||||||
return find_in_parent(self) if par else None
|
|
||||||
elif (
|
elif (
|
||||||
len(self) == 1
|
len(self) == 1
|
||||||
and len(self._tokdict) == 1
|
and len(self._tokdict) == 1
|
||||||
|
@ -623,7 +658,7 @@ class ParseResults:
|
||||||
for k, v in items:
|
for k, v in items:
|
||||||
if out:
|
if out:
|
||||||
out.append(NL)
|
out.append(NL)
|
||||||
out.append("{}{}- {}: ".format(indent, (" " * _depth), k))
|
out.append(f"{indent}{(' ' * _depth)}- {k}: ")
|
||||||
if isinstance(v, ParseResults):
|
if isinstance(v, ParseResults):
|
||||||
if v:
|
if v:
|
||||||
out.append(
|
out.append(
|
||||||
|
@ -685,7 +720,7 @@ class ParseResults:
|
||||||
num = Word(nums)
|
num = Word(nums)
|
||||||
func = Forward()
|
func = Forward()
|
||||||
term = ident | num | Group('(' + func + ')')
|
term = ident | num | Group('(' + func + ')')
|
||||||
func <<= ident + Group(Optional(delimited_list(term)))
|
func <<= ident + Group(Optional(DelimitedList(term)))
|
||||||
result = func.parse_string("fna a,b,(fnb c,d,200),100")
|
result = func.parse_string("fna a,b,(fnb c,d,200),100")
|
||||||
result.pprint(width=40)
|
result.pprint(width=40)
|
||||||
|
|
||||||
|
@ -705,7 +740,7 @@ class ParseResults:
|
||||||
self._toklist,
|
self._toklist,
|
||||||
(
|
(
|
||||||
self._tokdict.copy(),
|
self._tokdict.copy(),
|
||||||
self._parent is not None and self._parent() or None,
|
None,
|
||||||
self._all_names,
|
self._all_names,
|
||||||
self._name,
|
self._name,
|
||||||
),
|
),
|
||||||
|
@ -714,9 +749,6 @@ class ParseResults:
|
||||||
def __setstate__(self, state):
|
def __setstate__(self, state):
|
||||||
self._toklist, (self._tokdict, par, inAccumNames, self._name) = state
|
self._toklist, (self._tokdict, par, inAccumNames, self._name) = state
|
||||||
self._all_names = set(inAccumNames)
|
self._all_names = set(inAccumNames)
|
||||||
if par is not None:
|
|
||||||
self._parent = wkref(par)
|
|
||||||
else:
|
|
||||||
self._parent = None
|
self._parent = None
|
||||||
|
|
||||||
def __getnewargs__(self):
|
def __getnewargs__(self):
|
||||||
|
@ -738,6 +770,7 @@ class ParseResults:
|
||||||
iter(obj)
|
iter(obj)
|
||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
# str's are iterable, but in pyparsing, we don't want to iterate over them
|
||||||
else:
|
else:
|
||||||
return not isinstance(obj, str_type)
|
return not isinstance(obj, str_type)
|
||||||
|
|
||||||
|
@ -752,8 +785,11 @@ class ParseResults:
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
asList = as_list
|
asList = as_list
|
||||||
|
"""Deprecated - use :class:`as_list`"""
|
||||||
asDict = as_dict
|
asDict = as_dict
|
||||||
|
"""Deprecated - use :class:`as_dict`"""
|
||||||
getName = get_name
|
getName = get_name
|
||||||
|
"""Deprecated - use :class:`get_name`"""
|
||||||
|
|
||||||
|
|
||||||
MutableMapping.register(ParseResults)
|
MutableMapping.register(ParseResults)
|
||||||
|
|
|
@ -222,7 +222,7 @@ class pyparsing_test:
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# warning here maybe?
|
# warning here maybe?
|
||||||
print("no validation for {!r}".format(test_string))
|
print(f"no validation for {test_string!r}")
|
||||||
|
|
||||||
# do this last, in case some specific test results can be reported instead
|
# do this last, in case some specific test results can be reported instead
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
|
@ -265,15 +265,18 @@ class pyparsing_test:
|
||||||
if expand_tabs:
|
if expand_tabs:
|
||||||
s = s.expandtabs()
|
s = s.expandtabs()
|
||||||
if mark_control is not None:
|
if mark_control is not None:
|
||||||
|
mark_control = typing.cast(str, mark_control)
|
||||||
if mark_control == "unicode":
|
if mark_control == "unicode":
|
||||||
tbl = str.maketrans(
|
transtable_map = {
|
||||||
{c: u for c, u in zip(range(0, 33), range(0x2400, 0x2433))}
|
c: u for c, u in zip(range(0, 33), range(0x2400, 0x2433))
|
||||||
| {127: 0x2421}
|
}
|
||||||
)
|
transtable_map[127] = 0x2421
|
||||||
|
tbl = str.maketrans(transtable_map)
|
||||||
eol_mark = ""
|
eol_mark = ""
|
||||||
else:
|
else:
|
||||||
|
ord_mark_control = ord(mark_control)
|
||||||
tbl = str.maketrans(
|
tbl = str.maketrans(
|
||||||
{c: mark_control for c in list(range(0, 32)) + [127]}
|
{c: ord_mark_control for c in list(range(0, 32)) + [127]}
|
||||||
)
|
)
|
||||||
s = s.translate(tbl)
|
s = s.translate(tbl)
|
||||||
if mark_spaces is not None and mark_spaces != " ":
|
if mark_spaces is not None and mark_spaces != " ":
|
||||||
|
@ -303,7 +306,7 @@ class pyparsing_test:
|
||||||
header0 = (
|
header0 = (
|
||||||
lead
|
lead
|
||||||
+ "".join(
|
+ "".join(
|
||||||
"{}{}".format(" " * 99, (i + 1) % 100)
|
f"{' ' * 99}{(i + 1) % 100}"
|
||||||
for i in range(max(max_line_len // 100, 1))
|
for i in range(max(max_line_len // 100, 1))
|
||||||
)
|
)
|
||||||
+ "\n"
|
+ "\n"
|
||||||
|
@ -313,10 +316,7 @@ class pyparsing_test:
|
||||||
header1 = (
|
header1 = (
|
||||||
header0
|
header0
|
||||||
+ lead
|
+ lead
|
||||||
+ "".join(
|
+ "".join(f" {(i + 1) % 10}" for i in range(-(-max_line_len // 10)))
|
||||||
" {}".format((i + 1) % 10)
|
|
||||||
for i in range(-(-max_line_len // 10))
|
|
||||||
)
|
|
||||||
+ "\n"
|
+ "\n"
|
||||||
)
|
)
|
||||||
header2 = lead + "1234567890" * (-(-max_line_len // 10)) + "\n"
|
header2 = lead + "1234567890" * (-(-max_line_len // 10)) + "\n"
|
||||||
|
@ -324,7 +324,7 @@ class pyparsing_test:
|
||||||
header1
|
header1
|
||||||
+ header2
|
+ header2
|
||||||
+ "\n".join(
|
+ "\n".join(
|
||||||
"{:{}d}:{}{}".format(i, lineno_width, line, eol_mark)
|
f"{i:{lineno_width}d}:{line}{eol_mark}"
|
||||||
for i, line in enumerate(s_lines, start=start_line)
|
for i, line in enumerate(s_lines, start=start_line)
|
||||||
)
|
)
|
||||||
+ "\n"
|
+ "\n"
|
||||||
|
|
|
@ -64,27 +64,27 @@ class unicode_set:
|
||||||
|
|
||||||
@_lazyclassproperty
|
@_lazyclassproperty
|
||||||
def printables(cls):
|
def printables(cls):
|
||||||
"all non-whitespace characters in this range"
|
"""all non-whitespace characters in this range"""
|
||||||
return "".join(filterfalse(str.isspace, cls._chars_for_ranges))
|
return "".join(filterfalse(str.isspace, cls._chars_for_ranges))
|
||||||
|
|
||||||
@_lazyclassproperty
|
@_lazyclassproperty
|
||||||
def alphas(cls):
|
def alphas(cls):
|
||||||
"all alphabetic characters in this range"
|
"""all alphabetic characters in this range"""
|
||||||
return "".join(filter(str.isalpha, cls._chars_for_ranges))
|
return "".join(filter(str.isalpha, cls._chars_for_ranges))
|
||||||
|
|
||||||
@_lazyclassproperty
|
@_lazyclassproperty
|
||||||
def nums(cls):
|
def nums(cls):
|
||||||
"all numeric digit characters in this range"
|
"""all numeric digit characters in this range"""
|
||||||
return "".join(filter(str.isdigit, cls._chars_for_ranges))
|
return "".join(filter(str.isdigit, cls._chars_for_ranges))
|
||||||
|
|
||||||
@_lazyclassproperty
|
@_lazyclassproperty
|
||||||
def alphanums(cls):
|
def alphanums(cls):
|
||||||
"all alphanumeric characters in this range"
|
"""all alphanumeric characters in this range"""
|
||||||
return cls.alphas + cls.nums
|
return cls.alphas + cls.nums
|
||||||
|
|
||||||
@_lazyclassproperty
|
@_lazyclassproperty
|
||||||
def identchars(cls):
|
def identchars(cls):
|
||||||
"all characters in this range that are valid identifier characters, plus underscore '_'"
|
"""all characters in this range that are valid identifier characters, plus underscore '_'"""
|
||||||
return "".join(
|
return "".join(
|
||||||
sorted(
|
sorted(
|
||||||
set(
|
set(
|
||||||
|
@ -100,13 +100,13 @@ class unicode_set:
|
||||||
def identbodychars(cls):
|
def identbodychars(cls):
|
||||||
"""
|
"""
|
||||||
all characters in this range that are valid identifier body characters,
|
all characters in this range that are valid identifier body characters,
|
||||||
plus the digits 0-9
|
plus the digits 0-9, and · (Unicode MIDDLE DOT)
|
||||||
"""
|
"""
|
||||||
return "".join(
|
return "".join(
|
||||||
sorted(
|
sorted(
|
||||||
set(
|
set(
|
||||||
cls.identchars
|
cls.identchars
|
||||||
+ "0123456789"
|
+ "0123456789·"
|
||||||
+ "".join(
|
+ "".join(
|
||||||
[c for c in cls._chars_for_ranges if ("_" + c).isidentifier()]
|
[c for c in cls._chars_for_ranges if ("_" + c).isidentifier()]
|
||||||
)
|
)
|
||||||
|
@ -114,6 +114,16 @@ class unicode_set:
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@_lazyclassproperty
|
||||||
|
def identifier(cls):
|
||||||
|
"""
|
||||||
|
a pyparsing Word expression for an identifier using this range's definitions for
|
||||||
|
identchars and identbodychars
|
||||||
|
"""
|
||||||
|
from pyparsing import Word
|
||||||
|
|
||||||
|
return Word(cls.identchars, cls.identbodychars)
|
||||||
|
|
||||||
|
|
||||||
class pyparsing_unicode(unicode_set):
|
class pyparsing_unicode(unicode_set):
|
||||||
"""
|
"""
|
||||||
|
@ -128,32 +138,32 @@ class pyparsing_unicode(unicode_set):
|
||||||
]
|
]
|
||||||
|
|
||||||
class BasicMultilingualPlane(unicode_set):
|
class BasicMultilingualPlane(unicode_set):
|
||||||
"Unicode set for the Basic Multilingual Plane"
|
"""Unicode set for the Basic Multilingual Plane"""
|
||||||
_ranges: UnicodeRangeList = [
|
_ranges: UnicodeRangeList = [
|
||||||
(0x0020, 0xFFFF),
|
(0x0020, 0xFFFF),
|
||||||
]
|
]
|
||||||
|
|
||||||
class Latin1(unicode_set):
|
class Latin1(unicode_set):
|
||||||
"Unicode set for Latin-1 Unicode Character Range"
|
"""Unicode set for Latin-1 Unicode Character Range"""
|
||||||
_ranges: UnicodeRangeList = [
|
_ranges: UnicodeRangeList = [
|
||||||
(0x0020, 0x007E),
|
(0x0020, 0x007E),
|
||||||
(0x00A0, 0x00FF),
|
(0x00A0, 0x00FF),
|
||||||
]
|
]
|
||||||
|
|
||||||
class LatinA(unicode_set):
|
class LatinA(unicode_set):
|
||||||
"Unicode set for Latin-A Unicode Character Range"
|
"""Unicode set for Latin-A Unicode Character Range"""
|
||||||
_ranges: UnicodeRangeList = [
|
_ranges: UnicodeRangeList = [
|
||||||
(0x0100, 0x017F),
|
(0x0100, 0x017F),
|
||||||
]
|
]
|
||||||
|
|
||||||
class LatinB(unicode_set):
|
class LatinB(unicode_set):
|
||||||
"Unicode set for Latin-B Unicode Character Range"
|
"""Unicode set for Latin-B Unicode Character Range"""
|
||||||
_ranges: UnicodeRangeList = [
|
_ranges: UnicodeRangeList = [
|
||||||
(0x0180, 0x024F),
|
(0x0180, 0x024F),
|
||||||
]
|
]
|
||||||
|
|
||||||
class Greek(unicode_set):
|
class Greek(unicode_set):
|
||||||
"Unicode set for Greek Unicode Character Ranges"
|
"""Unicode set for Greek Unicode Character Ranges"""
|
||||||
_ranges: UnicodeRangeList = [
|
_ranges: UnicodeRangeList = [
|
||||||
(0x0342, 0x0345),
|
(0x0342, 0x0345),
|
||||||
(0x0370, 0x0377),
|
(0x0370, 0x0377),
|
||||||
|
@ -193,7 +203,7 @@ class pyparsing_unicode(unicode_set):
|
||||||
]
|
]
|
||||||
|
|
||||||
class Cyrillic(unicode_set):
|
class Cyrillic(unicode_set):
|
||||||
"Unicode set for Cyrillic Unicode Character Range"
|
"""Unicode set for Cyrillic Unicode Character Range"""
|
||||||
_ranges: UnicodeRangeList = [
|
_ranges: UnicodeRangeList = [
|
||||||
(0x0400, 0x052F),
|
(0x0400, 0x052F),
|
||||||
(0x1C80, 0x1C88),
|
(0x1C80, 0x1C88),
|
||||||
|
@ -206,7 +216,7 @@ class pyparsing_unicode(unicode_set):
|
||||||
]
|
]
|
||||||
|
|
||||||
class Chinese(unicode_set):
|
class Chinese(unicode_set):
|
||||||
"Unicode set for Chinese Unicode Character Range"
|
"""Unicode set for Chinese Unicode Character Range"""
|
||||||
_ranges: UnicodeRangeList = [
|
_ranges: UnicodeRangeList = [
|
||||||
(0x2E80, 0x2E99),
|
(0x2E80, 0x2E99),
|
||||||
(0x2E9B, 0x2EF3),
|
(0x2E9B, 0x2EF3),
|
||||||
|
@ -229,8 +239,7 @@ class pyparsing_unicode(unicode_set):
|
||||||
]
|
]
|
||||||
|
|
||||||
class Japanese(unicode_set):
|
class Japanese(unicode_set):
|
||||||
"Unicode set for Japanese Unicode Character Range, combining Kanji, Hiragana, and Katakana ranges"
|
"""Unicode set for Japanese Unicode Character Range, combining Kanji, Hiragana, and Katakana ranges"""
|
||||||
_ranges: UnicodeRangeList = []
|
|
||||||
|
|
||||||
class Kanji(unicode_set):
|
class Kanji(unicode_set):
|
||||||
"Unicode set for Kanji Unicode Character Range"
|
"Unicode set for Kanji Unicode Character Range"
|
||||||
|
@ -240,7 +249,7 @@ class pyparsing_unicode(unicode_set):
|
||||||
]
|
]
|
||||||
|
|
||||||
class Hiragana(unicode_set):
|
class Hiragana(unicode_set):
|
||||||
"Unicode set for Hiragana Unicode Character Range"
|
"""Unicode set for Hiragana Unicode Character Range"""
|
||||||
_ranges: UnicodeRangeList = [
|
_ranges: UnicodeRangeList = [
|
||||||
(0x3041, 0x3096),
|
(0x3041, 0x3096),
|
||||||
(0x3099, 0x30A0),
|
(0x3099, 0x30A0),
|
||||||
|
@ -252,7 +261,7 @@ class pyparsing_unicode(unicode_set):
|
||||||
]
|
]
|
||||||
|
|
||||||
class Katakana(unicode_set):
|
class Katakana(unicode_set):
|
||||||
"Unicode set for Katakana Unicode Character Range"
|
"""Unicode set for Katakana Unicode Character Range"""
|
||||||
_ranges: UnicodeRangeList = [
|
_ranges: UnicodeRangeList = [
|
||||||
(0x3099, 0x309C),
|
(0x3099, 0x309C),
|
||||||
(0x30A0, 0x30FF),
|
(0x30A0, 0x30FF),
|
||||||
|
@ -265,8 +274,18 @@ class pyparsing_unicode(unicode_set):
|
||||||
(0x1F213,),
|
(0x1F213,),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
漢字 = Kanji
|
||||||
|
カタカナ = Katakana
|
||||||
|
ひらがな = Hiragana
|
||||||
|
|
||||||
|
_ranges = (
|
||||||
|
Kanji._ranges
|
||||||
|
+ Hiragana._ranges
|
||||||
|
+ Katakana._ranges
|
||||||
|
)
|
||||||
|
|
||||||
class Hangul(unicode_set):
|
class Hangul(unicode_set):
|
||||||
"Unicode set for Hangul (Korean) Unicode Character Range"
|
"""Unicode set for Hangul (Korean) Unicode Character Range"""
|
||||||
_ranges: UnicodeRangeList = [
|
_ranges: UnicodeRangeList = [
|
||||||
(0x1100, 0x11FF),
|
(0x1100, 0x11FF),
|
||||||
(0x302E, 0x302F),
|
(0x302E, 0x302F),
|
||||||
|
@ -288,17 +307,17 @@ class pyparsing_unicode(unicode_set):
|
||||||
Korean = Hangul
|
Korean = Hangul
|
||||||
|
|
||||||
class CJK(Chinese, Japanese, Hangul):
|
class CJK(Chinese, Japanese, Hangul):
|
||||||
"Unicode set for combined Chinese, Japanese, and Korean (CJK) Unicode Character Range"
|
"""Unicode set for combined Chinese, Japanese, and Korean (CJK) Unicode Character Range"""
|
||||||
|
|
||||||
class Thai(unicode_set):
|
class Thai(unicode_set):
|
||||||
"Unicode set for Thai Unicode Character Range"
|
"""Unicode set for Thai Unicode Character Range"""
|
||||||
_ranges: UnicodeRangeList = [
|
_ranges: UnicodeRangeList = [
|
||||||
(0x0E01, 0x0E3A),
|
(0x0E01, 0x0E3A),
|
||||||
(0x0E3F, 0x0E5B)
|
(0x0E3F, 0x0E5B)
|
||||||
]
|
]
|
||||||
|
|
||||||
class Arabic(unicode_set):
|
class Arabic(unicode_set):
|
||||||
"Unicode set for Arabic Unicode Character Range"
|
"""Unicode set for Arabic Unicode Character Range"""
|
||||||
_ranges: UnicodeRangeList = [
|
_ranges: UnicodeRangeList = [
|
||||||
(0x0600, 0x061B),
|
(0x0600, 0x061B),
|
||||||
(0x061E, 0x06FF),
|
(0x061E, 0x06FF),
|
||||||
|
@ -306,7 +325,7 @@ class pyparsing_unicode(unicode_set):
|
||||||
]
|
]
|
||||||
|
|
||||||
class Hebrew(unicode_set):
|
class Hebrew(unicode_set):
|
||||||
"Unicode set for Hebrew Unicode Character Range"
|
"""Unicode set for Hebrew Unicode Character Range"""
|
||||||
_ranges: UnicodeRangeList = [
|
_ranges: UnicodeRangeList = [
|
||||||
(0x0591, 0x05C7),
|
(0x0591, 0x05C7),
|
||||||
(0x05D0, 0x05EA),
|
(0x05D0, 0x05EA),
|
||||||
|
@ -320,33 +339,23 @@ class pyparsing_unicode(unicode_set):
|
||||||
]
|
]
|
||||||
|
|
||||||
class Devanagari(unicode_set):
|
class Devanagari(unicode_set):
|
||||||
"Unicode set for Devanagari Unicode Character Range"
|
"""Unicode set for Devanagari Unicode Character Range"""
|
||||||
_ranges: UnicodeRangeList = [
|
_ranges: UnicodeRangeList = [
|
||||||
(0x0900, 0x097F),
|
(0x0900, 0x097F),
|
||||||
(0xA8E0, 0xA8FF)
|
(0xA8E0, 0xA8FF)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
BMP = BasicMultilingualPlane
|
||||||
|
|
||||||
|
# add language identifiers using language Unicode
|
||||||
|
العربية = Arabic
|
||||||
|
中文 = Chinese
|
||||||
|
кириллица = Cyrillic
|
||||||
|
Ελληνικά = Greek
|
||||||
|
עִברִית = Hebrew
|
||||||
|
日本語 = Japanese
|
||||||
|
한국어 = Korean
|
||||||
|
ไทย = Thai
|
||||||
|
देवनागरी = Devanagari
|
||||||
|
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
|
|
||||||
pyparsing_unicode.Japanese._ranges = (
|
|
||||||
pyparsing_unicode.Japanese.Kanji._ranges
|
|
||||||
+ pyparsing_unicode.Japanese.Hiragana._ranges
|
|
||||||
+ pyparsing_unicode.Japanese.Katakana._ranges
|
|
||||||
)
|
|
||||||
|
|
||||||
pyparsing_unicode.BMP = pyparsing_unicode.BasicMultilingualPlane
|
|
||||||
|
|
||||||
# add language identifiers using language Unicode
|
|
||||||
pyparsing_unicode.العربية = pyparsing_unicode.Arabic
|
|
||||||
pyparsing_unicode.中文 = pyparsing_unicode.Chinese
|
|
||||||
pyparsing_unicode.кириллица = pyparsing_unicode.Cyrillic
|
|
||||||
pyparsing_unicode.Ελληνικά = pyparsing_unicode.Greek
|
|
||||||
pyparsing_unicode.עִברִית = pyparsing_unicode.Hebrew
|
|
||||||
pyparsing_unicode.日本語 = pyparsing_unicode.Japanese
|
|
||||||
pyparsing_unicode.Japanese.漢字 = pyparsing_unicode.Japanese.Kanji
|
|
||||||
pyparsing_unicode.Japanese.カタカナ = pyparsing_unicode.Japanese.Katakana
|
|
||||||
pyparsing_unicode.Japanese.ひらがな = pyparsing_unicode.Japanese.Hiragana
|
|
||||||
pyparsing_unicode.한국어 = pyparsing_unicode.Korean
|
|
||||||
pyparsing_unicode.ไทย = pyparsing_unicode.Thai
|
|
||||||
pyparsing_unicode.देवनागरी = pyparsing_unicode.Devanagari
|
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
# util.py
|
# util.py
|
||||||
|
import inspect
|
||||||
import warnings
|
import warnings
|
||||||
import types
|
import types
|
||||||
import collections
|
import collections
|
||||||
import itertools
|
import itertools
|
||||||
from functools import lru_cache
|
from functools import lru_cache, wraps
|
||||||
from typing import List, Union, Iterable
|
from typing import Callable, List, Union, Iterable, TypeVar, cast
|
||||||
|
|
||||||
_bslash = chr(92)
|
_bslash = chr(92)
|
||||||
|
C = TypeVar("C", bound=Callable)
|
||||||
|
|
||||||
|
|
||||||
class __config_flags:
|
class __config_flags:
|
||||||
|
@ -20,18 +22,15 @@ class __config_flags:
|
||||||
def _set(cls, dname, value):
|
def _set(cls, dname, value):
|
||||||
if dname in cls._fixed_names:
|
if dname in cls._fixed_names:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"{}.{} {} is {} and cannot be overridden".format(
|
f"{cls.__name__}.{dname} {cls._type_desc} is {str(getattr(cls, dname)).upper()}"
|
||||||
cls.__name__,
|
f" and cannot be overridden",
|
||||||
dname,
|
stacklevel=3,
|
||||||
cls._type_desc,
|
|
||||||
str(getattr(cls, dname)).upper(),
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
if dname in cls._all_names:
|
if dname in cls._all_names:
|
||||||
setattr(cls, dname, value)
|
setattr(cls, dname, value)
|
||||||
else:
|
else:
|
||||||
raise ValueError("no such {} {!r}".format(cls._type_desc, dname))
|
raise ValueError(f"no such {cls._type_desc} {dname!r}")
|
||||||
|
|
||||||
enable = classmethod(lambda cls, name: cls._set(name, True))
|
enable = classmethod(lambda cls, name: cls._set(name, True))
|
||||||
disable = classmethod(lambda cls, name: cls._set(name, False))
|
disable = classmethod(lambda cls, name: cls._set(name, False))
|
||||||
|
@ -45,7 +44,7 @@ def col(loc: int, strg: str) -> int:
|
||||||
|
|
||||||
Note: the default parsing behavior is to expand tabs in the input string
|
Note: the default parsing behavior is to expand tabs in the input string
|
||||||
before starting the parsing process. See
|
before starting the parsing process. See
|
||||||
:class:`ParserElement.parseString` for more
|
:class:`ParserElement.parse_string` for more
|
||||||
information on parsing strings containing ``<TAB>`` s, and suggested
|
information on parsing strings containing ``<TAB>`` s, and suggested
|
||||||
methods to maintain a consistent view of the parsed string, the parse
|
methods to maintain a consistent view of the parsed string, the parse
|
||||||
location, and line and column positions within the parsed string.
|
location, and line and column positions within the parsed string.
|
||||||
|
@ -60,7 +59,7 @@ def lineno(loc: int, strg: str) -> int:
|
||||||
The first line is number 1.
|
The first line is number 1.
|
||||||
|
|
||||||
Note - the default parsing behavior is to expand tabs in the input string
|
Note - the default parsing behavior is to expand tabs in the input string
|
||||||
before starting the parsing process. See :class:`ParserElement.parseString`
|
before starting the parsing process. See :class:`ParserElement.parse_string`
|
||||||
for more information on parsing strings containing ``<TAB>`` s, and
|
for more information on parsing strings containing ``<TAB>`` s, and
|
||||||
suggested methods to maintain a consistent view of the parsed string, the
|
suggested methods to maintain a consistent view of the parsed string, the
|
||||||
parse location, and line and column positions within the parsed string.
|
parse location, and line and column positions within the parsed string.
|
||||||
|
@ -102,19 +101,24 @@ class _UnboundedCache:
|
||||||
class _FifoCache:
|
class _FifoCache:
|
||||||
def __init__(self, size):
|
def __init__(self, size):
|
||||||
self.not_in_cache = not_in_cache = object()
|
self.not_in_cache = not_in_cache = object()
|
||||||
cache = collections.OrderedDict()
|
cache = {}
|
||||||
|
keyring = [object()] * size
|
||||||
cache_get = cache.get
|
cache_get = cache.get
|
||||||
|
cache_pop = cache.pop
|
||||||
|
keyiter = itertools.cycle(range(size))
|
||||||
|
|
||||||
def get(_, key):
|
def get(_, key):
|
||||||
return cache_get(key, not_in_cache)
|
return cache_get(key, not_in_cache)
|
||||||
|
|
||||||
def set_(_, key, value):
|
def set_(_, key, value):
|
||||||
cache[key] = value
|
cache[key] = value
|
||||||
while len(cache) > size:
|
i = next(keyiter)
|
||||||
cache.popitem(last=False)
|
cache_pop(keyring[i], None)
|
||||||
|
keyring[i] = key
|
||||||
|
|
||||||
def clear(_):
|
def clear(_):
|
||||||
cache.clear()
|
cache.clear()
|
||||||
|
keyring[:] = [object()] * size
|
||||||
|
|
||||||
self.size = size
|
self.size = size
|
||||||
self.get = types.MethodType(get, self)
|
self.get = types.MethodType(get, self)
|
||||||
|
@ -189,9 +193,9 @@ def _collapse_string_to_ranges(
|
||||||
is_consecutive.value = next(is_consecutive.counter)
|
is_consecutive.value = next(is_consecutive.counter)
|
||||||
return is_consecutive.value
|
return is_consecutive.value
|
||||||
|
|
||||||
is_consecutive.prev = 0
|
is_consecutive.prev = 0 # type: ignore [attr-defined]
|
||||||
is_consecutive.counter = itertools.count()
|
is_consecutive.counter = itertools.count() # type: ignore [attr-defined]
|
||||||
is_consecutive.value = -1
|
is_consecutive.value = -1 # type: ignore [attr-defined]
|
||||||
|
|
||||||
def escape_re_range_char(c):
|
def escape_re_range_char(c):
|
||||||
return "\\" + c if c in r"\^-][" else c
|
return "\\" + c if c in r"\^-][" else c
|
||||||
|
@ -215,9 +219,7 @@ def _collapse_string_to_ranges(
|
||||||
else:
|
else:
|
||||||
sep = "" if ord(last) == ord(first) + 1 else "-"
|
sep = "" if ord(last) == ord(first) + 1 else "-"
|
||||||
ret.append(
|
ret.append(
|
||||||
"{}{}{}".format(
|
f"{escape_re_range_char(first)}{sep}{escape_re_range_char(last)}"
|
||||||
escape_re_range_char(first), sep, escape_re_range_char(last)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
ret = [escape_re_range_char(c) for c in s]
|
ret = [escape_re_range_char(c) for c in s]
|
||||||
|
@ -233,3 +235,50 @@ def _flatten(ll: list) -> list:
|
||||||
else:
|
else:
|
||||||
ret.append(i)
|
ret.append(i)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def _make_synonym_function(compat_name: str, fn: C) -> C:
|
||||||
|
# In a future version, uncomment the code in the internal _inner() functions
|
||||||
|
# to begin emitting DeprecationWarnings.
|
||||||
|
|
||||||
|
# Unwrap staticmethod/classmethod
|
||||||
|
fn = getattr(fn, "__func__", fn)
|
||||||
|
|
||||||
|
# (Presence of 'self' arg in signature is used by explain_exception() methods, so we take
|
||||||
|
# some extra steps to add it if present in decorated function.)
|
||||||
|
if "self" == list(inspect.signature(fn).parameters)[0]:
|
||||||
|
|
||||||
|
@wraps(fn)
|
||||||
|
def _inner(self, *args, **kwargs):
|
||||||
|
# warnings.warn(
|
||||||
|
# f"Deprecated - use {fn.__name__}", DeprecationWarning, stacklevel=3
|
||||||
|
# )
|
||||||
|
return fn(self, *args, **kwargs)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
@wraps(fn)
|
||||||
|
def _inner(*args, **kwargs):
|
||||||
|
# warnings.warn(
|
||||||
|
# f"Deprecated - use {fn.__name__}", DeprecationWarning, stacklevel=3
|
||||||
|
# )
|
||||||
|
return fn(*args, **kwargs)
|
||||||
|
|
||||||
|
_inner.__doc__ = f"""Deprecated - use :class:`{fn.__name__}`"""
|
||||||
|
_inner.__name__ = compat_name
|
||||||
|
_inner.__annotations__ = fn.__annotations__
|
||||||
|
if isinstance(fn, types.FunctionType):
|
||||||
|
_inner.__kwdefaults__ = fn.__kwdefaults__
|
||||||
|
elif isinstance(fn, type) and hasattr(fn, "__init__"):
|
||||||
|
_inner.__kwdefaults__ = fn.__init__.__kwdefaults__
|
||||||
|
else:
|
||||||
|
_inner.__kwdefaults__ = None
|
||||||
|
_inner.__qualname__ = fn.__qualname__
|
||||||
|
return cast(C, _inner)
|
||||||
|
|
||||||
|
|
||||||
|
def replaced_by_pep8(fn: C) -> Callable[[Callable], C]:
|
||||||
|
"""
|
||||||
|
Decorator for pre-PEP8 compatibility synonyms, to link them to the new function.
|
||||||
|
"""
|
||||||
|
return lambda other: _make_synonym_function(other.__name__, fn)
|
||||||
|
|
|
@ -32,7 +32,7 @@ plexapi==4.13.4
|
||||||
portend==3.2.0
|
portend==3.2.0
|
||||||
profilehooks==1.12.0
|
profilehooks==1.12.0
|
||||||
PyJWT==2.8.0
|
PyJWT==2.8.0
|
||||||
pyparsing==3.0.9
|
pyparsing==3.1.1
|
||||||
python-dateutil==2.8.2
|
python-dateutil==2.8.2
|
||||||
python-twitter==3.5
|
python-twitter==3.5
|
||||||
pytz==2023.3
|
pytz==2023.3
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue