You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
FixtureRequest.node should be typed to return a Node #13888
Currently the property node of FixtureRequest is defined as
@property@abc.abstractmethoddefnode(self):
"""Underlying collection node (depends on current request scope)."""raiseNotImplementedError()
which implicitly types the return type as Any. However, based on the name of the function and the underlying implementations it should return a nodes.Node.
Unfortunately, when I tried this on a fork, I got the following error:
mypy............................................................................Failed
- hook id: mypy
- exit code: 1
src/_pytest/junitxml.py:294: error: "Node" has no attribute "user_properties" [attr-defined]
Found 1 error in 1 file (checked 239 source files)
This happens because junitxml actually expects to receive a nodes.NodeItem instead of a plain nodes.Node.
One quick fix for this would be to put a type assertion in junitxml, but I'm not sure if that's the preferred approach. I'd be happy to send a PR if someone could give ve some guidance on how to best resolve this.
We actually don't expose Node, but it's mostly equivalent to Item | Collector.
However, the reason we don't type request.node is that returning a general Item | Collector would often be annoying, since the user knows that it's a more specific node type (e.g. Function) but the typing cannot know that. So we opt for less type safety over forcing users to do assert isinstance or casts.
Thanks Ran for the response, I had not noticed that nodes.Node is not exported.
Typing it as Item | Collector would work for our use case as we are accessing nodeid (request.node.nodeid). Having types is important as without the type annotations we need to type the result explicitly.
I understand that adding types in the presence of subclass may become annoying specially when one knows the type must be of certain class. However, I would argue that these assumptions could be error prone as those assumptions may change, specially for users of pytest (inside pytest assumptions should be safer). In fact, in the particular case of pytest, the proposed change would only require an instance check in junitxml.
Note also that given that Node is not exported, if we wanted to type request.node on the consumer side, we would need to somehow know that this is equivalent to Item | Collector. Maybe a reference could be added to the docs.
Reacted by Oskar Haarklou Veileborg and Contrabang
Activity
bluetech commentedon Nov 10, 2025
We actually don't expose
Node, but it's mostly equivalent toItem | Collector.However, the reason we don't type
request.nodeis that returning a generalItem | Collectorwould often be annoying, since the user knows that it's a more specific node type (e.g.Function) but the typing cannot know that. So we opt for less type safety over forcing users to doassert isinstanceorcasts.sk- commentedon Nov 10, 2025
Thanks Ran for the response, I had not noticed that
nodes.Nodeis not exported.Typing it as
Item | Collectorwould work for our use case as we are accessing nodeid (request.node.nodeid). Having types is important as without the type annotations we need to type the result explicitly.I understand that adding types in the presence of subclass may become annoying specially when one knows the type must be of certain class. However, I would argue that these assumptions could be error prone as those assumptions may change, specially for users of pytest (inside pytest assumptions should be safer). In fact, in the particular case of pytest, the proposed change would only require an instance check in junitxml.
Note also that given that
Nodeis not exported, if we wanted to typerequest.nodeon the consumer side, we would need to somehow know that this is equivalent toItem | Collector. Maybe a reference could be added to the docs.Annotate FixtureRequest.node as returning Any
Document why FixtureRequest.node is not type-annotated