mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-06 13:11:15 -07:00
Bump pyparsing from 3.0.7 to 3.0.9 (#1741)
* Bump pyparsing from 3.0.7 to 3.0.9 Bumps [pyparsing](https://github.com/pyparsing/pyparsing) from 3.0.7 to 3.0.9. - [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.7...pyparsing_3.0.9) --- updated-dependencies: - dependency-name: pyparsing dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Update pyparsing==3.0.9 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
93b6370759
commit
d17015de44
12 changed files with 322 additions and 232 deletions
|
@ -1,6 +1,6 @@
|
||||||
# module pyparsing.py
|
# module pyparsing.py
|
||||||
#
|
#
|
||||||
# Copyright (c) 2003-2021 Paul T. McGuire
|
# Copyright (c) 2003-2022 Paul T. McGuire
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||||||
# a copy of this software and associated documentation files (the
|
# a copy of this software and associated documentation files (the
|
||||||
|
@ -105,14 +105,17 @@ class version_info(NamedTuple):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def __version__(self):
|
def __version__(self):
|
||||||
return "{}.{}.{}".format(self.major, self.minor, self.micro) + (
|
return (
|
||||||
"{}{}{}".format(
|
"{}.{}.{}".format(self.major, self.minor, self.micro)
|
||||||
"r" if self.releaselevel[0] == "c" else "",
|
+ (
|
||||||
self.releaselevel[0],
|
"{}{}{}".format(
|
||||||
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 "{} {} / {}".format(__name__, self.__version__, __version_time__)
|
||||||
|
@ -125,8 +128,8 @@ class version_info(NamedTuple):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
__version_info__ = version_info(3, 0, 7, "final", 0)
|
__version_info__ = version_info(3, 0, 9, "final", 0)
|
||||||
__version_time__ = "15 Jan 2022 04:10 UTC"
|
__version_time__ = "05 May 2022 07:02 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>"
|
||||||
|
|
|
@ -55,7 +55,7 @@ def replace_with(repl_str):
|
||||||
na = one_of("N/A NA").set_parse_action(replace_with(math.nan))
|
na = one_of("N/A NA").set_parse_action(replace_with(math.nan))
|
||||||
term = na | num
|
term = na | num
|
||||||
|
|
||||||
OneOrMore(term).parse_string("324 234 N/A 234") # -> [324, 234, nan, 234]
|
term[1, ...].parse_string("324 234 N/A 234") # -> [324, 234, nan, 234]
|
||||||
"""
|
"""
|
||||||
return lambda s, l, t: [repl_str]
|
return lambda s, l, t: [repl_str]
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
# core.py
|
# core.py
|
||||||
#
|
#
|
||||||
import os
|
import os
|
||||||
|
import typing
|
||||||
from typing import (
|
from typing import (
|
||||||
Optional as OptionalType,
|
|
||||||
Iterable as IterableType,
|
|
||||||
NamedTuple,
|
NamedTuple,
|
||||||
Union,
|
Union,
|
||||||
Callable,
|
Callable,
|
||||||
|
@ -14,7 +13,6 @@ from typing import (
|
||||||
List,
|
List,
|
||||||
TextIO,
|
TextIO,
|
||||||
Set,
|
Set,
|
||||||
Dict as DictType,
|
|
||||||
Sequence,
|
Sequence,
|
||||||
)
|
)
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
@ -23,7 +21,6 @@ import string
|
||||||
import copy
|
import copy
|
||||||
import warnings
|
import warnings
|
||||||
import re
|
import re
|
||||||
import sre_constants
|
|
||||||
import sys
|
import sys
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
import traceback
|
import traceback
|
||||||
|
@ -53,7 +50,7 @@ _MAX_INT = sys.maxsize
|
||||||
str_type: Tuple[type, ...] = (str, bytes)
|
str_type: Tuple[type, ...] = (str, bytes)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2003-2021 Paul T. McGuire
|
# Copyright (c) 2003-2022 Paul T. McGuire
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||||||
# a copy of this software and associated documentation files (the
|
# a copy of this software and associated documentation files (the
|
||||||
|
@ -76,6 +73,19 @@ str_type: Tuple[type, ...] = (str, bytes)
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
|
if sys.version_info >= (3, 8):
|
||||||
|
from functools import cached_property
|
||||||
|
else:
|
||||||
|
|
||||||
|
class cached_property:
|
||||||
|
def __init__(self, func):
|
||||||
|
self._func = func
|
||||||
|
|
||||||
|
def __get__(self, instance, owner=None):
|
||||||
|
ret = instance.__dict__[self._func.__name__] = self._func(instance)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class __compat__(__config_flags):
|
class __compat__(__config_flags):
|
||||||
"""
|
"""
|
||||||
A cross-version compatibility configuration for pyparsing features that will be
|
A cross-version compatibility configuration for pyparsing features that will be
|
||||||
|
@ -180,7 +190,7 @@ del __config_flags
|
||||||
|
|
||||||
|
|
||||||
def _should_enable_warnings(
|
def _should_enable_warnings(
|
||||||
cmd_line_warn_options: IterableType[str], warn_env_var: OptionalType[str]
|
cmd_line_warn_options: typing.Iterable[str], warn_env_var: typing.Optional[str]
|
||||||
) -> bool:
|
) -> bool:
|
||||||
enable = bool(warn_env_var)
|
enable = bool(warn_env_var)
|
||||||
for warn_opt in cmd_line_warn_options:
|
for warn_opt in cmd_line_warn_options:
|
||||||
|
@ -246,10 +256,10 @@ hexnums = nums + "ABCDEFabcdef"
|
||||||
alphanums = alphas + nums
|
alphanums = alphas + nums
|
||||||
printables = "".join([c for c in string.printable if c not in string.whitespace])
|
printables = "".join([c for c in string.printable if c not in string.whitespace])
|
||||||
|
|
||||||
_trim_arity_call_line = None
|
_trim_arity_call_line: traceback.StackSummary = None
|
||||||
|
|
||||||
|
|
||||||
def _trim_arity(func, maxargs=2):
|
def _trim_arity(func, max_limit=3):
|
||||||
"""decorator to trim function calls to match the arity of the target"""
|
"""decorator to trim function calls to match the arity of the target"""
|
||||||
global _trim_arity_call_line
|
global _trim_arity_call_line
|
||||||
|
|
||||||
|
@ -267,16 +277,12 @@ def _trim_arity(func, maxargs=2):
|
||||||
# synthesize what would be returned by traceback.extract_stack at the call to
|
# synthesize what would be returned by traceback.extract_stack at the call to
|
||||||
# user's parse action 'func', so that we don't incur call penalty at parse time
|
# user's parse action 'func', so that we don't incur call penalty at parse time
|
||||||
|
|
||||||
LINE_DIFF = 11
|
# fmt: off
|
||||||
|
LINE_DIFF = 7
|
||||||
# IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND
|
# IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND
|
||||||
# THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!!
|
# THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!!
|
||||||
_trim_arity_call_line = (
|
_trim_arity_call_line = (_trim_arity_call_line or traceback.extract_stack(limit=2)[-1])
|
||||||
_trim_arity_call_line or traceback.extract_stack(limit=2)[-1]
|
pa_call_line_synth = (_trim_arity_call_line[0], _trim_arity_call_line[1] + LINE_DIFF)
|
||||||
)
|
|
||||||
pa_call_line_synth = (
|
|
||||||
_trim_arity_call_line[0],
|
|
||||||
_trim_arity_call_line[1] + LINE_DIFF,
|
|
||||||
)
|
|
||||||
|
|
||||||
def wrapper(*args):
|
def wrapper(*args):
|
||||||
nonlocal found_arity, limit
|
nonlocal found_arity, limit
|
||||||
|
@ -297,16 +303,18 @@ def _trim_arity(func, maxargs=2):
|
||||||
del tb
|
del tb
|
||||||
|
|
||||||
if trim_arity_type_error:
|
if trim_arity_type_error:
|
||||||
if limit <= maxargs:
|
if limit < max_limit:
|
||||||
limit += 1
|
limit += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
raise
|
raise
|
||||||
|
# fmt: on
|
||||||
|
|
||||||
# copy func name to wrapper for sensible debug output
|
# copy func name to wrapper for sensible debug output
|
||||||
# (can't use functools.wraps, since that messes with function signature)
|
# (can't use functools.wraps, since that messes with function signature)
|
||||||
func_name = getattr(func, "__name__", getattr(func, "__class__").__name__)
|
func_name = getattr(func, "__name__", getattr(func, "__class__").__name__)
|
||||||
wrapper.__name__ = func_name
|
wrapper.__name__ = func_name
|
||||||
|
wrapper.__doc__ = func.__doc__
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
@ -394,7 +402,7 @@ class ParserElement(ABC):
|
||||||
|
|
||||||
DEFAULT_WHITE_CHARS: str = " \n\t\r"
|
DEFAULT_WHITE_CHARS: str = " \n\t\r"
|
||||||
verbose_stacktrace: bool = False
|
verbose_stacktrace: bool = False
|
||||||
_literalStringClass: OptionalType[type] = None
|
_literalStringClass: typing.Optional[type] = None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def set_default_whitespace_chars(chars: str) -> None:
|
def set_default_whitespace_chars(chars: str) -> None:
|
||||||
|
@ -404,11 +412,11 @@ class ParserElement(ABC):
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
# default whitespace chars are space, <TAB> and newline
|
# default whitespace chars are space, <TAB> and newline
|
||||||
OneOrMore(Word(alphas)).parse_string("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl']
|
Word(alphas)[1, ...].parse_string("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl']
|
||||||
|
|
||||||
# change to just treat newline as significant
|
# change to just treat newline as significant
|
||||||
ParserElement.set_default_whitespace_chars(" \t")
|
ParserElement.set_default_whitespace_chars(" \t")
|
||||||
OneOrMore(Word(alphas)).parse_string("abc def\nghi jkl") # -> ['abc', 'def']
|
Word(alphas)[1, ...].parse_string("abc def\nghi jkl") # -> ['abc', 'def']
|
||||||
"""
|
"""
|
||||||
ParserElement.DEFAULT_WHITE_CHARS = chars
|
ParserElement.DEFAULT_WHITE_CHARS = chars
|
||||||
|
|
||||||
|
@ -440,13 +448,13 @@ class ParserElement(ABC):
|
||||||
ParserElement._literalStringClass = cls
|
ParserElement._literalStringClass = cls
|
||||||
|
|
||||||
class DebugActions(NamedTuple):
|
class DebugActions(NamedTuple):
|
||||||
debug_try: OptionalType[DebugStartAction]
|
debug_try: typing.Optional[DebugStartAction]
|
||||||
debug_match: OptionalType[DebugSuccessAction]
|
debug_match: typing.Optional[DebugSuccessAction]
|
||||||
debug_fail: OptionalType[DebugExceptionAction]
|
debug_fail: typing.Optional[DebugExceptionAction]
|
||||||
|
|
||||||
def __init__(self, savelist: bool = False):
|
def __init__(self, savelist: bool = False):
|
||||||
self.parseAction: List[ParseAction] = list()
|
self.parseAction: List[ParseAction] = list()
|
||||||
self.failAction: OptionalType[ParseFailAction] = None
|
self.failAction: typing.Optional[ParseFailAction] = None
|
||||||
self.customName = None
|
self.customName = None
|
||||||
self._defaultName = None
|
self._defaultName = None
|
||||||
self.resultsName = None
|
self.resultsName = None
|
||||||
|
@ -467,7 +475,6 @@ class ParserElement(ABC):
|
||||||
self.modalResults = True
|
self.modalResults = True
|
||||||
# custom debug actions
|
# custom debug actions
|
||||||
self.debugActions = self.DebugActions(None, None, None)
|
self.debugActions = self.DebugActions(None, None, None)
|
||||||
self.re = None
|
|
||||||
# avoid redundant calls to preParse
|
# avoid redundant calls to preParse
|
||||||
self.callPreparse = True
|
self.callPreparse = True
|
||||||
self.callDuringTry = False
|
self.callDuringTry = False
|
||||||
|
@ -501,7 +508,7 @@ class ParserElement(ABC):
|
||||||
integerK = integer.copy().add_parse_action(lambda toks: toks[0] * 1024) + Suppress("K")
|
integerK = integer.copy().add_parse_action(lambda toks: toks[0] * 1024) + Suppress("K")
|
||||||
integerM = integer.copy().add_parse_action(lambda toks: toks[0] * 1024 * 1024) + Suppress("M")
|
integerM = integer.copy().add_parse_action(lambda toks: toks[0] * 1024 * 1024) + Suppress("M")
|
||||||
|
|
||||||
print(OneOrMore(integerK | integerM | integer).parse_string("5K 100 640K 256M"))
|
print((integerK | integerM | integer)[1, ...].parse_string("5K 100 640K 256M"))
|
||||||
|
|
||||||
prints::
|
prints::
|
||||||
|
|
||||||
|
@ -886,7 +893,7 @@ class ParserElement(ABC):
|
||||||
|
|
||||||
# cache for left-recursion in Forward references
|
# cache for left-recursion in Forward references
|
||||||
recursion_lock = RLock()
|
recursion_lock = RLock()
|
||||||
recursion_memos: DictType[
|
recursion_memos: typing.Dict[
|
||||||
Tuple[int, "Forward", bool], Tuple[int, Union[ParseResults, Exception]]
|
Tuple[int, "Forward", bool], Tuple[int, Union[ParseResults, Exception]]
|
||||||
] = {}
|
] = {}
|
||||||
|
|
||||||
|
@ -976,7 +983,7 @@ class ParserElement(ABC):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def enable_left_recursion(
|
def enable_left_recursion(
|
||||||
cache_size_limit: OptionalType[int] = None, *, force=False
|
cache_size_limit: typing.Optional[int] = None, *, force=False
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Enables "bounded recursion" parsing, which allows for both direct and indirect
|
Enables "bounded recursion" parsing, which allows for both direct and indirect
|
||||||
|
@ -1342,7 +1349,7 @@ class ParserElement(ABC):
|
||||||
last = e
|
last = e
|
||||||
yield instring[last:]
|
yield instring[last:]
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other) -> "ParserElement":
|
||||||
"""
|
"""
|
||||||
Implementation of ``+`` operator - returns :class:`And`. Adding strings to a :class:`ParserElement`
|
Implementation of ``+`` operator - returns :class:`And`. Adding strings to a :class:`ParserElement`
|
||||||
converts them to :class:`Literal`s by default.
|
converts them to :class:`Literal`s by default.
|
||||||
|
@ -1382,7 +1389,7 @@ class ParserElement(ABC):
|
||||||
)
|
)
|
||||||
return And([self, other])
|
return And([self, other])
|
||||||
|
|
||||||
def __radd__(self, other):
|
def __radd__(self, other) -> "ParserElement":
|
||||||
"""
|
"""
|
||||||
Implementation of ``+`` operator when left operand is not a :class:`ParserElement`
|
Implementation of ``+`` operator when left operand is not a :class:`ParserElement`
|
||||||
"""
|
"""
|
||||||
|
@ -1399,7 +1406,7 @@ class ParserElement(ABC):
|
||||||
)
|
)
|
||||||
return other + self
|
return other + self
|
||||||
|
|
||||||
def __sub__(self, other):
|
def __sub__(self, other) -> "ParserElement":
|
||||||
"""
|
"""
|
||||||
Implementation of ``-`` operator, returns :class:`And` with error stop
|
Implementation of ``-`` operator, returns :class:`And` with error stop
|
||||||
"""
|
"""
|
||||||
|
@ -1413,7 +1420,7 @@ class ParserElement(ABC):
|
||||||
)
|
)
|
||||||
return self + And._ErrorStop() + other
|
return self + And._ErrorStop() + other
|
||||||
|
|
||||||
def __rsub__(self, other):
|
def __rsub__(self, other) -> "ParserElement":
|
||||||
"""
|
"""
|
||||||
Implementation of ``-`` operator when left operand is not a :class:`ParserElement`
|
Implementation of ``-`` operator when left operand is not a :class:`ParserElement`
|
||||||
"""
|
"""
|
||||||
|
@ -1427,7 +1434,7 @@ class ParserElement(ABC):
|
||||||
)
|
)
|
||||||
return other - self
|
return other - self
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other) -> "ParserElement":
|
||||||
"""
|
"""
|
||||||
Implementation of ``*`` operator, allows use of ``expr * 3`` in place of
|
Implementation of ``*`` operator, allows use of ``expr * 3`` in place of
|
||||||
``expr + expr + expr``. Expressions may also be multiplied by a 2-integer
|
``expr + expr + expr``. Expressions may also be multiplied by a 2-integer
|
||||||
|
@ -1513,10 +1520,10 @@ class ParserElement(ABC):
|
||||||
ret = And([self] * minElements)
|
ret = And([self] * minElements)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def __rmul__(self, other):
|
def __rmul__(self, other) -> "ParserElement":
|
||||||
return self.__mul__(other)
|
return self.__mul__(other)
|
||||||
|
|
||||||
def __or__(self, other):
|
def __or__(self, other) -> "ParserElement":
|
||||||
"""
|
"""
|
||||||
Implementation of ``|`` operator - returns :class:`MatchFirst`
|
Implementation of ``|`` operator - returns :class:`MatchFirst`
|
||||||
"""
|
"""
|
||||||
|
@ -1533,7 +1540,7 @@ class ParserElement(ABC):
|
||||||
)
|
)
|
||||||
return MatchFirst([self, other])
|
return MatchFirst([self, other])
|
||||||
|
|
||||||
def __ror__(self, other):
|
def __ror__(self, other) -> "ParserElement":
|
||||||
"""
|
"""
|
||||||
Implementation of ``|`` operator when left operand is not a :class:`ParserElement`
|
Implementation of ``|`` operator when left operand is not a :class:`ParserElement`
|
||||||
"""
|
"""
|
||||||
|
@ -1547,7 +1554,7 @@ class ParserElement(ABC):
|
||||||
)
|
)
|
||||||
return other | self
|
return other | self
|
||||||
|
|
||||||
def __xor__(self, other):
|
def __xor__(self, other) -> "ParserElement":
|
||||||
"""
|
"""
|
||||||
Implementation of ``^`` operator - returns :class:`Or`
|
Implementation of ``^`` operator - returns :class:`Or`
|
||||||
"""
|
"""
|
||||||
|
@ -1561,7 +1568,7 @@ class ParserElement(ABC):
|
||||||
)
|
)
|
||||||
return Or([self, other])
|
return Or([self, other])
|
||||||
|
|
||||||
def __rxor__(self, other):
|
def __rxor__(self, other) -> "ParserElement":
|
||||||
"""
|
"""
|
||||||
Implementation of ``^`` operator when left operand is not a :class:`ParserElement`
|
Implementation of ``^`` operator when left operand is not a :class:`ParserElement`
|
||||||
"""
|
"""
|
||||||
|
@ -1575,7 +1582,7 @@ class ParserElement(ABC):
|
||||||
)
|
)
|
||||||
return other ^ self
|
return other ^ self
|
||||||
|
|
||||||
def __and__(self, other):
|
def __and__(self, other) -> "ParserElement":
|
||||||
"""
|
"""
|
||||||
Implementation of ``&`` operator - returns :class:`Each`
|
Implementation of ``&`` operator - returns :class:`Each`
|
||||||
"""
|
"""
|
||||||
|
@ -1589,7 +1596,7 @@ class ParserElement(ABC):
|
||||||
)
|
)
|
||||||
return Each([self, other])
|
return Each([self, other])
|
||||||
|
|
||||||
def __rand__(self, other):
|
def __rand__(self, other) -> "ParserElement":
|
||||||
"""
|
"""
|
||||||
Implementation of ``&`` operator when left operand is not a :class:`ParserElement`
|
Implementation of ``&`` operator when left operand is not a :class:`ParserElement`
|
||||||
"""
|
"""
|
||||||
|
@ -1603,7 +1610,7 @@ class ParserElement(ABC):
|
||||||
)
|
)
|
||||||
return other & self
|
return other & self
|
||||||
|
|
||||||
def __invert__(self):
|
def __invert__(self) -> "ParserElement":
|
||||||
"""
|
"""
|
||||||
Implementation of ``~`` operator - returns :class:`NotAny`
|
Implementation of ``~`` operator - returns :class:`NotAny`
|
||||||
"""
|
"""
|
||||||
|
@ -1653,7 +1660,7 @@ class ParserElement(ABC):
|
||||||
ret = self * tuple(key[:2])
|
ret = self * tuple(key[:2])
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def __call__(self, name: str = None):
|
def __call__(self, name: str = None) -> "ParserElement":
|
||||||
"""
|
"""
|
||||||
Shortcut for :class:`set_results_name`, with ``list_all_matches=False``.
|
Shortcut for :class:`set_results_name`, with ``list_all_matches=False``.
|
||||||
|
|
||||||
|
@ -1729,7 +1736,7 @@ class ParserElement(ABC):
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
patt = OneOrMore(Word(alphas))
|
patt = Word(alphas)[1, ...]
|
||||||
patt.parse_string('ablaj /* comment */ lskjd')
|
patt.parse_string('ablaj /* comment */ lskjd')
|
||||||
# -> ['ablaj']
|
# -> ['ablaj']
|
||||||
|
|
||||||
|
@ -1789,7 +1796,7 @@ class ParserElement(ABC):
|
||||||
# turn on debugging for wd
|
# turn on debugging for wd
|
||||||
wd.set_debug()
|
wd.set_debug()
|
||||||
|
|
||||||
OneOrMore(term).parse_string("abc 123 xyz 890")
|
term[1, ...].parse_string("abc 123 xyz 890")
|
||||||
|
|
||||||
prints::
|
prints::
|
||||||
|
|
||||||
|
@ -1944,12 +1951,12 @@ class ParserElement(ABC):
|
||||||
self,
|
self,
|
||||||
tests: Union[str, List[str]],
|
tests: Union[str, List[str]],
|
||||||
parse_all: bool = True,
|
parse_all: bool = True,
|
||||||
comment: OptionalType[Union["ParserElement", str]] = "#",
|
comment: typing.Optional[Union["ParserElement", str]] = "#",
|
||||||
full_dump: bool = True,
|
full_dump: bool = True,
|
||||||
print_results: bool = True,
|
print_results: bool = True,
|
||||||
failure_tests: bool = False,
|
failure_tests: bool = False,
|
||||||
post_parse: Callable[[str, ParseResults], str] = None,
|
post_parse: Callable[[str, ParseResults], str] = None,
|
||||||
file: OptionalType[TextIO] = None,
|
file: typing.Optional[TextIO] = None,
|
||||||
with_line_numbers: bool = False,
|
with_line_numbers: bool = False,
|
||||||
*,
|
*,
|
||||||
parseAll: bool = True,
|
parseAll: bool = True,
|
||||||
|
@ -2140,6 +2147,7 @@ class ParserElement(ABC):
|
||||||
output_html: Union[TextIO, Path, str],
|
output_html: Union[TextIO, Path, str],
|
||||||
vertical: int = 3,
|
vertical: int = 3,
|
||||||
show_results_names: bool = False,
|
show_results_names: bool = False,
|
||||||
|
show_groups: bool = False,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -2152,7 +2160,7 @@ class ParserElement(ABC):
|
||||||
instead of horizontally (default=3)
|
instead of horizontally (default=3)
|
||||||
- show_results_names - bool flag whether diagram should show annotations for
|
- show_results_names - bool flag whether diagram should show annotations for
|
||||||
defined results names
|
defined results names
|
||||||
|
- show_groups - bool flag whether groups should be highlighted with an unlabeled surrounding box
|
||||||
Additional diagram-formatting keyword arguments can also be included;
|
Additional diagram-formatting keyword arguments can also be included;
|
||||||
see railroad.Diagram class.
|
see railroad.Diagram class.
|
||||||
"""
|
"""
|
||||||
|
@ -2170,6 +2178,7 @@ class ParserElement(ABC):
|
||||||
self,
|
self,
|
||||||
vertical=vertical,
|
vertical=vertical,
|
||||||
show_results_names=show_results_names,
|
show_results_names=show_results_names,
|
||||||
|
show_groups=show_groups,
|
||||||
diagram_kwargs=kwargs,
|
diagram_kwargs=kwargs,
|
||||||
)
|
)
|
||||||
if isinstance(output_html, (str, Path)):
|
if isinstance(output_html, (str, Path)):
|
||||||
|
@ -2219,7 +2228,7 @@ class _PendingSkip(ParserElement):
|
||||||
def _generateDefaultName(self):
|
def _generateDefaultName(self):
|
||||||
return str(self.anchor + Empty()).replace("Empty", "...")
|
return str(self.anchor + Empty()).replace("Empty", "...")
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other) -> "ParserElement":
|
||||||
skipper = SkipTo(other).set_name("...")("_skipped*")
|
skipper = SkipTo(other).set_name("...")("_skipped*")
|
||||||
if self.must_skip:
|
if self.must_skip:
|
||||||
|
|
||||||
|
@ -2374,11 +2383,11 @@ class Keyword(Token):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
match_string: str = "",
|
match_string: str = "",
|
||||||
ident_chars: OptionalType[str] = None,
|
ident_chars: typing.Optional[str] = None,
|
||||||
caseless: bool = False,
|
caseless: bool = False,
|
||||||
*,
|
*,
|
||||||
matchString: str = "",
|
matchString: str = "",
|
||||||
identChars: OptionalType[str] = None,
|
identChars: typing.Optional[str] = None,
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
identChars = identChars or ident_chars
|
identChars = identChars or ident_chars
|
||||||
|
@ -2468,7 +2477,7 @@ class CaselessLiteral(Literal):
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
OneOrMore(CaselessLiteral("CMD")).parse_string("cmd CMD Cmd10")
|
CaselessLiteral("CMD")[1, ...].parse_string("cmd CMD Cmd10")
|
||||||
# -> ['CMD', 'CMD', 'CMD']
|
# -> ['CMD', 'CMD', 'CMD']
|
||||||
|
|
||||||
(Contrast with example for :class:`CaselessKeyword`.)
|
(Contrast with example for :class:`CaselessKeyword`.)
|
||||||
|
@ -2493,7 +2502,7 @@ class CaselessKeyword(Keyword):
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
OneOrMore(CaselessKeyword("CMD")).parse_string("cmd CMD Cmd10")
|
CaselessKeyword("CMD")[1, ...].parse_string("cmd CMD Cmd10")
|
||||||
# -> ['CMD', 'CMD']
|
# -> ['CMD', 'CMD']
|
||||||
|
|
||||||
(Contrast with example for :class:`CaselessLiteral`.)
|
(Contrast with example for :class:`CaselessLiteral`.)
|
||||||
|
@ -2502,10 +2511,10 @@ class CaselessKeyword(Keyword):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
match_string: str = "",
|
match_string: str = "",
|
||||||
ident_chars: OptionalType[str] = None,
|
ident_chars: typing.Optional[str] = None,
|
||||||
*,
|
*,
|
||||||
matchString: str = "",
|
matchString: str = "",
|
||||||
identChars: OptionalType[str] = None,
|
identChars: typing.Optional[str] = None,
|
||||||
):
|
):
|
||||||
identChars = identChars or ident_chars
|
identChars = identChars or ident_chars
|
||||||
match_string = matchString or match_string
|
match_string = matchString or match_string
|
||||||
|
@ -2669,17 +2678,17 @@ class Word(Token):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
init_chars: str = "",
|
init_chars: str = "",
|
||||||
body_chars: OptionalType[str] = None,
|
body_chars: typing.Optional[str] = None,
|
||||||
min: int = 1,
|
min: int = 1,
|
||||||
max: int = 0,
|
max: int = 0,
|
||||||
exact: int = 0,
|
exact: int = 0,
|
||||||
as_keyword: bool = False,
|
as_keyword: bool = False,
|
||||||
exclude_chars: OptionalType[str] = None,
|
exclude_chars: typing.Optional[str] = None,
|
||||||
*,
|
*,
|
||||||
initChars: OptionalType[str] = None,
|
initChars: typing.Optional[str] = None,
|
||||||
bodyChars: OptionalType[str] = None,
|
bodyChars: typing.Optional[str] = None,
|
||||||
asKeyword: bool = False,
|
asKeyword: bool = False,
|
||||||
excludeChars: OptionalType[str] = None,
|
excludeChars: typing.Optional[str] = None,
|
||||||
):
|
):
|
||||||
initChars = initChars or init_chars
|
initChars = initChars or init_chars
|
||||||
bodyChars = bodyChars or body_chars
|
bodyChars = bodyChars or body_chars
|
||||||
|
@ -2773,7 +2782,7 @@ class Word(Token):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.re = re.compile(self.reString)
|
self.re = re.compile(self.reString)
|
||||||
except sre_constants.error:
|
except re.error:
|
||||||
self.re = None
|
self.re = None
|
||||||
else:
|
else:
|
||||||
self.re_match = self.re.match
|
self.re_match = self.re.match
|
||||||
|
@ -2861,10 +2870,10 @@ class Char(_WordRegex):
|
||||||
self,
|
self,
|
||||||
charset: str,
|
charset: str,
|
||||||
as_keyword: bool = False,
|
as_keyword: bool = False,
|
||||||
exclude_chars: OptionalType[str] = None,
|
exclude_chars: typing.Optional[str] = None,
|
||||||
*,
|
*,
|
||||||
asKeyword: bool = False,
|
asKeyword: bool = False,
|
||||||
excludeChars: OptionalType[str] = None,
|
excludeChars: typing.Optional[str] = None,
|
||||||
):
|
):
|
||||||
asKeyword = asKeyword or as_keyword
|
asKeyword = asKeyword or as_keyword
|
||||||
excludeChars = excludeChars or exclude_chars
|
excludeChars = excludeChars or exclude_chars
|
||||||
|
@ -2926,19 +2935,12 @@ class Regex(Token):
|
||||||
if not pattern:
|
if not pattern:
|
||||||
raise ValueError("null string passed to Regex; use Empty() instead")
|
raise ValueError("null string passed to Regex; use Empty() instead")
|
||||||
|
|
||||||
self.pattern = pattern
|
self._re = None
|
||||||
|
self.reString = self.pattern = pattern
|
||||||
self.flags = flags
|
self.flags = flags
|
||||||
|
|
||||||
try:
|
|
||||||
self.re = re.compile(self.pattern, self.flags)
|
|
||||||
self.reString = self.pattern
|
|
||||||
except sre_constants.error:
|
|
||||||
raise ValueError(
|
|
||||||
"invalid pattern ({!r}) passed to Regex".format(pattern)
|
|
||||||
)
|
|
||||||
|
|
||||||
elif hasattr(pattern, "pattern") and hasattr(pattern, "match"):
|
elif hasattr(pattern, "pattern") and hasattr(pattern, "match"):
|
||||||
self.re = pattern
|
self._re = pattern
|
||||||
self.pattern = self.reString = pattern.pattern
|
self.pattern = self.reString = pattern.pattern
|
||||||
self.flags = flags
|
self.flags = flags
|
||||||
|
|
||||||
|
@ -2947,11 +2949,8 @@ class Regex(Token):
|
||||||
"Regex may only be constructed with a string or a compiled RE object"
|
"Regex may only be constructed with a string or a compiled RE object"
|
||||||
)
|
)
|
||||||
|
|
||||||
self.re_match = self.re.match
|
|
||||||
|
|
||||||
self.errmsg = "Expected " + self.name
|
self.errmsg = "Expected " + self.name
|
||||||
self.mayIndexError = False
|
self.mayIndexError = False
|
||||||
self.mayReturnEmpty = self.re_match("") is not None
|
|
||||||
self.asGroupList = asGroupList
|
self.asGroupList = asGroupList
|
||||||
self.asMatch = asMatch
|
self.asMatch = asMatch
|
||||||
if self.asGroupList:
|
if self.asGroupList:
|
||||||
|
@ -2959,6 +2958,26 @@ class Regex(Token):
|
||||||
if self.asMatch:
|
if self.asMatch:
|
||||||
self.parseImpl = self.parseImplAsMatch
|
self.parseImpl = self.parseImplAsMatch
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def re(self):
|
||||||
|
if self._re:
|
||||||
|
return self._re
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
return re.compile(self.pattern, self.flags)
|
||||||
|
except re.error:
|
||||||
|
raise ValueError(
|
||||||
|
"invalid pattern ({!r}) passed to Regex".format(self.pattern)
|
||||||
|
)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def re_match(self):
|
||||||
|
return self.re.match
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def mayReturnEmpty(self):
|
||||||
|
return self.re_match("") is not None
|
||||||
|
|
||||||
def _generateDefaultName(self):
|
def _generateDefaultName(self):
|
||||||
return "Re:({})".format(repr(self.pattern).replace("\\\\", "\\"))
|
return "Re:({})".format(repr(self.pattern).replace("\\\\", "\\"))
|
||||||
|
|
||||||
|
@ -3067,18 +3086,18 @@ class QuotedString(Token):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
quote_char: str = "",
|
quote_char: str = "",
|
||||||
esc_char: OptionalType[str] = None,
|
esc_char: typing.Optional[str] = None,
|
||||||
esc_quote: OptionalType[str] = None,
|
esc_quote: typing.Optional[str] = None,
|
||||||
multiline: bool = False,
|
multiline: bool = False,
|
||||||
unquote_results: bool = True,
|
unquote_results: bool = True,
|
||||||
end_quote_char: OptionalType[str] = None,
|
end_quote_char: typing.Optional[str] = None,
|
||||||
convert_whitespace_escapes: bool = True,
|
convert_whitespace_escapes: bool = True,
|
||||||
*,
|
*,
|
||||||
quoteChar: str = "",
|
quoteChar: str = "",
|
||||||
escChar: OptionalType[str] = None,
|
escChar: typing.Optional[str] = None,
|
||||||
escQuote: OptionalType[str] = None,
|
escQuote: typing.Optional[str] = None,
|
||||||
unquoteResults: bool = True,
|
unquoteResults: bool = True,
|
||||||
endQuoteChar: OptionalType[str] = None,
|
endQuoteChar: typing.Optional[str] = None,
|
||||||
convertWhitespaceEscapes: bool = True,
|
convertWhitespaceEscapes: bool = True,
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -3168,7 +3187,7 @@ class QuotedString(Token):
|
||||||
self.re = re.compile(self.pattern, self.flags)
|
self.re = re.compile(self.pattern, self.flags)
|
||||||
self.reString = self.pattern
|
self.reString = self.pattern
|
||||||
self.re_match = self.re.match
|
self.re_match = self.re.match
|
||||||
except sre_constants.error:
|
except re.error:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"invalid pattern {!r} passed to Regex".format(self.pattern)
|
"invalid pattern {!r} passed to Regex".format(self.pattern)
|
||||||
)
|
)
|
||||||
|
@ -3579,7 +3598,7 @@ class ParseExpression(ParserElement):
|
||||||
post-processing parsed tokens.
|
post-processing parsed tokens.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, exprs: IterableType[ParserElement], savelist: bool = False):
|
def __init__(self, exprs: typing.Iterable[ParserElement], savelist: bool = False):
|
||||||
super().__init__(savelist)
|
super().__init__(savelist)
|
||||||
self.exprs: List[ParserElement]
|
self.exprs: List[ParserElement]
|
||||||
if isinstance(exprs, _generatorType):
|
if isinstance(exprs, _generatorType):
|
||||||
|
@ -3746,7 +3765,7 @@ class And(ParseExpression):
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
integer = Word(nums)
|
integer = Word(nums)
|
||||||
name_expr = OneOrMore(Word(alphas))
|
name_expr = Word(alphas)[1, ...]
|
||||||
|
|
||||||
expr = And([integer("id"), name_expr("name"), integer("age")])
|
expr = And([integer("id"), name_expr("name"), integer("age")])
|
||||||
# more easily written as:
|
# more easily written as:
|
||||||
|
@ -3761,7 +3780,9 @@ class And(ParseExpression):
|
||||||
def _generateDefaultName(self):
|
def _generateDefaultName(self):
|
||||||
return "-"
|
return "-"
|
||||||
|
|
||||||
def __init__(self, exprs_arg: IterableType[ParserElement], savelist: bool = True):
|
def __init__(
|
||||||
|
self, exprs_arg: typing.Iterable[ParserElement], savelist: bool = True
|
||||||
|
):
|
||||||
exprs: List[ParserElement] = list(exprs_arg)
|
exprs: List[ParserElement] = list(exprs_arg)
|
||||||
if exprs and Ellipsis in exprs:
|
if exprs and Ellipsis in exprs:
|
||||||
tmp = []
|
tmp = []
|
||||||
|
@ -3826,7 +3847,9 @@ class And(ParseExpression):
|
||||||
seen.add(id(cur))
|
seen.add(id(cur))
|
||||||
if isinstance(cur, IndentedBlock):
|
if isinstance(cur, IndentedBlock):
|
||||||
prev.add_parse_action(
|
prev.add_parse_action(
|
||||||
lambda s, l, t, cur_=cur: setattr(cur_, "parent_anchor", col(l, s))
|
lambda s, l, t, cur_=cur: setattr(
|
||||||
|
cur_, "parent_anchor", col(l, s)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
subs = cur.recurse()
|
subs = cur.recurse()
|
||||||
|
@ -3903,7 +3926,7 @@ class Or(ParseExpression):
|
||||||
[['123'], ['3.1416'], ['789']]
|
[['123'], ['3.1416'], ['789']]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, exprs: IterableType[ParserElement], savelist: bool = False):
|
def __init__(self, exprs: typing.Iterable[ParserElement], savelist: bool = False):
|
||||||
super().__init__(exprs, savelist)
|
super().__init__(exprs, savelist)
|
||||||
if self.exprs:
|
if self.exprs:
|
||||||
self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs)
|
self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs)
|
||||||
|
@ -4058,7 +4081,7 @@ class MatchFirst(ParseExpression):
|
||||||
print(number.search_string("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']]
|
print(number.search_string("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, exprs: IterableType[ParserElement], savelist: bool = False):
|
def __init__(self, exprs: typing.Iterable[ParserElement], savelist: bool = False):
|
||||||
super().__init__(exprs, savelist)
|
super().__init__(exprs, savelist)
|
||||||
if self.exprs:
|
if self.exprs:
|
||||||
self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs)
|
self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs)
|
||||||
|
@ -4209,7 +4232,7 @@ class Each(ParseExpression):
|
||||||
- size: 20
|
- size: 20
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, exprs: IterableType[ParserElement], savelist: bool = True):
|
def __init__(self, exprs: typing.Iterable[ParserElement], savelist: bool = True):
|
||||||
super().__init__(exprs, savelist)
|
super().__init__(exprs, savelist)
|
||||||
if self.exprs:
|
if self.exprs:
|
||||||
self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs)
|
self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs)
|
||||||
|
@ -4545,7 +4568,7 @@ class FollowedBy(ParseElementEnhance):
|
||||||
label = data_word + FollowedBy(':')
|
label = data_word + FollowedBy(':')
|
||||||
attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join))
|
attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join))
|
||||||
|
|
||||||
OneOrMore(attr_expr).parse_string("shape: SQUARE color: BLACK posn: upper left").pprint()
|
attr_expr[1, ...].parse_string("shape: SQUARE color: BLACK posn: upper left").pprint()
|
||||||
|
|
||||||
prints::
|
prints::
|
||||||
|
|
||||||
|
@ -4596,7 +4619,7 @@ class PrecededBy(ParseElementEnhance):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, expr: Union[ParserElement, str], retreat: OptionalType[int] = None
|
self, expr: Union[ParserElement, str], retreat: typing.Optional[int] = None
|
||||||
):
|
):
|
||||||
super().__init__(expr)
|
super().__init__(expr)
|
||||||
self.expr = self.expr().leave_whitespace()
|
self.expr = self.expr().leave_whitespace()
|
||||||
|
@ -4707,7 +4730,7 @@ class NotAny(ParseElementEnhance):
|
||||||
|
|
||||||
# very crude boolean expression - to support parenthesis groups and
|
# very crude boolean expression - to support parenthesis groups and
|
||||||
# operation hierarchy, use infix_notation
|
# operation hierarchy, use infix_notation
|
||||||
boolean_expr = boolean_term + ZeroOrMore((AND | OR) + boolean_term)
|
boolean_expr = boolean_term + ((AND | OR) + boolean_term)[...]
|
||||||
|
|
||||||
# integers that are followed by "." are actually floats
|
# integers that are followed by "." are actually floats
|
||||||
integer = Word(nums) + ~Char(".")
|
integer = Word(nums) + ~Char(".")
|
||||||
|
@ -4735,9 +4758,9 @@ class _MultipleMatch(ParseElementEnhance):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
expr: ParserElement,
|
expr: ParserElement,
|
||||||
stop_on: OptionalType[Union[ParserElement, str]] = None,
|
stop_on: typing.Optional[Union[ParserElement, str]] = None,
|
||||||
*,
|
*,
|
||||||
stopOn: OptionalType[Union[ParserElement, str]] = None,
|
stopOn: typing.Optional[Union[ParserElement, str]] = None,
|
||||||
):
|
):
|
||||||
super().__init__(expr)
|
super().__init__(expr)
|
||||||
stopOn = stopOn or stop_on
|
stopOn = stopOn or stop_on
|
||||||
|
@ -4826,7 +4849,7 @@ class OneOrMore(_MultipleMatch):
|
||||||
attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).set_parse_action(' '.join))
|
attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).set_parse_action(' '.join))
|
||||||
|
|
||||||
text = "shape: SQUARE posn: upper left color: BLACK"
|
text = "shape: SQUARE posn: upper left color: BLACK"
|
||||||
OneOrMore(attr_expr).parse_string(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']]
|
attr_expr[1, ...].parse_string(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']]
|
||||||
|
|
||||||
# use stop_on attribute for OneOrMore to avoid reading label string as part of the data
|
# use stop_on attribute for OneOrMore to avoid reading label string as part of the data
|
||||||
attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join))
|
attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join))
|
||||||
|
@ -4856,9 +4879,9 @@ class ZeroOrMore(_MultipleMatch):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
expr: ParserElement,
|
expr: ParserElement,
|
||||||
stop_on: OptionalType[Union[ParserElement, str]] = None,
|
stop_on: typing.Optional[Union[ParserElement, str]] = None,
|
||||||
*,
|
*,
|
||||||
stopOn: OptionalType[Union[ParserElement, str]] = None,
|
stopOn: typing.Optional[Union[ParserElement, str]] = None,
|
||||||
):
|
):
|
||||||
super().__init__(expr, stopOn=stopOn or stop_on)
|
super().__init__(expr, stopOn=stopOn or stop_on)
|
||||||
self.mayReturnEmpty = True
|
self.mayReturnEmpty = True
|
||||||
|
@ -5002,20 +5025,20 @@ class SkipTo(ParseElementEnhance):
|
||||||
prints::
|
prints::
|
||||||
|
|
||||||
['101', 'Critical', 'Intermittent system crash', '6']
|
['101', 'Critical', 'Intermittent system crash', '6']
|
||||||
- days_open: 6
|
- days_open: '6'
|
||||||
- desc: Intermittent system crash
|
- desc: 'Intermittent system crash'
|
||||||
- issue_num: 101
|
- issue_num: '101'
|
||||||
- sev: Critical
|
- sev: 'Critical'
|
||||||
['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14']
|
['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14']
|
||||||
- days_open: 14
|
- days_open: '14'
|
||||||
- desc: Spelling error on Login ('log|n')
|
- desc: "Spelling error on Login ('log|n')"
|
||||||
- issue_num: 94
|
- issue_num: '94'
|
||||||
- sev: Cosmetic
|
- sev: 'Cosmetic'
|
||||||
['79', 'Minor', 'System slow when running too many reports', '47']
|
['79', 'Minor', 'System slow when running too many reports', '47']
|
||||||
- days_open: 47
|
- days_open: '47'
|
||||||
- desc: System slow when running too many reports
|
- desc: 'System slow when running too many reports'
|
||||||
- issue_num: 79
|
- issue_num: '79'
|
||||||
- sev: Minor
|
- sev: 'Minor'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -5023,7 +5046,7 @@ class SkipTo(ParseElementEnhance):
|
||||||
other: Union[ParserElement, str],
|
other: Union[ParserElement, str],
|
||||||
include: bool = False,
|
include: bool = False,
|
||||||
ignore: bool = None,
|
ignore: bool = None,
|
||||||
fail_on: OptionalType[Union[ParserElement, str]] = None,
|
fail_on: typing.Optional[Union[ParserElement, str]] = None,
|
||||||
*,
|
*,
|
||||||
failOn: Union[ParserElement, str] = None,
|
failOn: Union[ParserElement, str] = None,
|
||||||
):
|
):
|
||||||
|
@ -5120,7 +5143,7 @@ class Forward(ParseElementEnhance):
|
||||||
parser created using ``Forward``.
|
parser created using ``Forward``.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, other: OptionalType[Union[ParserElement, str]] = None):
|
def __init__(self, other: typing.Optional[Union[ParserElement, str]] = None):
|
||||||
self.caller_frame = traceback.extract_stack(limit=2)[0]
|
self.caller_frame = traceback.extract_stack(limit=2)[0]
|
||||||
super().__init__(other, savelist=False)
|
super().__init__(other, savelist=False)
|
||||||
self.lshift_line = None
|
self.lshift_line = None
|
||||||
|
@ -5372,7 +5395,7 @@ class Combine(TokenConverter):
|
||||||
join_string: str = "",
|
join_string: str = "",
|
||||||
adjacent: bool = True,
|
adjacent: bool = True,
|
||||||
*,
|
*,
|
||||||
joinString: OptionalType[str] = None,
|
joinString: typing.Optional[str] = None,
|
||||||
):
|
):
|
||||||
super().__init__(expr)
|
super().__init__(expr)
|
||||||
joinString = joinString if joinString is not None else join_string
|
joinString = joinString if joinString is not None else join_string
|
||||||
|
@ -5459,10 +5482,10 @@ class Dict(TokenConverter):
|
||||||
attr_expr = (label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join))
|
attr_expr = (label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join))
|
||||||
|
|
||||||
# print attributes as plain groups
|
# print attributes as plain groups
|
||||||
print(OneOrMore(attr_expr).parse_string(text).dump())
|
print(attr_expr[1, ...].parse_string(text).dump())
|
||||||
|
|
||||||
# instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names
|
# instead of OneOrMore(expr), parse using Dict(Group(expr)[1, ...]) - Dict will auto-assign names
|
||||||
result = Dict(OneOrMore(Group(attr_expr))).parse_string(text)
|
result = Dict(Group(attr_expr)[1, ...]).parse_string(text)
|
||||||
print(result.dump())
|
print(result.dump())
|
||||||
|
|
||||||
# access named fields as dict entries, or output as dict
|
# access named fields as dict entries, or output as dict
|
||||||
|
@ -5473,10 +5496,10 @@ class Dict(TokenConverter):
|
||||||
|
|
||||||
['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap']
|
['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap']
|
||||||
[['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
|
[['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
|
||||||
- color: light blue
|
- color: 'light blue'
|
||||||
- posn: upper left
|
- posn: 'upper left'
|
||||||
- shape: SQUARE
|
- shape: 'SQUARE'
|
||||||
- texture: burlap
|
- texture: 'burlap'
|
||||||
SQUARE
|
SQUARE
|
||||||
{'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'}
|
{'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'}
|
||||||
|
|
||||||
|
@ -5535,12 +5558,12 @@ class Suppress(TokenConverter):
|
||||||
|
|
||||||
source = "a, b, c,d"
|
source = "a, b, c,d"
|
||||||
wd = Word(alphas)
|
wd = Word(alphas)
|
||||||
wd_list1 = wd + ZeroOrMore(',' + wd)
|
wd_list1 = wd + (',' + wd)[...]
|
||||||
print(wd_list1.parse_string(source))
|
print(wd_list1.parse_string(source))
|
||||||
|
|
||||||
# often, delimiters that are useful during parsing are just in the
|
# often, delimiters that are useful during parsing are just in the
|
||||||
# way afterward - use Suppress to keep them out of the parsed output
|
# way afterward - use Suppress to keep them out of the parsed output
|
||||||
wd_list2 = wd + ZeroOrMore(Suppress(',') + wd)
|
wd_list2 = wd + (Suppress(',') + wd)[...]
|
||||||
print(wd_list2.parse_string(source))
|
print(wd_list2.parse_string(source))
|
||||||
|
|
||||||
# Skipped text (using '...') can be suppressed as well
|
# Skipped text (using '...') can be suppressed as well
|
||||||
|
@ -5564,13 +5587,13 @@ class Suppress(TokenConverter):
|
||||||
expr = _PendingSkip(NoMatch())
|
expr = _PendingSkip(NoMatch())
|
||||||
super().__init__(expr)
|
super().__init__(expr)
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other) -> "ParserElement":
|
||||||
if isinstance(self.expr, _PendingSkip):
|
if isinstance(self.expr, _PendingSkip):
|
||||||
return Suppress(SkipTo(other)) + other
|
return Suppress(SkipTo(other)) + other
|
||||||
else:
|
else:
|
||||||
return super().__add__(other)
|
return super().__add__(other)
|
||||||
|
|
||||||
def __sub__(self, other):
|
def __sub__(self, other) -> "ParserElement":
|
||||||
if isinstance(self.expr, _PendingSkip):
|
if isinstance(self.expr, _PendingSkip):
|
||||||
return Suppress(SkipTo(other)) - other
|
return Suppress(SkipTo(other)) - other
|
||||||
else:
|
else:
|
||||||
|
@ -5599,7 +5622,7 @@ def trace_parse_action(f: ParseAction) -> ParseAction:
|
||||||
def remove_duplicate_chars(tokens):
|
def remove_duplicate_chars(tokens):
|
||||||
return ''.join(sorted(set(''.join(tokens))))
|
return ''.join(sorted(set(''.join(tokens))))
|
||||||
|
|
||||||
wds = OneOrMore(wd).set_parse_action(remove_duplicate_chars)
|
wds = wd[1, ...].set_parse_action(remove_duplicate_chars)
|
||||||
print(wds.parse_string("slkdjs sld sldd sdlf sdljf"))
|
print(wds.parse_string("slkdjs sld sldd sdlf sdljf"))
|
||||||
|
|
||||||
prints::
|
prints::
|
||||||
|
@ -5705,18 +5728,18 @@ def token_map(func, *args) -> ParseAction:
|
||||||
|
|
||||||
Example (compare the last to example in :class:`ParserElement.transform_string`::
|
Example (compare the last to example in :class:`ParserElement.transform_string`::
|
||||||
|
|
||||||
hex_ints = OneOrMore(Word(hexnums)).set_parse_action(token_map(int, 16))
|
hex_ints = Word(hexnums)[1, ...].set_parse_action(token_map(int, 16))
|
||||||
hex_ints.run_tests('''
|
hex_ints.run_tests('''
|
||||||
00 11 22 aa FF 0a 0d 1a
|
00 11 22 aa FF 0a 0d 1a
|
||||||
''')
|
''')
|
||||||
|
|
||||||
upperword = Word(alphas).set_parse_action(token_map(str.upper))
|
upperword = Word(alphas).set_parse_action(token_map(str.upper))
|
||||||
OneOrMore(upperword).run_tests('''
|
upperword[1, ...].run_tests('''
|
||||||
my kingdom for a horse
|
my kingdom for a horse
|
||||||
''')
|
''')
|
||||||
|
|
||||||
wd = Word(alphas).set_parse_action(token_map(str.title))
|
wd = Word(alphas).set_parse_action(token_map(str.title))
|
||||||
OneOrMore(wd).set_parse_action(' '.join).run_tests('''
|
wd[1, ...].set_parse_action(' '.join).run_tests('''
|
||||||
now is the winter of our discontent made glorious summer by this sun of york
|
now is the winter of our discontent made glorious summer by this sun of york
|
||||||
''')
|
''')
|
||||||
|
|
||||||
|
@ -5772,7 +5795,9 @@ punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]")
|
||||||
|
|
||||||
# build list of built-in expressions, for future reference if a global default value
|
# build list of built-in expressions, for future reference if a global default value
|
||||||
# gets updated
|
# gets updated
|
||||||
_builtin_exprs = [v for v in vars().values() if isinstance(v, ParserElement)]
|
_builtin_exprs: List[ParserElement] = [
|
||||||
|
v for v in vars().values() if isinstance(v, ParserElement)
|
||||||
|
]
|
||||||
|
|
||||||
# backward compatibility names
|
# backward compatibility names
|
||||||
tokenMap = token_map
|
tokenMap = token_map
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import railroad
|
import railroad
|
||||||
import pyparsing
|
import pyparsing
|
||||||
from pkg_resources import resource_filename
|
import typing
|
||||||
from typing import (
|
from typing import (
|
||||||
List,
|
List,
|
||||||
Optional,
|
|
||||||
NamedTuple,
|
NamedTuple,
|
||||||
Generic,
|
Generic,
|
||||||
TypeVar,
|
TypeVar,
|
||||||
|
@ -16,13 +15,42 @@ from jinja2 import Template
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
with open(resource_filename(__name__, "template.jinja2"), encoding="utf-8") as fp:
|
|
||||||
template = Template(fp.read())
|
jinja2_template_source = """\
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
{% if not head %}
|
||||||
|
<style type="text/css">
|
||||||
|
.railroad-heading {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% else %}
|
||||||
|
{{ head | safe }}
|
||||||
|
{% endif %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{{ body | safe }}
|
||||||
|
{% for diagram in diagrams %}
|
||||||
|
<div class="railroad-group">
|
||||||
|
<h1 class="railroad-heading">{{ diagram.title }}</h1>
|
||||||
|
<div class="railroad-description">{{ diagram.text }}</div>
|
||||||
|
<div class="railroad-svg">
|
||||||
|
{{ diagram.svg }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
template = Template(jinja2_template_source)
|
||||||
|
|
||||||
# Note: ideally this would be a dataclass, but we're supporting Python 3.5+ so we can't do this yet
|
# Note: ideally this would be a dataclass, but we're supporting Python 3.5+ so we can't do this yet
|
||||||
NamedDiagram = NamedTuple(
|
NamedDiagram = NamedTuple(
|
||||||
"NamedDiagram",
|
"NamedDiagram",
|
||||||
[("name", str), ("diagram", Optional[railroad.DiagramItem]), ("index", int)],
|
[("name", str), ("diagram", typing.Optional[railroad.DiagramItem]), ("index", int)],
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
A simple structure for associating a name with a railroad diagram
|
A simple structure for associating a name with a railroad diagram
|
||||||
|
@ -54,7 +82,7 @@ class AnnotatedItem(railroad.Group):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, label: str, item):
|
def __init__(self, label: str, item):
|
||||||
super().__init__(item=item, label="[{}]".format(label))
|
super().__init__(item=item, label="[{}]".format(label) if label else label)
|
||||||
|
|
||||||
|
|
||||||
class EditablePartial(Generic[T]):
|
class EditablePartial(Generic[T]):
|
||||||
|
@ -106,6 +134,8 @@ def railroad_to_html(diagrams: List[NamedDiagram], **kwargs) -> str:
|
||||||
"""
|
"""
|
||||||
data = []
|
data = []
|
||||||
for diagram in diagrams:
|
for diagram in diagrams:
|
||||||
|
if diagram.diagram is None:
|
||||||
|
continue
|
||||||
io = StringIO()
|
io = StringIO()
|
||||||
diagram.diagram.writeSvg(io.write)
|
diagram.diagram.writeSvg(io.write)
|
||||||
title = diagram.name
|
title = diagram.name
|
||||||
|
@ -134,9 +164,10 @@ def resolve_partial(partial: "EditablePartial[T]") -> T:
|
||||||
|
|
||||||
def to_railroad(
|
def to_railroad(
|
||||||
element: pyparsing.ParserElement,
|
element: pyparsing.ParserElement,
|
||||||
diagram_kwargs: Optional[dict] = None,
|
diagram_kwargs: typing.Optional[dict] = None,
|
||||||
vertical: int = 3,
|
vertical: int = 3,
|
||||||
show_results_names: bool = False,
|
show_results_names: bool = False,
|
||||||
|
show_groups: bool = False,
|
||||||
) -> List[NamedDiagram]:
|
) -> List[NamedDiagram]:
|
||||||
"""
|
"""
|
||||||
Convert a pyparsing element tree into a list of diagrams. This is the recommended entrypoint to diagram
|
Convert a pyparsing element tree into a list of diagrams. This is the recommended entrypoint to diagram
|
||||||
|
@ -147,6 +178,8 @@ def to_railroad(
|
||||||
shown vertically instead of horizontally
|
shown vertically instead of horizontally
|
||||||
:param show_results_names - bool to indicate whether results name annotations should be
|
:param show_results_names - bool to indicate whether results name annotations should be
|
||||||
included in the diagram
|
included in the diagram
|
||||||
|
:param show_groups - bool to indicate whether groups should be highlighted with an unlabeled
|
||||||
|
surrounding box
|
||||||
"""
|
"""
|
||||||
# Convert the whole tree underneath the root
|
# Convert the whole tree underneath the root
|
||||||
lookup = ConverterState(diagram_kwargs=diagram_kwargs or {})
|
lookup = ConverterState(diagram_kwargs=diagram_kwargs or {})
|
||||||
|
@ -156,6 +189,7 @@ def to_railroad(
|
||||||
parent=None,
|
parent=None,
|
||||||
vertical=vertical,
|
vertical=vertical,
|
||||||
show_results_names=show_results_names,
|
show_results_names=show_results_names,
|
||||||
|
show_groups=show_groups,
|
||||||
)
|
)
|
||||||
|
|
||||||
root_id = id(element)
|
root_id = id(element)
|
||||||
|
@ -211,12 +245,12 @@ class ElementState:
|
||||||
parent: EditablePartial,
|
parent: EditablePartial,
|
||||||
number: int,
|
number: int,
|
||||||
name: str = None,
|
name: str = None,
|
||||||
parent_index: Optional[int] = None,
|
parent_index: typing.Optional[int] = None,
|
||||||
):
|
):
|
||||||
#: The pyparsing element that this represents
|
#: The pyparsing element that this represents
|
||||||
self.element: pyparsing.ParserElement = element
|
self.element: pyparsing.ParserElement = element
|
||||||
#: The name of the element
|
#: The name of the element
|
||||||
self.name: str = name
|
self.name: typing.Optional[str] = name
|
||||||
#: The output Railroad element in an unconverted state
|
#: The output Railroad element in an unconverted state
|
||||||
self.converted: EditablePartial = converted
|
self.converted: EditablePartial = converted
|
||||||
#: The parent Railroad element, which we store so that we can extract this if it's duplicated
|
#: The parent Railroad element, which we store so that we can extract this if it's duplicated
|
||||||
|
@ -224,7 +258,7 @@ class ElementState:
|
||||||
#: The order in which we found this element, used for sorting diagrams if this is extracted into a diagram
|
#: The order in which we found this element, used for sorting diagrams if this is extracted into a diagram
|
||||||
self.number: int = number
|
self.number: int = number
|
||||||
#: The index of this inside its parent
|
#: The index of this inside its parent
|
||||||
self.parent_index: Optional[int] = parent_index
|
self.parent_index: typing.Optional[int] = parent_index
|
||||||
#: If true, we should extract this out into a subdiagram
|
#: If true, we should extract this out into a subdiagram
|
||||||
self.extract: bool = False
|
self.extract: bool = False
|
||||||
#: If true, all of this element's children have been filled out
|
#: If true, all of this element's children have been filled out
|
||||||
|
@ -265,7 +299,7 @@ class ConverterState:
|
||||||
Stores some state that persists between recursions into the element tree
|
Stores some state that persists between recursions into the element tree
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, diagram_kwargs: Optional[dict] = None):
|
def __init__(self, diagram_kwargs: typing.Optional[dict] = None):
|
||||||
#: A dictionary mapping ParserElements to state relating to them
|
#: A dictionary mapping ParserElements to state relating to them
|
||||||
self._element_diagram_states: Dict[int, ElementState] = {}
|
self._element_diagram_states: Dict[int, ElementState] = {}
|
||||||
#: A dictionary mapping ParserElement IDs to subdiagrams generated from them
|
#: A dictionary mapping ParserElement IDs to subdiagrams generated from them
|
||||||
|
@ -356,13 +390,14 @@ def _apply_diagram_item_enhancements(fn):
|
||||||
|
|
||||||
def _inner(
|
def _inner(
|
||||||
element: pyparsing.ParserElement,
|
element: pyparsing.ParserElement,
|
||||||
parent: Optional[EditablePartial],
|
parent: typing.Optional[EditablePartial],
|
||||||
lookup: ConverterState = None,
|
lookup: ConverterState = None,
|
||||||
vertical: int = None,
|
vertical: int = None,
|
||||||
index: int = 0,
|
index: int = 0,
|
||||||
name_hint: str = None,
|
name_hint: str = None,
|
||||||
show_results_names: bool = False,
|
show_results_names: bool = False,
|
||||||
) -> Optional[EditablePartial]:
|
show_groups: bool = False,
|
||||||
|
) -> typing.Optional[EditablePartial]:
|
||||||
|
|
||||||
ret = fn(
|
ret = fn(
|
||||||
element,
|
element,
|
||||||
|
@ -372,6 +407,7 @@ def _apply_diagram_item_enhancements(fn):
|
||||||
index,
|
index,
|
||||||
name_hint,
|
name_hint,
|
||||||
show_results_names,
|
show_results_names,
|
||||||
|
show_groups,
|
||||||
)
|
)
|
||||||
|
|
||||||
# apply annotation for results name, if present
|
# apply annotation for results name, if present
|
||||||
|
@ -405,13 +441,14 @@ def _visible_exprs(exprs: Iterable[pyparsing.ParserElement]):
|
||||||
@_apply_diagram_item_enhancements
|
@_apply_diagram_item_enhancements
|
||||||
def _to_diagram_element(
|
def _to_diagram_element(
|
||||||
element: pyparsing.ParserElement,
|
element: pyparsing.ParserElement,
|
||||||
parent: Optional[EditablePartial],
|
parent: typing.Optional[EditablePartial],
|
||||||
lookup: ConverterState = None,
|
lookup: ConverterState = None,
|
||||||
vertical: int = None,
|
vertical: int = None,
|
||||||
index: int = 0,
|
index: int = 0,
|
||||||
name_hint: str = None,
|
name_hint: str = None,
|
||||||
show_results_names: bool = False,
|
show_results_names: bool = False,
|
||||||
) -> Optional[EditablePartial]:
|
show_groups: bool = False,
|
||||||
|
) -> typing.Optional[EditablePartial]:
|
||||||
"""
|
"""
|
||||||
Recursively converts a PyParsing Element to a railroad Element
|
Recursively converts a PyParsing Element to a railroad Element
|
||||||
:param lookup: The shared converter state that keeps track of useful things
|
:param lookup: The shared converter state that keeps track of useful things
|
||||||
|
@ -423,6 +460,7 @@ def _to_diagram_element(
|
||||||
:param name_hint: If provided, this will override the generated name
|
:param name_hint: If provided, this will override the generated name
|
||||||
:param show_results_names: bool flag indicating whether to add annotations for results names
|
:param show_results_names: bool flag indicating whether to add annotations for results names
|
||||||
:returns: The converted version of the input element, but as a Partial that hasn't yet been constructed
|
:returns: The converted version of the input element, but as a Partial that hasn't yet been constructed
|
||||||
|
:param show_groups: bool flag indicating whether to show groups using bounding box
|
||||||
"""
|
"""
|
||||||
exprs = element.recurse()
|
exprs = element.recurse()
|
||||||
name = name_hint or element.customName or element.__class__.__name__
|
name = name_hint or element.customName or element.__class__.__name__
|
||||||
|
@ -437,7 +475,7 @@ def _to_diagram_element(
|
||||||
if isinstance(
|
if isinstance(
|
||||||
element,
|
element,
|
||||||
(
|
(
|
||||||
pyparsing.TokenConverter,
|
# pyparsing.TokenConverter,
|
||||||
# pyparsing.Forward,
|
# pyparsing.Forward,
|
||||||
pyparsing.Located,
|
pyparsing.Located,
|
||||||
),
|
),
|
||||||
|
@ -457,6 +495,7 @@ def _to_diagram_element(
|
||||||
index=index,
|
index=index,
|
||||||
name_hint=propagated_name,
|
name_hint=propagated_name,
|
||||||
show_results_names=show_results_names,
|
show_results_names=show_results_names,
|
||||||
|
show_groups=show_groups,
|
||||||
)
|
)
|
||||||
|
|
||||||
# If the element isn't worth extracting, we always treat it as the first time we say it
|
# If the element isn't worth extracting, we always treat it as the first time we say it
|
||||||
|
@ -510,6 +549,15 @@ def _to_diagram_element(
|
||||||
ret = EditablePartial.from_call(AnnotatedItem, label="LOOKAHEAD", item="")
|
ret = EditablePartial.from_call(AnnotatedItem, label="LOOKAHEAD", item="")
|
||||||
elif isinstance(element, pyparsing.PrecededBy):
|
elif isinstance(element, pyparsing.PrecededBy):
|
||||||
ret = EditablePartial.from_call(AnnotatedItem, label="LOOKBEHIND", item="")
|
ret = EditablePartial.from_call(AnnotatedItem, label="LOOKBEHIND", item="")
|
||||||
|
elif isinstance(element, pyparsing.Group):
|
||||||
|
if show_groups:
|
||||||
|
ret = EditablePartial.from_call(AnnotatedItem, label="", item="")
|
||||||
|
else:
|
||||||
|
ret = EditablePartial.from_call(railroad.Group, label="", item="")
|
||||||
|
elif isinstance(element, pyparsing.TokenConverter):
|
||||||
|
ret = EditablePartial.from_call(
|
||||||
|
AnnotatedItem, label=type(element).__name__.lower(), 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):
|
||||||
|
@ -558,6 +606,7 @@ def _to_diagram_element(
|
||||||
vertical=vertical,
|
vertical=vertical,
|
||||||
index=i,
|
index=i,
|
||||||
show_results_names=show_results_names,
|
show_results_names=show_results_names,
|
||||||
|
show_groups=show_groups,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Some elements don't need to be shown in the diagram
|
# Some elements don't need to be shown in the diagram
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
{% if not head %}
|
|
||||||
<style type="text/css">
|
|
||||||
.railroad-heading {
|
|
||||||
font-family: monospace;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
{% else %}
|
|
||||||
{{ hear | safe }}
|
|
||||||
{% endif %}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{{ body | safe }}
|
|
||||||
{% for diagram in diagrams %}
|
|
||||||
<div class="railroad-group">
|
|
||||||
<h1 class="railroad-heading">{{ diagram.title }}</h1>
|
|
||||||
<div class="railroad-description">{{ diagram.text }}</div>
|
|
||||||
<div class="railroad-svg">
|
|
||||||
{{ diagram.svg }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from typing import Optional
|
import typing
|
||||||
|
|
||||||
from .util import col, line, lineno, _collapse_string_to_ranges
|
from .util import col, line, lineno, _collapse_string_to_ranges
|
||||||
from .unicode import pyparsing_unicode as ppu
|
from .unicode import pyparsing_unicode as ppu
|
||||||
|
@ -25,7 +25,7 @@ class ParseBaseException(Exception):
|
||||||
self,
|
self,
|
||||||
pstr: str,
|
pstr: str,
|
||||||
loc: int = 0,
|
loc: int = 0,
|
||||||
msg: Optional[str] = None,
|
msg: typing.Optional[str] = None,
|
||||||
elem=None,
|
elem=None,
|
||||||
):
|
):
|
||||||
self.loc = loc
|
self.loc = loc
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# helpers.py
|
# helpers.py
|
||||||
import html.entities
|
import html.entities
|
||||||
import re
|
import re
|
||||||
|
import typing
|
||||||
|
|
||||||
from . import __diag__
|
from . import __diag__
|
||||||
from .core import *
|
from .core import *
|
||||||
|
@ -14,8 +15,8 @@ def delimited_list(
|
||||||
expr: Union[str, ParserElement],
|
expr: Union[str, ParserElement],
|
||||||
delim: Union[str, ParserElement] = ",",
|
delim: Union[str, ParserElement] = ",",
|
||||||
combine: bool = False,
|
combine: bool = False,
|
||||||
min: OptionalType[int] = None,
|
min: typing.Optional[int] = None,
|
||||||
max: OptionalType[int] = None,
|
max: typing.Optional[int] = None,
|
||||||
*,
|
*,
|
||||||
allow_trailing_delim: bool = False,
|
allow_trailing_delim: bool = False,
|
||||||
) -> ParserElement:
|
) -> ParserElement:
|
||||||
|
@ -69,9 +70,9 @@ def delimited_list(
|
||||||
|
|
||||||
def counted_array(
|
def counted_array(
|
||||||
expr: ParserElement,
|
expr: ParserElement,
|
||||||
int_expr: OptionalType[ParserElement] = None,
|
int_expr: typing.Optional[ParserElement] = None,
|
||||||
*,
|
*,
|
||||||
intExpr: OptionalType[ParserElement] = None,
|
intExpr: typing.Optional[ParserElement] = None,
|
||||||
) -> ParserElement:
|
) -> ParserElement:
|
||||||
"""Helper to define a counted list of expressions.
|
"""Helper to define a counted list of expressions.
|
||||||
|
|
||||||
|
@ -185,7 +186,9 @@ def match_previous_expr(expr: ParserElement) -> ParserElement:
|
||||||
def must_match_these_tokens(s, l, t):
|
def must_match_these_tokens(s, l, t):
|
||||||
theseTokens = _flatten(t.as_list())
|
theseTokens = _flatten(t.as_list())
|
||||||
if theseTokens != matchTokens:
|
if theseTokens != matchTokens:
|
||||||
raise ParseException(s, l, "Expected {}, found{}".format(matchTokens, theseTokens))
|
raise ParseException(
|
||||||
|
s, l, "Expected {}, found{}".format(matchTokens, theseTokens)
|
||||||
|
)
|
||||||
|
|
||||||
rep.set_parse_action(must_match_these_tokens, callDuringTry=True)
|
rep.set_parse_action(must_match_these_tokens, callDuringTry=True)
|
||||||
|
|
||||||
|
@ -195,7 +198,7 @@ def match_previous_expr(expr: ParserElement) -> ParserElement:
|
||||||
|
|
||||||
|
|
||||||
def one_of(
|
def one_of(
|
||||||
strs: Union[IterableType[str], str],
|
strs: Union[typing.Iterable[str], str],
|
||||||
caseless: bool = False,
|
caseless: bool = False,
|
||||||
use_regex: bool = True,
|
use_regex: bool = True,
|
||||||
as_keyword: bool = False,
|
as_keyword: bool = False,
|
||||||
|
@ -310,7 +313,7 @@ def one_of(
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
except sre_constants.error:
|
except re.error:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"Exception creating Regex for one_of, building MatchFirst", stacklevel=2
|
"Exception creating Regex for one_of, building MatchFirst", stacklevel=2
|
||||||
)
|
)
|
||||||
|
@ -335,7 +338,7 @@ def dict_of(key: ParserElement, value: ParserElement) -> ParserElement:
|
||||||
|
|
||||||
text = "shape: SQUARE posn: upper left color: light blue texture: burlap"
|
text = "shape: SQUARE posn: upper left color: light blue texture: burlap"
|
||||||
attr_expr = (label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join))
|
attr_expr = (label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join))
|
||||||
print(OneOrMore(attr_expr).parse_string(text).dump())
|
print(attr_expr[1, ...].parse_string(text).dump())
|
||||||
|
|
||||||
attr_label = label
|
attr_label = label
|
||||||
attr_value = Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join)
|
attr_value = Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join)
|
||||||
|
@ -350,10 +353,10 @@ def dict_of(key: ParserElement, value: ParserElement) -> ParserElement:
|
||||||
prints::
|
prints::
|
||||||
|
|
||||||
[['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
|
[['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
|
||||||
- color: light blue
|
- color: 'light blue'
|
||||||
- posn: upper left
|
- posn: 'upper left'
|
||||||
- shape: SQUARE
|
- shape: 'SQUARE'
|
||||||
- texture: burlap
|
- texture: 'burlap'
|
||||||
SQUARE
|
SQUARE
|
||||||
SQUARE
|
SQUARE
|
||||||
{'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'}
|
{'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'}
|
||||||
|
@ -459,7 +462,7 @@ def locatedExpr(expr: ParserElement) -> ParserElement:
|
||||||
def nested_expr(
|
def nested_expr(
|
||||||
opener: Union[str, ParserElement] = "(",
|
opener: Union[str, ParserElement] = "(",
|
||||||
closer: Union[str, ParserElement] = ")",
|
closer: Union[str, ParserElement] = ")",
|
||||||
content: OptionalType[ParserElement] = None,
|
content: typing.Optional[ParserElement] = None,
|
||||||
ignore_expr: ParserElement = quoted_string(),
|
ignore_expr: ParserElement = quoted_string(),
|
||||||
*,
|
*,
|
||||||
ignoreExpr: ParserElement = quoted_string(),
|
ignoreExpr: ParserElement = quoted_string(),
|
||||||
|
@ -680,6 +683,8 @@ def make_xml_tags(
|
||||||
return _makeTags(tag_str, True)
|
return _makeTags(tag_str, True)
|
||||||
|
|
||||||
|
|
||||||
|
any_open_tag: ParserElement
|
||||||
|
any_close_tag: ParserElement
|
||||||
any_open_tag, any_close_tag = make_html_tags(
|
any_open_tag, any_close_tag = make_html_tags(
|
||||||
Word(alphas, alphanums + "_:").set_name("any tag")
|
Word(alphas, alphanums + "_:").set_name("any tag")
|
||||||
)
|
)
|
||||||
|
@ -708,7 +713,7 @@ InfixNotationOperatorSpec = Union[
|
||||||
InfixNotationOperatorArgType,
|
InfixNotationOperatorArgType,
|
||||||
int,
|
int,
|
||||||
OpAssoc,
|
OpAssoc,
|
||||||
OptionalType[ParseAction],
|
typing.Optional[ParseAction],
|
||||||
],
|
],
|
||||||
Tuple[
|
Tuple[
|
||||||
InfixNotationOperatorArgType,
|
InfixNotationOperatorArgType,
|
||||||
|
@ -758,10 +763,14 @@ def infix_notation(
|
||||||
a tuple or list of functions, this is equivalent to calling
|
a tuple or list of functions, this is equivalent to calling
|
||||||
``set_parse_action(*fn)``
|
``set_parse_action(*fn)``
|
||||||
(:class:`ParserElement.set_parse_action`)
|
(:class:`ParserElement.set_parse_action`)
|
||||||
- ``lpar`` - expression for matching left-parentheses
|
- ``lpar`` - expression for matching left-parentheses; if passed as a
|
||||||
(default= ``Suppress('(')``)
|
str, then will be parsed as Suppress(lpar). If lpar is passed as
|
||||||
- ``rpar`` - expression for matching right-parentheses
|
an expression (such as ``Literal('(')``), then it will be kept in
|
||||||
(default= ``Suppress(')')``)
|
the parsed results, and grouped with them. (default= ``Suppress('(')``)
|
||||||
|
- ``rpar`` - expression for matching right-parentheses; if passed as a
|
||||||
|
str, then will be parsed as Suppress(rpar). If rpar is passed as
|
||||||
|
an expression (such as ``Literal(')')``), then it will be kept in
|
||||||
|
the parsed results, and grouped with them. (default= ``Suppress(')')``)
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
|
@ -803,9 +812,17 @@ def infix_notation(
|
||||||
_FB.__name__ = "FollowedBy>"
|
_FB.__name__ = "FollowedBy>"
|
||||||
|
|
||||||
ret = Forward()
|
ret = Forward()
|
||||||
lpar = Suppress(lpar)
|
if isinstance(lpar, str):
|
||||||
rpar = Suppress(rpar)
|
lpar = Suppress(lpar)
|
||||||
lastExpr = base_expr | (lpar + ret + rpar)
|
if isinstance(rpar, str):
|
||||||
|
rpar = Suppress(rpar)
|
||||||
|
|
||||||
|
# if lpar and rpar are not suppressed, wrap in group
|
||||||
|
if not (isinstance(rpar, Suppress) and isinstance(rpar, Suppress)):
|
||||||
|
lastExpr = base_expr | Group(lpar + ret + rpar)
|
||||||
|
else:
|
||||||
|
lastExpr = base_expr | (lpar + ret + rpar)
|
||||||
|
|
||||||
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]
|
||||||
if isinstance(opExpr, str_type):
|
if isinstance(opExpr, str_type):
|
||||||
|
@ -826,7 +843,7 @@ 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().set_name(term_name)
|
thisExpr: Forward = Forward().set_name(term_name)
|
||||||
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, ...])
|
||||||
|
@ -931,7 +948,7 @@ def indentedBlock(blockStatementExpr, indentStack, indent=True, backup_stacks=[]
|
||||||
assignment = Group(identifier + "=" + rvalue)
|
assignment = Group(identifier + "=" + rvalue)
|
||||||
stmt << (funcDef | assignment | identifier)
|
stmt << (funcDef | assignment | identifier)
|
||||||
|
|
||||||
module_body = OneOrMore(stmt)
|
module_body = stmt[1, ...]
|
||||||
|
|
||||||
parseTree = module_body.parseString(data)
|
parseTree = module_body.parseString(data)
|
||||||
parseTree.pprint()
|
parseTree.pprint()
|
||||||
|
@ -1041,7 +1058,9 @@ python_style_comment = Regex(r"#.*").set_name("Python style comment")
|
||||||
|
|
||||||
# build list of built-in expressions, for future reference if a global default value
|
# build list of built-in expressions, for future reference if a global default value
|
||||||
# gets updated
|
# gets updated
|
||||||
_builtin_exprs = [v for v in vars().values() if isinstance(v, ParserElement)]
|
_builtin_exprs: List[ParserElement] = [
|
||||||
|
v for v in vars().values() if isinstance(v, ParserElement)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
# pre-PEP8 compatible names
|
# pre-PEP8 compatible names
|
||||||
|
|
0
lib/pyparsing/py.typed
Normal file
0
lib/pyparsing/py.typed
Normal file
|
@ -65,9 +65,9 @@ class ParseResults:
|
||||||
'month' in result -> True
|
'month' in result -> True
|
||||||
'minutes' in result -> False
|
'minutes' in result -> False
|
||||||
result.dump() -> ['1999', '/', '12', '/', '31']
|
result.dump() -> ['1999', '/', '12', '/', '31']
|
||||||
- day: 31
|
- day: '31'
|
||||||
- month: 12
|
- month: '12'
|
||||||
- year: 1999
|
- year: '1999'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_null_values: Tuple[Any, ...] = (None, [], "", ())
|
_null_values: Tuple[Any, ...] = (None, [], "", ())
|
||||||
|
@ -287,7 +287,7 @@ class ParseResults:
|
||||||
print(numlist.parse_string("0 123 321")) # -> ['123', '321']
|
print(numlist.parse_string("0 123 321")) # -> ['123', '321']
|
||||||
|
|
||||||
label = Word(alphas)
|
label = Word(alphas)
|
||||||
patt = label("LABEL") + OneOrMore(Word(nums))
|
patt = label("LABEL") + Word(nums)[1, ...]
|
||||||
print(patt.parse_string("AAB 123 321").dump())
|
print(patt.parse_string("AAB 123 321").dump())
|
||||||
|
|
||||||
# Use pop() in a parse action to remove named result (note that corresponding value is not
|
# Use pop() in a parse action to remove named result (note that corresponding value is not
|
||||||
|
@ -301,7 +301,7 @@ class ParseResults:
|
||||||
prints::
|
prints::
|
||||||
|
|
||||||
['AAB', '123', '321']
|
['AAB', '123', '321']
|
||||||
- LABEL: AAB
|
- LABEL: 'AAB'
|
||||||
|
|
||||||
['AAB', '123', '321']
|
['AAB', '123', '321']
|
||||||
"""
|
"""
|
||||||
|
@ -394,7 +394,7 @@ class ParseResults:
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
patt = OneOrMore(Word(alphas))
|
patt = Word(alphas)[1, ...]
|
||||||
|
|
||||||
# use a parse action to append the reverse of the matched strings, to make a palindrome
|
# use a parse action to append the reverse of the matched strings, to make a palindrome
|
||||||
def make_palindrome(tokens):
|
def make_palindrome(tokens):
|
||||||
|
@ -487,7 +487,7 @@ class ParseResults:
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
patt = OneOrMore(Word(alphas))
|
patt = Word(alphas)[1, ...]
|
||||||
result = patt.parse_string("sldkj lsdkj sldkj")
|
result = patt.parse_string("sldkj lsdkj sldkj")
|
||||||
# even though the result prints in string-like form, it is actually a pyparsing ParseResults
|
# even though the result prints in string-like form, it is actually a pyparsing ParseResults
|
||||||
print(type(result), result) # -> <class 'pyparsing.ParseResults'> ['sldkj', 'lsdkj', 'sldkj']
|
print(type(result), result) # -> <class 'pyparsing.ParseResults'> ['sldkj', 'lsdkj', 'sldkj']
|
||||||
|
@ -554,7 +554,7 @@ class ParseResults:
|
||||||
user_data = (Group(house_number_expr)("house_number")
|
user_data = (Group(house_number_expr)("house_number")
|
||||||
| Group(ssn_expr)("ssn")
|
| Group(ssn_expr)("ssn")
|
||||||
| Group(integer)("age"))
|
| Group(integer)("age"))
|
||||||
user_info = OneOrMore(user_data)
|
user_info = user_data[1, ...]
|
||||||
|
|
||||||
result = user_info.parse_string("22 111-22-3333 #221B")
|
result = user_info.parse_string("22 111-22-3333 #221B")
|
||||||
for item in result:
|
for item in result:
|
||||||
|
@ -603,15 +603,15 @@ class ParseResults:
|
||||||
integer = Word(nums)
|
integer = Word(nums)
|
||||||
date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
|
date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
|
||||||
|
|
||||||
result = date_str.parse_string('12/31/1999')
|
result = date_str.parse_string('1999/12/31')
|
||||||
print(result.dump())
|
print(result.dump())
|
||||||
|
|
||||||
prints::
|
prints::
|
||||||
|
|
||||||
['12', '/', '31', '/', '1999']
|
['1999', '/', '12', '/', '31']
|
||||||
- day: 1999
|
- day: '31'
|
||||||
- month: 31
|
- month: '12'
|
||||||
- year: 12
|
- year: '1999'
|
||||||
"""
|
"""
|
||||||
out = []
|
out = []
|
||||||
NL = "\n"
|
NL = "\n"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# testing.py
|
# testing.py
|
||||||
|
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from typing import Optional
|
import typing
|
||||||
|
|
||||||
from .core import (
|
from .core import (
|
||||||
ParserElement,
|
ParserElement,
|
||||||
|
@ -237,12 +237,12 @@ class pyparsing_test:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def with_line_numbers(
|
def with_line_numbers(
|
||||||
s: str,
|
s: str,
|
||||||
start_line: Optional[int] = None,
|
start_line: typing.Optional[int] = None,
|
||||||
end_line: Optional[int] = None,
|
end_line: typing.Optional[int] = None,
|
||||||
expand_tabs: bool = True,
|
expand_tabs: bool = True,
|
||||||
eol_mark: str = "|",
|
eol_mark: str = "|",
|
||||||
mark_spaces: Optional[str] = None,
|
mark_spaces: typing.Optional[str] = None,
|
||||||
mark_control: Optional[str] = None,
|
mark_control: typing.Optional[str] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Helpful method for debugging a parser - prints a string with line and column numbers.
|
Helpful method for debugging a parser - prints a string with line and column numbers.
|
||||||
|
|
|
@ -120,7 +120,18 @@ class pyparsing_unicode(unicode_set):
|
||||||
A namespace class for defining common language unicode_sets.
|
A namespace class for defining common language unicode_sets.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_ranges: UnicodeRangeList = [(32, sys.maxunicode)]
|
# fmt: off
|
||||||
|
|
||||||
|
# define ranges in language character sets
|
||||||
|
_ranges: UnicodeRangeList = [
|
||||||
|
(0x0020, sys.maxunicode),
|
||||||
|
]
|
||||||
|
|
||||||
|
class BasicMultilingualPlane(unicode_set):
|
||||||
|
"Unicode set for the Basic Multilingual Plane"
|
||||||
|
_ranges: UnicodeRangeList = [
|
||||||
|
(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"
|
||||||
|
@ -278,11 +289,13 @@ class pyparsing_unicode(unicode_set):
|
||||||
|
|
||||||
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"
|
||||||
pass
|
|
||||||
|
|
||||||
class Thai(unicode_set):
|
class Thai(unicode_set):
|
||||||
"Unicode set for Thai Unicode Character Range"
|
"Unicode set for Thai Unicode Character Range"
|
||||||
_ranges: UnicodeRangeList = [(0x0E01, 0x0E3A), (0x0E3F, 0x0E5B)]
|
_ranges: UnicodeRangeList = [
|
||||||
|
(0x0E01, 0x0E3A),
|
||||||
|
(0x0E3F, 0x0E5B)
|
||||||
|
]
|
||||||
|
|
||||||
class Arabic(unicode_set):
|
class Arabic(unicode_set):
|
||||||
"Unicode set for Arabic Unicode Character Range"
|
"Unicode set for Arabic Unicode Character Range"
|
||||||
|
@ -308,7 +321,12 @@ 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 = [(0x0900, 0x097F), (0xA8E0, 0xA8FF)]
|
_ranges: UnicodeRangeList = [
|
||||||
|
(0x0900, 0x097F),
|
||||||
|
(0xA8E0, 0xA8FF)
|
||||||
|
]
|
||||||
|
|
||||||
|
# fmt: on
|
||||||
|
|
||||||
|
|
||||||
pyparsing_unicode.Japanese._ranges = (
|
pyparsing_unicode.Japanese._ranges = (
|
||||||
|
@ -317,7 +335,9 @@ pyparsing_unicode.Japanese._ranges = (
|
||||||
+ pyparsing_unicode.Japanese.Katakana._ranges
|
+ pyparsing_unicode.Japanese.Katakana._ranges
|
||||||
)
|
)
|
||||||
|
|
||||||
# define ranges in language character sets
|
pyparsing_unicode.BMP = pyparsing_unicode.BasicMultilingualPlane
|
||||||
|
|
||||||
|
# add language identifiers using language Unicode
|
||||||
pyparsing_unicode.العربية = pyparsing_unicode.Arabic
|
pyparsing_unicode.العربية = pyparsing_unicode.Arabic
|
||||||
pyparsing_unicode.中文 = pyparsing_unicode.Chinese
|
pyparsing_unicode.中文 = pyparsing_unicode.Chinese
|
||||||
pyparsing_unicode.кириллица = pyparsing_unicode.Cyrillic
|
pyparsing_unicode.кириллица = pyparsing_unicode.Cyrillic
|
||||||
|
|
|
@ -31,7 +31,7 @@ plexapi==4.9.2
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
profilehooks==1.12.0
|
profilehooks==1.12.0
|
||||||
PyJWT==2.3.0
|
PyJWT==2.3.0
|
||||||
pyparsing==3.0.7
|
pyparsing==3.0.9
|
||||||
python-dateutil==2.8.2
|
python-dateutil==2.8.2
|
||||||
python-twitter==3.5
|
python-twitter==3.5
|
||||||
pytz==2022.1
|
pytz==2022.1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue