From 68b985346b3fba4360a1edfbbfd642a95dbd393b Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 14 Nov 2023 16:44:55 +0100 Subject: [PATCH] add type annotations, pass over Node to more --- src/_pytest/main.py | 1 + src/_pytest/nodes.py | 27 ++++++++++++++++++--------- testing/test_nodes.py | 2 +- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 47ebad471..919f9faf9 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -545,6 +545,7 @@ class Session(nodes.Collector): ``Session`` collects the initial paths given as arguments to pytest. """ + parent: None Interrupted = Interrupted Failed = Failed # Set on the session by runner.pytest_sessionstart. diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 6d3a6d8c1..ea3a46781 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -138,8 +138,13 @@ class Node(abc.ABC, metaclass=NodeMeta): #: for methods not migrated to ``pathlib.Path`` yet, such as #: :meth:`Item.reportinfo `. Will be deprecated in #: a future release, prefer using :attr:`path` instead. + name: str + parent: Node | None + config: Config + session: Session fspath: LEGACY_PATH + _nodeid: str # Use __slots__ to make attribute access faster. # Note that __dict__ is still available. __slots__ = ( @@ -156,7 +161,7 @@ class Node(abc.ABC, metaclass=NodeMeta): def __init__( self, name: str, - parent: Node | None = None, + parent: Node | None, config: Config | None = None, session: Session | None = None, fspath: LEGACY_PATH | None = None, @@ -200,13 +205,9 @@ class Node(abc.ABC, metaclass=NodeMeta): #: Allow adding of extra keywords to use for matching. self.extra_keyword_matches: set[str] = set() - if nodeid is not None: - assert "::()" not in nodeid - self._nodeid = nodeid - else: - if not self.parent: - raise TypeError("nodeid or parent must be provided") - self._nodeid = self.parent.nodeid + "::" + self.name + self._nodeid = self._make_nodeid( + name=self.name, parent=self.parent, given=nodeid + ) #: A place where plugins can store information on the node for their #: own use. @@ -214,6 +215,15 @@ class Node(abc.ABC, metaclass=NodeMeta): # Deprecated alias. Was never public. Can be removed in a few releases. self._store = self.stash + @classmethod + def _make_nodeid(cls, name: str, parent: Node | None, given: str | None) -> str: + if given is not None: + assert "::()" not in given + return given + else: + assert parent is not None + return f"{parent.nodeid}::{name}" + @classmethod def from_parent(cls, parent: Node, **kw) -> Self: """Public constructor for Nodes. @@ -598,7 +608,6 @@ class FSCollector(Collector, abc.ABC): if nodeid and os.sep != SEP: nodeid = nodeid.replace(os.sep, SEP) - super().__init__( name=name, parent=parent, diff --git a/testing/test_nodes.py b/testing/test_nodes.py index f039acf24..e85f21578 100644 --- a/testing/test_nodes.py +++ b/testing/test_nodes.py @@ -31,7 +31,7 @@ def test_node_direct_construction_deprecated() -> None: " for more details." ), ): - nodes.Node(None, session=None) # type: ignore[arg-type] + nodes.Node(None, parent=None, session=None) # type: ignore[arg-type] def test_subclassing_both_item_and_collector_deprecated(