From 396a7def751cd7d6c615f9d81d5a49f2b50bfeaa Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 27 Jan 2022 11:49:18 +0100 Subject: [PATCH] Add additional docs for uncooperative ctor deprecation (#9498) * Add additional docs for uncooperative ctor deprecation Fixes #9488 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Break up long line * Recommend kwonly args Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- doc/en/deprecations.rst | 38 ++++++++++++++++++++++++++++ doc/en/example/nonpython/conftest.py | 4 +-- src/_pytest/nodes.py | 5 +++- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index a667fc4cc..d9fb4d6b0 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -56,6 +56,10 @@ Plugins which implement custom items and collectors are encouraged to replace ``fspath`` parameters (``py.path.local``) with ``path`` parameters (``pathlib.Path``), and drop any other usage of the ``py`` library if possible. +If possible, plugins with custom items should use :ref:`cooperative +constructors ` to avoid hardcoding +arguments they only pass on to the superclass. + .. note:: The name of the :class:`~_pytest.nodes.Node` arguments and attributes (the new attribute being ``path``) is **the opposite** of the situation for @@ -191,6 +195,40 @@ Instead, a separate collector node should be used, which collects the item. See .. _example pr fixing inheritance: https://github.com/asmeurer/pytest-flakes/pull/40/files +.. _uncooperative-constructors-deprecated: + +Constructors of custom :class:`pytest.Node` subclasses should take ``**kwargs`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 7.0 + +If custom subclasses of nodes like :class:`pytest.Item` override the +``__init__`` method, they should take ``**kwargs``. Thus, + +.. code-block:: python + + class CustomItem(pytest.Item): + def __init__(self, name, parent, additional_arg): + super().__init__(name, parent) + self.additional_arg = additional_arg + +should be turned into: + +.. code-block:: python + + class CustomItem(pytest.Item): + def __init__(self, *, additional_arg, **kwargs): + super().__init__(**kwargs) + self.additional_arg = additional_arg + +to avoid hard-coding the arguments pytest can pass to the superclass. +See :ref:`non-python tests` for a full example. + +For cases without conflicts, no deprecation warning is emitted. For cases with +conflicts (such as :class:`pytest.File` now taking ``path`` instead of +``fspath``, as :ref:`outlined above `), a +deprecation warning is now raised. + Backward compatibilities in ``Parser.addoption`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/en/example/nonpython/conftest.py b/doc/en/example/nonpython/conftest.py index 7ec413403..bc39a1f6b 100644 --- a/doc/en/example/nonpython/conftest.py +++ b/doc/en/example/nonpython/conftest.py @@ -18,8 +18,8 @@ class YamlFile(pytest.File): class YamlItem(pytest.Item): - def __init__(self, name, parent, spec): - super().__init__(name, parent) + def __init__(self, *, spec, **kwargs): + super().__init__(**kwargs) self.spec = spec def runtest(self): diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 53dea04e7..6e8454ad7 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -145,7 +145,10 @@ class NodeMeta(type): warnings.warn( PytestDeprecationWarning( - f"{self} is not using a cooperative constructor and only takes {set(known_kw)}" + f"{self} is not using a cooperative constructor and only takes {set(known_kw)}.\n" + "See https://docs.pytest.org/en/stable/deprecations.html" + "#constructors-of-custom-pytest-node-subclasses-should-take-kwargs " + "for more details." ) )