diff --git a/changelog/8447.deprecation.rst b/changelog/8447.deprecation.rst new file mode 100644 index 00000000000..098ca89be75 --- /dev/null +++ b/changelog/8447.deprecation.rst @@ -0,0 +1,4 @@ +Warn when inheritance is used to bring Collectors into Items, +it was never sanely supported and triggers hard to debug errors. + +Instead of inheritance composition should be used. diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 40bc4d4965b..9ff4c1325ba 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -34,6 +34,7 @@ from _pytest.pathlib import absolutepath from _pytest.pathlib import commonpath from _pytest.store import Store +from _pytest.warning_types import PytestWarning if TYPE_CHECKING: # Imported here due to circular import. @@ -610,6 +611,19 @@ class Item(Node): nextitem = None + def __init_subclass__(cls): + problems = ", ".join( + base.__name__ for base in cls.__bases__ if issubclass(base, Collector) + ) + if problems: + warnings.warn( + f"{cls.__name__} is a Item subclass and should not be a collector.\n" + f"however its bases {problems} are collectors\n" + "please split the collection and the items into 2 node types\n" + "TODO: doc link", + PytestWarning, + ) + def __init__( self, name, diff --git a/testing/test_nodes.py b/testing/test_nodes.py index 4d7e6cba2ae..5b989f727b8 100644 --- a/testing/test_nodes.py +++ b/testing/test_nodes.py @@ -39,6 +39,16 @@ def test_node_from_parent_disallowed_arguments() -> None: nodes.Node.from_parent(None, config=None) # type: ignore[arg-type] +def test_subclassing_node_with_item_warns() -> None: + + with pytest.warns( + PytestWarning, match="SoWrong is a Item subclass and should not be a collector" + ): + + class SoWrong(nodes.Item, nodes.File): + pass + + @pytest.mark.parametrize( "warn_type, msg", [(DeprecationWarning, "deprecated"), (PytestWarning, "pytest")] )