Small cleanups on _pytest.compat

Small improvements and cleanups
This commit is contained in:
Bruno Oliveira 2019-06-15 10:06:37 -03:00
parent 240828d912
commit 355eb5adfb
5 changed files with 25 additions and 30 deletions

View File

@ -10,6 +10,7 @@ from contextlib import contextmanager
from inspect import Parameter
from inspect import signature
import attr
import py
import _pytest
@ -29,10 +30,6 @@ def _format_args(func):
return str(signature(func))
isfunction = inspect.isfunction
isclass = inspect.isclass
# used to work around a python2 exception info leak
exc_clear = getattr(sys, "exc_clear", lambda: None)
# The type of re.compile objects is not exposed in Python.
REGEX_TYPE = type(re.compile(""))
@ -129,11 +126,15 @@ def getfuncargnames(function, is_method=False, cls=None):
return arg_names
@contextmanager
def dummy_context_manager():
"""Context manager that does nothing, useful in situations where you might need an actual context manager or not
depending on some condition. Using this allow to keep the same code"""
yield
if sys.version_info < (3, 7):
@contextmanager
def nullcontext():
yield
else:
from contextlib import nullcontext # noqa
def get_default_arg_names(function):
@ -191,6 +192,7 @@ def ascii_escaped(val):
return _translate_non_printable(ret)
@attr.s
class _PytestWrapper:
"""Dummy wrapper around a function object for internal use only.
@ -199,8 +201,7 @@ class _PytestWrapper:
to issue warnings when the fixture function is called directly.
"""
def __init__(self, obj):
self.obj = obj
obj = attr.ib()
def get_real_func(obj):
@ -280,7 +281,7 @@ def safe_getattr(object, name, default):
def safe_isclass(obj):
"""Ignore any exception via isinstance on Python 3."""
try:
return isclass(obj)
return inspect.isclass(obj)
except Exception:
return False
@ -304,8 +305,8 @@ def _setup_collect_fakemodule():
pytest.collect = ModuleType("pytest.collect")
pytest.collect.__all__ = [] # used for setns
for attr in COLLECT_FAKEMODULE_ATTRIBUTES:
setattr(pytest.collect, attr, getattr(pytest, attr))
for attr_name in COLLECT_FAKEMODULE_ATTRIBUTES:
setattr(pytest.collect, attr_name, getattr(pytest, attr_name))
class CaptureIO(io.TextIOWrapper):

View File

@ -16,7 +16,6 @@ from _pytest._code.code import FormattedExcinfo
from _pytest._code.code import TerminalRepr
from _pytest.compat import _format_args
from _pytest.compat import _PytestWrapper
from _pytest.compat import exc_clear
from _pytest.compat import FuncargnamesCompatAttr
from _pytest.compat import get_real_func
from _pytest.compat import get_real_method
@ -25,7 +24,6 @@ from _pytest.compat import getfuncargnames
from _pytest.compat import getimfunc
from _pytest.compat import getlocation
from _pytest.compat import is_generator
from _pytest.compat import isclass
from _pytest.compat import NOTSET
from _pytest.compat import safe_getattr
from _pytest.deprecated import FIXTURE_FUNCTION_CALL
@ -572,10 +570,6 @@ class FixtureRequest(FuncargnamesCompatAttr):
# check if a higher-level scoped fixture accesses a lower level one
subrequest._check_scope(argname, self.scope, scope)
# clear sys.exc_info before invoking the fixture (python bug?)
# if it's not explicitly cleared it will leak into the call
exc_clear()
try:
# call the fixture function
fixturedef.execute(request=subrequest)
@ -970,7 +964,7 @@ class FixtureFunctionMarker:
name = attr.ib(default=None)
def __call__(self, function):
if isclass(function):
if inspect.isclass(function):
raise ValueError("class fixtures not supported (maybe in the future)")
if getattr(function, "_pytestfixturefunction", False):

View File

@ -6,7 +6,7 @@ from contextlib import contextmanager
import py
import pytest
from _pytest.compat import dummy_context_manager
from _pytest.compat import nullcontext
from _pytest.config import create_terminal_writer
from _pytest.pathlib import Path
@ -436,7 +436,7 @@ class LoggingPlugin:
self.log_cli_handler = None
self.live_logs_context = lambda: dummy_context_manager()
self.live_logs_context = lambda: nullcontext()
# Note that the lambda for the live_logs_context is needed because
# live_logs_context can otherwise not be entered multiple times due
# to limitations of contextlib.contextmanager.
@ -676,7 +676,7 @@ class _LiveLoggingStreamHandler(logging.StreamHandler):
ctx_manager = (
self.capture_manager.global_and_fixture_disabled()
if self.capture_manager
else dummy_context_manager()
else nullcontext()
)
with ctx_manager:
if not self._first_record_emitted:

View File

@ -23,8 +23,6 @@ from _pytest.compat import getfslineno
from _pytest.compat import getimfunc
from _pytest.compat import getlocation
from _pytest.compat import is_generator
from _pytest.compat import isclass
from _pytest.compat import isfunction
from _pytest.compat import NOTSET
from _pytest.compat import REGEX_TYPE
from _pytest.compat import safe_getattr
@ -207,7 +205,7 @@ def pytest_pycollect_makeitem(collector, name, obj):
# We need to try and unwrap the function if it's a functools.partial
# or a funtools.wrapped.
# We musn't if it's been wrapped with mock.patch (python 2 only)
if not (isfunction(obj) or isfunction(get_real_func(obj))):
if not (inspect.isfunction(obj) or inspect.isfunction(get_real_func(obj))):
filename, lineno = getfslineno(obj)
warnings.warn_explicit(
message=PytestCollectionWarning(
@ -1190,7 +1188,7 @@ def _idval(val, argname, idx, idfn, item, config):
return ascii_escaped(val.pattern)
elif enum is not None and isinstance(val, enum.Enum):
return str(val)
elif (isclass(val) or isfunction(val)) and hasattr(val, "__name__"):
elif (inspect.isclass(val) or inspect.isfunction(val)) and hasattr(val, "__name__"):
return val.__name__
return str(argname) + str(idx)

View File

@ -1,3 +1,4 @@
import inspect
import math
import pprint
import sys
@ -13,7 +14,6 @@ from more_itertools.more import always_iterable
import _pytest._code
from _pytest import deprecated
from _pytest.compat import isclass
from _pytest.compat import STRING_TYPES
from _pytest.outcomes import fail
@ -658,7 +658,9 @@ def raises(expected_exception, *args, **kwargs):
"""
__tracebackhide__ = True
for exc in filterfalse(isclass, always_iterable(expected_exception, BASE_TYPE)):
for exc in filterfalse(
inspect.isclass, always_iterable(expected_exception, BASE_TYPE)
):
msg = (
"exceptions must be old-style classes or"
" derived from BaseException, not %s"