Hard failure when constructing Node subclasses

This commit is contained in:
Bruno Oliveira 2020-08-17 17:34:28 -03:00
parent c747dc5248
commit 73e06373dc
5 changed files with 36 additions and 56 deletions

View File

@ -4,3 +4,5 @@ removed:
* The ``funcargnames`` read-only property of ``FixtureRequest``, ``Metafunc``, and ``Function`` classes. Use ``fixturenames`` attribute.
* ``@pytest.fixture`` no longer supports positional arguments, pass all arguments by keyword instead.
* Direct construction of ``Node`` subclasses now raise an error, use ``from_parent`` instead.

View File

@ -43,7 +43,6 @@ it, use `function._request._fillfixtures()` instead, though note this is not
a public API and may break in the future.
``--no-print-logs`` command-line option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -58,35 +57,6 @@ A ``--show-capture`` command-line option was added in ``pytest 3.5.0`` which all
display captured output when tests fail: ``no``, ``stdout``, ``stderr``, ``log`` or ``all`` (the default).
Node Construction changed to ``Node.from_parent``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 5.4
The construction of nodes now should use the named constructor ``from_parent``.
This limitation in api surface intends to enable better/simpler refactoring of the collection tree.
This means that instead of :code:`MyItem(name="foo", parent=collector, obj=42)`
one now has to invoke :code:`MyItem.from_parent(collector, name="foo")`.
Plugins that wish to support older versions of pytest and suppress the warning can use
`hasattr` to check if `from_parent` exists in that version:
.. code-block:: python
def pytest_pycollect_makeitem(collector, name, obj):
if hasattr(MyItem, "from_parent"):
item = MyItem.from_parent(collector, name="foo")
item.obj = 42
return item
else:
return MyItem(name="foo", parent=collector, obj=42)
Note that ``from_parent`` should only be called with keyword arguments for the parameters.
``junit_family`` default value change to "xunit2"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -162,6 +132,33 @@ Removed Features
As stated in our :ref:`backwards-compatibility` policy, deprecated features are removed only in major releases after
an appropriate period of deprecation has passed.
Node Construction changed to ``Node.from_parent``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 6.0
The construction of nodes now should use the named constructor ``from_parent``.
This limitation in api surface intends to enable better/simpler refactoring of the collection tree.
This means that instead of :code:`MyItem(name="foo", parent=collector, obj=42)`
one now has to invoke :code:`MyItem.from_parent(collector, name="foo")`.
Plugins that wish to support older versions of pytest and suppress the warning can use
`hasattr` to check if `from_parent` exists in that version:
.. code-block:: python
def pytest_pycollect_makeitem(collector, name, obj):
if hasattr(MyItem, "from_parent"):
item = MyItem.from_parent(collector, name="foo")
item.obj = 42
return item
else:
return MyItem(name="foo", parent=collector, obj=42)
Note that ``from_parent`` should only be called with keyword arguments for the parameters.
``pytest.fixture`` arguments are keyword only
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -30,13 +30,6 @@ RESULT_LOG = PytestDeprecationWarning(
"See https://docs.pytest.org/en/stable/deprecations.html#result-log-result-log for more information."
)
NODE_USE_FROM_PARENT = UnformattedWarning(
PytestDeprecationWarning,
"Direct construction of {name} has been deprecated, please use {name}.from_parent.\n"
"See "
"https://docs.pytest.org/en/stable/deprecations.html#node-construction-changed-to-node-from-parent"
" for more details.",
)
JUNIT_XML_DEFAULT_FAMILY = PytestDeprecationWarning(
"The 'junit_family' default value will change to 'xunit2' in pytest 6.0. See:\n"

View File

@ -26,7 +26,6 @@ from _pytest.compat import TYPE_CHECKING
from _pytest.config import Config
from _pytest.config import ConftestImportFailure
from _pytest.deprecated import FSCOLLECTOR_GETHOOKPROXY_ISINITPATH
from _pytest.deprecated import NODE_USE_FROM_PARENT
from _pytest.fixtures import FixtureDef
from _pytest.fixtures import FixtureLookupError
from _pytest.mark.structures import Mark
@ -97,8 +96,13 @@ _NodeType = TypeVar("_NodeType", bound="Node")
class NodeMeta(type):
def __call__(self, *k, **kw):
warnings.warn(NODE_USE_FROM_PARENT.format(name=self.__name__), stacklevel=2)
return super().__call__(*k, **kw)
msg = (
"Direct construction of {name} has been deprecated, please use {name}.from_parent.\n"
"See "
"https://docs.pytest.org/en/stable/deprecations.html#node-construction-changed-to-node-from-parent"
" for more details."
).format(name=self.__name__)
fail(msg, pytrace=False)
def _create(self, *k, **kw):
return super().__call__(*k, **kw)

View File

@ -1,11 +1,9 @@
import copy
import inspect
import warnings
from unittest import mock
import pytest
from _pytest import deprecated
from _pytest import nodes
from _pytest.config import Config
from _pytest.pytester import Testdir
@ -106,20 +104,6 @@ def test_warn_about_imminent_junit_family_default_change(testdir, junit_family):
result.stdout.fnmatch_lines([warning_msg])
def test_node_direct_ctor_warning() -> None:
class MockConfig:
pass
ms = MockConfig()
with pytest.warns(
DeprecationWarning,
match="Direct construction of .* has been deprecated, please use .*.from_parent.*",
) as w:
nodes.Node(name="test", config=ms, session=ms, nodeid="None") # type: ignore
assert w[0].lineno == inspect.currentframe().f_lineno - 1 # type: ignore
assert w[0].filename == __file__
@pytest.mark.skip(reason="should be reintroduced in 6.1: #7361")
def test_fillfuncargs_is_deprecated() -> None:
with pytest.warns(