Skip to content

Commit

Permalink
Merge pull request #7660 from nicoddemus/deprecated-features
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoddemus committed Aug 19, 2020
2 parents c98525b + 372a094 commit d69abff
Show file tree
Hide file tree
Showing 20 changed files with 105 additions and 806 deletions.
18 changes: 18 additions & 0 deletions changelog/5585.breaking.rst
@@ -0,0 +1,18 @@
As per our policy, the following features have been deprecated in the 5.X series and are now
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.

* The default value for ``junit_family`` has changed to ``xunit2``. If you require the old format, add ``junit_family=xunit1`` to your configuration file.

* The ``TerminalReporter`` no longer has a ``writer`` attribute. Plugin authors may use the public functions of the ``TerminalReporter`` instead of accessing the ``TerminalWriter`` object directly.

* The ``--result-log`` option has been removed. Users are recommended to use the `pytest-reportlog <https://github.com/pytest-dev/pytest-reportlog>`__ plugin instead.


For more information consult
`Deprecations and Removals <https://docs.pytest.org/en/stable/deprecations.html>`__ in the docs.
126 changes: 72 additions & 54 deletions doc/en/deprecations.rst
Expand Up @@ -30,11 +30,19 @@ This hook has an `item` parameter which cannot be serialized by ``pytest-xdist``
Use the ``pytest_warning_recored`` hook instead, which replaces the ``item`` parameter
by a ``nodeid`` parameter.

The ``pytest.collect`` module
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. deprecated:: 6.0

The ``pytest.collect`` module is no longer part of the public API, all its names
should now be imported from ``pytest`` directly instead.


The ``pytest._fillfuncargs`` function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. deprecated:: 5.5
.. deprecated:: 6.0

This function was kept for backward compatibility with an older plugin.

Expand All @@ -43,6 +51,11 @@ it, use `function._request._fillfixtures()` instead, though note this is not
a public API and may break in the future.


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.

``--no-print-logs`` command-line option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -59,38 +72,46 @@ display captured output when tests fail: ``no``, ``stdout``, ``stderr``, ``log``



Node Construction changed to ``Node.from_parent``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Result log (``--result-log``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. deprecated:: 5.4
.. deprecated:: 4.0
.. versionremoved:: 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.
The ``--result-log`` option produces a stream of test reports which can be
analysed at runtime, but it uses a custom format which requires users to implement their own
parser.

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")`.
The `pytest-reportlog <https://github.com/pytest-dev/pytest-reportlog>`__ plugin provides a ``--report-log`` option, a more standard and extensible alternative, producing
one JSON object per-line, and should cover the same use cases. Please try it out and provide feedback.

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:
The ``pytest-reportlog`` plugin might even be merged into the core
at some point, depending on the plans for the plugins and number of users using it.

.. code-block:: python
``pytest_collect_directory`` hook
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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)
.. versionremoved:: 6.0

Note that ``from_parent`` should only be called with keyword arguments for the parameters.
The ``pytest_collect_directory`` has not worked properly for years (it was called
but the results were ignored). Users may consider using :func:`pytest_collection_modifyitems <_pytest.hookspec.pytest_collection_modifyitems>` instead.

TerminalReporter.writer
~~~~~~~~~~~~~~~~~~~~~~~

.. versionremoved:: 6.0

The ``TerminalReporter.writer`` attribute has been deprecated and should no longer be used. This
was inadvertently exposed as part of the public API of that plugin and ties it too much
with ``py.io.TerminalWriter``.

Plugins that used ``TerminalReporter.writer`` directly should instead use ``TerminalReporter``
methods that provide the same functionality.

``junit_family`` default value change to "xunit2"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. deprecated:: 5.2
.. versionchanged:: 6.0

The default value of ``junit_family`` option will change to ``xunit2`` in pytest 6.0, which
is an update of the old ``xunit1`` format and is supported by default in modern tools
Expand Down Expand Up @@ -126,55 +147,52 @@ Services known to support the ``xunit2`` format:
* `Jenkins <https://www.jenkins.io/>`__ with the `JUnit <https://plugins.jenkins.io/junit>`__ plugin.
* `Azure Pipelines <https://azure.microsoft.com/en-us/services/devops/pipelines>`__.

Node Construction changed to ``Node.from_parent``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``funcargnames`` alias for ``fixturenames``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. deprecated:: 5.0

The ``FixtureRequest``, ``Metafunc``, and ``Function`` classes track the names of
their associated fixtures, with the aptly-named ``fixturenames`` attribute.
.. versionchanged:: 6.0

Prior to pytest 2.3, this attribute was named ``funcargnames``, and we have kept
that as an alias since. It is finally due for removal, as it is often confusing
in places where we or plugin authors must distinguish between fixture names and
names supplied by non-fixture things such as ``pytest.mark.parametrize``.
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")`.

Result log (``--result-log``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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:

.. deprecated:: 4.0
.. code-block:: python
The ``--result-log`` option produces a stream of test reports which can be
analysed at runtime, but it uses a custom format which requires users to implement their own
parser.
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)
The `pytest-reportlog <https://github.com/pytest-dev/pytest-reportlog>`__ plugin provides a ``--report-log`` option, a more standard and extensible alternative, producing
one JSON object per-line, and should cover the same use cases. Please try it out and provide feedback.
Note that ``from_parent`` should only be called with keyword arguments for the parameters.

The plan is remove the ``--result-log`` option in pytest 6.0 if ``pytest-reportlog`` proves satisfactory
to all users and is deemed stable. The ``pytest-reportlog`` plugin might even be merged into the core
at some point, depending on the plans for the plugins and number of users using it.

TerminalReporter.writer
~~~~~~~~~~~~~~~~~~~~~~~
``pytest.fixture`` arguments are keyword only
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. deprecated:: 5.4
.. versionremoved:: 6.0

The ``TerminalReporter.writer`` attribute has been deprecated and should no longer be used. This
was inadvertently exposed as part of the public API of that plugin and ties it too much
with ``py.io.TerminalWriter``.
Passing arguments to pytest.fixture() as positional arguments has been removed - pass them by keyword instead.

Plugins that used ``TerminalReporter.writer`` directly should instead use ``TerminalReporter``
methods that provide the same functionality.
``funcargnames`` alias for ``fixturenames``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. versionremoved:: 6.0

Removed Features
----------------
The ``FixtureRequest``, ``Metafunc``, and ``Function`` classes track the names of
their associated fixtures, with the aptly-named ``fixturenames`` attribute.

As stated in our :ref:`backwards-compatibility` policy, deprecated features are removed only in major releases after
an appropriate period of deprecation has passed.
Prior to pytest 2.3, this attribute was named ``funcargnames``, and we have kept
that as an alias since. It is finally due for removal, as it is often confusing
in places where we or plugin authors must distinguish between fixture names and
names supplied by non-fixture things such as ``pytest.mark.parametrize``.


``pytest.config`` global
Expand Down
1 change: 0 additions & 1 deletion doc/en/reference.rst
Expand Up @@ -656,7 +656,6 @@ Collection hooks

.. autofunction:: pytest_collection
.. autofunction:: pytest_ignore_collect
.. autofunction:: pytest_collect_directory
.. autofunction:: pytest_collect_file
.. autofunction:: pytest_pycollect_makemodule

Expand Down
1 change: 0 additions & 1 deletion src/_pytest/config/__init__.py
Expand Up @@ -239,7 +239,6 @@ def directory_arg(path: str, optname: str) -> str:
"nose",
"assertion",
"junitxml",
"resultlog",
"doctest",
"cacheprovider",
"freeze_support",
Expand Down
39 changes: 0 additions & 39 deletions src/_pytest/deprecated.py
Expand Up @@ -19,58 +19,19 @@
"pytest_faulthandler",
}

FUNCARGNAMES = PytestDeprecationWarning(
"The `funcargnames` attribute was an alias for `fixturenames`, "
"since pytest 2.3 - use the newer attribute instead."
)

FILLFUNCARGS = PytestDeprecationWarning(
"The `_fillfuncargs` function is deprecated, use "
"function._request._fillfixtures() instead if you cannot avoid reaching into internals."
)

RESULT_LOG = PytestDeprecationWarning(
"--result-log is deprecated, please try the new pytest-reportlog plugin.\n"
"See https://docs.pytest.org/en/stable/deprecations.html#result-log-result-log for more information."
)

FIXTURE_POSITIONAL_ARGUMENTS = PytestDeprecationWarning(
"Passing arguments to pytest.fixture() as positional arguments is deprecated - pass them "
"as a keyword argument instead."
)

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"
" https://docs.pytest.org/en/stable/deprecations.html#junit-family-default-value-change-to-xunit2\n"
"for more information."
)

COLLECT_DIRECTORY_HOOK = PytestDeprecationWarning(
"The pytest_collect_directory hook is not working.\n"
"Please use collect_ignore in conftests or pytest_collection_modifyitems."
)

PYTEST_COLLECT_MODULE = UnformattedWarning(
PytestDeprecationWarning,
"pytest.collect.{name} was moved to pytest.{name}\n"
"Please update to the new name.",
)


TERMINALWRITER_WRITER = PytestDeprecationWarning(
"The TerminalReporter.writer attribute is deprecated, use TerminalReporter._tw instead at your own risk.\n"
"See https://docs.pytest.org/en/stable/deprecations.html#terminalreporter-writer for more information."
)


MINUS_K_DASH = PytestDeprecationWarning(
"The `-k '-expr'` syntax to -k is deprecated.\nUse `-k 'not expr'` instead."
)
Expand Down
58 changes: 1 addition & 57 deletions src/_pytest/fixtures.py
Expand Up @@ -2,7 +2,6 @@
import inspect
import os
import sys
import warnings
from collections import defaultdict
from collections import deque
from types import TracebackType
Expand Down Expand Up @@ -46,8 +45,6 @@
from _pytest.config import _PluggyPlugin
from _pytest.config import Config
from _pytest.config.argparsing import Parser
from _pytest.deprecated import FIXTURE_POSITIONAL_ARGUMENTS
from _pytest.deprecated import FUNCARGNAMES
from _pytest.mark import ParameterSet
from _pytest.outcomes import fail
from _pytest.outcomes import TEST_OUTCOME
Expand Down Expand Up @@ -457,12 +454,6 @@ def fixturenames(self) -> List[str]:
result.extend(set(self._fixture_defs).difference(result))
return result

@property
def funcargnames(self) -> List[str]:
"""Alias attribute for ``fixturenames`` for pre-2.3 compatibility."""
warnings.warn(FUNCARGNAMES, stacklevel=2)
return self.fixturenames

@property
def node(self):
"""Underlying collection node (depends on current request scope)."""
Expand Down Expand Up @@ -1253,7 +1244,7 @@ def fixture( # noqa: F811

def fixture( # noqa: F811
fixture_function: Optional[_FixtureFunction] = None,
*args: Any,
*,
scope: "Union[_Scope, Callable[[str, Config], _Scope]]" = "function",
params: Optional[Iterable[object]] = None,
autouse: bool = False,
Expand Down Expand Up @@ -1315,53 +1306,6 @@ def fixture( # noqa: F811
name the decorated function ``fixture_<fixturename>`` and then use
``@pytest.fixture(name='<fixturename>')``.
"""
# Positional arguments backward compatibility.
# If a kwarg is equal to its default, assume it was not explicitly
# passed, i.e. not duplicated. The more correct way is to use a
# **kwargs and check `in`, but that obfuscates the function signature.
if isinstance(fixture_function, str):
# It's actually the first positional argument, scope.
args = (fixture_function, *args) # type: ignore[unreachable]
fixture_function = None
duplicated_args = []
if len(args) > 0:
if scope == "function":
scope = args[0]
else:
duplicated_args.append("scope")
if len(args) > 1:
if params is None:
params = args[1]
else:
duplicated_args.append("params")
if len(args) > 2:
if autouse is False:
autouse = args[2]
else:
duplicated_args.append("autouse")
if len(args) > 3:
if ids is None:
ids = args[3]
else:
duplicated_args.append("ids")
if len(args) > 4:
if name is None:
name = args[4]
else:
duplicated_args.append("name")
if len(args) > 5:
raise TypeError(
"fixture() takes 5 positional arguments but {} were given".format(len(args))
)
if duplicated_args:
raise TypeError(
"The fixture arguments are defined as positional and keyword: {}. "
"Use only keyword arguments.".format(", ".join(duplicated_args))
)
if args:
warnings.warn(FIXTURE_POSITIONAL_ARGUMENTS, stacklevel=2)
# End backward compatiblity.

fixture_marker = FixtureFunctionMarker(
scope=scope, params=params, autouse=autouse, ids=ids, name=name,
)
Expand Down
11 changes: 0 additions & 11 deletions src/_pytest/hookspec.py
Expand Up @@ -12,7 +12,6 @@
import py.path
from pluggy import HookspecMarker

from .deprecated import COLLECT_DIRECTORY_HOOK
from _pytest.compat import TYPE_CHECKING

if TYPE_CHECKING:
Expand Down Expand Up @@ -262,16 +261,6 @@ def pytest_ignore_collect(path: py.path.local, config: "Config") -> Optional[boo
"""


@hookspec(firstresult=True, warn_on_impl=COLLECT_DIRECTORY_HOOK)
def pytest_collect_directory(path: py.path.local, parent) -> Optional[object]:
"""Called before traversing a directory for collection files.
Stops at first non-None result, see :ref:`firstresult`.
:param py.path.local path: The path to analyze.
"""


def pytest_collect_file(path: py.path.local, parent) -> "Optional[Collector]":
"""Return collection Node or None for the given path.
Expand Down

0 comments on commit d69abff

Please sign in to comment.