Skip to content

Deprecate and remove nose pluginΒ #9886

@nicoddemus

Description

@nicoddemus

nose has long been in maintenance only mode, and we support it via our nose.py plugin.

The nose.py plugin however is not trivial to maintain, and it dips its toes in a few places through the code:

def isnosetest(self, obj: object) -> bool:
"""Look for the __test__ attribute, which is applied by the
@nose.tools.istest decorator.
"""
# We explicitly check for "is True" here to not mistakenly treat
# classes with a custom __getattr__ returning something truthy (like a
# function) as test classes.
return safe_getattr(obj, "__test__", False) is True

has_nose = self.config.pluginmanager.has_plugin("nose")

has_nose = self.config.pluginmanager.has_plugin("nose")

# This is actually only needed for nose, which reuses unittest.SkipTest for
# its own nose.SkipTest. For unittest TestCases, SkipTest is already
# handled internally, and doesn't reach here.

Also it can cause confusion such as in #9549.

Perhaps it is time to deprecate nose, and eventually removing it? If there is a large test suite which still requires this, they can just pin pytest until the last version that still supports it.

It could become a third party plugin. but unless someone volunteers to do it, I don't think it should be pytest's core responsibility to maintain such a plugin.


How to deprecate it?

nose.py actually just handles calling the nose-specific setup and teardown methods:

@hookimpl(trylast=True)
def pytest_runtest_setup(item: Item) -> None:
if not isinstance(item, Function):
return
# Don't do nose style setup/teardown on direct unittest style classes.
if isinstance(item, TestCaseFunction):
return
# Capture the narrowed type of item for the teardown closure,
# see https://github.com/python/mypy/issues/2608
func = item
call_optional(func.obj, "setup")
func.addfinalizer(lambda: call_optional(func.obj, "teardown"))
# NOTE: Module- and class-level fixtures are handled in python.py
# with `pluginmanager.has_plugin("nose")` checks.
# It would have been nicer to implement them outside of core, but
# it's not straightforward.

We could issue a deprecation warning when one of those functions are called, which AFAIK is basically what our nose support entails.

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: deprecationfeature that will be removed in the futuretype: proposalproposal for a new feature, often to gather opinions or design the API around the new feature

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions