mark/structures: micro-optimize item.keywords/NodeKeywords

This commit is contained in:
Ran Benita 2021-10-05 16:30:57 +03:00
parent 54811b24e2
commit c4b9b14a44
1 changed files with 25 additions and 8 deletions

View File

@ -539,6 +539,8 @@ MARK_GEN = MarkGenerator(_ispytest=True)
@final
class NodeKeywords(MutableMapping[str, Any]):
__slots__ = ("node", "parent", "_markers")
def __init__(self, node: "Node") -> None:
self.node = node
self.parent = node.parent
@ -555,21 +557,36 @@ class NodeKeywords(MutableMapping[str, Any]):
def __setitem__(self, key: str, value: Any) -> None:
self._markers[key] = value
# Note: we could've avoided explicitly implementing some of the methods
# below and use the collections.abc fallback, but that would be slow.
def __contains__(self, key: object) -> bool:
return (
key in self._markers
or self.parent is not None
and key in self.parent.keywords
)
def update( # type: ignore[override]
self,
other: Union[Mapping[str, Any], Iterable[Tuple[str, Any]]] = (),
**kwds: Any,
) -> None:
self._markers.update(other)
self._markers.update(kwds)
def __delitem__(self, key: str) -> None:
raise ValueError("cannot delete key in keywords dict")
def __iter__(self) -> Iterator[str]:
seen = self._seen()
return iter(seen)
def _seen(self) -> Set[str]:
seen = set(self._markers)
yield from self._markers
if self.parent is not None:
seen.update(self.parent.keywords)
return seen
yield from self.parent.keywords
def __len__(self) -> int:
return len(self._seen())
return len(self._markers) + (
len(self.parent.keywords) if self.parent is not None else 0
)
def __repr__(self) -> str:
return f"<NodeKeywords for node {self.node}>"