]>
git.madduck.net Git - etc/vim.git/blobdiff - src/blib2to3/pytree.py
madduck's git repository
Every one of the projects in this repository is available at the canonical
URL git://git.madduck.net/madduck/pub/<projectpath> — see
each project's metadata for the exact URL.
All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@ git. madduck. net .
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
SSH access, as well as push access can be individually
arranged .
If you use my repositories frequently, consider adding the following
snippet to ~/.gitconfig and using the third clone URL listed for each
project:
[url "git://git.madduck.net/madduck/"]
insteadOf = madduck:
There's also a pattern matching implementation here.
"""
There's also a pattern matching implementation here.
"""
-# mypy: allow-untyped-defs
+# mypy: allow-untyped-defs, allow-incomplete-defs
from typing import (
Any,
from typing import (
Any,
Iterator,
List,
Optional,
Iterator,
List,
Optional,
- Set,
- Iterable,
- Sequence,
from blib2to3.pgen2.grammar import Grammar
__author__ = "Guido van Rossum <guido@python.org>"
from blib2to3.pgen2.grammar import Grammar
__author__ = "Guido van Rossum <guido@python.org>"
import sys
from io import StringIO
import sys
from io import StringIO
-HUGE: int = 0x7fffffff # maximum repeat count, default max
+HUGE: int = 0x7FFFFFFF # maximum repeat count, default max
-_type_reprs: Dict[int, Union[Text , int]] = {}
+_type_reprs: Dict[int, Union[str , int]] = {}
-def type_repr(type_num: int) -> Union[Text , int]:
+def type_repr(type_num: int) -> Union[str , int]:
global _type_reprs
if not _type_reprs:
from .pygram import python_symbols
global _type_reprs
if not _type_reprs:
from .pygram import python_symbols
return _type_reprs.setdefault(type_num, type_num)
return _type_reprs.setdefault(type_num, type_num)
+_P = TypeVar("_P", bound="Base" )
NL = Union["Node", "Leaf"]
NL = Union["Node", "Leaf"]
-Context = Tuple[Text , Tuple[int, int]]
-RawNode = Tuple[int, Optional[Text ], Optional[Context], Optional[List[NL]]]
+Context = Tuple[str , Tuple[int, int]]
+RawNode = Tuple[int, Optional[str ], Optional[Context], Optional[List[NL]]]
"""
Abstract base class for Node and Leaf.
"""
Abstract base class for Node and Leaf.
return NotImplemented
return self._eq(other)
return NotImplemented
return self._eq(other)
- __hash__ = None # type: Any # For Py3 compatibility.
-
- def prefix(self) -> Text :
+ def prefix(self) -> str :
raise NotImplementedError
def _eq(self: _P, other: _P) -> bool:
raise NotImplementedError
def _eq(self: _P, other: _P) -> bool:
"""
raise NotImplementedError
"""
raise NotImplementedError
+ def __deepcopy__(self: _P, memo: Any) -> _P:
+ return self.clone()
+
def clone(self: _P) -> _P:
"""
Return a cloned (deep) copy of self.
def clone(self: _P) -> _P:
"""
Return a cloned (deep) copy of self.
return 0
return 1 + self.parent.depth()
return 0
return 1 + self.parent.depth()
- def get_suffix(self) -> Text :
+ def get_suffix(self) -> str :
"""
Return the string immediately following the invocant node. This is
effectively equivalent to node.next_sibling.prefix
"""
Return the string immediately following the invocant node. This is
effectively equivalent to node.next_sibling.prefix
"""Concrete implementation for interior nodes."""
fixers_applied: Optional[List[Any]]
"""Concrete implementation for interior nodes."""
fixers_applied: Optional[List[Any]]
- used_names: Optional[Set[Text ]]
+ used_names: Optional[Set[str ]]
def __init__(
self,
type: int,
children: List[NL],
context: Optional[Any] = None,
def __init__(
self,
type: int,
children: List[NL],
context: Optional[Any] = None,
- prefix: Optional[Text ] = None,
+ prefix: Optional[str ] = None,
fixers_applied: Optional[List[Any]] = None,
) -> None:
"""
fixers_applied: Optional[List[Any]] = None,
) -> None:
"""
else:
self.fixers_applied = None
else:
self.fixers_applied = None
- def __repr__(self) -> Text :
+ def __repr__(self) -> str :
"""Return a canonical string representation."""
assert self.type is not None
"""Return a canonical string representation."""
assert self.type is not None
- return "%s(%s, %r)" % (
+ return "{}({}, {!r})".format (
self.__class__.__name__,
type_repr(self.type),
self.children,
)
self.__class__.__name__,
type_repr(self.type),
self.children,
)
- def __str__(self) -> Text :
+ def __str__(self) -> str :
"""
Return a pretty string representation.
"""
Return a pretty string representation.
"""
return "".join(map(str, self.children))
"""
return "".join(map(str, self.children))
- def _eq(self, other) -> bool:
+ def _eq(self, other: Base ) -> bool:
"""Compare two nodes for equality."""
return (self.type, self.children) == (other.type, other.children)
"""Compare two nodes for equality."""
return (self.type, self.children) == (other.type, other.children)
yield from child.pre_order()
@property
yield from child.pre_order()
@property
- def prefix(self) -> Text :
+ def prefix(self) -> str :
"""
The whitespace and comments preceding this node in the input.
"""
"""
The whitespace and comments preceding this node in the input.
"""
return self.children[0].prefix
@prefix.setter
return self.children[0].prefix
@prefix.setter
- def prefix(self, prefix) -> None:
+ def prefix(self, prefix: str ) -> None:
if self.children:
self.children[0].prefix = prefix
if self.children:
self.children[0].prefix = prefix
"""Concrete implementation for leaf nodes."""
# Default values for instance variables
"""Concrete implementation for leaf nodes."""
# Default values for instance variables
fixers_applied: List[Any]
bracket_depth: int
fixers_applied: List[Any]
bracket_depth: int
- opening_bracket: "Leaf"
- used_names: Optional[Set[Text]]
+ # Changed later in brackets.py
+ opening_bracket: Optional["Leaf"] = None
+ used_names: Optional[Set[str]]
_prefix = "" # Whitespace and comments preceding this token in the input
lineno: int = 0 # Line where this token starts in the input
column: int = 0 # Column where this token starts in the input
_prefix = "" # Whitespace and comments preceding this token in the input
lineno: int = 0 # Line where this token starts in the input
column: int = 0 # Column where this token starts in the input
+ # If not None, this Leaf is created by converting a block of fmt off/skip
+ # code, and `fmt_pass_converted_first_leaf` points to the first Leaf in the
+ # converted code.
+ fmt_pass_converted_first_leaf: Optional["Leaf"] = None
def __init__(
self,
type: int,
def __init__(
self,
type: int,
context: Optional[Context] = None,
context: Optional[Context] = None,
- prefix: Optional[Text ] = None,
+ prefix: Optional[str ] = None,
fixers_applied: List[Any] = [],
fixers_applied: List[Any] = [],
+ opening_bracket: Optional["Leaf"] = None,
+ fmt_pass_converted_first_leaf: Optional["Leaf"] = None,
) -> None:
"""
Initializer.
) -> None:
"""
Initializer.
self._prefix = prefix
self.fixers_applied: Optional[List[Any]] = fixers_applied[:]
self.children = []
self._prefix = prefix
self.fixers_applied: Optional[List[Any]] = fixers_applied[:]
self.children = []
+ self.opening_bracket = opening_bracket
+ self.fmt_pass_converted_first_leaf = fmt_pass_converted_first_leaf
def __repr__(self) -> str:
"""Return a canonical string representation."""
from .pgen2.token import tok_name
assert self.type is not None
def __repr__(self) -> str:
"""Return a canonical string representation."""
from .pgen2.token import tok_name
assert self.type is not None
- return "%s(%s, %r)" % (
+ return "{}({}, {!r})".format (
self.__class__.__name__,
tok_name.get(self.type, self.type),
self.value,
)
self.__class__.__name__,
tok_name.get(self.type, self.type),
self.value,
)
- def __str__(self) -> Text :
+ def __str__(self) -> str :
"""
Return a pretty string representation.
This reproduces the input source exactly.
"""
"""
Return a pretty string representation.
This reproduces the input source exactly.
"""
- return self.prefix + str(self.value)
+ return self._ prefix + str(self.value)
- def _eq(self, other) -> bool:
+ def _eq(self, other: "Leaf" ) -> bool:
"""Compare two nodes for equality."""
return (self.type, self.value) == (other.type, other.value)
"""Compare two nodes for equality."""
return (self.type, self.value) == (other.type, other.value)
- def prefix(self) -> Text :
+ def prefix(self) -> str :
"""
The whitespace and comments preceding this token in the input.
"""
return self._prefix
@prefix.setter
"""
The whitespace and comments preceding this token in the input.
"""
return self._prefix
@prefix.setter
- def prefix(self, prefix) -> None:
+ def prefix(self, prefix: str ) -> None:
self.changed()
self._prefix = prefix
self.changed()
self._prefix = prefix
return Leaf(type, value or "", context=context)
return Leaf(type, value or "", context=context)
-_Results = Dict[Text, NL]
-
+_Results = Dict[str, NL]
-class BasePattern(object):
"""
A pattern is a tree matching pattern.
"""
A pattern is a tree matching pattern.
type: Optional[int]
type = None # Node type (token if < 256, symbol if >= 256)
content: Any = None # Optional content matching pattern
type: Optional[int]
type = None # Node type (token if < 256, symbol if >= 256)
content: Any = None # Optional content matching pattern
- name: Optional[Text ] = None # Optional name used to store match in results dict
+ name: Optional[str ] = None # Optional name used to store match in results dict
def __new__(cls, *args, **kwds):
"""Constructor that prevents BasePattern from being instantiated."""
assert cls is not BasePattern, "Cannot instantiate BasePattern"
return object.__new__(cls)
def __new__(cls, *args, **kwds):
"""Constructor that prevents BasePattern from being instantiated."""
assert cls is not BasePattern, "Cannot instantiate BasePattern"
return object.__new__(cls)
- def __repr__(self) -> Text :
+ def __repr__(self) -> str :
assert self.type is not None
args = [type_repr(self.type), self.content, self.name]
while args and args[-1] is None:
del args[-1]
assert self.type is not None
args = [type_repr(self.type), self.content, self.name]
while args and args[-1] is None:
del args[-1]
- return "%s(%s)" % (self.__class__.__name__, ", ".join(map(repr, args)))
+ return "{}({})".format (self.__class__.__name__, ", ".join(map(repr, args)))
def _submatch(self, node, results=None) -> bool:
raise NotImplementedError
def _submatch(self, node, results=None) -> bool:
raise NotImplementedError
def __init__(
self,
type: Optional[int] = None,
def __init__(
self,
type: Optional[int] = None,
- content: Optional[Text ] = None,
- name: Optional[Text ] = None,
+ content: Optional[str ] = None,
+ name: Optional[str ] = None,
) -> None:
"""
Initializer. Takes optional type, content, and name.
) -> None:
"""
Initializer. Takes optional type, content, and name.
self.content = content
self.name = name
self.content = content
self.name = name
- def match(self, node: NL, results=None):
+ def match(self, node: NL, results=None) -> bool :
"""Override match() to insist on a leaf node."""
if not isinstance(node, Leaf):
return False
"""Override match() to insist on a leaf node."""
if not isinstance(node, Leaf):
return False
class NodePattern(BasePattern):
class NodePattern(BasePattern):
wildcards: bool = False
def __init__(
self,
type: Optional[int] = None,
wildcards: bool = False
def __init__(
self,
type: Optional[int] = None,
- content: Optional[Iterable[Text ]] = None,
- name: Optional[Text ] = None,
+ content: Optional[Iterable[str ]] = None,
+ name: Optional[str ] = None,
) -> None:
"""
Initializer. Takes optional type, content, and name.
) -> None:
"""
Initializer. Takes optional type, content, and name.
newcontent = list(content)
for i, item in enumerate(newcontent):
assert isinstance(item, BasePattern), (i, item)
newcontent = list(content)
for i, item in enumerate(newcontent):
assert isinstance(item, BasePattern), (i, item)
- if isinstance(item, WildcardPattern):
- self.wildcards = True
+ # I don't even think this code is used anywhere, but it does cause
+ # unreachable errors from mypy. This function's signature does look
+ # odd though *shrug*.
+ if isinstance(item, WildcardPattern): # type: ignore[unreachable]
+ self.wildcards = True # type: ignore[unreachable]
- self.content = newcontent
+ self.content = newcontent # TODO: this is unbound when content is None
self.name = name
def _submatch(self, node, results=None) -> bool:
self.name = name
def _submatch(self, node, results=None) -> bool:
class WildcardPattern(BasePattern):
class WildcardPattern(BasePattern):
"""
A wildcard pattern can match zero or more nodes.
"""
A wildcard pattern can match zero or more nodes.
- content: Optional[Text ] = None,
+ content: Optional[str ] = None,
min: int = 0,
max: int = HUGE,
min: int = 0,
max: int = HUGE,
- name: Optional[Text ] = None,
+ name: Optional[str ] = None,
) -> None:
"""
Initializer.
) -> None:
"""
Initializer.
class NegatedPattern(BasePattern):
class NegatedPattern(BasePattern):
- def __init__(self, content: Optional[Any ] = None) -> None:
+ def __init__(self, content: Optional[BasePattern ] = None) -> None:
# We only match an empty sequence of nodes in its entirety
return len(nodes) == 0
# We only match an empty sequence of nodes in its entirety
return len(nodes) == 0
- def generate_matches(self, nodes) -> Iterator[Tuple[int, _Results]]:
+ def generate_matches(self, nodes: List[NL] ) -> Iterator[Tuple[int, _Results]]:
if self.content is None:
# Return a match if there is an empty sequence
if len(nodes) == 0:
if self.content is None:
# Return a match if there is an empty sequence
if len(nodes) == 0:
r.update(r0)
r.update(r1)
yield c0 + c1, r
r.update(r0)
r.update(r1)
yield c0 + c1, r
-
-
-_Convert = Callable[[Grammar, RawNode], Any]