diff --git a/src/_pytest/_code/__init__.py b/src/_pytest/_code/__init__.py index 815c13b42..7885d51de 100644 --- a/src/_pytest/_code/__init__.py +++ b/src/_pytest/_code/__init__.py @@ -4,6 +4,7 @@ from .code import Code # noqa from .code import ExceptionInfo # noqa from .code import Frame # noqa from .code import Traceback # noqa +from .code import filter_traceback # noqa from .code import getrawcode # noqa from .source import Source # noqa from .source import compile_ as compile # noqa diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index b2321c02d..c0f6d21a2 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -6,8 +6,10 @@ import traceback from inspect import CO_VARARGS, CO_VARKEYWORDS import attr +import pluggy import re from weakref import ref +import _pytest from _pytest.compat import _PY2, _PY3, PY35, safe_str from six import text_type import py @@ -1007,3 +1009,36 @@ else: return "maximum recursion depth exceeded" in str(excinfo.value) except UnicodeError: return False + + +# relative paths that we use to filter traceback entries from appearing to the user; +# see filter_traceback +# note: if we need to add more paths than what we have now we should probably use a list +# for better maintenance + +_PLUGGY_DIR = py.path.local(pluggy.__file__.rstrip("oc")) +# pluggy is either a package or a single module depending on the version +if _PLUGGY_DIR.basename == "__init__.py": + _PLUGGY_DIR = _PLUGGY_DIR.dirpath() +_PYTEST_DIR = py.path.local(_pytest.__file__).dirpath() +_PY_DIR = py.path.local(py.__file__).dirpath() + + +def filter_traceback(entry): + """Return True if a TracebackEntry instance should be removed from tracebacks: + * dynamically generated code (no code to show up for it); + * internal traceback from pytest or its internal libraries, py and pluggy. + """ + # entry.path might sometimes return a str object when the entry + # points to dynamically generated code + # see https://bitbucket.org/pytest-dev/py/issues/71 + raw_filename = entry.frame.code.raw.co_filename + is_generated = "<" in raw_filename and ">" in raw_filename + if is_generated: + return False + # entry.path might point to a non-existing file, in which case it will + # also return a str object. see #1133 + p = py.path.local(entry.path) + return ( + not p.relto(_PLUGGY_DIR) and not p.relto(_PYTEST_DIR) and not p.relto(_PY_DIR) + ) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 363412abb..3a3e064a9 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -19,6 +19,7 @@ import _pytest._code import _pytest.hookspec # the extension point definitions import _pytest.assertion from pluggy import PluginManager, HookimplMarker, HookspecMarker +from _pytest._code import ExceptionInfo, filter_traceback from _pytest.compat import safe_str from .exceptions import UsageError, PrintHelp from .findpaths import determine_setup, exists @@ -57,15 +58,11 @@ def main(args=None, plugins=None): try: config = _prepareconfig(args, plugins) except ConftestImportFailure as e: - from _pytest._code import ExceptionInfo - exc_info = ExceptionInfo(e.excinfo) tw = py.io.TerminalWriter(sys.stderr) tw.line( "ImportError while loading conftest '{e.path}'.".format(e=e), red=True ) - from _pytest.python import filter_traceback - exc_info.traceback = exc_info.traceback.filter(filter_traceback) exc_repr = ( exc_info.getrepr(style="short", chain=False) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index e9d05666f..8337c7469 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -16,7 +16,7 @@ from _pytest.main import FSHookProxy from _pytest.config import hookimpl import _pytest -import pluggy +from _pytest._code import filter_traceback from _pytest import fixtures from _pytest import nodes from _pytest import deprecated @@ -46,37 +46,6 @@ from _pytest.mark.structures import ( ) from _pytest.warning_types import RemovedInPytest4Warning, PytestWarning -# relative paths that we use to filter traceback entries from appearing to the user; -# see filter_traceback -# note: if we need to add more paths than what we have now we should probably use a list -# for better maintenance -_pluggy_dir = py.path.local(pluggy.__file__.rstrip("oc")) -# pluggy is either a package or a single module depending on the version -if _pluggy_dir.basename == "__init__.py": - _pluggy_dir = _pluggy_dir.dirpath() -_pytest_dir = py.path.local(_pytest.__file__).dirpath() -_py_dir = py.path.local(py.__file__).dirpath() - - -def filter_traceback(entry): - """Return True if a TracebackEntry instance should be removed from tracebacks: - * dynamically generated code (no code to show up for it); - * internal traceback from pytest or its internal libraries, py and pluggy. - """ - # entry.path might sometimes return a str object when the entry - # points to dynamically generated code - # see https://bitbucket.org/pytest-dev/py/issues/71 - raw_filename = entry.frame.code.raw.co_filename - is_generated = "<" in raw_filename and ">" in raw_filename - if is_generated: - return False - # entry.path might point to a non-existing file, in which case it will - # also return a str object. see #1133 - p = py.path.local(entry.path) - return ( - not p.relto(_pluggy_dir) and not p.relto(_pytest_dir) and not p.relto(_py_dir) - ) - def pyobj_property(name): def get(self):