aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/pytest/py2/_pytest/main.py
diff options
context:
space:
mode:
authordeshevoy <deshevoy@yandex-team.ru>2022-02-10 16:46:56 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:46:56 +0300
commite988f30484abe5fdeedcc7a5d3c226c01a21800c (patch)
tree0a217b173aabb57b7e51f8a169989b1a3e0309fe /contrib/python/pytest/py2/_pytest/main.py
parent33ee501c05d3f24036ae89766a858930ae66c548 (diff)
downloadydb-e988f30484abe5fdeedcc7a5d3c226c01a21800c.tar.gz
Restoring authorship annotation for <deshevoy@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/pytest/py2/_pytest/main.py')
-rw-r--r--contrib/python/pytest/py2/_pytest/main.py1378
1 files changed, 689 insertions, 689 deletions
diff --git a/contrib/python/pytest/py2/_pytest/main.py b/contrib/python/pytest/py2/_pytest/main.py
index a9d310cb62d..5bfa2e1ff14 100644
--- a/contrib/python/pytest/py2/_pytest/main.py
+++ b/contrib/python/pytest/py2/_pytest/main.py
@@ -1,177 +1,177 @@
# -*- coding: utf-8 -*-
-""" core implementation of testing process: init, session, runtest loop. """
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import contextlib
+""" core implementation of testing process: init, session, runtest loop. """
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+import contextlib
import fnmatch
-import functools
-import os
-import pkgutil
-import sys
+import functools
+import os
+import pkgutil
+import sys
import warnings
-
-import attr
-import py
-import six
-
-import _pytest._code
-from _pytest import nodes
-from _pytest.config import directory_arg
-from _pytest.config import hookimpl
-from _pytest.config import UsageError
+
+import attr
+import py
+import six
+
+import _pytest._code
+from _pytest import nodes
+from _pytest.config import directory_arg
+from _pytest.config import hookimpl
+from _pytest.config import UsageError
from _pytest.deprecated import PYTEST_CONFIG_GLOBAL
-from _pytest.outcomes import exit
-from _pytest.runner import collect_one_node
-
-# exitcodes for the command line
-EXIT_OK = 0
-EXIT_TESTSFAILED = 1
-EXIT_INTERRUPTED = 2
-EXIT_INTERNALERROR = 3
-EXIT_USAGEERROR = 4
-EXIT_NOTESTSCOLLECTED = 5
-
-
-def pytest_addoption(parser):
- parser.addini(
- "norecursedirs",
- "directory patterns to avoid for recursion",
- type="args",
- default=[".*", "build", "dist", "CVS", "_darcs", "{arch}", "*.egg", "venv"],
- )
- parser.addini(
- "testpaths",
- "directories to search for tests when no files or directories are given in the "
- "command line.",
- type="args",
- default=[],
- )
- group = parser.getgroup("general", "running and selection options")
- group._addoption(
- "-x",
- "--exitfirst",
- action="store_const",
- dest="maxfail",
- const=1,
- help="exit instantly on first error or failed test.",
- ),
- group._addoption(
- "--maxfail",
- metavar="num",
- action="store",
- type=int,
- dest="maxfail",
- default=0,
- help="exit after first num failures or errors.",
- )
- group._addoption(
+from _pytest.outcomes import exit
+from _pytest.runner import collect_one_node
+
+# exitcodes for the command line
+EXIT_OK = 0
+EXIT_TESTSFAILED = 1
+EXIT_INTERRUPTED = 2
+EXIT_INTERNALERROR = 3
+EXIT_USAGEERROR = 4
+EXIT_NOTESTSCOLLECTED = 5
+
+
+def pytest_addoption(parser):
+ parser.addini(
+ "norecursedirs",
+ "directory patterns to avoid for recursion",
+ type="args",
+ default=[".*", "build", "dist", "CVS", "_darcs", "{arch}", "*.egg", "venv"],
+ )
+ parser.addini(
+ "testpaths",
+ "directories to search for tests when no files or directories are given in the "
+ "command line.",
+ type="args",
+ default=[],
+ )
+ group = parser.getgroup("general", "running and selection options")
+ group._addoption(
+ "-x",
+ "--exitfirst",
+ action="store_const",
+ dest="maxfail",
+ const=1,
+ help="exit instantly on first error or failed test.",
+ ),
+ group._addoption(
+ "--maxfail",
+ metavar="num",
+ action="store",
+ type=int,
+ dest="maxfail",
+ default=0,
+ help="exit after first num failures or errors.",
+ )
+ group._addoption(
"--strict-markers",
- "--strict",
- action="store_true",
+ "--strict",
+ action="store_true",
help="markers not registered in the `markers` section of the configuration file raise errors.",
- )
- group._addoption(
- "-c",
- metavar="file",
- type=str,
- dest="inifilename",
- help="load configuration from `file` instead of trying to locate one of the implicit "
- "configuration files.",
- )
- group._addoption(
- "--continue-on-collection-errors",
- action="store_true",
- default=False,
- dest="continue_on_collection_errors",
- help="Force test execution even if collection errors occur.",
- )
- group._addoption(
- "--rootdir",
- action="store",
- dest="rootdir",
- help="Define root directory for tests. Can be relative path: 'root_dir', './root_dir', "
- "'root_dir/another_dir/'; absolute path: '/home/user/root_dir'; path with variables: "
- "'$HOME/root_dir'.",
- )
-
- group = parser.getgroup("collect", "collection")
- group.addoption(
- "--collectonly",
- "--collect-only",
- action="store_true",
- help="only collect tests, don't execute them.",
- ),
- group.addoption(
- "--pyargs",
- action="store_true",
- help="try to interpret all arguments as python packages.",
- )
- group.addoption(
- "--ignore",
- action="append",
- metavar="path",
- help="ignore path during collection (multi-allowed).",
- )
- group.addoption(
+ )
+ group._addoption(
+ "-c",
+ metavar="file",
+ type=str,
+ dest="inifilename",
+ help="load configuration from `file` instead of trying to locate one of the implicit "
+ "configuration files.",
+ )
+ group._addoption(
+ "--continue-on-collection-errors",
+ action="store_true",
+ default=False,
+ dest="continue_on_collection_errors",
+ help="Force test execution even if collection errors occur.",
+ )
+ group._addoption(
+ "--rootdir",
+ action="store",
+ dest="rootdir",
+ help="Define root directory for tests. Can be relative path: 'root_dir', './root_dir', "
+ "'root_dir/another_dir/'; absolute path: '/home/user/root_dir'; path with variables: "
+ "'$HOME/root_dir'.",
+ )
+
+ group = parser.getgroup("collect", "collection")
+ group.addoption(
+ "--collectonly",
+ "--collect-only",
+ action="store_true",
+ help="only collect tests, don't execute them.",
+ ),
+ group.addoption(
+ "--pyargs",
+ action="store_true",
+ help="try to interpret all arguments as python packages.",
+ )
+ group.addoption(
+ "--ignore",
+ action="append",
+ metavar="path",
+ help="ignore path during collection (multi-allowed).",
+ )
+ group.addoption(
"--ignore-glob",
action="append",
metavar="path",
help="ignore path pattern during collection (multi-allowed).",
)
group.addoption(
- "--deselect",
- action="append",
- metavar="nodeid_prefix",
- help="deselect item during collection (multi-allowed).",
- )
- # when changing this to --conf-cut-dir, config.py Conftest.setinitial
- # needs upgrading as well
- group.addoption(
- "--confcutdir",
- dest="confcutdir",
- default=None,
- metavar="dir",
- type=functools.partial(directory_arg, optname="--confcutdir"),
- help="only load conftest.py's relative to specified dir.",
- )
- group.addoption(
- "--noconftest",
- action="store_true",
- dest="noconftest",
- default=False,
- help="Don't load any conftest.py files.",
- )
- group.addoption(
- "--keepduplicates",
- "--keep-duplicates",
- action="store_true",
- dest="keepduplicates",
- default=False,
- help="Keep duplicate tests.",
- )
- group.addoption(
- "--collect-in-virtualenv",
- action="store_true",
- dest="collect_in_virtualenv",
- default=False,
- help="Don't ignore tests in a local virtualenv directory",
- )
-
- group = parser.getgroup("debugconfig", "test session debugging and configuration")
- group.addoption(
- "--basetemp",
- dest="basetemp",
- default=None,
- metavar="dir",
- help=(
- "base temporary directory for this test run."
- "(warning: this directory is removed if it exists)"
- ),
- )
-
-
+ "--deselect",
+ action="append",
+ metavar="nodeid_prefix",
+ help="deselect item during collection (multi-allowed).",
+ )
+ # when changing this to --conf-cut-dir, config.py Conftest.setinitial
+ # needs upgrading as well
+ group.addoption(
+ "--confcutdir",
+ dest="confcutdir",
+ default=None,
+ metavar="dir",
+ type=functools.partial(directory_arg, optname="--confcutdir"),
+ help="only load conftest.py's relative to specified dir.",
+ )
+ group.addoption(
+ "--noconftest",
+ action="store_true",
+ dest="noconftest",
+ default=False,
+ help="Don't load any conftest.py files.",
+ )
+ group.addoption(
+ "--keepduplicates",
+ "--keep-duplicates",
+ action="store_true",
+ dest="keepduplicates",
+ default=False,
+ help="Keep duplicate tests.",
+ )
+ group.addoption(
+ "--collect-in-virtualenv",
+ action="store_true",
+ dest="collect_in_virtualenv",
+ default=False,
+ help="Don't ignore tests in a local virtualenv directory",
+ )
+
+ group = parser.getgroup("debugconfig", "test session debugging and configuration")
+ group.addoption(
+ "--basetemp",
+ dest="basetemp",
+ default=None,
+ metavar="dir",
+ help=(
+ "base temporary directory for this test run."
+ "(warning: this directory is removed if it exists)"
+ ),
+ )
+
+
class _ConfigDeprecated(object):
def __init__(self, config):
self.__dict__["_config"] = config
@@ -188,121 +188,121 @@ class _ConfigDeprecated(object):
return "{}({!r})".format(type(self).__name__, self._config)
-def pytest_configure(config):
+def pytest_configure(config):
__import__("pytest").config = _ConfigDeprecated(config) # compatibility
-
-
-def wrap_session(config, doit):
- """Skeleton command line program"""
- session = Session(config)
- session.exitstatus = EXIT_OK
- initstate = 0
- try:
- try:
- config._do_configure()
- initstate = 1
- config.hook.pytest_sessionstart(session=session)
- initstate = 2
- session.exitstatus = doit(config, session) or 0
- except UsageError:
+
+
+def wrap_session(config, doit):
+ """Skeleton command line program"""
+ session = Session(config)
+ session.exitstatus = EXIT_OK
+ initstate = 0
+ try:
+ try:
+ config._do_configure()
+ initstate = 1
+ config.hook.pytest_sessionstart(session=session)
+ initstate = 2
+ session.exitstatus = doit(config, session) or 0
+ except UsageError:
session.exitstatus = EXIT_USAGEERROR
- raise
- except Failed:
- session.exitstatus = EXIT_TESTSFAILED
+ raise
+ except Failed:
+ session.exitstatus = EXIT_TESTSFAILED
except (KeyboardInterrupt, exit.Exception):
excinfo = _pytest._code.ExceptionInfo.from_current()
- exitstatus = EXIT_INTERRUPTED
+ exitstatus = EXIT_INTERRUPTED
if isinstance(excinfo.value, exit.Exception):
- if excinfo.value.returncode is not None:
- exitstatus = excinfo.value.returncode
+ if excinfo.value.returncode is not None:
+ exitstatus = excinfo.value.returncode
if initstate < 2:
sys.stderr.write(
"{}: {}\n".format(excinfo.typename, excinfo.value.msg)
)
- config.hook.pytest_keyboard_interrupt(excinfo=excinfo)
- session.exitstatus = exitstatus
- except: # noqa
+ config.hook.pytest_keyboard_interrupt(excinfo=excinfo)
+ session.exitstatus = exitstatus
+ except: # noqa
excinfo = _pytest._code.ExceptionInfo.from_current()
- config.notify_exception(excinfo, config.option)
- session.exitstatus = EXIT_INTERNALERROR
- if excinfo.errisinstance(SystemExit):
+ config.notify_exception(excinfo, config.option)
+ session.exitstatus = EXIT_INTERNALERROR
+ if excinfo.errisinstance(SystemExit):
sys.stderr.write("mainloop: caught unexpected SystemExit!\n")
-
- finally:
- excinfo = None # Explicitly break reference cycle.
- session.startdir.chdir()
- if initstate >= 2:
- config.hook.pytest_sessionfinish(
- session=session, exitstatus=session.exitstatus
- )
- config._ensure_unconfigure()
- return session.exitstatus
-
-
-def pytest_cmdline_main(config):
- return wrap_session(config, _main)
-
-
-def _main(config, session):
- """ default command line protocol for initialization, session,
- running tests and reporting. """
- config.hook.pytest_collection(session=session)
- config.hook.pytest_runtestloop(session=session)
-
- if session.testsfailed:
- return EXIT_TESTSFAILED
- elif session.testscollected == 0:
- return EXIT_NOTESTSCOLLECTED
-
-
-def pytest_collection(session):
- return session.perform_collect()
-
-
-def pytest_runtestloop(session):
- if session.testsfailed and not session.config.option.continue_on_collection_errors:
- raise session.Interrupted("%d errors during collection" % session.testsfailed)
-
- if session.config.option.collectonly:
- return True
-
- for i, item in enumerate(session.items):
- nextitem = session.items[i + 1] if i + 1 < len(session.items) else None
- item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
- if session.shouldfail:
- raise session.Failed(session.shouldfail)
- if session.shouldstop:
- raise session.Interrupted(session.shouldstop)
- return True
-
-
-def _in_venv(path):
- """Attempts to detect if ``path`` is the root of a Virtual Environment by
- checking for the existence of the appropriate activate script"""
- bindir = path.join("Scripts" if sys.platform.startswith("win") else "bin")
- if not bindir.isdir():
- return False
- activates = (
- "activate",
- "activate.csh",
- "activate.fish",
- "Activate",
- "Activate.bat",
- "Activate.ps1",
- )
- return any([fname.basename in activates for fname in bindir.listdir()])
-
-
-def pytest_ignore_collect(path, config):
- ignore_paths = config._getconftest_pathlist("collect_ignore", path=path.dirpath())
- ignore_paths = ignore_paths or []
- excludeopt = config.getoption("ignore")
- if excludeopt:
- ignore_paths.extend([py.path.local(x) for x in excludeopt])
-
- if py.path.local(path) in ignore_paths:
- return True
-
+
+ finally:
+ excinfo = None # Explicitly break reference cycle.
+ session.startdir.chdir()
+ if initstate >= 2:
+ config.hook.pytest_sessionfinish(
+ session=session, exitstatus=session.exitstatus
+ )
+ config._ensure_unconfigure()
+ return session.exitstatus
+
+
+def pytest_cmdline_main(config):
+ return wrap_session(config, _main)
+
+
+def _main(config, session):
+ """ default command line protocol for initialization, session,
+ running tests and reporting. """
+ config.hook.pytest_collection(session=session)
+ config.hook.pytest_runtestloop(session=session)
+
+ if session.testsfailed:
+ return EXIT_TESTSFAILED
+ elif session.testscollected == 0:
+ return EXIT_NOTESTSCOLLECTED
+
+
+def pytest_collection(session):
+ return session.perform_collect()
+
+
+def pytest_runtestloop(session):
+ if session.testsfailed and not session.config.option.continue_on_collection_errors:
+ raise session.Interrupted("%d errors during collection" % session.testsfailed)
+
+ if session.config.option.collectonly:
+ return True
+
+ for i, item in enumerate(session.items):
+ nextitem = session.items[i + 1] if i + 1 < len(session.items) else None
+ item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
+ if session.shouldfail:
+ raise session.Failed(session.shouldfail)
+ if session.shouldstop:
+ raise session.Interrupted(session.shouldstop)
+ return True
+
+
+def _in_venv(path):
+ """Attempts to detect if ``path`` is the root of a Virtual Environment by
+ checking for the existence of the appropriate activate script"""
+ bindir = path.join("Scripts" if sys.platform.startswith("win") else "bin")
+ if not bindir.isdir():
+ return False
+ activates = (
+ "activate",
+ "activate.csh",
+ "activate.fish",
+ "Activate",
+ "Activate.bat",
+ "Activate.ps1",
+ )
+ return any([fname.basename in activates for fname in bindir.listdir()])
+
+
+def pytest_ignore_collect(path, config):
+ ignore_paths = config._getconftest_pathlist("collect_ignore", path=path.dirpath())
+ ignore_paths = ignore_paths or []
+ excludeopt = config.getoption("ignore")
+ if excludeopt:
+ ignore_paths.extend([py.path.local(x) for x in excludeopt])
+
+ if py.path.local(path) in ignore_paths:
+ return True
+
ignore_globs = config._getconftest_pathlist(
"collect_ignore_glob", path=path.dirpath()
)
@@ -317,131 +317,131 @@ def pytest_ignore_collect(path, config):
):
return True
- allow_in_venv = config.getoption("collect_in_virtualenv")
- if not allow_in_venv and _in_venv(path):
- return True
-
- return False
-
-
-def pytest_collection_modifyitems(items, config):
- deselect_prefixes = tuple(config.getoption("deselect") or [])
- if not deselect_prefixes:
- return
-
- remaining = []
- deselected = []
- for colitem in items:
- if colitem.nodeid.startswith(deselect_prefixes):
- deselected.append(colitem)
- else:
- remaining.append(colitem)
-
- if deselected:
- config.hook.pytest_deselected(items=deselected)
- items[:] = remaining
-
-
-@contextlib.contextmanager
-def _patched_find_module():
- """Patch bug in pkgutil.ImpImporter.find_module
-
- When using pkgutil.find_loader on python<3.4 it removes symlinks
- from the path due to a call to os.path.realpath. This is not consistent
- with actually doing the import (in these versions, pkgutil and __import__
- did not share the same underlying code). This can break conftest
- discovery for pytest where symlinks are involved.
-
- The only supported python<3.4 by pytest is python 2.7.
- """
- if six.PY2: # python 3.4+ uses importlib instead
-
- def find_module_patched(self, fullname, path=None):
- # Note: we ignore 'path' argument since it is only used via meta_path
- subname = fullname.split(".")[-1]
- if subname != fullname and self.path is None:
- return None
- if self.path is None:
- path = None
- else:
- # original: path = [os.path.realpath(self.path)]
- path = [self.path]
- try:
- file, filename, etc = pkgutil.imp.find_module(subname, path)
- except ImportError:
- return None
- return pkgutil.ImpLoader(fullname, file, filename, etc)
-
- old_find_module = pkgutil.ImpImporter.find_module
- pkgutil.ImpImporter.find_module = find_module_patched
- try:
- yield
- finally:
- pkgutil.ImpImporter.find_module = old_find_module
- else:
- yield
-
-
-class FSHookProxy(object):
- def __init__(self, fspath, pm, remove_mods):
- self.fspath = fspath
- self.pm = pm
- self.remove_mods = remove_mods
-
- def __getattr__(self, name):
- x = self.pm.subset_hook_caller(name, remove_plugins=self.remove_mods)
- self.__dict__[name] = x
- return x
-
-
-class NoMatch(Exception):
- """ raised if matching cannot locate a matching names. """
-
-
-class Interrupted(KeyboardInterrupt):
- """ signals an interrupted test run. """
-
- __module__ = "builtins" # for py3
-
-
-class Failed(Exception):
- """ signals a stop as failed test run. """
-
-
-@attr.s
-class _bestrelpath_cache(dict):
- path = attr.ib()
-
- def __missing__(self, path):
- r = self.path.bestrelpath(path)
- self[path] = r
- return r
-
-
-class Session(nodes.FSCollector):
- Interrupted = Interrupted
- Failed = Failed
-
- def __init__(self, config):
- nodes.FSCollector.__init__(
- self, config.rootdir, parent=None, config=config, session=self, nodeid=""
- )
- self.testsfailed = 0
- self.testscollected = 0
- self.shouldstop = False
- self.shouldfail = False
- self.trace = config.trace.root.get("collection")
- self._norecursepatterns = config.getini("norecursedirs")
+ allow_in_venv = config.getoption("collect_in_virtualenv")
+ if not allow_in_venv and _in_venv(path):
+ return True
+
+ return False
+
+
+def pytest_collection_modifyitems(items, config):
+ deselect_prefixes = tuple(config.getoption("deselect") or [])
+ if not deselect_prefixes:
+ return
+
+ remaining = []
+ deselected = []
+ for colitem in items:
+ if colitem.nodeid.startswith(deselect_prefixes):
+ deselected.append(colitem)
+ else:
+ remaining.append(colitem)
+
+ if deselected:
+ config.hook.pytest_deselected(items=deselected)
+ items[:] = remaining
+
+
+@contextlib.contextmanager
+def _patched_find_module():
+ """Patch bug in pkgutil.ImpImporter.find_module
+
+ When using pkgutil.find_loader on python<3.4 it removes symlinks
+ from the path due to a call to os.path.realpath. This is not consistent
+ with actually doing the import (in these versions, pkgutil and __import__
+ did not share the same underlying code). This can break conftest
+ discovery for pytest where symlinks are involved.
+
+ The only supported python<3.4 by pytest is python 2.7.
+ """
+ if six.PY2: # python 3.4+ uses importlib instead
+
+ def find_module_patched(self, fullname, path=None):
+ # Note: we ignore 'path' argument since it is only used via meta_path
+ subname = fullname.split(".")[-1]
+ if subname != fullname and self.path is None:
+ return None
+ if self.path is None:
+ path = None
+ else:
+ # original: path = [os.path.realpath(self.path)]
+ path = [self.path]
+ try:
+ file, filename, etc = pkgutil.imp.find_module(subname, path)
+ except ImportError:
+ return None
+ return pkgutil.ImpLoader(fullname, file, filename, etc)
+
+ old_find_module = pkgutil.ImpImporter.find_module
+ pkgutil.ImpImporter.find_module = find_module_patched
+ try:
+ yield
+ finally:
+ pkgutil.ImpImporter.find_module = old_find_module
+ else:
+ yield
+
+
+class FSHookProxy(object):
+ def __init__(self, fspath, pm, remove_mods):
+ self.fspath = fspath
+ self.pm = pm
+ self.remove_mods = remove_mods
+
+ def __getattr__(self, name):
+ x = self.pm.subset_hook_caller(name, remove_plugins=self.remove_mods)
+ self.__dict__[name] = x
+ return x
+
+
+class NoMatch(Exception):
+ """ raised if matching cannot locate a matching names. """
+
+
+class Interrupted(KeyboardInterrupt):
+ """ signals an interrupted test run. """
+
+ __module__ = "builtins" # for py3
+
+
+class Failed(Exception):
+ """ signals a stop as failed test run. """
+
+
+@attr.s
+class _bestrelpath_cache(dict):
+ path = attr.ib()
+
+ def __missing__(self, path):
+ r = self.path.bestrelpath(path)
+ self[path] = r
+ return r
+
+
+class Session(nodes.FSCollector):
+ Interrupted = Interrupted
+ Failed = Failed
+
+ def __init__(self, config):
+ nodes.FSCollector.__init__(
+ self, config.rootdir, parent=None, config=config, session=self, nodeid=""
+ )
+ self.testsfailed = 0
+ self.testscollected = 0
+ self.shouldstop = False
+ self.shouldfail = False
+ self.trace = config.trace.root.get("collection")
+ self._norecursepatterns = config.getini("norecursedirs")
self.startdir = config.invocation_dir
- self._initialpaths = frozenset()
- # Keep track of any collected nodes in here, so we don't duplicate fixtures
- self._node_cache = {}
- self._bestrelpathcache = _bestrelpath_cache(config.rootdir)
- # Dirnames of pkgs with dunder-init files.
- self._pkg_roots = {}
-
- self.config.pluginmanager.register(self, name="session")
-
+ self._initialpaths = frozenset()
+ # Keep track of any collected nodes in here, so we don't duplicate fixtures
+ self._node_cache = {}
+ self._bestrelpathcache = _bestrelpath_cache(config.rootdir)
+ # Dirnames of pkgs with dunder-init files.
+ self._pkg_roots = {}
+
+ self.config.pluginmanager.register(self, name="session")
+
def __repr__(self):
return "<%s %s exitstatus=%r testsfailed=%d testscollected=%d>" % (
self.__class__.__name__,
@@ -451,176 +451,176 @@ class Session(nodes.FSCollector):
self.testscollected,
)
- def _node_location_to_relpath(self, node_path):
- # bestrelpath is a quite slow function
- return self._bestrelpathcache[node_path]
-
- @hookimpl(tryfirst=True)
- def pytest_collectstart(self):
- if self.shouldfail:
- raise self.Failed(self.shouldfail)
- if self.shouldstop:
- raise self.Interrupted(self.shouldstop)
-
- @hookimpl(tryfirst=True)
- def pytest_runtest_logreport(self, report):
- if report.failed and not hasattr(report, "wasxfail"):
- self.testsfailed += 1
- maxfail = self.config.getvalue("maxfail")
- if maxfail and self.testsfailed >= maxfail:
- self.shouldfail = "stopping after %d failures" % (self.testsfailed)
-
- pytest_collectreport = pytest_runtest_logreport
-
- def isinitpath(self, path):
- return path in self._initialpaths
-
- def gethookproxy(self, 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)
- remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
- if remove_mods:
- # one or more conftests are not in use at this fspath
- proxy = FSHookProxy(fspath, pm, remove_mods)
- else:
- # all plugis are active for this fspath
- proxy = self.config.hook
- return proxy
-
- def perform_collect(self, args=None, genitems=True):
- hook = self.config.hook
- try:
- items = self._perform_collect(args, genitems)
- self.config.pluginmanager.check_pending()
- hook.pytest_collection_modifyitems(
- session=self, config=self.config, items=items
- )
- finally:
- hook.pytest_collection_finish(session=self)
- self.testscollected = len(items)
- return items
-
- def _perform_collect(self, args, genitems):
- if args is None:
- args = self.config.args
- self.trace("perform_collect", self, args)
- self.trace.root.indent += 1
- self._notfound = []
- initialpaths = []
- self._initialparts = []
- self.items = items = []
- for arg in args:
- parts = self._parsearg(arg)
- self._initialparts.append(parts)
- initialpaths.append(parts[0])
- self._initialpaths = frozenset(initialpaths)
- rep = collect_one_node(self)
- self.ihook.pytest_collectreport(report=rep)
- self.trace.root.indent -= 1
- if self._notfound:
- errors = []
- for arg, exc in self._notfound:
- line = "(no name %r in any of %r)" % (arg, exc.args[0])
- errors.append("not found: %s\n%s" % (arg, line))
- # XXX: test this
- raise UsageError(*errors)
- if not genitems:
- return rep.result
- else:
- if rep.passed:
- for node in rep.result:
- self.items.extend(self.genitems(node))
- return items
-
- def collect(self):
- for initialpart in self._initialparts:
- arg = "::".join(map(str, initialpart))
- self.trace("processing argument", arg)
- self.trace.root.indent += 1
- try:
- for x in self._collect(arg):
- yield x
- except NoMatch:
- # we are inside a make_report hook so
- # we cannot directly pass through the exception
- self._notfound.append((arg, sys.exc_info()[1]))
-
- self.trace.root.indent -= 1
-
- def _collect(self, arg):
- from _pytest.python import Package
-
- names = self._parsearg(arg)
- argpath = names.pop(0)
-
- # Start with a Session root, and delve to argpath item (dir or file)
- # and stack all Packages found on the way.
- # No point in finding packages when collecting doctests
+ def _node_location_to_relpath(self, node_path):
+ # bestrelpath is a quite slow function
+ return self._bestrelpathcache[node_path]
+
+ @hookimpl(tryfirst=True)
+ def pytest_collectstart(self):
+ if self.shouldfail:
+ raise self.Failed(self.shouldfail)
+ if self.shouldstop:
+ raise self.Interrupted(self.shouldstop)
+
+ @hookimpl(tryfirst=True)
+ def pytest_runtest_logreport(self, report):
+ if report.failed and not hasattr(report, "wasxfail"):
+ self.testsfailed += 1
+ maxfail = self.config.getvalue("maxfail")
+ if maxfail and self.testsfailed >= maxfail:
+ self.shouldfail = "stopping after %d failures" % (self.testsfailed)
+
+ pytest_collectreport = pytest_runtest_logreport
+
+ def isinitpath(self, path):
+ return path in self._initialpaths
+
+ def gethookproxy(self, 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)
+ remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
+ if remove_mods:
+ # one or more conftests are not in use at this fspath
+ proxy = FSHookProxy(fspath, pm, remove_mods)
+ else:
+ # all plugis are active for this fspath
+ proxy = self.config.hook
+ return proxy
+
+ def perform_collect(self, args=None, genitems=True):
+ hook = self.config.hook
+ try:
+ items = self._perform_collect(args, genitems)
+ self.config.pluginmanager.check_pending()
+ hook.pytest_collection_modifyitems(
+ session=self, config=self.config, items=items
+ )
+ finally:
+ hook.pytest_collection_finish(session=self)
+ self.testscollected = len(items)
+ return items
+
+ def _perform_collect(self, args, genitems):
+ if args is None:
+ args = self.config.args
+ self.trace("perform_collect", self, args)
+ self.trace.root.indent += 1
+ self._notfound = []
+ initialpaths = []
+ self._initialparts = []
+ self.items = items = []
+ for arg in args:
+ parts = self._parsearg(arg)
+ self._initialparts.append(parts)
+ initialpaths.append(parts[0])
+ self._initialpaths = frozenset(initialpaths)
+ rep = collect_one_node(self)
+ self.ihook.pytest_collectreport(report=rep)
+ self.trace.root.indent -= 1
+ if self._notfound:
+ errors = []
+ for arg, exc in self._notfound:
+ line = "(no name %r in any of %r)" % (arg, exc.args[0])
+ errors.append("not found: %s\n%s" % (arg, line))
+ # XXX: test this
+ raise UsageError(*errors)
+ if not genitems:
+ return rep.result
+ else:
+ if rep.passed:
+ for node in rep.result:
+ self.items.extend(self.genitems(node))
+ return items
+
+ def collect(self):
+ for initialpart in self._initialparts:
+ arg = "::".join(map(str, initialpart))
+ self.trace("processing argument", arg)
+ self.trace.root.indent += 1
+ try:
+ for x in self._collect(arg):
+ yield x
+ except NoMatch:
+ # we are inside a make_report hook so
+ # we cannot directly pass through the exception
+ self._notfound.append((arg, sys.exc_info()[1]))
+
+ self.trace.root.indent -= 1
+
+ def _collect(self, arg):
+ from _pytest.python import Package
+
+ names = self._parsearg(arg)
+ argpath = names.pop(0)
+
+ # Start with a Session root, and delve to argpath item (dir or file)
+ # and stack all Packages found on the way.
+ # No point in finding packages when collecting doctests
if not self.config.getoption("doctestmodules", False):
- pm = self.config.pluginmanager
- for parent in reversed(argpath.parts()):
- if pm._confcutdir and pm._confcutdir.relto(parent):
- break
-
- if parent.isdir():
- pkginit = parent.join("__init__.py")
- if pkginit.isfile():
- if pkginit not in self._node_cache:
- col = self._collectfile(pkginit, handle_dupes=False)
- if col:
- if isinstance(col[0], Package):
- self._pkg_roots[parent] = col[0]
- # always store a list in the cache, matchnodes expects it
- self._node_cache[col[0].fspath] = [col[0]]
-
- # If it's a directory argument, recurse and look for any Subpackages.
- # Let the Package collector deal with subnodes, don't collect here.
- if argpath.check(dir=1):
- assert not names, "invalid arg %r" % (arg,)
-
- seen_dirs = set()
- for path in argpath.visit(
+ pm = self.config.pluginmanager
+ for parent in reversed(argpath.parts()):
+ if pm._confcutdir and pm._confcutdir.relto(parent):
+ break
+
+ if parent.isdir():
+ pkginit = parent.join("__init__.py")
+ if pkginit.isfile():
+ if pkginit not in self._node_cache:
+ col = self._collectfile(pkginit, handle_dupes=False)
+ if col:
+ if isinstance(col[0], Package):
+ self._pkg_roots[parent] = col[0]
+ # always store a list in the cache, matchnodes expects it
+ self._node_cache[col[0].fspath] = [col[0]]
+
+ # If it's a directory argument, recurse and look for any Subpackages.
+ # Let the Package collector deal with subnodes, don't collect here.
+ if argpath.check(dir=1):
+ assert not names, "invalid arg %r" % (arg,)
+
+ seen_dirs = set()
+ for path in argpath.visit(
fil=self._visit_filter, rec=self._recurse, bf=True, sort=True
- ):
- dirpath = path.dirpath()
- if dirpath not in seen_dirs:
- # Collect packages first.
- seen_dirs.add(dirpath)
- pkginit = dirpath.join("__init__.py")
- if pkginit.exists():
- for x in self._collectfile(pkginit):
- yield x
- if isinstance(x, Package):
- self._pkg_roots[dirpath] = x
- if dirpath in self._pkg_roots:
- # Do not collect packages here.
- continue
-
- for x in self._collectfile(path):
- key = (type(x), x.fspath)
- if key in self._node_cache:
- yield self._node_cache[key]
- else:
- self._node_cache[key] = x
- yield x
- else:
- assert argpath.check(file=1)
-
- if argpath in self._node_cache:
- col = self._node_cache[argpath]
- else:
- collect_root = self._pkg_roots.get(argpath.dirname, self)
+ ):
+ dirpath = path.dirpath()
+ if dirpath not in seen_dirs:
+ # Collect packages first.
+ seen_dirs.add(dirpath)
+ pkginit = dirpath.join("__init__.py")
+ if pkginit.exists():
+ for x in self._collectfile(pkginit):
+ yield x
+ if isinstance(x, Package):
+ self._pkg_roots[dirpath] = x
+ if dirpath in self._pkg_roots:
+ # Do not collect packages here.
+ continue
+
+ for x in self._collectfile(path):
+ key = (type(x), x.fspath)
+ if key in self._node_cache:
+ yield self._node_cache[key]
+ else:
+ self._node_cache[key] = x
+ yield x
+ else:
+ assert argpath.check(file=1)
+
+ if argpath in self._node_cache:
+ col = self._node_cache[argpath]
+ else:
+ collect_root = self._pkg_roots.get(argpath.dirname, self)
col = collect_root._collectfile(argpath, handle_dupes=False)
- if col:
- self._node_cache[argpath] = col
- m = self.matchnodes(col, names)
- # 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":
+ if col:
+ self._node_cache[argpath] = col
+ m = self.matchnodes(col, names)
+ # 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":
try:
yield next(m[0].collect())
except StopIteration:
@@ -628,46 +628,46 @@ class Session(nodes.FSCollector):
# file in it, which gets ignored by the default
# "python_files" option.
pass
- return
- for y in m:
- yield y
-
- def _collectfile(self, path, handle_dupes=True):
+ return
+ for y in m:
+ yield y
+
+ def _collectfile(self, path, handle_dupes=True):
assert path.isfile(), "%r is not a file (isdir=%r, exists=%r, islink=%r)" % (
path,
path.isdir(),
path.exists(),
path.islink(),
)
- ihook = self.gethookproxy(path)
- if not self.isinitpath(path):
- if ihook.pytest_ignore_collect(path=path, config=self.config):
- return ()
-
- if handle_dupes:
- keepduplicates = self.config.getoption("keepduplicates")
- if not keepduplicates:
- duplicate_paths = self.config.pluginmanager._duplicatepaths
- if path in duplicate_paths:
- return ()
- else:
- duplicate_paths.add(path)
-
- return ihook.pytest_collect_file(path=path, parent=self)
-
- def _recurse(self, dirpath):
- if dirpath.basename == "__pycache__":
- return False
- ihook = self.gethookproxy(dirpath.dirpath())
- if ihook.pytest_ignore_collect(path=dirpath, config=self.config):
- return False
- for pat in self._norecursepatterns:
- if dirpath.check(fnmatch=pat):
- return False
- ihook = self.gethookproxy(dirpath)
- ihook.pytest_collect_directory(path=dirpath, parent=self)
- return True
-
+ ihook = self.gethookproxy(path)
+ if not self.isinitpath(path):
+ if ihook.pytest_ignore_collect(path=path, config=self.config):
+ return ()
+
+ if handle_dupes:
+ keepduplicates = self.config.getoption("keepduplicates")
+ if not keepduplicates:
+ duplicate_paths = self.config.pluginmanager._duplicatepaths
+ if path in duplicate_paths:
+ return ()
+ else:
+ duplicate_paths.add(path)
+
+ return ihook.pytest_collect_file(path=path, parent=self)
+
+ def _recurse(self, dirpath):
+ if dirpath.basename == "__pycache__":
+ return False
+ ihook = self.gethookproxy(dirpath.dirpath())
+ if ihook.pytest_ignore_collect(path=dirpath, config=self.config):
+ return False
+ for pat in self._norecursepatterns:
+ if dirpath.check(fnmatch=pat):
+ return False
+ ihook = self.gethookproxy(dirpath)
+ ihook.pytest_collect_directory(path=dirpath, parent=self)
+ return True
+
if six.PY2:
@staticmethod
@@ -680,101 +680,101 @@ class Session(nodes.FSCollector):
def _visit_filter(f):
return f.check(file=1)
- def _tryconvertpyarg(self, x):
- """Convert a dotted module name to path."""
- try:
- with _patched_find_module():
- loader = pkgutil.find_loader(x)
- except ImportError:
- return x
- if loader is None:
- return x
- # This method is sometimes invoked when AssertionRewritingHook, which
- # does not define a get_filename method, is already in place:
- try:
- with _patched_find_module():
- path = loader.get_filename(x)
- except AttributeError:
- # Retrieve path from AssertionRewritingHook:
- path = loader.modules[x][0].co_filename
- if loader.is_package(x):
- path = os.path.dirname(path)
- return path
-
- def _parsearg(self, arg):
- """ return (fspath, names) tuple after checking the file exists. """
- parts = str(arg).split("::")
- if self.config.option.pyargs:
- parts[0] = self._tryconvertpyarg(parts[0])
- relpath = parts[0].replace("/", os.sep)
- path = self.config.invocation_dir.join(relpath, abs=True)
- if not path.check():
- if self.config.option.pyargs:
- raise UsageError(
- "file or package not found: " + arg + " (missing __init__.py?)"
- )
- raise UsageError("file not found: " + arg)
- parts[0] = path.realpath()
- return parts
-
- def matchnodes(self, matching, names):
- self.trace("matchnodes", matching, names)
- self.trace.root.indent += 1
- nodes = self._matchnodes(matching, names)
- num = len(nodes)
- self.trace("matchnodes finished -> ", num, "nodes")
- self.trace.root.indent -= 1
- if num == 0:
- raise NoMatch(matching, names[:1])
- return nodes
-
- def _matchnodes(self, matching, names):
- if not matching or not names:
- return matching
- name = names[0]
- assert name
- nextnames = names[1:]
- resultnodes = []
- for node in matching:
- if isinstance(node, nodes.Item):
- if not names:
- resultnodes.append(node)
- continue
- assert isinstance(node, nodes.Collector)
- key = (type(node), node.nodeid)
- if key in self._node_cache:
- rep = self._node_cache[key]
- else:
- rep = collect_one_node(node)
- self._node_cache[key] = rep
- if rep.passed:
- has_matched = False
- for x in rep.result:
- # TODO: remove parametrized workaround once collection structure contains parametrization
- if x.name == name or x.name.split("[")[0] == name:
- resultnodes.extend(self.matchnodes([x], nextnames))
- has_matched = True
- # XXX accept IDs that don't have "()" for class instances
- if not has_matched and len(rep.result) == 1 and x.name == "()":
- nextnames.insert(0, name)
- resultnodes.extend(self.matchnodes([x], nextnames))
- else:
- # report collection failures here to avoid failing to run some test
- # specified in the command line because the module could not be
- # imported (#134)
- node.ihook.pytest_collectreport(report=rep)
- return resultnodes
-
- def genitems(self, node):
- self.trace("genitems", node)
- if isinstance(node, nodes.Item):
- node.ihook.pytest_itemcollected(item=node)
- yield node
- else:
- assert isinstance(node, nodes.Collector)
- rep = collect_one_node(node)
- if rep.passed:
- for subnode in rep.result:
- for x in self.genitems(subnode):
- yield x
- node.ihook.pytest_collectreport(report=rep)
+ def _tryconvertpyarg(self, x):
+ """Convert a dotted module name to path."""
+ try:
+ with _patched_find_module():
+ loader = pkgutil.find_loader(x)
+ except ImportError:
+ return x
+ if loader is None:
+ return x
+ # This method is sometimes invoked when AssertionRewritingHook, which
+ # does not define a get_filename method, is already in place:
+ try:
+ with _patched_find_module():
+ path = loader.get_filename(x)
+ except AttributeError:
+ # Retrieve path from AssertionRewritingHook:
+ path = loader.modules[x][0].co_filename
+ if loader.is_package(x):
+ path = os.path.dirname(path)
+ return path
+
+ def _parsearg(self, arg):
+ """ return (fspath, names) tuple after checking the file exists. """
+ parts = str(arg).split("::")
+ if self.config.option.pyargs:
+ parts[0] = self._tryconvertpyarg(parts[0])
+ relpath = parts[0].replace("/", os.sep)
+ path = self.config.invocation_dir.join(relpath, abs=True)
+ if not path.check():
+ if self.config.option.pyargs:
+ raise UsageError(
+ "file or package not found: " + arg + " (missing __init__.py?)"
+ )
+ raise UsageError("file not found: " + arg)
+ parts[0] = path.realpath()
+ return parts
+
+ def matchnodes(self, matching, names):
+ self.trace("matchnodes", matching, names)
+ self.trace.root.indent += 1
+ nodes = self._matchnodes(matching, names)
+ num = len(nodes)
+ self.trace("matchnodes finished -> ", num, "nodes")
+ self.trace.root.indent -= 1
+ if num == 0:
+ raise NoMatch(matching, names[:1])
+ return nodes
+
+ def _matchnodes(self, matching, names):
+ if not matching or not names:
+ return matching
+ name = names[0]
+ assert name
+ nextnames = names[1:]
+ resultnodes = []
+ for node in matching:
+ if isinstance(node, nodes.Item):
+ if not names:
+ resultnodes.append(node)
+ continue
+ assert isinstance(node, nodes.Collector)
+ key = (type(node), node.nodeid)
+ if key in self._node_cache:
+ rep = self._node_cache[key]
+ else:
+ rep = collect_one_node(node)
+ self._node_cache[key] = rep
+ if rep.passed:
+ has_matched = False
+ for x in rep.result:
+ # TODO: remove parametrized workaround once collection structure contains parametrization
+ if x.name == name or x.name.split("[")[0] == name:
+ resultnodes.extend(self.matchnodes([x], nextnames))
+ has_matched = True
+ # XXX accept IDs that don't have "()" for class instances
+ if not has_matched and len(rep.result) == 1 and x.name == "()":
+ nextnames.insert(0, name)
+ resultnodes.extend(self.matchnodes([x], nextnames))
+ else:
+ # report collection failures here to avoid failing to run some test
+ # specified in the command line because the module could not be
+ # imported (#134)
+ node.ihook.pytest_collectreport(report=rep)
+ return resultnodes
+
+ def genitems(self, node):
+ self.trace("genitems", node)
+ if isinstance(node, nodes.Item):
+ node.ihook.pytest_itemcollected(item=node)
+ yield node
+ else:
+ assert isinstance(node, nodes.Collector)
+ rep = collect_one_node(node)
+ if rep.passed:
+ for subnode in rep.result:
+ for x in self.genitems(subnode):
+ yield x
+ node.ihook.pytest_collectreport(report=rep)