diff --git a/changelog/6981.deprecation.rst b/changelog/6981.deprecation.rst new file mode 100644 index 00000000000..ac32706faec --- /dev/null +++ b/changelog/6981.deprecation.rst @@ -0,0 +1 @@ +Deprecate the ``pytest.collect`` module as it's just aliases into ``pytest``. diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 1845d9d91ef..8aff8d57da4 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -336,30 +336,6 @@ def safe_isclass(obj: object) -> bool: return False -COLLECT_FAKEMODULE_ATTRIBUTES = ( - "Collector", - "Module", - "Function", - "Instance", - "Session", - "Item", - "Class", - "File", - "_fillfuncargs", -) - - -def _setup_collect_fakemodule() -> None: - from types import ModuleType - import pytest - - # Types ignored because the module is created dynamically. - pytest.collect = ModuleType("pytest.collect") # type: ignore - pytest.collect.__all__ = [] # type: ignore # used for setns - for attr_name in COLLECT_FAKEMODULE_ATTRIBUTES: - setattr(pytest.collect, attr_name, getattr(pytest, attr_name)) # type: ignore - - class CaptureIO(io.TextIOWrapper): def __init__(self) -> None: super().__init__(io.BytesIO(), encoding="UTF-8", newline="", write_through=True) diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 28ca02550d4..ba1a43fcbff 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -55,3 +55,9 @@ "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.", +) diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 33bc3d0fbe5..5c93decc3c5 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -2,9 +2,9 @@ """ pytest: unit and functional testing with Python. """ +from . import collect from _pytest import __version__ from _pytest.assertion import register_assert_rewrite -from _pytest.compat import _setup_collect_fakemodule from _pytest.config import cmdline from _pytest.config import ExitCode from _pytest.config import hookimpl @@ -46,7 +46,6 @@ from _pytest.warning_types import PytestUnknownMarkWarning from _pytest.warning_types import PytestWarning - set_trace = __pytestPDB.set_trace __all__ = [ @@ -55,6 +54,7 @@ "approx", "Class", "cmdline", + "collect", "Collector", "deprecated_call", "exit", @@ -93,7 +93,3 @@ "xfail", "yield_fixture", ] - - -_setup_collect_fakemodule() -del _setup_collect_fakemodule diff --git a/src/pytest/collect.py b/src/pytest/collect.py new file mode 100644 index 00000000000..73c9d35a0df --- /dev/null +++ b/src/pytest/collect.py @@ -0,0 +1,38 @@ +import sys +import warnings +from types import ModuleType + +import pytest +from _pytest.deprecated import PYTEST_COLLECT_MODULE + + +COLLECT_FAKEMODULE_ATTRIBUTES = [ + "Collector", + "Module", + "Function", + "Instance", + "Session", + "Item", + "Class", + "File", + "_fillfuncargs", +] + + +class FakeCollectModule(ModuleType): + def __init__(self): + super().__init__("pytest.collect") + self.__all__ = list(COLLECT_FAKEMODULE_ATTRIBUTES) + self.__pytest = pytest + + def __dir__(self): + return dir(super()) + self.__all__ + + def __getattr__(self, name): + if name not in self.__all__: + raise AttributeError(name) + warnings.warn(PYTEST_COLLECT_MODULE.format(name=name), stacklevel=2) + return getattr(pytest, name) + + +sys.modules["pytest.collect"] = FakeCollectModule() diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index b5c66d9f5f1..bea7a0fdcbf 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -25,6 +25,13 @@ def test(): ) +@pytest.mark.parametrize("attribute", pytest.collect.__all__) # type: ignore +# false positive due to dynamic attribute +def test_pytest_collect_module_deprecated(attribute): + with pytest.warns(DeprecationWarning, match=attribute): + getattr(pytest.collect, attribute) + + def test_terminal_reporter_writer_attr(pytestconfig): """Check that TerminalReporter._tw is also available as 'writer' (#2984) This attribute has been deprecated in 5.4.