diff --git a/.coveragerc b/.coveragerc index bc0afe5c..29bc9dec 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,4 +1,5 @@ [run] +branch = True source = zope.interface [report] @@ -8,4 +9,3 @@ exclude_lines = class I[A-Z]\w+\((Interface|I[A-Z].*)\): raise NotImplementedError self\.fail - @_skip_under_py2 diff --git a/.gitignore b/.gitignore index f261c9d5..35946f41 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.so __pycache__ .coverage +.coverage.* .installed.cfg nosetests.xml coverage.xml diff --git a/src/zope/interface/_compat.py b/src/zope/interface/_compat.py index b9c19dcb..fb61e13b 100644 --- a/src/zope/interface/_compat.py +++ b/src/zope/interface/_compat.py @@ -16,7 +16,7 @@ import sys import types -if sys.version_info[0] < 3: #pragma NO COVER +if sys.version_info[0] < 3: def _normalize_name(name): if isinstance(name, basestring): @@ -31,7 +31,7 @@ def _normalize_name(name): PYTHON3 = False PYTHON2 = True -else: # pragma: no cover +else: def _normalize_name(name): if isinstance(name, bytes): @@ -48,11 +48,11 @@ def _normalize_name(name): PYTHON3 = True PYTHON2 = False -def _skip_under_py3k(test_method): # pragma: no cover +def _skip_under_py3k(test_method): import unittest return unittest.skipIf(sys.version_info[0] >= 3, "Only on Python 2")(test_method) -def _skip_under_py2(test_method): # pragma: no cover +def _skip_under_py2(test_method): import unittest return unittest.skipIf(sys.version_info[0] < 3, "Only on Python 3")(test_method) diff --git a/src/zope/interface/adapter.py b/src/zope/interface/adapter.py index b39ceba3..d4825b2a 100644 --- a/src/zope/interface/adapter.py +++ b/src/zope/interface/adapter.py @@ -410,7 +410,7 @@ def subscriptions(self, required, provided): try: from zope.interface._zope_interface_coptimizations import LookupBase -except ImportError: # pragma: no cover +except ImportError: LookupBase = LookupBaseFallback @@ -446,7 +446,7 @@ def subscriptions(self, required, provided): try: from zope.interface._zope_interface_coptimizations import VerifyingBase -except ImportError: # pragma: no cover +except ImportError: VerifyingBase = VerifyingBaseFallback diff --git a/src/zope/interface/advice.py b/src/zope/interface/advice.py index 6bf4815a..e55930d5 100644 --- a/src/zope/interface/advice.py +++ b/src/zope/interface/advice.py @@ -28,9 +28,9 @@ from types import FunctionType try: from types import ClassType -except ImportError: # pragma: no cover Python > 3.x +except ImportError: __python3 = True -else: # pragma: no cover Python < 3.x +else: __python3 = False import sys diff --git a/src/zope/interface/declarations.py b/src/zope/interface/declarations.py index 13433bd8..acea1207 100644 --- a/src/zope/interface/declarations.py +++ b/src/zope/interface/declarations.py @@ -436,8 +436,6 @@ def __call__(self, ob): def _implements(name, interfaces, classImplements): # This entire approach is invalid under Py3K. Don't even try to fix # the coverage for this block there. :( - if PYTHON3: # pragma: no cover - raise TypeError('Class advice impossible in Python3') frame = sys._getframe(2) locals = frame.f_locals @@ -481,7 +479,7 @@ def implements(*interfaces): """ # This entire approach is invalid under Py3K. Don't even try to fix # the coverage for this block there. :( - if PYTHON3: # pragma: no cover + if PYTHON3: raise TypeError(_ADVICE_ERROR % 'implementer') _implements("implements", interfaces, classImplements) @@ -509,7 +507,7 @@ def implementsOnly(*interfaces): """ # This entire approach is invalid under Py3K. Don't even try to fix # the coverage for this block there. :( - if PYTHON3: # pragma: no cover + if PYTHON3: raise TypeError(_ADVICE_ERROR % 'implementer_only') _implements("implementsOnly", interfaces, classImplementsOnly) @@ -581,7 +579,7 @@ def directlyProvides(object, *interfaces): # Note that we can't get here from Py3k tests: there is no normal # class which isn't descriptor aware. if not isinstance(object, - DescriptorAwareMetaClasses): # pragma: no cover Py3k + DescriptorAwareMetaClasses): raise TypeError("Attempt to make an interface declaration on a " "non-descriptor-aware class") @@ -641,9 +639,9 @@ def __get__(self, inst, cls): # Try to get C base: try: import zope.interface._zope_interface_coptimizations -except ImportError: # pragma: no cover +except ImportError: pass -else: # pragma: no cover +else: from zope.interface._zope_interface_coptimizations import ClassProvidesBase @@ -715,7 +713,7 @@ def classProvides(*interfaces): # This entire approach is invalid under Py3K. Don't even try to fix # the coverage for this block there. :( - if PYTHON3: # pragma: no cover + if PYTHON3: raise TypeError(_ADVICE_ERROR % 'provider') frame = sys._getframe(1) @@ -918,9 +916,9 @@ def _normalizeargs(sequence, output = None): try: import zope.interface._zope_interface_coptimizations -except ImportError: # pragma: no cover +except ImportError: pass -else: # pragma: no cover PyPy +else: from zope.interface._zope_interface_coptimizations import implementedBy from zope.interface._zope_interface_coptimizations import providedBy from zope.interface._zope_interface_coptimizations import ( diff --git a/src/zope/interface/interface.py b/src/zope/interface/interface.py index 382f14cb..e44f93f4 100644 --- a/src/zope/interface/interface.py +++ b/src/zope/interface/interface.py @@ -115,7 +115,7 @@ def isOrExtends(self, interface): SpecificationBase = SpecificationBasePy try: from zope.interface._zope_interface_coptimizations import SpecificationBase -except ImportError: # pragma: no cover +except ImportError: pass _marker = object() @@ -156,14 +156,14 @@ def __adapt__(self, obj): InterfaceBase = InterfaceBasePy try: from zope.interface._zope_interface_coptimizations import InterfaceBase -except ImportError: # pragma: no cover +except ImportError: pass adapter_hooks = [] try: from zope.interface._zope_interface_coptimizations import adapter_hooks -except ImportError: # pragma: no cover +except ImportError: pass diff --git a/src/zope/interface/tests/advisory_testing.py b/src/zope/interface/tests/advisory_testing.py index 30dadc55..b159e937 100644 --- a/src/zope/interface/tests/advisory_testing.py +++ b/src/zope/interface/tests/advisory_testing.py @@ -32,7 +32,7 @@ def pong(klass): class ClassicClass: __metaclass__ = ClassType classLevelFrameInfo = getFrameInfo(sys._getframe()) -except ImportError: # pragma: no cover (Py3, this module may not even be imported) +except ImportError: ClassicClass = None class NewStyleClass: diff --git a/src/zope/interface/tests/odd.py b/src/zope/interface/tests/odd.py index 7789a76c..74c61584 100644 --- a/src/zope/interface/tests/odd.py +++ b/src/zope/interface/tests/odd.py @@ -72,7 +72,7 @@ def __getattribute__(cls, name): if name == '__class__': return cls # Under Python 3.6, __prepare__ gets requested - return type.__getattribute__(cls, name) # pragma: no cover + return type.__getattribute__(cls, name) class MetaClass(object): diff --git a/src/zope/interface/tests/test_adapter.py b/src/zope/interface/tests/test_adapter.py index 24c33346..7420e1c6 100644 --- a/src/zope/interface/tests/test_adapter.py +++ b/src/zope/interface/tests/test_adapter.py @@ -558,7 +558,7 @@ def test_optimizations(self): from zope.interface.adapter import LookupBaseFallback try: import zope.interface._zope_interface_coptimizations - except ImportError: # pragma: no cover (pypy) + except ImportError: self.assertIs(self._getTargetClass(), LookupBaseFallback) else: self.assertIsNot(self._getTargetClass(), LookupBaseFallback) @@ -729,7 +729,7 @@ def test_optimizations(self): from zope.interface.adapter import VerifyingBaseFallback try: import zope.interface._zope_interface_coptimizations - except ImportError: # pragma: no cover (pypy) + except ImportError: self.assertIs(self._getTargetClass(), VerifyingBaseFallback) else: self.assertIsNot(self._getTargetClass(), VerifyingBaseFallback) @@ -1390,7 +1390,7 @@ def test__normalize_name_str(self): STR = b'str' if sys.version_info[0] < 3: self.assertEqual(_normalize_name(STR), unicode(STR)) - else: # pragma: no cover (tox runs coverage on Python 2) + else: self.assertEqual(_normalize_name(STR), str(STR, 'ascii')) def test__normalize_name_unicode(self): diff --git a/src/zope/interface/tests/test_declarations.py b/src/zope/interface/tests/test_declarations.py index 05b09a53..43f95c82 100644 --- a/src/zope/interface/tests/test_declarations.py +++ b/src/zope/interface/tests/test_declarations.py @@ -31,7 +31,7 @@ def _run_generated_code(self, code, globs, locs, exec(code, globs, locs) self.assertEqual(len(log), 0) # no longer warn return True - else: # pragma: no cover (tox runs coverage on Python 2) + else: try: exec(code, globs, locs) except TypeError: @@ -339,10 +339,14 @@ class Foo(object): def test_dictless_wo_existing_Implements_cant_assign___implemented__(self): class Foo(object): - def _get_impl(self): return None - def _set_impl(self, val): raise TypeError + def _get_impl(self): + raise NotImplementedError() + def _set_impl(self, val): + raise TypeError __implemented__ = property(_get_impl, _set_impl) - def __call__(self): pass #act like a factory + def __call__(self): + # act like a factory + raise NotImplementedError() foo = Foo() self.assertRaises(TypeError, self._callFUT, foo) @@ -479,7 +483,7 @@ def test_optimizations(self): from zope.interface.declarations import implementedBy try: import zope.interface._zope_interface_coptimizations - except ImportError: # pragma: no cover (pypy) + except ImportError: self.assertIs(implementedBy, implementedByFallback) else: self.assertIsNot(implementedBy, implementedByFallback) @@ -685,7 +689,8 @@ def test_function(self): from zope.interface.interface import InterfaceClass IFoo = InterfaceClass('IFoo') decorator = self._makeOne(IFoo) - def _function(): pass + def _function(): + raise NotImplementedError() self.assertRaises(ValueError, decorator, _function) def test_method(self): @@ -693,7 +698,8 @@ def test_method(self): IFoo = InterfaceClass('IFoo') decorator = self._makeOne(IFoo) class Bar: - def _method(): pass + def _method(): + raise NotImplementedError() self.assertRaises(ValueError, decorator, Bar._method) def test_oldstyle_class(self): @@ -752,9 +758,8 @@ def test_simple(self): warnings.resetwarnings() try: exec(CODE, globs, locs) - except TypeError: # pragma: no cover (tox runs coverage on Python 2) - if not PYTHON3: - raise + except TypeError: + self.assertTrue(PYTHON3, "Must be Python 3") else: if PYTHON3: self.fail("Didn't raise TypeError") @@ -1130,7 +1135,7 @@ def test_optimizations(self): from zope.interface.declarations import ClassProvidesBaseFallback try: import zope.interface._zope_interface_coptimizations - except ImportError: # pragma: no cover (pypy) + except ImportError: self.assertIs(self._getTargetClass(), ClassProvidesBaseFallback) else: self.assertIsNot(self._getTargetClass(), ClassProvidesBaseFallback) @@ -1441,7 +1446,7 @@ def test_optimizations(self): from zope.interface.declarations import getObjectSpecification try: import zope.interface._zope_interface_coptimizations - except ImportError: # pragma: no cover (pypy) + except ImportError: self.assertIs(getObjectSpecification, getObjectSpecificationFallback) else: @@ -1538,7 +1543,7 @@ def test_optimizations(self): from zope.interface.declarations import providedBy try: import zope.interface._zope_interface_coptimizations - except ImportError: # pragma: no cover (pypy) + except ImportError: self.assertIs(providedBy, providedByFallback) else: self.assertIsNot(providedBy, providedByFallback) @@ -1609,7 +1614,7 @@ def test_optimizations(self): ObjectSpecificationDescriptorFallback) try: import zope.interface._zope_interface_coptimizations - except ImportError: # pragma: no cover (pypy) + except ImportError: self.assertIs(self._getTargetClass(), ObjectSpecificationDescriptorFallback) else: diff --git a/src/zope/interface/tests/test_exceptions.py b/src/zope/interface/tests/test_exceptions.py index 94009f6f..ae73f9cf 100644 --- a/src/zope/interface/tests/test_exceptions.py +++ b/src/zope/interface/tests/test_exceptions.py @@ -27,9 +27,8 @@ def _getTargetClass(self): from zope.interface.exceptions import DoesNotImplement return DoesNotImplement - def _makeOne(self, iface=None): - if iface is None: - iface = _makeIface() + def _makeOne(self): + iface = _makeIface() return self._getTargetClass()(iface) def test___str__(self): @@ -45,9 +44,8 @@ def _getTargetClass(self): from zope.interface.exceptions import BrokenImplementation return BrokenImplementation - def _makeOne(self, iface=None, name='missing'): - if iface is None: - iface = _makeIface() + def _makeOne(self, name='missing'): + iface = _makeIface() return self._getTargetClass()(iface, name) def test___str__(self): @@ -72,4 +70,3 @@ def test___str__(self): self.assertEqual(str(dni), 'The implementation of aMethod violates its contract\n' ' because I said so.\n ') - diff --git a/src/zope/interface/tests/test_interface.py b/src/zope/interface/tests/test_interface.py index f14c76fe..58ed8084 100644 --- a/src/zope/interface/tests/test_interface.py +++ b/src/zope/interface/tests/test_interface.py @@ -16,6 +16,8 @@ # pylint:disable=protected-access import unittest +from zope.interface._compat import _skip_under_py3k + _marker = object() @@ -214,7 +216,7 @@ def test_optimizations(self): from zope.interface.interface import SpecificationBasePy try: import zope.interface._zope_interface_coptimizations - except ImportError: # pragma: no cover (pypy) + except ImportError: self.assertIs(self._getTargetClass(), SpecificationBasePy) else: self.assertIsNot(self._getTargetClass(), SpecificationBasePy) @@ -291,7 +293,7 @@ def test_optimizations(self): from zope.interface.interface import InterfaceBasePy try: import zope.interface._zope_interface_coptimizations - except ImportError: # pragma: no cover (pypy) + except ImportError: self.assertIs(self._getTargetClass(), InterfaceBasePy) else: self.assertIsNot(self._getTargetClass(), InterfaceBasePy) @@ -1677,21 +1679,22 @@ class I(Interface): self.assertEqual(I.__doc__, "") self.assertEqual(list(I), ['__doc__']) + @_skip_under_py3k def testIssue228(self): # Test for http://collector.zope.org/Zope3-dev/228 # Old style classes don't have a '__class__' attribute + # No old style classes in Python 3, so the test becomes moot. import sys - if sys.version[0] < '3': - # No old style classes in Python 3, so the test becomes moot. - from zope.interface import Interface - class I(Interface): - "xxx" + from zope.interface import Interface + + class I(Interface): + "xxx" - class OldStyle: - __providedBy__ = None + class OldStyle: + __providedBy__ = None - self.assertRaises(AttributeError, I.providedBy, OldStyle) + self.assertRaises(AttributeError, I.providedBy, OldStyle) def test_invariant_as_decorator(self): from zope.interface import Interface diff --git a/src/zope/interface/tests/test_odd_declarations.py b/src/zope/interface/tests/test_odd_declarations.py index 5480730b..46e7675f 100644 --- a/src/zope/interface/tests/test_odd_declarations.py +++ b/src/zope/interface/tests/test_odd_declarations.py @@ -257,9 +257,12 @@ class C(A, B): self.assertEqual(c.c, 1) c.c - import sys - if sys.version[0] == '2': # This test only makes sense under Python 2.x + try: from types import ClassType + except ImportError: + pass + else: + # This test only makes sense under Python 2.x assert not isinstance(C, (type, ClassType)) self.assertIs(C.__class__.__class__, C.__class__) diff --git a/src/zope/interface/verify.py b/src/zope/interface/verify.py index 5a0e684a..098b484a 100644 --- a/src/zope/interface/verify.py +++ b/src/zope/interface/verify.py @@ -66,10 +66,10 @@ def _verify(iface, candidate, tentative=0, vtype=None): continue if isinstance(attr, FunctionType): - if sys.version[0] == '3' and isinstance(candidate, type): + if sys.version_info[0] >= 3 and isinstance(candidate, type): # This is an "unbound method" in Python 3. meth = fromFunction(attr, iface, name=name, - imlevel=1) # pragma: no cover + imlevel=1) else: # Nope, just a normal function meth = fromFunction(attr, iface, name=name) @@ -85,7 +85,7 @@ def _verify(iface, candidate, tentative=0, vtype=None): raise BrokenMethodImplementation(name, "Not a method") # sigh, it's callable, but we don't know how to introspect it, so # we have to give it a pass. - continue # pragma: no cover + continue # Make sure that the required and implemented method signatures are # the same. diff --git a/tox.ini b/tox.ini index 608fa008..3ed2be4b 100644 --- a/tox.ini +++ b/tox.ini @@ -4,9 +4,12 @@ envlist = [testenv] commands = - python setup.py -q test -q {posargs} + coverage run setup.py -q test -q {posargs} deps = - zope.event + .[test] + coverage +setenv = + COVERAGE_FILE=.coverage.{envname} [testenv:py27-pure] setenv = @@ -24,15 +27,15 @@ commands = {[testenv]commands} [testenv:coverage] -usedevelop = true -basepython = - python2.7 +setenv = + COVERAGE_FILE=.coverage +skip_install = true commands = - coverage run setup.py -q test -q {posargs} - coverage report --skip-covered -deps = - {[testenv]deps} - coverage + coverage erase + coverage combine + coverage report + coverage html + coverage xml [testenv:docs] basepython =