Merge master into features

This commit is contained in:
Daniel Hahler
2019-01-14 17:15:39 +01:00
23 changed files with 278 additions and 66 deletions

View File

@@ -512,7 +512,13 @@ def _format_assertmsg(obj):
def _should_repr_global_name(obj):
return not hasattr(obj, "__name__") and not callable(obj)
if callable(obj):
return False
try:
return not hasattr(obj, "__name__")
except Exception:
return True
def _format_boolop(explanations, is_or):

View File

@@ -151,6 +151,8 @@ def assertrepr_compare(config, op, left, right):
elif type(left) == type(right) and (isdatacls(left) or isattrs(left)):
type_fn = (isdatacls, isattrs)
explanation = _compare_eq_cls(left, right, verbose, type_fn)
elif verbose:
explanation = _compare_eq_verbose(left, right)
if isiterable(left) and isiterable(right):
expl = _compare_eq_iterable(left, right, verbose)
if explanation is not None:
@@ -236,6 +238,18 @@ def _diff_text(left, right, verbose=False):
return explanation
def _compare_eq_verbose(left, right):
keepends = True
left_lines = repr(left).splitlines(keepends)
right_lines = repr(right).splitlines(keepends)
explanation = []
explanation += [u"-" + line for line in left_lines]
explanation += [u"+" + line for line in right_lines]
return explanation
def _compare_eq_iterable(left, right, verbose=False):
if not verbose:
return [u"Use -v to get the full diff"]

View File

@@ -3,17 +3,19 @@ from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import inspect
import platform
import sys
import traceback
from contextlib import contextmanager
import pytest
from _pytest._code.code import ExceptionInfo
from _pytest._code.code import ReprFileLocation
from _pytest._code.code import TerminalRepr
from _pytest.compat import safe_getattr
from _pytest.fixtures import FixtureRequest
DOCTEST_REPORT_CHOICE_NONE = "none"
DOCTEST_REPORT_CHOICE_CDIFF = "cdiff"
DOCTEST_REPORT_CHOICE_NDIFF = "ndiff"
@@ -346,10 +348,61 @@ def _check_all_skipped(test):
pytest.skip("all tests skipped by +SKIP option")
def _is_mocked(obj):
"""
returns if a object is possibly a mock object by checking the existence of a highly improbable attribute
"""
return (
safe_getattr(obj, "pytest_mock_example_attribute_that_shouldnt_exist", None)
is not None
)
@contextmanager
def _patch_unwrap_mock_aware():
"""
contextmanager which replaces ``inspect.unwrap`` with a version
that's aware of mock objects and doesn't recurse on them
"""
real_unwrap = getattr(inspect, "unwrap", None)
if real_unwrap is None:
yield
else:
def _mock_aware_unwrap(obj, stop=None):
if stop is None:
return real_unwrap(obj, stop=_is_mocked)
else:
return real_unwrap(obj, stop=lambda obj: _is_mocked(obj) or stop(obj))
inspect.unwrap = _mock_aware_unwrap
try:
yield
finally:
inspect.unwrap = real_unwrap
class DoctestModule(pytest.Module):
def collect(self):
import doctest
class MockAwareDocTestFinder(doctest.DocTestFinder):
"""
a hackish doctest finder that overrides stdlib internals to fix a stdlib bug
https://github.com/pytest-dev/pytest/issues/3456
https://bugs.python.org/issue25532
"""
def _find(self, tests, obj, name, module, source_lines, globs, seen):
if _is_mocked(obj):
return
with _patch_unwrap_mock_aware():
doctest.DocTestFinder._find(
self, tests, obj, name, module, source_lines, globs, seen
)
if self.fspath.basename == "conftest.py":
module = self.config.pluginmanager._importconftest(self.fspath)
else:
@@ -361,7 +414,7 @@ class DoctestModule(pytest.Module):
else:
raise
# uses internal doctest module parsing mechanism
finder = doctest.DocTestFinder()
finder = MockAwareDocTestFinder()
optionflags = get_optionflags(self)
runner = _get_runner(
verbose=0,

View File

@@ -150,10 +150,10 @@ class ApproxNumpy(ApproxBase):
if np.isscalar(actual):
for i in np.ndindex(self.expected.shape):
yield actual, np.asscalar(self.expected[i])
yield actual, self.expected[i].item()
else:
for i in np.ndindex(self.expected.shape):
yield np.asscalar(actual[i]), np.asscalar(self.expected[i])
yield actual[i].item(), self.expected[i].item()
class ApproxMapping(ApproxBase):