Question: import inspect import os import sys<ins>import warnings</ins> from collections import defaultdict from collections import deque from types import TracebackType

Reintroduce warnings postponed in 6.0 A few warnings were introduced near the 6.0 release, so we can't comply with the "2 versions minimum with warnings", so for 6.0 these warnings were suppressed in We should reintroduce them in 6.1.


Question: from _pytest.config import _PluggyPlugin from _pytest.config import Config from _pytest.config.argparsing import Parser<ins>from _pytest.deprecated import FILLFUNCARGS</ins> from _pytest.mark import ParameterSet from _pytest.outcomes import fail from _pytest.outcomes import TEST_OUTCOME


Question: def fillfixtures(function: "Function") -> None:     """Fill missing funcargs for a test function."""    # Uncomment this after 6.0 release (#7361)    # warnings.warn(FILLFUNCARGS, stacklevel=2)    warnings.warn(FILLFUNCARGS, stacklevel=2)     try:         request = function._request     except AttributeError:diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py-- a/src/_pytest/hookspec.py++ b/src/_pytest/hookspec.py


Question: from pluggy import HookspecMarker  from _pytest.compat import TYPE_CHECKING<ins>from _pytest.deprecated import WARNING_CAPTURED_HOOK</ins>  if TYPE_CHECKING:     import pdb


Question: """  # Uncomment this after 6.0 release (#7361)# @hookspec(historic=True, warn_on_impl=WARNING_CAPTURED_HOOK)@hookspec(historic=True)@hookspec(historic=True, warn_on_impl=WARNING_CAPTURED_HOOK) def pytest_warning_captured(     warning_message: "warnings.WarningMessage",     when: "Literal['config', 'collect', 'runtest']",diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py-- a/src/_pytest/mark/__init__.py++ b/src/_pytest/mark/__init__.py


Question: """Generic mechanism for marking and selecting python functions.""" import typing<ins>import warnings</ins> from typing import AbstractSet from typing import List from typing import Optional


Question: from _pytest.config import hookimpl from _pytest.config import UsageError from _pytest.config.argparsing import Parser<ins>from _pytest.deprecated import MINUS_K_COLONfrom _pytest.deprecated import MINUS_K_DASH</ins> from _pytest.store import StoreKey  if TYPE_CHECKING:


Question: if keywordexpr.startswith("-"):         # To be removed in pytest 7.0.0.        # Uncomment this after 6.0 release (#7361)        # warnings.warn(MINUS_K_DASH, stacklevel=2)        warnings.warn(MINUS_K_DASH, stacklevel=2)         keywordexpr = "not " + keywordexpr[1:]     selectuntil = False     if keywordexpr[-1:] == ":":         # To be removed in pytest 7.0.0.        # Uncomment this after 6.0 release (#7361)        # warnings.warn(MINUS_K_COLON, stacklevel=2)        warnings.warn(MINUS_K_COLON, stacklevel=2)         selectuntil = True         keywordexpr = keywordexpr[:-1] diff --git a/src/pytest/collect.py b/src/pytest/collect.py-- a/src/pytest/collect.py++ b/src/pytest/collect.py


Question: import sysimport warnings from types import ModuleType from typing import Any from typing import List  import pytestfrom _pytest.deprecated import PYTEST_COLLECT_MODULE  COLLECT_FAKEMODULE_ATTRIBUTES = [     "Collector",


Question: def __getattr__(self, name: str) -> Any:         if name not in self.__all__:             raise AttributeError(name)        # Uncomment this after 6.0 release (#7361)        # warnings.warn(PYTEST_COLLECT_MODULE.format(name=name), stacklevel=2)        warnings.warn(PYTEST_COLLECT_MODULE.format(name=name), stacklevel=2)         return getattr(pytest, name)


Question: "The pytest_warning_captured is deprecated and will be removed in a future release.\n"     "Please use pytest_warning_recorded instead." )FSCOLLECTOR_GETHOOKPROXY_ISINITPATH = PytestDeprecationWarning(    "The gethookproxy() and isinitpath() methods of FSCollector and Package are deprecated; "    "use self.session.gethookproxy() and self.session.isinitpath() instead. ")diff --git a/src/_pytest/main.py b/src/_pytest/main.py-- a/src/_pytest/main.py++ b/src/_pytest/main.py

Since pytest 6.0.0, pylint complains about unimplemented abstract methods in custom collector Hi, we have implemented a custom pytest collector that takes testcases from YAML files. Starting with pytest 6.0.0, pylint reports the following about that collector: The collector has worked fine for a long time, and it still works fine. The line pylint reports this on is the class definition of a collector class that is based on pytest.File: The whole source code is here: Versions: Python 3.8.0 (default, Oct 15 2019, 17:49:23). This happens on all Python 3.x versions we used pytest 6.0.1 with (3.5, 3.6, 3.7, 3.8), on macOS and Ubuntu. pylint 2.4.4 astroid 2.3.3 platform linux -- Python 3.8.0, pytest-6.0.1, py-1.9.0, pluggy-0.13.1 plugins: cov-2.10.0, yagot-0.5.0, requests-mock-1.8.0 Please let me know in case a collector has to implement these methods.


Question: from _pytest.config import directory_arg from _pytest.config import ExitCode from _pytest.config import hookimpl<ins>from _pytest.config import PytestPluginManager</ins> from _pytest.config import UsageError from _pytest.config.argparsing import Parser from _pytest.fixtures import FixtureManager


Question: items[:] = remaining  <ins>class FSHookProxy:    def __init__(self, pm: PytestPluginManager, remove_mods) -> None:        self.pm = pm        self.remove_mods = remove_mods    def __getattr__(self, name: str):        x = self.pm.subset_hook_caller(name, remove_plugins=self.remove_mods)        self.__dict__[name] = x        return x</ins> class NoMatch(Exception):     """Matching cannot locate matching names."""


Question: return path in self._initialpaths      def gethookproxy(self, fspath: py.path.local):        return super()._gethookproxy(fspath)        # Check if we have the common case of running        # hooks with all conftest.py files.        pm = self.config.pluginmanager        my_conftestmodules = pm._getconftestmodules(            fspath, self.config.getoption("importmode")        )        remove_mods = pm._conftest_plugins.difference(my_conftestmodules)        if remove_mods:            # One or more conftests are not in use at this fspath.            proxy = FSHookProxy(pm, remove_mods)        else:            # All plugins are active for this fspath.            proxy = self.config.hook        return proxy      @overload     def perform_collect(diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py-- a/src/_pytest/nodes.py++ b/src/_pytest/nodes.py


Question: from _pytest.compat import TYPE_CHECKING from _pytest.config import Config from _pytest.config import ConftestImportFailurefrom _pytest.config import PytestPluginManagerfrom _pytest.deprecated import FSCOLLECTOR_GETHOOKPROXY_ISINITPATH from _pytest.deprecated import NODE_USE_FROM_PARENT from _pytest.fixtures import FixtureDef from _pytest.fixtures import FixtureLookupError


Question: return fspath.relto(initial_path)  <del>class FSHookProxy:    def __init__(self, pm: PytestPluginManager, remove_mods) -> None:        self.pm = pm        self.remove_mods = remove_mods    def __getattr__(self, name: str):        x = self.pm.subset_hook_caller(name, remove_plugins=self.remove_mods)        self.__dict__[name] = x        return x</del> class FSCollector(Collector):     def __init__(         self,


Question: """The public constructor."""         return super().from_parent(parent=parent, fspath=fspath, **kw)     def _gethookproxy(self, fspath: py.path.local):        # Check if we have the common case of running        # hooks with all conftest.py files.        pm = self.config.pluginmanager        my_conftestmodules = pm._getconftestmodules(            fspath, self.config.getoption("importmode")        )        remove_mods = pm._conftest_plugins.difference(my_conftestmodules)        if remove_mods:            # One or more conftests are not in use at this fspath.            proxy = FSHookProxy(pm, remove_mods)        else:            # All plugins are active for this fspath.            proxy = self.config.hook        return proxy     def gethookproxy(self, fspath: py.path.local):        raise NotImplementedError()        warnings.warn(FSCOLLECTOR_GETHOOKPROXY_ISINITPATH, stacklevel=2)        return self.session.gethookproxy(fspath)    def isinitpath(self, path: py.path.local) -> bool:        warnings.warn(FSCOLLECTOR_GETHOOKPROXY_ISINITPATH, stacklevel=2)        return self.session.isinitpath(path)      def _recurse(self, direntry: "os.DirEntry[str]") -> bool:         if direntry.name == "__pycache__":             return False         path = py.path.local(direntry.path)        ihook = self._gethookproxy(path.dirpath())        ihook = self.session.gethookproxy(path.dirpath())         if ihook.pytest_ignore_collect(path=path, config=self.config):             return False         for pat in self._norecursepatterns:             if path.check(fnmatch=pat):                 return False        ihook = self._gethookproxy(path)        ihook = self.session.gethookproxy(path)         ihook.pytest_collect_directory(path=path, parent=self)         return True     def isinitpath(self, path: py.path.local) -> bool:        raise NotImplementedError()     def _collectfile(         self, path: py.path.local, handle_dupes: bool = True     ) -> Sequence[Collector]:


Question: ), "{!r} is not a file (isdir={!r}, exists={!r}, islink={!r})".format(             path, path.isdir(), path.exists(), path.islink()         )        ihook = self.gethookproxy(path)        if not self.isinitpath(path):        ihook = self.session.gethookproxy(path)        if not self.session.isinitpath(path):             if ihook.pytest_ignore_collect(path=path, config=self.config):                 return () diff --git a/src/_pytest/python.py b/src/_pytest/python.py-- a/src/_pytest/python.py++ b/src/_pytest/python.py


Question: from _pytest.config import ExitCode from _pytest.config import hookimpl from _pytest.config.argparsing import Parser<ins>from _pytest.deprecated import FSCOLLECTOR_GETHOOKPROXY_ISINITPATH</ins> from _pytest.deprecated import FUNCARGNAMES from _pytest.fixtures import FuncFixtureInfo from _pytest.main import Session


Question: self.addfinalizer(func)      def gethookproxy(self, fspath: py.path.local):        return super()._gethookproxy(fspath)        warnings.warn(FSCOLLECTOR_GETHOOKPROXY_ISINITPATH, stacklevel=2)        return self.session.gethookproxy(fspath)      def isinitpath(self, path: py.path.local) -> bool:        return path in self.session._initialpaths        warnings.warn(FSCOLLECTOR_GETHOOKPROXY_ISINITPATH, stacklevel=2)        return self.session.isinitpath(path)      def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]:         this_path = self.fspath.dirpath()


Question: # Save the original log-level to restore it during teardown.         self._initial_logger_levels.setdefault(logger, logger_obj.level)         logger_obj.setLevel(level)        self._initial_handler_level = self.handler.level        if self._initial_handler_level is None:            self._initial_handler_level = self.handler.level         self.handler.setLevel(level)      @contextmanager

logging: handler level restored incorrectly if caplog.setlevel is called more than once pytest version: 6.0.1 The fix in (backported to 6.0.1) has a bug where it does a "set" instead of "setdefault" to the . So if there are multiple calls to , the level will be restored to that of the one-before-last call, instead of the value before the test. Will submit a fix for this shortly.


Question: return                 expect_docstring = False             elif (                not isinstance(item, ast.ImportFrom)                or item.level > 0                or item.module != "__future__"                isinstance(item, ast.ImportFrom)                and item.level == 0                and item.module == "__future__"             ):                lineno = item.lineno                pass            else:                 break             pos += 1        # Special case: for a decorated function, set the lineno to that of the        # first decorator, not the `def`. Issue #4984.        if isinstance(item, ast.FunctionDef) and item.decorator_list:            lineno = item.decorator_list[0].lineno         else:             lineno = item.lineno         imports = [

Crash with NameError through decorator during collection pytest crashes when trying to collect the following file: The failure representation works with : I've started writing a test, but it fails in both modes like the first case above:


Question: from typing import List from typing import Optional<ins>from typing import TYPE_CHECKING</ins>  import pytest from _pytest import nodes

[Feature] Allow a --sw-skip shorthand cli arg like --sw itself permits The stepwise plugin exposes a shorthand option for the stepwise itself, however it requires a longer arg only for skip, I think these should be consistent and should offer shorthand versions for both. Expected:


Question: from _pytest.main import Session from _pytest.reports import TestReport <ins>if TYPE_CHECKING:    from _pytest.cacheprovider import CacheSTEPWISE_CACHE_DIR = "cache/stepwise"</ins>  def pytest_addoption(parser: Parser) -> None:     group = parser.getgroup("general")


Question: "--sw",         "--stepwise",         action="store_true",        default=False,         dest="stepwise",         help="exit on test failure and continue from last failing test next time",     )     group.addoption(        "--sw-skip",         "--stepwise-skip",         action="store_true",        default=False,         dest="stepwise_skip",         help="ignore the first failing test but stop on the next failing test",     )


Question: @pytest.hookimpl def pytest_configure(config: Config) -> None:    config.pluginmanager.register(StepwisePlugin(config), "stepwiseplugin")    # We should always have a cache as cache provider plugin uses tryfirst=True    if config.getoption("stepwise"):        config.pluginmanager.register(StepwisePlugin(config), "stepwiseplugin")def pytest_sessionfinish(session: Session) -> None:    if not session.config.getoption("stepwise"):        assert session.config.cache is not None        # Clear the list of failing tests if the plugin is not active.        session.config.cache.set(STEPWISE_CACHE_DIR, [])   class StepwisePlugin:     def __init__(self, config: Config) -> None:         self.config = config        self.active = config.getvalue("stepwise")         self.session: Optional[Session] = None         self.report_status = ""        if self.active:            assert config.cache is not None            self.lastfailed = config.cache.get("cache/stepwise", None)            self.skip = config.getvalue("stepwise_skip")        assert config.cache is not None        self.cache: Cache = config.cache        self.lastfailed: Optional[str] = self.cache.get(STEPWISE_CACHE_DIR, None)        self.skip: bool = config.getoption("stepwise_skip")      def pytest_sessionstart(self, session: Session) -> None:         self.session = session      def pytest_collection_modifyitems(        self, session: Session, config: Config, items: List[nodes.Item]        self, config: Config, items: List[nodes.Item]     ) -> None:        if not self.active:            return         if not self.lastfailed:             self.report_status = "no previously failed tests, not skipping."             return         already_passed = []        found = False        # Make a list of all tests that have been run before the last failing one.        for item in items:        # check all item nodes until we find a match on last failed        failed_index = None        for index, item in enumerate(items):             if item.nodeid == self.lastfailed:                found = True                failed_index = index                 break            else:                already_passed.append(item)          # If the previously failed test was not found among the test items,         # do not skip any tests.        if not found:        if failed_index is None:             self.report_status = "previously failed test not found, not skipping."            already_passed = []         else:            self.report_status = "skipping {} already passed items.".format(                len(already_passed)            )        for item in already_passed:            items.remove(item)        config.hook.pytest_deselected(items=already_passed)            self.report_status = f"skipping {failed_index} already passed items."            deselected = items[:failed_index]            del items[:failed_index]            config.hook.pytest_deselected(items=deselected)      def pytest_runtest_logreport(self, report: TestReport) -> None:        if not self.active:            return         if report.failed:             if self.skip:                 # Remove test from the failed ones (if it exists) and unset the skip option


Question: self.lastfailed = None      def pytest_report_collectionfinish(self) -> Optional[str]:        if self.active and self.config.getoption("verbose") >= 0 and self.report_status:            return "stepwise: %s" % self.report_status        if self.config.getoption("verbose") >= 0 and self.report_status:            return f"stepwise: {self.report_status}"         return None     def pytest_sessionfinish(self, session: Session) -> None:        assert self.config.cache is not None        if self.active:            self.config.cache.set("cache/stepwise", self.lastfailed)        else:            # Clear the list of failing tests if the plugin is not active.            self.config.cache.set("cache/stepwise", [])    def pytest_sessionfinish(self) -> None:        self.cache.set(STEPWISE_CACHE_DIR, self.lastfailed)


Question: entries = sorted(os.scandir(path), key=lambda entry: entry.name)     yield from entries     for entry in entries:        if entry.is_dir(follow_symlinks=False) and recurse(entry):        if entry.is_dir() and recurse(entry):             yield from visit(entry.path, recurse)

Symlinked directories not collected since pytest 6.1.0 When there is a symlink to a directory in a test directory, is is just skipped over, but it should be followed and collected as usual. This regressed in (included in 6.1.0). For some reason I a in there, I don't remember why, but it does not match the previous behavior and should be removed. PR for this is coming up.


Question: self._validate_plugins()         self._warn_about_skipped_plugins()         if self.known_args_namespace.strict:            self.issue_config_time_warning(                _pytest.deprecated.STRICT_OPTION, stacklevel=2            )         if self.known_args_namespace.confcutdir is None and self.inipath is not None:             confcutdir = str(self.inipath.parent)             self.known_args_namespace.confcutdir = confcutdirdiff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py-- a/src/_pytest/deprecated.py++ b/src/_pytest/deprecated.py

Deprecate I don't see the point in removing it in a release just to reintroduce it again, that just makes things more confusing for everyone. Originally posted by in


Question: "The gethookproxy() and isinitpath() methods of FSCollector and Package are deprecated; "     "use self.session.gethookproxy() and self.session.isinitpath() instead. " )STRICT_OPTION = PytestDeprecationWarning(    "The --strict option is deprecated, use --strict-markers instead.")diff --git a/src/_pytest/main.py b/src/_pytest/main.py-- a/src/_pytest/main.py++ b/src/_pytest/main.py


Question: )     group._addoption(         "--strict-markers",        "--strict",         action="store_true",         help="markers not registered in the `markers` section of the configuration file raise errors.",     )    group._addoption(        "--strict", action="store_true", help="(deprecated) alias to --strict-markers.",    )     group._addoption(         "-c",         metavar="file",diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py-- a/src/_pytest/mark/structures.py++ b/src/_pytest/mark/structures.py


Question: # If the name is not in the set of known marks after updating,             # then it really is time to issue a warning or an error.             if name not in self._markers:                if self._config.option.strict_markers:                if self._config.option.strict_markers or self._config.option.strict:                     fail(                         f"{name!r} not found in `markers` configuration option",                         pytrace=False,


Question: self._notfound.append((report_arg, col))                     continue                 # If __init__.py was the only file requested, then the matched node will be                # the corresponding Package, and the first yielded item will be the __init__                # Module itself, so just use that. If this special case isn't taken, then all                # the files in the package will be yielded.                if argpath.basename == "__init__.py":                    assert isinstance(matching[0], nodes.Collector)                # If __init__.py was the only file requested, then the matched                # node will be the corresponding Package (by default), and the                # first yielded item will be the __init__ Module itself, so                # just use that. If this special case isn't taken, then all the                # files in the package will be yielded.                if argpath.basename == "__init__.py" and isinstance(                    matching[0], Package                ):                     try:                         yield next(iter(matching[0].collect()))                     except StopIteration:

Doctest collection only returns single test for <!-- Thanks for submitting an issue! Quick check-list while reporting bugs: --will only collect a single doctest because of this: Introduced a while back by here: See failing tests: Failing doctest collection When the module is an the doctest collection only picks up 1 doctest.


Question: """Injects a hidden auto-use fixture to invoke setUpClass/setup_method and corresponding         teardown functions (#517)."""         class_fixture = _make_xunit_fixture(            cls, "setUpClass", "tearDownClass", scope="class", pass_self=False            cls,            "setUpClass",            "tearDownClass",            "doClassCleanups",            scope="class",            pass_self=False,         )         if class_fixture:             cls.__pytest_class_setup = class_fixture  # type: ignore[attr-defined]          method_fixture = _make_xunit_fixture(            cls, "setup_method", "teardown_method", scope="function", pass_self=True            cls,            "setup_method",            "teardown_method",            None,            scope="function",            pass_self=True,         )         if method_fixture:             cls.__pytest_method_setup = method_fixture  # type: ignore[attr-defined]   def _make_xunit_fixture(    obj: type, setup_name: str, teardown_name: str, scope: "_Scope", pass_self: bool    obj: type,    setup_name: str,    teardown_name: str,    cleanup_name: Optional[str],    scope: "_Scope",    pass_self: bool, ):     setup = getattr(obj, setup_name, None)     teardown = getattr(obj, teardown_name, None)     if setup is None and teardown is None:         return None     if cleanup_name:        cleanup = getattr(obj, cleanup_name, lambda *args: None)    else:        def cleanup(*args):            pass     @pytest.fixture(         scope=scope,         autouse=True,

Class cleanups in Python 3.8+ are not called Did not see mentioned anywhere in this repo, which is the method that should be called. See Repo: With unittest: With Pytest:


Question: reason = self.__unittest_skip_why__             pytest.skip(reason)         if setup is not None:            if pass_self:                setup(self, request.function)            else:                setup()            try:                if pass_self:                    setup(self, request.function)                else:                    setup()            # unittest does not call the cleanup function for every BaseException, so we            # follow this here.            except Exception:                if pass_self:                    cleanup(self)                else:                    cleanup()                raise         yield        if teardown is not None:        try:            if teardown is not None:                if pass_self:                    teardown(self, request.function)                else:                    teardown()        finally:             if pass_self:                teardown(self, request.function)                cleanup(self)             else:                teardown()                cleanup()      return fixture


Question: "warnings",     "logging",     "reports",    *(["unraisableexception", "threadexception"] if sys.version_info >= (3, 8) else []),     "faulthandler", ) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py-- a/src/_pytest/pytester.py++ b/src/_pytest/pytester.py

set sys.unraisablehook (py38) Python 3.8 has a new hook: sys.unraisablehook Pytest should set this to be able to associate unraisable exceptions with tests


Question: stderr=f2,                 close_fds=(sys.platform != "win32"),             )            if isinstance(stdin, bytes):            if popen.stdin is not None:                 popen.stdin.close()              def handle_timeout() -> None:diff --git a/src/_pytest/threadexception.py b/src/_pytest/threadexception.pynew file mode 100644-- /dev/null++ b/src/_pytest/threadexception.py


Question: import threadingimport tracebackimport warningsfrom types import TracebackTypefrom typing import Anyfrom typing import Callablefrom typing import Generatorfrom typing import Optionalfrom typing import Typeimport pytest# Copied from cpython/Lib/test/support/threading_helper.py, with modifications.class catch_threading_exception:    """Context manager catching threading.Thread exception using    threading.excepthook.    Storing exc_value using a custom hook can create a reference cycle. The    reference cycle is broken explicitly when the context manager exits.    Storing thread using a custom hook can resurrect it if it is set to an    object which is being finalized. Exiting the context manager clears the    stored object.    Usage:        with threading_helper.catch_threading_exception() as cm:            # code spawning a thread which raises an exception            ...            # check the thread exception: use cm.args            ...        # cm.args attribute no longer exists at this point        # (to break a reference cycle)    """    def __init__(self) -> None:        # See https://github.com/python/typeshed/issues/4767 regarding the underscore.        self.args: Optional["threading._ExceptHookArgs"] = None        self._old_hook: Optional[Callable[["threading._ExceptHookArgs"], Any]] = None    def _hook(self, args: "threading._ExceptHookArgs") -> None:        self.args = args    def __enter__(self) -> "catch_threading_exception":        self._old_hook = threading.excepthook        threading.excepthook = self._hook        return self    def __exit__(        self,        exc_type: Optional[Type[BaseException]],        exc_val: Optional[BaseException],        exc_tb: Optional[TracebackType],    ) -> None:        assert self._old_hook is not None        threading.excepthook = self._old_hook        self._old_hook = None        del self.argsdef thread_exception_runtest_hook() -> Generator[None, None, None]:    with catch_threading_exception() as cm:        yield        if cm.args:            if cm.args.thread is not None:                thread_name = cm.args.thread.name            else:                thread_name = "<unknown>"            msg = f"Exception in thread {thread_name}\n\n"            msg += "".join(                traceback.format_exception(                    cm.args.exc_type, cm.args.exc_value, cm.args.exc_traceback,                )            )            warnings.warn(pytest.PytestUnhandledThreadExceptionWarning(msg))@pytest.hookimpl(hookwrapper=True, trylast=True)def pytest_runtest_setup() -> Generator[None, None, None]:    yield from thread_exception_runtest_hook()@pytest.hookimpl(hookwrapper=True, tryfirst=True)def pytest_runtest_call() -> Generator[None, None, None]:    yield from thread_exception_runtest_hook()@pytest.hookimpl(hookwrapper=True, tryfirst=True)def pytest_runtest_teardown() -> Generator[None, None, None]:    yield from thread_exception_runtest_hook()diff --git a/src/_pytest/unraisableexception.py b/src/_pytest/unraisableexception.pynew file mode 100644-- /dev/null++ b/src/_pytest/unraisableexception.py


Question: import sysimport tracebackimport warningsfrom types import TracebackTypefrom typing import Anyfrom typing import Callablefrom typing import Generatorfrom typing import Optionalfrom typing import Typeimport pytest# Copied from cpython/Lib/test/support/__init__.py, with modifications.class catch_unraisable_exception:    """Context manager catching unraisable exception using sys.unraisablehook.    Storing the exception value (cm.unraisable.exc_value) creates a reference    cycle. The reference cycle is broken explicitly when the context manager    exits.    Storing the object (cm.unraisable.object) can resurrect it if it is set to    an object which is being finalized. Exiting the context manager clears the    stored object.    Usage:        with catch_unraisable_exception() as cm:            # code creating an "unraisable exception"            ...            # check the unraisable exception: use cm.unraisable            ...        # cm.unraisable attribute no longer exists at this point        # (to break a reference cycle)    """    def __init__(self) -> None:        self.unraisable: Optional["sys.UnraisableHookArgs"] = None        self._old_hook: Optional[Callable[["sys.UnraisableHookArgs"], Any]] = None    def _hook(self, unraisable: "sys.UnraisableHookArgs") -> None:        # Storing unraisable.object can resurrect an object which is being        # finalized. Storing unraisable.exc_value creates a reference cycle.        self.unraisable = unraisable    def __enter__(self) -> "catch_unraisable_exception":        self._old_hook = sys.unraisablehook        sys.unraisablehook = self._hook        return self    def __exit__(        self,        exc_type: Optional[Type[BaseException]],        exc_val: Optional[BaseException],        exc_tb: Optional[TracebackType],    ) -> None:        assert self._old_hook is not None        sys.unraisablehook = self._old_hook        self._old_hook = None        del self.unraisabledef unraisable_exception_runtest_hook() -> Generator[None, None, None]:    with catch_unraisable_exception() as cm:        yield        if cm.unraisable:            if cm.unraisable.err_msg is not None:                err_msg = cm.unraisable.err_msg            else:                err_msg = "Exception ignored in"            msg = f"{err_msg}: {cm.unraisable.object!r}\n\n"            msg += "".join(                traceback.format_exception(                    cm.unraisable.exc_type,                    cm.unraisable.exc_value,                    cm.unraisable.exc_traceback,                )            )            warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))@pytest.hookimpl(hookwrapper=True, tryfirst=True)def pytest_runtest_setup() -> Generator[None, None, None]:    yield from unraisable_exception_runtest_hook()@pytest.hookimpl(hookwrapper=True, tryfirst=True)def pytest_runtest_call() -> Generator[None, None, None]:    yield from unraisable_exception_runtest_hook()@pytest.hookimpl(hookwrapper=True, tryfirst=True)def pytest_runtest_teardown() -> Generator[None, None, None]:    yield from unraisable_exception_runtest_hook()diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py-- a/src/_pytest/warning_types.py++ b/src/_pytest/warning_types.py


Question: __module__ = "pytest"  @finalclass PytestUnraisableExceptionWarning(PytestWarning):    """An unraisable exception was reported.    Unraisable exceptions are exceptions raised in :meth:`__del__ <object.__del__>`    implementations and similar situations when the exception cannot be raised    as normal.    """    __module__ = "pytest"@finalclass PytestUnhandledThreadExceptionWarning(PytestWarning):    """An unhandled exception occurred in a :class:`~threading.Thread`.    Such exceptions don't propagate normally.    """    __module__ = "pytest" _W = TypeVar("_W", bound=PytestWarning)  diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py-- a/src/pytest/__init__.py++ b/src/pytest/__init__.py


Question: from _pytest.warning_types import PytestDeprecationWarning from _pytest.warning_types import PytestExperimentalApiWarning from _pytest.warning_types import PytestUnhandledCoroutineWarningfrom _pytest.warning_types import PytestUnhandledThreadExceptionWarning from _pytest.warning_types import PytestUnknownMarkWarningfrom _pytest.warning_types import PytestUnraisableExceptionWarning from _pytest.warning_types import PytestWarning  set_trace = __pytestPDB.set_trace


Question: "PytestDeprecationWarning",     "PytestExperimentalApiWarning",     "PytestUnhandledCoroutineWarning",    "PytestUnhandledThreadExceptionWarning",     "PytestUnknownMarkWarning",    "PytestUnraisableExceptionWarning",     "PytestWarning",     "raises",     "register_assert_rewrite",


Question: """  # -------------------------------------------------------------------------# Hooks for influencing skipping# -------------------------------------------------------------------------def pytest_markeval_namespace(config: "Config") -> Dict[str, Any]:    """Called when constructing the globals dictionary used for    evaluating string conditions in xfail/skipif markers.    This is useful when the condition for a marker requires    objects that are expensive or impossible to obtain during    collection time, which is required by normal boolean    conditions.    .. versionadded:: 6.2    :param _pytest.config.Config config: The pytest config object.    :returns: A dictionary of additional globals to add.    """ # ------------------------------------------------------------------------- # error handling and internal debugging hooks # -------------------------------------------------------------------------diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py-- a/src/_pytest/skipping.py++ b/src/_pytest/skipping.py

Allow contibuting additional global variables for skipif/xfail [ ] Include documentation when adding new features. [x] Include new tests or update existing tests when applicable. [X] Allow maintainers to push and squash when merging my commits. Please uncheck this if you prefer to squash the commits yourself. for details.


Question: import platform import sys import traceback<ins>from collections.abc import Mapping</ins> from typing import Generator from typing import Optional from typing import Tuple


Question: "platform": platform,             "config": item.config,         }<ins>        for dictionary in reversed(            item.ihook.pytest_markeval_namespace(config=item.config)        ):            if not isinstance(dictionary, Mapping):                raise ValueError(                    "pytest_markeval_namespace() needs to return a dict, got {!r}".format(                        dictionary                    )                )            globals_.update(dictionary)</ins>         if hasattr(item, "obj"):             globals_.update(item.obj.__globals__)  # type: ignore[attr-defined]         try:


Question: @staticmethod     def _get_stderr_fileno():         try:            return sys.stderr.fileno()            fileno = sys.stderr.fileno()            # The Twisted Logger will return an invalid file descriptor since it is not backed            # by an FD. So, let's also forward this to the same code path as with pytest-xdist.            if fileno == -1:                raise AttributeError()            return fileno         except (AttributeError, io.UnsupportedOperation):             # pytest-xdist monkeypatches sys.stderr with an object that is not an actual file.             # https://docs.python.org/3/library/faulthandler.html#issue-with-file-descriptors

Problem with faulthandler when used with Twisted Logger and "pytest --capture=no" Dear developers, thanks a stack for conceiving and maintaining this excellent package. I never expected to file an issue or submit a patch here, but here we go. On behalf of , we are currently in the progress of finally upgrading to Python 3. Kotori is based on Twisted and uses for testing. Within , we tried hard to apply some magic to make everything work together on all occasions with respect to appropriately configuring to our needs. We are on macOS 10.13.6. The background on this is that the Twisted Logger intercepts the logging by providing a file-like wrapper around the stream, which is obviously not an actual stream. In this case, when running with , 's fails when trying to restore the stream through at [1] as this will actually return , in turn signaling an invalid file descriptor [2]. It will a) raise the exception outlined below and b) won't stop the process on teardown. [1] [2] This problem is mitigated by . With kind regards, Andreas.


Question: # use a sub-directory in the temproot to speed-up             # make_numbered_dir() call             rootdir = temproot.joinpath(f"pytest-of-{user}")            rootdir.mkdir(exist_ok=True)            try:                rootdir.mkdir(exist_ok=True)            except OSError:                # getuser() likely returned illegal characters for the platform, use unknown back off mechanism                rootdir = temproot.joinpath("pytest-of-unknown")                rootdir.mkdir(exist_ok=True)             basetemp = make_numbered_dir_with_cleanup(                 prefix="pytest-", root=rootdir, keep=3, lock_timeout=LOCK_TIMEOUT             )

tmpdir creation fails when the username contains illegal characters for directory names , and rely on for determining the directory. I found that the user name returned by may return characters that are not allowed for directory names. This may lead to errors while creating the temporary directory. The situation in which I reproduced this issue was while being logged in through an ssh connection into my Windows 10 x64 Enterprise version (1909) using an OpenSSHforWindows7.7p1 server. In this configuration the command returns my domain username e.g. instead of as when logged in regularly using a local session. When trying to create a temp directory in pytest through e.g. this fails with the following error message: I could also reproduce this without the complicated ssh/windows setup with pytest 6.2.2 using the following commands from a : Thanks for having a look at this!


Question: autouse=True,             scope="module",             # Use a unique name to speed up lookup.            name=f"xunit_setup_module_fixture_{self.obj.__name__}",            name=f"_xunit_setup_module_fixture_{self.obj.__name__}",         )         def xunit_setup_module_fixture(request) -> Generator[None, None, None]:             if setup_module is not None:

Starting v6.2.0, unittest setUpClass fixtures are no longer "private" <!-- Thanks for submitting an issue! Quick check-list while reporting bugs: --Minimal example: The expected (and previously implemented behavior) is that this fixture's name would start with an underscore, and would therefore only get printed if the additional flag was used. As it stands, I don't see a way to hide such generated fixtures which will not have a docstring. This breaks a code-quality CI script that makes sure we don't have undocumented pytest fixtures (and the code-base has many legacy tests that use unittest, and that will not get upgraded).


Question: autouse=True,             scope="function",             # Use a unique name to speed up lookup.            name=f"xunit_setup_function_fixture_{self.obj.__name__}",            name=f"_xunit_setup_function_fixture_{self.obj.__name__}",         )         def xunit_setup_function_fixture(request) -> Generator[None, None, None]:             if request.instance is not None:


Question: autouse=True,             scope="class",             # Use a unique name to speed up lookup.            name=f"xunit_setup_class_fixture_{self.obj.__qualname__}",            name=f"_xunit_setup_class_fixture_{self.obj.__qualname__}",         )         def xunit_setup_class_fixture(cls) -> Generator[None, None, None]:             if setup_class is not None:


Question: autouse=True,             scope="function",             # Use a unique name to speed up lookup.            name=f"xunit_setup_method_fixture_{self.obj.__qualname__}",            name=f"_xunit_setup_method_fixture_{self.obj.__qualname__}",         )         def xunit_setup_method_fixture(self, request) -> Generator[None, None, None]:             method = request.functiondiff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py-- a/src/_pytest/unittest.py++ b/src/_pytest/unittest.py


Question: scope=scope,         autouse=True,         # Use a unique name to speed up lookup.        name=f"unittest_{setup_name}_fixture_{obj.__qualname__}",        name=f"_unittest_{setup_name}_fixture_{obj.__qualname__}",     )     def fixture(self, request: FixtureRequest) -> Generator[None, None, None]:         if _is_skipped(self):


Question: return not (actual == self)      def _approx_scalar(self, x) -> "ApproxScalar":<ins>        if isinstance(x, Decimal):            return ApproxDecimal(x, rel=self.rel, abs=self.abs, nan_ok=self.nan_ok)</ins>         return ApproxScalar(x, rel=self.rel, abs=self.abs, nan_ok=self.nan_ok)      def _yield_comparisons(self, actual):

approx: Better handle Decimal in sequences and mappings <!-- Thanks for suggesting a feature! Quick check-list while suggesting features: --Right now handles Decimal comparisons gracefully, thanks to We can do this: also knows how to handle sequences and mappings: doesn't handle Decimal within sequences and mappings: Both of these tests fail with <!-- A clear and concise description of what you want to happen. --I would like these kind of tests to be passing :) A linked PR should be following shortly :eyes: <!-- Provide examples of real-world use cases that this would enable and how it solves the problem described above. --<!-- Have you tried to workaround the problem using a pytest plugin or other tools? Or a different approach to solving this issue? Please elaborate here. --<!-- Add any other context, links, etc. about the feature here. --


Question: "#configuring-hook-specs-impls-using-markers", ) MARKED_FIXTURE = PytestRemovedIn8Warning(    "Marks applied to fixtures have no effect\n"    "See docs: https://docs.pytest.org/en/stable/deprecations.html#applying-a-mark-to-a-fixture-function") # You want to make some `__init__` or function "private". # #   def my_private_function(some, args):diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py-- a/src/_pytest/fixtures.py++ b/src/_pytest/fixtures.py

Generate an error when a mark is applied to a fixture Follow up from . We should generate an error if a is applied to a fixture. There is a warning in about this problem which should be updated once this issue is dealt with.


Question: from _pytest.config import Config from _pytest.config.argparsing import Parser from _pytest.deprecated import check_ispytest<ins>from _pytest.deprecated import MARKED_FIXTURE</ins> from _pytest.deprecated import YIELD_FIXTURE from _pytest.mark import Mark from _pytest.mark import ParameterSet


Question: "fixture is being applied more than once to the same function"             )         if hasattr(function, "pytestmark"):            warnings.warn(MARKED_FIXTURE, stacklevel=2)         function = wrap_function_to_error_out_if_called_directly(function, self)          name = self.name or function.__name__diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py-- a/src/_pytest/mark/structures.py++ b/src/_pytest/mark/structures.py


Question: from ..compat import NotSetType from _pytest.config import Config from _pytest.deprecated import check_ispytest<ins>from _pytest.deprecated import MARKED_FIXTURE</ins> from _pytest.outcomes import fail from _pytest.warning_types import PytestUnknownMarkWarning


Question: This is used to implement the Mark declarations/decorators correctly.     """     assert isinstance(mark, Mark), mark<ins>    from ..fixtures import getfixturemarker    if getfixturemarker(obj) is not None:        warnings.warn(MARKED_FIXTURE, stacklevel=2)</ins>     # Always reassign name to avoid updating pytestmark in a reference that     # was only borrowed.     obj.pytestmark = [*get_unpacked_marks(obj, consider_mro=False), mark]


Question: @classmethod     def from_config(cls, config: Config) -> "Session":        session: Session = cls._create(config)        session: Session = cls._create(config=config)         return session      def __repr__(self) -> str:diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py-- a/src/_pytest/nodes.py++ b/src/_pytest/nodes.py

Unexpected keyword argument 'path' from plugins While troubleshooting , I stumbled onto a new error, a that occurs when using pytest-black against the current main HEAD (), easily reproducible with an empty test file and pip-run: Same problem happens with pytest-checkdocs:


Question: import os import warningsfrom inspect import signature from pathlib import Path from typing import Any from typing import Callablefrom typing import cast from typing import Iterable from typing import Iterator from typing import List


Question: from _pytest.pathlib import absolutepath from _pytest.pathlib import commonpath from _pytest.store import Store<ins>from _pytest.warning_types import PytestWarning</ins>  if TYPE_CHECKING:     # Imported here due to circular import.


Question: fail(msg, pytrace=False)      def _create(self, *k, **kw):        return super().__call__(*k, **kw)        try:            return super().__call__(*k, **kw)        except TypeError:            sig = signature(getattr(self, "__init__"))            known_kw = {k: v for k, v in kw.items() if k in sig.parameters}            from .warning_types import PytestDeprecationWarning            warnings.warn(                PytestDeprecationWarning(                    f"{self} is not using a cooperative constructor and only takes {set(known_kw)}"                )            )            return super().__call__(*k, **known_kw)   class Node(metaclass=NodeMeta):


Question: class FSCollector(Collector):     def __init__(         self,        fspath: Optional[LEGACY_PATH],        path: Optional[Path],        parent=None,        fspath: Optional[LEGACY_PATH] = None,        path_or_parent: Optional[Union[Path, Node]] = None,        path: Optional[Path] = None,        name: Optional[str] = None,        parent: Optional[Node] = None,         config: Optional[Config] = None,         session: Optional["Session"] = None,         nodeid: Optional[str] = None,     ) -> None:        if path_or_parent:            if isinstance(path_or_parent, Node):                assert parent is None                parent = cast(FSCollector, path_or_parent)            elif isinstance(path_or_parent, Path):                assert path is None                path = path_or_parent         path, fspath = _imply_path(path, fspath=fspath)        name = path.name        if parent is not None and parent.path != path:            try:                rel = path.relative_to(parent.path)            except ValueError:                pass            else:                name = str(rel)            name = name.replace(os.sep, SEP)        if name is None:            name = path.name            if parent is not None and parent.path != path:                try:                    rel = path.relative_to(parent.path)                except ValueError:                    pass                else:                    name = str(rel)                name = name.replace(os.sep, SEP)         self.path = path         session = session or parent.session        if session is None:            assert parent is not None            session = parent.session          if nodeid is None:             try:


Question: nodeid = nodeid.replace(os.sep, SEP)          super().__init__(            name, parent, config, session, nodeid=nodeid, fspath=fspath, path=path            name=name,            parent=parent,            config=config,            session=session,            nodeid=nodeid,            path=path,         )      @classmethod


Question: nextitem = None <ins>    def __init_subclass__(cls) -> None:        problems = ", ".join(            base.__name__ for base in cls.__bases__ if issubclass(base, Collector)        )        if problems:            warnings.warn(                f"{cls.__name__} is an Item subclass and should not be a collector, "                f"however its bases {problems} are collectors.\n"                "Please split the Collectors and the Item into separate node types.\n"                "Pytest Doc example: https://docs.pytest.org/en/latest/example/nonpython.html\n"                "example pull request on a plugin: https://github.com/asmeurer/pytest-flakes/pull/40/",                PytestWarning,            )</ins>     def __init__(         self,         name,


Question: config: Optional[Config] = None,         session: Optional["Session"] = None,         nodeid: Optional[str] = None,        **kw,     ) -> None:        super().__init__(name, parent, config, session, nodeid=nodeid)        super().__init__(            name=name,            parent=parent,            config=config,            session=session,            nodeid=nodeid,            **kw,        )         self._report_sections: List[Tuple[str, str, str]] = []          #: A list of tuples (name, value) that holds user defined properties


Question: return path.joinpath(".lock")  <del>def ensure_reset_dir(path: Path) -> None:    """Ensure the given path is an empty directory."""    if path.exists():        rm_rf(path)    path.mkdir()</del> def on_rm_rf_error(func, path: str, exc, *, start_path: Path) -> bool:     """Handle known read-only errors during rmtree.

Minor temporary directory security issue in pytest versions before 6.2.3 A minor temporary directory security issue was found in pytest versions before 6.2.3. This issue is fixed in pytest 6.2.3. pytest used to create directories under with world-readable permissions. This means that any user in the system was able to read information written by tests in temporary directories (such as those created by the fixture). Now the directories are created with private permissions. pytest used to silenty use a pre-existing ` directory, even if owned by another user. This means another user could pre-create such a directory and gain control of another user's temporary directory. Now such a condition results in an error.


Question: pass  def make_numbered_dir(root: Path, prefix: str) -> Path:def make_numbered_dir(root: Path, prefix: str, mode: int = 0o700) -> Path:     """Create a directory with an increased number as suffix for the given prefix."""     for i in range(10):         # try up to 10 times to create the folder


Question: new_number = max_existing + 1         new_path = root.joinpath(f"{prefix}{new_number}")         try:            new_path.mkdir()            new_path.mkdir(mode=mode)         except Exception:             pass         else:


Question: def make_numbered_dir_with_cleanup(    root: Path, prefix: str, keep: int, lock_timeout: float    root: Path,    prefix: str,    keep: int,    lock_timeout: float,    mode: int, ) -> Path:     """Create a numbered dir with a cleanup lock and remove old ones."""     e = None     for i in range(10):         try:            p = make_numbered_dir(root, prefix)            p = make_numbered_dir(root, prefix, mode)             lock_path = create_cleanup_lock(p)             register_cleanup_lock_removal(lock_path)         except Exception as exc:diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py-- a/src/_pytest/pytester.py++ b/src/_pytest/pytester.py


Question: :py:class:`Pytester.TimeoutExpired`.         """         __tracebackhide__ = True        p = make_numbered_dir(root=self.path, prefix="runpytest-")        p = make_numbered_dir(root=self.path, prefix="runpytest-", mode=0o700)         args = ("--basetemp=%s" % p,) + args         plugins = [x for x in self.plugins if isinstance(x, str)]         if plugins:


Question: The pexpect child is returned.         """         basetemp = self.path / "temp-pexpect"        basetemp.mkdir()        basetemp.mkdir(mode=0o700)         invoke = " ".join(map(str, self._getpytestargs()))         cmd = f"{invoke} --basetemp={basetemp} {string}"         return self.spawn(cmd, expect_timeout=expect_timeout)diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py-- a/src/_pytest/tmpdir.py++ b/src/_pytest/tmpdir.py


Question: import attr from .pathlib import ensure_reset_dir from .pathlib import LOCK_TIMEOUT from .pathlib import make_numbered_dir from .pathlib import make_numbered_dir_with_cleanupfrom .pathlib import rm_rf from _pytest.compat import final from _pytest.compat import LEGACY_PATH from _pytest.compat import legacy_path


Question: basename = self._ensure_relative_to_basetemp(basename)         if not numbered:             p = self.getbasetemp().joinpath(basename)            p.mkdir()            p.mkdir(mode=0o700)         else:            p = make_numbered_dir(root=self.getbasetemp(), prefix=basename)            p = make_numbered_dir(root=self.getbasetemp(), prefix=basename, mode=0o700)             self._trace("mktemp", p)         return p      def getbasetemp(self) -> Path:        """Return base temporary directory."""        """Return the base temporary directory, creating it if needed."""         if self._basetemp is not None:             return self._basetemp          if self._given_basetemp is not None:             basetemp = self._given_basetemp            ensure_reset_dir(basetemp)            if basetemp.exists():                rm_rf(basetemp)            basetemp.mkdir(mode=0o700)             basetemp = basetemp.resolve()         else:             from_env = os.environ.get("PYTEST_DEBUG_TEMPROOT")


Question: # make_numbered_dir() call             rootdir = temproot.joinpath(f"pytest-of-{user}")             try:                rootdir.mkdir(exist_ok=True)                rootdir.mkdir(mode=0o700, exist_ok=True)             except OSError:                 # getuser() likely returned illegal characters for the platform, use unknown back off mechanism                 rootdir = temproot.joinpath("pytest-of-unknown")                rootdir.mkdir(exist_ok=True)                rootdir.mkdir(mode=0o700, exist_ok=True)            # Because we use exist_ok=True with a predictable name, make sure            # we are the owners, to prevent any funny business (on unix, where            # temproot is usually shared).            # Also, to keep things private, fixup any world-readable temp            # rootdir's permissions. Historically 0o755 was used, so we can't            # just error out on this, at least for a while.            if hasattr(os, "getuid"):                rootdir_stat = rootdir.stat()                uid = os.getuid()                # getuid shouldn't fail, but cpython defines such a case.                # Let's hope for the best.                if uid != -1:                    if rootdir_stat.st_uid != uid:                        raise OSError(                            f"The temporary directory {rootdir} is not owned by the current user. "                            "Fix this and try again."                        )                    if (rootdir_stat.st_mode & 0o077) != 0:                        os.chmod(rootdir, rootdir_stat.st_mode & ~0o077)             basetemp = make_numbered_dir_with_cleanup(                prefix="pytest-", root=rootdir, keep=3, lock_timeout=LOCK_TIMEOUT                prefix="pytest-",                root=rootdir,                keep=3,                lock_timeout=LOCK_TIMEOUT,                mode=0o700,             )         assert basetemp is not None, basetemp        self._basetemp = t = basetemp        self._trace("new basetemp", t)        return t        self._basetemp = basetemp        self._trace("new basetemp", basetemp)        return basetemp   @final


Question: logging.DEBUG: {"purple"},         logging.NOTSET: set(),     }    LEVELNAME_FMT_REGEX = re.compile(r"%\(levelname\)([+-.]?\d*s)")    LEVELNAME_FMT_REGEX = re.compile(r"%\(levelname\)([+-.]?\d*(?:\.\d+)?s)")      def __init__(self, terminalwriter: TerminalWriter, *args, **kwargs) -> None:         super().__init__(*args, **kwargs)

No color output when specifying log format string with precision-formatted levelname <!-- Thanks for submitting an issue! Quick check-list while reporting bugs: --Pytest fails to output colorfully with the following log format string in This is due to  fails to match the format string due to the presence of precision bit.


Question: def _find_lineno(self, obj, source_lines):                 """Doctest code does not take into account `@property`, this                is a hackish way to fix it.                is a hackish way to fix it. https://bugs.python.org/issue17446                 https://bugs.python.org/issue17446                Wrapped Doctests will need to be unwrapped so the correct                line number is returned. This will be reported upstream. #8796                 """                 if isinstance(obj, property):                     obj = getattr(obj, "fget", obj)                if hasattr(obj, "__wrapped__"):                    # Get the main obj in case of it being wrapped                    obj = inspect.unwrap(obj)                 # Type ignored because this is a private function.                 return doctest.DocTestFinder._find_lineno(  # type: ignore                     self,

Internal error when adding a skip mark to a doctest inside a contextmanager To reproduce: This is a simplified issue from a real use case in the scikit-learn repo. We sometimes want to skip doctests, for example when matplotlib (an optional dependency) is not installed. If there is be a better way to do it with pytest than using , let me know. <details<summaryconda list output</summary</details


Question: if e.allow_module_level:                 raise             raise self.CollectError(<del>                "Using pytest.skip outside of a test is not allowed. "                "To decorate a test function, use the @pytest.mark.skip "                "or @pytest.mark.skipif decorators instead, and to skip a "                "module use `pytestmark = pytest.mark.{skip,skipif}."</del><ins>                "Using pytest.skip outside of a test will skip the entire module. "                "If that's your intention, pass `allow_module_level=True`. "                "If you want to skip a specific test or an entire class, "                "use the @pytest.mark.skip or @pytest.mark.skipif decorators."</ins>             ) from e         self.config.pluginmanager.consider_module(mod)         return mod

Improve handling of skip for module level This is potentially about updating docs, updating error messages or introducing a new API. Consider the following scenario: is using Python 3,8 syntax: It should not be tested under Python 3.6 and 3.7. This is a proper way to skip the test in Python older than 3.8: My actual test involves parameterize and a 3.8 only class, so skipping the test itself is not sufficient because the 3.8 class was used in the parameterization. A naive user will try to initially skip the module like: This issues this error: Using outside of a test is not allowed. To decorate a test function, use the or decorators instead, and to skip a module use `pytestmark = {skip,skipif}. The proposed solution , does not work in my case: pytest continues to process the file and fail when it hits the 3.8 syntax (when running with an older version of Python). The correct solution, to use skip as a function is actively discouraged by the error message. This area feels a bit unpolished. A few ideas to improve: skip with in the error message. this seems in conflict with the spirit of the message. an alternative API to skip a module to make things easier: , which can call .


Question: errors: int = 0,         xpassed: int = 0,         xfailed: int = 0,<ins>        warnings: int = 0,</ins>     ) -> None:         """Assert that the specified outcomes appear with the respective         numbers (0 means it didn't occur) in the text output from a test run."""

Enhance warning assertion capabilities while writing some other bits and pieces, I had a use case for checking the omitted, has a that doesn't quite offer yet the information is already available in there, I suspect there is a good reason why we don't have so I propose some additional capabilities on to handle warnings in isolation. With the full dict comparison may get a bit intrusive as far as warning capture is concerned. something simple like: Thoughts?


Question: errors=errors,             xpassed=xpassed,             xfailed=xfailed,            warnings=warnings,         )  diff --git a/src/_pytest/pytester_assertions.py b/src/_pytest/pytester_assertions.py-- a/src/_pytest/pytester_assertions.py++ b/src/_pytest/pytester_assertions.py


Question: errors: int = 0,     xpassed: int = 0,     xfailed: int = 0,<ins>    warnings: int = 0,</ins> ) -> None:     """Assert that the specified outcomes appear with the respective     numbers (0 means it didn't occur) in the text output from a test run."""


Question: "errors": outcomes.get("errors", 0),         "xpassed": outcomes.get("xpassed", 0),         "xfailed": outcomes.get("xfailed", 0),<ins>        "warnings": outcomes.get("warnings", 0),</ins>     }     expected = {         "passed": passed,


Question: "errors": errors,         "xpassed": xpassed,         "xfailed": xfailed,<ins>        "warnings": warnings,</ins>     }     assert obtained == expected


Question: expr:       and_expr ('or' and_expr)* and_expr:   not_expr ('and' not_expr)* not_expr:   'not' not_expr | '(' expr ')' | identident:      (\w|:|\+|-|\.|\[|\])+ident:      (\w|:|\+|-|\.|\[|\]|\\)+  The semantics are:

pytest -k doesn't work with "\"? <div type='discussions-op-text'<supOriginally posted by nguydavi August 7, 2021</supHey! I've been trying to use passing the name I got by parametrizing my test. For example, Note the error message I tried escaping the but that didn't work, the only way I can make it work is to remove the backslashes completely, Is just not supported by ? Or am I missing something ? Thanks! EDIT: A possible test case Which is then referred by as . Essentially a new line character in the string brings the issue (or any escaped character probably)</div


Question: yield Token(TokenType.RPAREN, ")", pos)                 pos += 1             else:                match = re.match(r"(:?\w|:|\+|-|\.|\[|\])+", input[pos:])                match = re.match(r"(:?\w|:|\+|-|\.|\[|\]|\\)+", input[pos:])                 if match:                     value = match.group(0)                     if value == "or":


Question: action="store_true",         default=False,         dest="stepwise_skip",        help="ignore the first failing test but stop on the next failing test",        help="ignore the first failing test but stop on the next failing test.\n"        "implicitly enables --stepwise.",     )   @pytest.hookimpl def pytest_configure(config: Config) -> None:    # We should always have a cache as cache provider plugin uses tryfirst=True    if config.option.stepwise_skip:        # allow --stepwise-skip to work on it's own merits.        config.option.stepwise = True     if config.getoption("stepwise"):         config.pluginmanager.register(StepwisePlugin(config), "stepwiseplugin")

has no effect without [x] a detailed description of the bug or problem you are having The flag will "exit on test failure and continue from last failing test". The flag is supposed to "ignore the first failing test but stop on the next failing test". However, it does nothing unless used in conjunction with . The combo requirement is not mentioned in the help text, seems redundant, and is surprising behavior. I recommend that should act the same as . [x] output of from the virtual environment you are using [x] pytest and operating system versions MacOS, Python 3.9.5, pytest-6.2.4 [x] minimal example if possible Example three failures: has no effect: works as expected, stopping after first failure: only works with to stop after second failure: I believe the above behavior, the combo of the flags, should work like that even if only is used.


Question: "See "             "https://docs.pytest.org/en/stable/deprecations.html#node-construction-changed-to-node-from-parent"             " for more details."        ).format(name=self.__name__)        ).format(name=f"{self.__module__}.{self.__name__}")         fail(msg, pytrace=False)      def _create(self, *k, **kw):

Show full qualified name on direct Node construction warning In , running pytest with many plugins installed gives this error: And is not clear which plugin is the culprit, I had to look at the source code of to figure it out. We might consider at least show the full qualified name of the offending class in that message, so users would see , which is a nudge in the right direction. Originally posted by in


Question: xpassed: int = 0,         xfailed: int = 0,         warnings: int = 0,<ins>        deselected: int = 0,</ins>     ) -> None:         """Assert that the specified outcomes appear with the respective         numbers (0 means it didn't occur) in the text output from a test run."""

Add a parameter to <!-- Thanks for suggesting a feature! Quick check-list while suggesting features: --<!-- What are you trying to do, that you are unable to achieve with pytest as it currently stands? --I'd like to be able to use to check deselected count. <!-- A clear and concise description of what you want to happen. --Add a parameter to <!-- Provide examples of real-world use cases that this would enable and how it solves the problem described above. --Plugins that use to change the and add change the deselected items need to be tested. Using to check the deselected count would be helpful. <!-- Have you tried to workaround the problem using a pytest plugin or other tools? Or a different approach to solving this issue? Please elaborate here. --Use instead of . returns a dictionary that includes , if there are any. However, if we have a series of tests, some that care about deselected, and some that don't, then we may have some tests using and some using , which is slightly annoying. <!-- Add any other context, links, etc. about the feature here. --


Question: xpassed=xpassed,             xfailed=xfailed,             warnings=warnings,            deselected=deselected,         )  diff --git a/src/_pytest/pytester_assertions.py b/src/_pytest/pytester_assertions.py-- a/src/_pytest/pytester_assertions.py++ b/src/_pytest/pytester_assertions.py


Question: xpassed: int = 0,     xfailed: int = 0,     warnings: int = 0,<ins>    deselected: int = 0,</ins> ) -> None:     """Assert that the specified outcomes appear with the respective     numbers (0 means it didn't occur) in the text output from a test run."""


Question: "xpassed": outcomes.get("xpassed", 0),         "xfailed": outcomes.get("xfailed", 0),         "warnings": outcomes.get("warnings", 0),<ins>        "deselected": outcomes.get("deselected", 0),</ins>     }     expected = {         "passed": passed,


Question: "xpassed": xpassed,         "xfailed": xfailed,         "warnings": warnings,<ins>        "deselected": deselected,</ins>     }     assert obtained == expected


Question: expr:       and_expr ('or' and_expr)* and_expr:   not_expr ('and' not_expr)* not_expr:   'not' not_expr | '(' expr ')' | identident:      (\w|:|\+|-|\.|\[|\]|\\)+ident:      (\w|:|\+|-|\.|\[|\]|\\|/)+  The semantics are:

test ids with s cannot be selected with By default pytest 6.2.2 parametrize does user arguments to generate IDs, but some of these ids cannot be used with option because you endup with errors like when trying to do so. The solution for this bug is to assure that auto-generated IDs are sanitized so they can be used with -k option. Example: As you can see the first parameter includes a slash, and for good reasons. It is far from practical to have to add custom "ids" for all of these, as you can have LOTS of them. There is another annoyance related to the -k selecting for parameterized tests, is the fact that square braces have special meanings for some shells and in order to use it you must remember to quote the strings. It would be much easier if the display and selecting of parametrized tests would use only shell-safe format, so we can easily copy/paste a failed test in run it. For example I think that using colon would be safe and arguably even easier to read: .


Question: yield Token(TokenType.RPAREN, ")", pos)                 pos += 1             else:                match = re.match(r"(:?\w|:|\+|-|\.|\[|\]|\\)+", input[pos:])                match = re.match(r"(:?\w|:|\+|-|\.|\[|\]|\\|/)+", input[pos:])                 if match:                     value = match.group(0)                     if value == "or":


Question: nodeid: Optional[str] = None,         **kw,     ) -> None:        # The first two arguments are intentionally passed positionally,        # to keep plugins who define a node type which inherits from        # (pytest.Item, pytest.File) working (see issue #8435).        # They can be made kwargs when the deprecation above is done.         super().__init__(            name=name,            parent=parent,            name,            parent,             config=config,             session=session,             nodeid=nodeid,


Question: values: List[int] = []     for x in ast.walk(node):         if isinstance(x, (ast.stmt, ast.ExceptHandler)):<ins>            # Before Python 3.8, the lineno of a decorated class or function pointed at the decorator.            # Since Python 3.8, the lineno points to the class/def, so need to include the decorators.            if isinstance(x, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)):                for d in x.decorator_list:                    values.append(d.lineno - 1)</ins>             values.append(x.lineno - 1)             for name in ("finalbody", "orelse"):                 val: Optional[List[ast.stmt]] = getattr(x, name, None)

Error message prints extra code line when using assert in python3.9 <!-- Thanks for submitting an issue! Quick check-list while reporting bugs: --- [x] a detailed description of the bug or problem you are having [x] output of from the virtual environment you are using [x] pytest and operating system versions [ ] minimal example if possible I have a test like this: The test "testrightstatement" fails at the first assertion,but print extra code (the "t" decorator) in error details, like this: And the same thing did not happen when using python3.7.10 Is there some problems when calculate the statement lineno? pytest 6.2.5 Windows 10 Seems to happen in python 3.9,not 3.7


Question: errors: int = 0,         xpassed: int = 0,         xfailed: int = 0,        warnings: int = 0,        deselected: int = 0,        warnings: Optional[int] = None,        deselected: Optional[int] = None,     ) -> None:        """Assert that the specified outcomes appear with the respective        numbers (0 means it didn't occur) in the text output from a test run."""        """        Assert that the specified outcomes appear with the respective        numbers (0 means it didn't occur) in the text output from a test run.        ``warnings`` and ``deselected`` are only checked if not None.        """         __tracebackhide__ = True         from _pytest.pytester_assertions import assert_outcomes diff --git a/src/_pytest/pytester_assertions.py b/src/_pytest/pytester_assertions.py-- a/src/_pytest/pytester_assertions.py++ b/src/_pytest/pytester_assertions.py

[prerelease] addition to is backwards-incompatible a new parameter to , cc However, this actually is an incompatible change: Doing e.g. followed by worked fine before, but now fails because the now included does not equal . This breaks pytest-bdd: - I could swear I also saw another project in fail after fixing the initial issue it had, but then Christmas and stuff came along and now I don't remember which one it was, and of course can't find it anymore. A (quite) reveals that more projects might be affected by this (excludes to avoid matches in copies of pytest's source code). Some examples I could dig up (but haven't verified): (maybe) I think the change in itself makes sense, but at the same time fixes like are a bit cumbersome. Two questions: What should we do about this for 7.0? (even if the answer just is "live with it and document it as backwards-incompatible in the changelog) What (if anything) should we do about this so that it doesn't happen again for future releases? I guess not much we can do, as long as we want to assume 0 for outcomes which have not been given...


Question: # hence cannot be subject to assertion rewriting, which requires a # module to not be already imported. from typing import Dict<ins>from typing import Optional</ins> from typing import Sequence from typing import Tuple from typing import Union


Question: errors: int = 0,     xpassed: int = 0,     xfailed: int = 0,    warnings: int = 0,    deselected: int = 0,    warnings: Optional[int] = None,    deselected: Optional[int] = None, ) -> None:     """Assert that the specified outcomes appear with the respective     numbers (0 means it didn't occur) in the text output from a test run."""


Question: "errors": outcomes.get("errors", 0),         "xpassed": outcomes.get("xpassed", 0),         "xfailed": outcomes.get("xfailed", 0),<del>        "warnings": outcomes.get("warnings", 0),        "deselected": outcomes.get("deselected", 0),</del>     }     expected = {         "passed": passed,


Question: "errors": errors,         "xpassed": xpassed,         "xfailed": xfailed,        "warnings": warnings,        "deselected": deselected,     }    if warnings is not None:        obtained["warnings"] = outcomes.get("warnings", 0)        expected["warnings"] = warnings    if deselected is not None:        obtained["deselected"] = outcomes.get("deselected", 0)        expected["deselected"] = deselected     assert obtained == expected


Question: _excinfo: Optional[List[_pytest._code.ExceptionInfo[BaseException]]] = None     _testcase: Optional["unittest.TestCase"] = None <ins>    def _getobj(self):        assert self.parent is not None        # Unlike a regular Function in a Class, where `item.obj` returns        # a *bound* method (attached to an instance), TestCaseFunction's        # `obj` returns an *unbound* method (not attached to an instance).        # This inconsistency is probably not desirable, but needs some        # consideration before changing.        return getattr(self.parent.obj, self.originalname)  # type: ignore[attr-defined]</ins>     def setup(self) -> None:         # A bound method to be called during teardown() if set (see 'runtest()').         self._explicit_tearDown: Optional[Callable[[], None]] = None

INTERNALERRORTypeError: init() missing 1 required positional argument: 'testmethod' [ ] a detailed description of the bug or problem you are having [ ] output of from the virtual environment you are using [ ] pytest and operating system versions pytest-7.0.0 CentOS Stream 8 [ ] minimal example if possible Issue happened only once, as far as I know. I will update this issue if it happens multiple times and if I manage to reproduce it outside of GitHub Actions CI.


Question: nextitem = None <del>    def __init_subclass__(cls) -> None:        problems = ", ".join(            base.__name__ for base in cls.__bases__ if issubclass(base, Collector)        )        if problems:            warnings.warn(                f"{cls.__name__} is an Item subclass and should not be a collector, "                f"however its bases {problems} are collectors.\n"                "Please split the Collectors and the Item into separate node types.\n"                "Pytest Doc example: https://docs.pytest.org/en/latest/example/nonpython.html\n"                "example pull request on a plugin: https://github.com/asmeurer/pytest-flakes/pull/40/",                PytestWarning,            )</del>     def __init__(         self,         name,

Pytest 7 not ignoring warnings as instructed on <!-- Thanks for submitting an issue! Quick check-list while reporting bugs: --- [x] a detailed description of the bug or problem you are having [x] output of from the virtual environment you are using [x] pytest and operating system versions [x] minimal example if possible Hello, with the latest version of Pytest a series of new issues has started to pop-up to warn users (and plugin maintainers) about future changes on how Pytest will work. This is a great work done by Pytest maintainers, and pushes the community towards a better future. However, after informing plugin maintainers about the upcoming changes, I would like to silence these warnings so I can focus in fixing the errors detected on the tests (otherwise the output is too big and difficult to scroll through to find useful information). To solve this, I naturally tried to modify my file with a filter for these warnings, however Pytest is still printing some of them even after I the warning filters. The following script can be used to reproduce the problem: Relevant output: (The warnings seem to be shown only once per worker per plugin, but considering you have 32 workers with and 4 plugins that haven't adapted to the changes yet, the output can be very verbose and difficult to navigate) Pytest should not print the warnings: -


Question: #: for this test.         self.user_properties: List[Tuple[str, object]] = [] <ins>        self._check_item_and_collector_diamond_inheritance()    def _check_item_and_collector_diamond_inheritance(self) -> None:        """        Check if the current type inherits from both File and Collector        at the same time, emitting a warning accordingly (#8447).        """        cls = type(self)        # We inject an attribute in the type to avoid issuing this warning        # for the same class more than once, which is not helpful.        # It is a hack, but was deemed acceptable in order to avoid        # flooding the user in the common case.        attr_name = "_pytest_diamond_inheritance_warning_shown"        if getattr(cls, attr_name, False):            return        setattr(cls, attr_name, True)        problems = ", ".join(            base.__name__ for base in cls.__bases__ if issubclass(base, Collector)        )        if problems:            warnings.warn(                f"{cls.__name__} is an Item subclass and should not be a collector, "                f"however its bases {problems} are collectors.\n"                "Please split the Collectors and the Item into separate node types.\n"                "Pytest Doc example: https://docs.pytest.org/en/latest/example/nonpython.html\n"                "example pull request on a plugin: https://github.com/asmeurer/pytest-flakes/pull/40/",                PytestWarning,            )</ins>     def runtest(self) -> None:         """Run the test case for this item.


Question: module_parts = module_name.split(".")     while module_name:         if module_name not in modules:            module = ModuleType(                module_name,                doc="Empty module created by pytest's importmode=importlib.",            )            modules[module_name] = module            try:                # If sys.meta_path is empty, calling import_module will issue                # a warning and raise ModuleNotFoundError. To avoid the                # warning, we check sys.meta_path explicitly and raise the error                # ourselves to fall back to creating a dummy module.                if not sys.meta_path:                    raise ModuleNotFoundError                importlib.import_module(module_name)            except ModuleNotFoundError:                module = ModuleType(                    module_name,                    doc="Empty module created by pytest's importmode=importlib.",                )                modules[module_name] = module         module_parts.pop(-1)         module_name = ".".join(module_parts)

0 regression: Existence of messes up package discovery with importlib + pythonpath mode (ModuleNotFoundError: No module named 'tests.<test-packages') Consider the following demo project: (existence of this file breaks package discovery) pytest (version 7.0.0) errors with: What's particularly surprising: The example works, when renaming the to e.g. . I.e., it seems that the existence of the implies that it is no longer possible to import from . Imports like this used to work with pre 7 pytest versions in mode despite the existence of a .


Question: import math import pprint<ins>from collections.abc import Collection</ins> from collections.abc import Sized from decimal import Decimal from numbers import Complex

Current implementation of cannot be used to compare sets The current implementation of yields incorrect results when used to compare sets. Consider the following self-explanatory code comparing two (equal as by ) sets: Although the two sets are obviously the same, the last equality check using approx is failing. A quick view into the implementation of makes it obvious why this is the case: In , only is used (in ), but since sets are unordered, so is the resulting iterator. This means, for sets such an implementation cannot work. What makes things worse is the confusion that seems to exist here between the different abstract base classes: In the method, clearly is mentioned, explicitly. However, a set is not a sequence type, but only a collection type (because of the missing order). It is, however, iterable and since this is the only thing that is actually checked in the implementation, the code seems to work for sets, where, in fact, it does not. As a first step, I would suggest one could keep the current implementation, but explicitly check for sequence types (i.e. classes having a method) and delete all mentions of in the code as well as on the documentation page and make it crystal clear that there is only an implementation for sequence types. But what would be way better would, of course, be an implementation for arbitrary container comparisons. Tested with pytest version 7.0.1.


Question: from typing import Callable from typing import cast from typing import Generic<del>from typing import Iterable</del> from typing import List from typing import Mapping from typing import Optional


Question: raise TypeError(msg.format(key, value, pprint.pformat(self.expected)))  class ApproxSequencelike(ApproxBase):class ApproxSequenceLike(ApproxBase):     """Perform approximate comparisons where the expected value is a sequence of numbers."""      def __repr__(self) -> str:         seq_type = type(self.expected)        if seq_type not in (tuple, list, set):        if seq_type not in (tuple, list):             seq_type = list         return "approx({!r})".format(             seq_type(self._approx_scalar(x) for x in self.expected)


Question: def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase:    """Assert that two numbers (or two sets of numbers) are equal to each other    """Assert that two numbers (or two ordered sequences of numbers) are equal to each other     within some tolerance.      Due to the :std:doc:`tutorial/floatingpoint`, numbers that we


Question: >>> 0.1 + 0.2 == approx(0.3)         True     The same syntax also works for sequences of numbers::    The same syntax also works for ordered sequences of numbers::          >>> (0.1 + 0.2, 0.2 + 0.4) == approx((0.3, 0.6))         True     Dictionary *values*::        >>> {'a': 0.1 + 0.2, 'b': 0.2 + 0.4} == approx({'a': 0.3, 'b': 0.6})        True     ``numpy`` arrays::          >>> import numpy as np                                                          # doctest: +SKIP


Question: >>> np.array([0.1, 0.2]) + np.array([0.2, 0.1]) == approx(0.3) # doctest: +SKIP         True <ins>    Only ordered sequences are supported, because ``approx`` needs    to infer the relative position of the sequences without ambiguity. This means    ``sets`` and other unordered sequences are not supported.    Finally, dictionary *values* can also be compared::        >>> {'a': 0.1 + 0.2, 'b': 0.2 + 0.4} == approx({'a': 0.3, 'b': 0.6})        True    The comparision will be true if both mappings have the same keys and their    respective values match the expected tolerances.    **Tolerances**</ins>     By default, ``approx`` considers numbers within a relative tolerance of     ``1e-6`` (i.e. one part in a million) of its expected value to be equal.     This treatment would lead to surprising results if the expected value was


Question: expected = _as_numpy_array(expected)         cls = ApproxNumpy     elif (        isinstance(expected, Iterable)        hasattr(expected, "__getitem__")         and isinstance(expected, Sized)         # Type ignored because the error is wrong -- not unreachable.         and not isinstance(expected, STRING_TYPES)  # type: ignore[unreachable]     ):        cls = ApproxSequencelike        cls = ApproxSequenceLike    elif (        isinstance(expected, Collection)        # Type ignored because the error is wrong -- not unreachable.        and not isinstance(expected, STRING_TYPES)  # type: ignore[unreachable]    ):        msg = f"pytest.approx() only supports ordered sequences, but got: {repr(expected)}"        raise TypeError(msg)     else:         cls = ApproxScalar


Question: """         if self._confcutdir is None:             return True        try:            path.relative_to(self._confcutdir)        except ValueError:            return False        return True        return path not in self._confcutdir.parents      def _try_load_conftest(         self, anchor: Path, importmode: Union[str, ImportMode], rootpath: Path

Version 7.1.0 seems like not picking up Over SciPy we have started to see the message in the title in our Azure Pipelines which started picking up 7.1.0 instead of 7.0.1 lastn ight. From the deprecation and removal list we couldn't see which item might have caused it. One speculation we might generate is that our mark is not registered in our file explicitly and maybe registrations are now obligatory. Here is a complete SciPy test suite example with all installation steps provided. And our file lives here Thank you for all the efforts.


Question: def _repr_compare(self, other_side: Sequence[float]) -> List[str]:         import math<del>        import numpy as np</del>          if len(self.expected) != len(other_side):             return [

ModuleNotFoundError for Numpy when fails <!-- Thanks for submitting an issue! Quick check-list while reporting bugs: --When using to compare lists in a test, a is raised for Numpy whenever the test fails. If the test succeeds, there is no such error. It appears that does not require Numpy to run, but the error message requires Numpy to display the details. Since does not require Numpy to function correctly, it should not require Numpy to display the error. macOS Big Sur Version 11.6.2 No which makes the whole error message confusing and leads you to believe it failed because Numpy is not installed instead of the fact it was an assertion error.


Question: abs_diff = abs(approx_value.expected - other_value)                 max_abs_diff = max(max_abs_diff, abs_diff)                 if other_value == 0.0:                    max_rel_diff = np.inf                    max_rel_diff = math.inf                 else:                     max_rel_diff = max(max_rel_diff, abs_diff / abs(other_value))                 different_ids.append(i)


Question: """     __tracebackhide__ = True <ins>    if not expected_exception:        raise ValueError(            f"Expected an exception type or a tuple of exception types, but got `{expected_exception!r}`. "            f"Raising exceptions is already understood as failing the test, so you don't need "            f"any special code to say 'this should never raise an exception'."        )</ins>     if isinstance(expected_exception, type):         excepted_exceptions: Tuple[Type[E], ...] = (expected_exception,)     else:

Improved error when (empty tuple) is passed to or When using as a context manager, you can pass an exception type or tuple of exception types; it's then an error if no exception is raised or if the exception raised is not an instance of the expected type(s). The same logic applies to , which has a near-identical API. The problem is that if you pass the empty tuple , this will always result in an error: even if an exception is raised, it can't be an instance of ! I think we should explicitly check tuple inputs, and raise a more helpful error message if they're empty. For example: "Passing is an error, because it's impossible to raise an exception which is not an instance of any type. Raising exceptions is already understood as failing the test, so you don't need any special code to say 'this should never raise an exception'." (for bonus points, should have the same message, with instead of ) The same logic, and same error message, applies to the argument to . "Passing is an error, because it's impossible to emit a warning which is not an instance of any type. To assert that no warnings are emitted, use <whatever we come up with for


Question: from _pytest.pathlib import visit from _pytest.scope import Scope from _pytest.warning_types import PytestCollectionWarningfrom _pytest.warning_types import PytestReturnNotNoneWarning from _pytest.warning_types import PytestUnhandledCoroutineWarning  if TYPE_CHECKING:     from typing_extensions import Literal     from _pytest.scope import _ScopeName

Test functions that return non-None should raise a warning/error Consider this test: Did you spot the error? The second parametrization has a typo, is 9, not 8. But this test actually doesn't test anything, because it returns the assertion rather than asserting it. This is a common enough mistake, and it wouldn't normally be a problem except that it can silently cause false positives in test suites. I propose that test functions that return anything except None fail with a message that cues users that they probably meant to assert rather than return. This feature could be disabled (or enabled, if there are backwards-compatibility issues) via a config flag if necessary.


Question: result = testfunction(**testargs)     if hasattr(result, "__await__") or hasattr(result, "__aiter__"):         async_warn_and_skip(pyfuncitem.nodeid)    elif result is not None:        warnings.warn(            PytestReturnNotNoneWarning(                f"Expected None, but {pyfuncitem.nodeid} returned {result!r}, which will be an error in a "                "future version of pytest.  Did you mean to use `assert` instead of `return`?"            )        )     return True  diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py-- a/src/_pytest/warning_types.py++ b/src/_pytest/warning_types.py


Question: __module__ = "pytest"  @finalclass PytestReturnNotNoneWarning(PytestDeprecationWarning):    """Warning emitted when a test function is returning value other than None."""    __module__ = "pytest" @final class PytestExperimentalApiWarning(PytestWarning, FutureWarning):     """Warning category used to denote experiments in pytest.diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py-- a/src/pytest/__init__.py++ b/src/pytest/__init__.py


Question: from _pytest.warning_types import PytestDeprecationWarning from _pytest.warning_types import PytestExperimentalApiWarning from _pytest.warning_types import PytestRemovedIn8Warning<ins>from _pytest.warning_types import PytestReturnNotNoneWarning</ins> from _pytest.warning_types import PytestUnhandledCoroutineWarning from _pytest.warning_types import PytestUnhandledThreadExceptionWarning from _pytest.warning_types import PytestUnknownMarkWarning


Question: "PytestDeprecationWarning",     "PytestExperimentalApiWarning",     "PytestRemovedIn8Warning",<ins>    "PytestReturnNotNoneWarning",</ins>     "Pytester",     "PytestPluginManager",     "PytestUnhandledCoroutineWarning",


Question: >>> enc.inverse_transform([[0, 1, 1, 0, 0], [0, 0, 0, 1, 0]])     array([['Male', 1],            [None, 2]], dtype=object)<ins>    >>> enc.get_feature_names()    array(['x0_Female', 'x0_Male', 'x1_1', 'x1_2', 'x1_3'], dtype=object)</ins>      See also     --------

add getfeaturenames to CategoricalEncoder We should add a ` to the new CategoricalEncoder, as discussed . I think it would be good to be consistent with the PolynomialFeature which allows passing in original feature names to map them to new feature names. Also see .


Question: return X_tr <ins>    def get_feature_names(self, input_features=None):        """Return feature names for output features.        Parameters        ----------        input_features : list of string, length n_features, optional            String names for input features if available. By default,            "x0", "x1", ... "xn_features" is used.        Returns        -------        output_feature_names : array of string, length n_output_features        """        check_is_fitted(self, 'categories_')        cats = self.categories_        if input_features is None:            input_features = ['x%d' % i for i in range(len(cats))]        elif(len(input_features) != len(self.categories_)):            raise ValueError(                "input_features should have length equal to number of "                "features ({}), got {}".format(len(self.categories_),                                               len(input_features)))        feature_names = []        for i in range(len(cats)):            names = [                input_features[i] + '_' + six.text_type(t) for t in cats[i]]            feature_names.extend(names)        return np.array(feature_names, dtype=object)</ins>  class OrdinalEncoder(_BaseEncoder):     """Encode categorical features as an integer array.


Question: store_cv_values : boolean, default=False         Flag indicating if the cross-validation values corresponding to        each alpha should be stored in the `cv_values_` attribute (see        below). This flag is only compatible with `cv=None` (i.e. using        each alpha should be stored in the ``cv_values_`` attribute (see        below). This flag is only compatible with ``cv=None`` (i.e. using         Generalized Cross-Validation).      Attributes     ----------     cv_values_ : array, shape = [n_samples, n_alphas] or \         shape = [n_samples, n_targets, n_alphas], optional        Cross-validation values for each alpha (if `store_cv_values=True` and \        `cv=None`). After `fit()` has been called, this attribute will \        contain the mean squared errors (by default) or the values of the \        `{loss,score}_func` function (if provided in the constructor).        Cross-validation values for each alpha (if ``store_cv_values=True``\        and ``cv=None``). After ``fit()`` has been called, this attribute \        will contain the mean squared errors (by default) or the values \        of the ``{loss,score}_func`` function (if provided in the constructor).      coef_ : array, shape = [n_features] or [n_targets, n_features]         Weight vector(s).

linearmodel.RidgeClassifierCV's Parameter storecvvalues issue Parameter storecvvalues error on sklearn.linearmodel.RidgeClassifierCV import numpy as np from sklearn import linearmodel as lm #test database n = 100 x = (n, 30) y = (size = n) rr = lm.RidgeClassifierCV(alphas = (0.1, 1000, 0.1), normalize = True, storecvvalues = True).fit(x, y) Expected to get the usual ridge regression model output, keeping the cross validation predictions as attribute. TypeError: init() got an unexpected keyword argument 'storecvvalues' lm.RidgeClassifierCV actually has no parameter storecvvalues, even though some attributes depends on it. Windows-10-10.0.-SP0 Python 3.6.3 (default, Oct 15 2017, 03:27:45) [MSC v.1900 64 bit (AMD64)] NumPy 1.13.3 SciPy 0.19.1 Scikit-Learn 0.19.1 Add storecvvalues boolean flag support to RidgeClassifierCV Add storecvvalues support to RidgeClassifierCV - documentation claims that usage of this flag is possible: While actually usage of this flag gives


Question: weights inversely proportional to class frequencies in the input data         as ``n_samples / (n_classes * np.bincount(y))``     store_cv_values : boolean, default=False        Flag indicating if the cross-validation values corresponding to        each alpha should be stored in the ``cv_values_`` attribute (see        below). This flag is only compatible with ``cv=None`` (i.e. using        Generalized Cross-Validation).     Attributes     ----------    cv_values_ : array, shape = [n_samples, n_alphas] or \    shape = [n_samples, n_responses, n_alphas], optional        Cross-validation values for each alpha (if `store_cv_values=True` and    `cv=None`). After `fit()` has been called, this attribute will contain \    the mean squared errors (by default) or the values of the \    `{loss,score}_func` function (if provided in the constructor).    cv_values_ : array, shape = [n_samples, n_targets, n_alphas], optional        Cross-validation values for each alpha (if ``store_cv_values=True`` and        ``cv=None``). After ``fit()`` has been called, this attribute will        contain the mean squared errors (by default) or the values of the        ``{loss,score}_func`` function (if provided in the constructor).      coef_ : array, shape = [n_features] or [n_targets, n_features]         Weight vector(s).


Question: advantage of the multi-variate response support in Ridge.     """     def __init__(self, alphas=(0.1, 1.0, 10.0), fit_intercept=True,                 normalize=False, scoring=None, cv=None, class_weight=None):                 normalize=False, scoring=None, cv=None, class_weight=None,                 store_cv_values=False):         super(RidgeClassifierCV, self).__init__(             alphas=alphas, fit_intercept=fit_intercept, normalize=normalize,            scoring=scoring, cv=cv)            scoring=scoring, cv=cv, store_cv_values=store_cv_values)         self.class_weight = class_weight      def fit(self, X, y, sample_weight=None):