[Checkins] SVN: zope.interface/branches/tseaver-no_2to3/src/zope/interface/ Close Py3k coverage gap to absolute minimum.

Tres Seaver cvs-admin at zope.org
Fri Apr 6 04:14:36 UTC 2012


Log message for revision 124987:
  Close Py3k coverage gap to absolute minimum.
  
  We *can't* test the classAdvice stuff under Py3k.  Need to deprecate it
  before the 4.0 release.

Changed:
  U   zope.interface/branches/tseaver-no_2to3/src/zope/interface/_compat.py
  U   zope.interface/branches/tseaver-no_2to3/src/zope/interface/advice.py
  U   zope.interface/branches/tseaver-no_2to3/src/zope/interface/declarations.py
  U   zope.interface/branches/tseaver-no_2to3/src/zope/interface/registry.py
  U   zope.interface/branches/tseaver-no_2to3/src/zope/interface/tests/test_advice.py
  U   zope.interface/branches/tseaver-no_2to3/src/zope/interface/tests/test_declarations.py

-=-
Modified: zope.interface/branches/tseaver-no_2to3/src/zope/interface/_compat.py
===================================================================
--- zope.interface/branches/tseaver-no_2to3/src/zope/interface/_compat.py	2012-04-06 04:14:27 UTC (rev 124986)
+++ zope.interface/branches/tseaver-no_2to3/src/zope/interface/_compat.py	2012-04-06 04:14:32 UTC (rev 124987)
@@ -26,8 +26,8 @@
             return unicode(name)
         raise TypeError("name must be a regular or unicode string")
 
-    class_types = (type, types.ClassType)
-    string_types = (basestring,)
+    CLASS_TYPES = (type, types.ClassType)
+    STRING_TYPES = (basestring,)
 
     _FUNC_DEFAULTS = 'func_defaults'
     _FUNC_CODE = 'func_code'
@@ -35,6 +35,9 @@
     _IM_FUNC = 'im_func'
     _BUILTINS = '__builtin__'
 
+    PYTHON3 = False
+    PYTHON2 = True
+
 else: #pragma NO COVER
 
     def _u(s):
@@ -47,8 +50,8 @@
             return name
         raise TypeError("name must be a string or ASCII-only bytes")
 
-    class_types = type
-    string_types = (str,)
+    CLASS_TYPES = (type,)
+    STRING_TYPES = (str,)
 
     _FUNC_DEFAULTS = '__defaults__'
     _FUNC_CODE = '__code__'
@@ -56,9 +59,19 @@
     _IM_FUNC = '__func__'
     _BUILTINS = 'builtins'
 
+    PYTHON3 = True
+    PYTHON2 = False
+
 def _skip_under_py3k(test_method): #pragma NO COVER
     if sys.version_info[0] < 3:
         return test_method
     def _dummy(*args):
         pass
     return _dummy
+
+def _skip_under_py2(test_method): #pragma NO COVER
+    if sys.version_info[0] > 2:
+        return test_method
+    def _dummy(*args):
+        pass
+    return _dummy

Modified: zope.interface/branches/tseaver-no_2to3/src/zope/interface/advice.py
===================================================================
--- zope.interface/branches/tseaver-no_2to3/src/zope/interface/advice.py	2012-04-06 04:14:27 UTC (rev 124986)
+++ zope.interface/branches/tseaver-no_2to3/src/zope/interface/advice.py	2012-04-06 04:14:32 UTC (rev 124987)
@@ -94,6 +94,10 @@
     callbacks *after* the last '__metaclass__' assignment in the containing
     class will be executed.  Be sure that classes using "advising" functions
     declare any '__metaclass__' *first*, to ensure all callbacks are run."""
+    # 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(depth)
     kind, module, caller_locals, caller_globals = getFrameInfo(frame)
@@ -184,7 +188,7 @@
 def minimalBases(classes):
     """Reduce a list of base classes to its ordered minimum equivalent"""
 
-    if not __python3:
+    if not __python3: #pragma NO COVER
         classes = [c for c in classes if c is not ClassType]
     candidates = []
 

Modified: zope.interface/branches/tseaver-no_2to3/src/zope/interface/declarations.py
===================================================================
--- zope.interface/branches/tseaver-no_2to3/src/zope/interface/declarations.py	2012-04-06 04:14:27 UTC (rev 124986)
+++ zope.interface/branches/tseaver-no_2to3/src/zope/interface/declarations.py	2012-04-06 04:14:32 UTC (rev 124987)
@@ -36,6 +36,7 @@
 from zope.interface.interface import InterfaceClass
 from zope.interface.interface import SpecificationBase
 from zope.interface.interface import Specification
+from zope.interface._compat import CLASS_TYPES as DescriptorAwareMetaClasses
 
 # Registry of class-implementation specifications
 BuiltinImplementationSpecifications = {}
@@ -249,7 +250,7 @@
             b = implementedBy(c)
             if b not in seen:
                 seen[b] = 1
-                bases.append(b)            
+                bases.append(b)
 
     spec.__bases__ = tuple(bases)
 
@@ -295,8 +296,8 @@
     def __call__(self, ob):
         if isinstance(ob, DescriptorAwareMetaClasses):
             classImplements(ob, *self.interfaces)
-            return ob            
-        
+            return ob
+
         spec = Implements(*self.interfaces)
         try:
             ob.__implemented__ = spec
@@ -341,9 +342,11 @@
         else:
             # Assume it's a class:
             classImplementsOnly(ob, *self.interfaces)
-            return ob            
-        
+            return 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 sys.version_info[0] >= 3: #pragma NO COVER
         raise TypeError('Class advice impossible in Python3')
     frame = sys._getframe(2)
@@ -386,7 +389,9 @@
         classImplements(C, I1)
 
       after the class has been created.
-      """
+    """
+    # This entire approach is invalid under Py3K.  Don't even try to fix
+    # the coverage for this block there. :(
     _implements("implements", interfaces, classImplements)
 
 def implementsOnly(*interfaces):
@@ -410,7 +415,9 @@
         classImplementsOnly(I1)
 
       after the class has been created.
-      """
+    """
+    # This entire approach is invalid under Py3K.  Don't even try to fix
+    # the coverage for this block there. :(
     _implements("implementsOnly", interfaces, classImplementsOnly)
 
 ##############################################################################
@@ -465,12 +472,7 @@
 
 Provides.__safe_for_unpickling__ = True
 
-try:
-    from types import ClassType
-    DescriptorAwareMetaClasses = ClassType, type
-except ImportError:  #pragma NO COVERAGE  (Python 3)
-    DescriptorAwareMetaClasses = (type,)
-    
+
 def directlyProvides(object, *interfaces):
     """Declare interfaces declared directly for an object
 
@@ -485,7 +487,8 @@
         # It's a meta class (well, at least it it could be an extension class)
         # 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):
+        if not isinstance(object,
+                          DescriptorAwareMetaClasses): #pragma NO COVER Py3k
             raise TypeError("Attempt to make an interface declaration on a "
                             "non-descriptor-aware class")
 
@@ -616,6 +619,8 @@
 
       after the class has been created.
     """
+    # This entire approach is invalid under Py3K.  Don't even try to fix
+    # the coverage for this block there. :(
     if sys.version_info[0] >= 3: #pragma NO COVER
         raise TypeError('Class advice impossible in Python3')
 
@@ -636,6 +641,8 @@
     addClassAdvisor(_classProvides_advice, depth=2)
 
 def _classProvides_advice(cls):
+    # This entire approach is invalid under Py3K.  Don't even try to fix
+    # the coverage for this block there. :(
     interfaces = cls.__dict__['__provides__']
     del cls.__provides__
     directlyProvides(cls, *interfaces)
@@ -649,7 +656,7 @@
 
     def __call__(self, ob):
         directlyProvides(ob, *self.interfaces)
-        return ob            
+        return ob
 
 def moduleProvides(*interfaces):
     """Declare interfaces provided by a module

Modified: zope.interface/branches/tseaver-no_2to3/src/zope/interface/registry.py
===================================================================
--- zope.interface/branches/tseaver-no_2to3/src/zope/interface/registry.py	2012-04-06 04:14:27 UTC (rev 124986)
+++ zope.interface/branches/tseaver-no_2to3/src/zope/interface/registry.py	2012-04-06 04:14:32 UTC (rev 124987)
@@ -35,15 +35,15 @@
 from zope.interface.declarations import providedBy
 from zope.interface.adapter import AdapterRegistry
 from zope.interface._compat import _u
-from zope.interface._compat import class_types
-from zope.interface._compat import string_types
+from zope.interface._compat import CLASS_TYPES
+from zope.interface._compat import STRING_TYPES
 
 
 @implementer(IComponents)
 class Components(object):
 
     def __init__(self, name='', bases=()):
-        assert isinstance(name, string_types)
+        assert isinstance(name, STRING_TYPES)
         self.__name__ = name
         self._init_registries()
         self._init_registrations()
@@ -415,7 +415,7 @@
         if r is None:
             r = Interface
         elif not ISpecification.providedBy(r):
-            if isinstance(r, class_types):
+            if isinstance(r, CLASS_TYPES):
                 r = implementedBy(r)
             else:
                 raise TypeError("Required specification must be a "

Modified: zope.interface/branches/tseaver-no_2to3/src/zope/interface/tests/test_advice.py
===================================================================
--- zope.interface/branches/tseaver-no_2to3/src/zope/interface/tests/test_advice.py	2012-04-06 04:14:27 UTC (rev 124986)
+++ zope.interface/branches/tseaver-no_2to3/src/zope/interface/tests/test_advice.py	2012-04-06 04:14:32 UTC (rev 124987)
@@ -28,6 +28,7 @@
 import unittest
 import sys
 
+from zope.interface._compat import _skip_under_py2
 from zope.interface._compat import _skip_under_py3k
 
 
@@ -185,19 +186,141 @@
         self.assertEqual(type(klass), ClassType)
 
 
+class Test_isClassAdvisor(unittest.TestCase):
+
+    def _callFUT(self, *args, **kw):
+        from zope.interface.advice import isClassAdvisor
+        return isClassAdvisor(*args, **kw)
+
+    def test_w_non_function(self):
+        self.assertEqual(self._callFUT(self), False)
+
+    def test_w_normal_function(self):
+        def foo():
+            pass
+        self.assertEqual(self._callFUT(foo), False)
+
+    def test_w_advisor_function(self):
+        def bar():
+            pass
+        bar.previousMetaclass = object()
+        self.assertEqual(self._callFUT(bar), True)
+
+
+class Test_determineMetaclass(unittest.TestCase):
+
+    def _callFUT(self, *args, **kw):
+        from zope.interface.advice import determineMetaclass
+        return determineMetaclass(*args, **kw)
+
     @_skip_under_py3k
+    def test_empty(self):
+        from types import ClassType
+        self.assertEquals(self._callFUT(()), ClassType)
+
+    def test_empty_w_explicit_metatype(self):
+        class Meta(type):
+            pass
+        self.assertEquals(self._callFUT((), Meta), Meta)
+
+    def test_single(self):
+        class Meta(type):
+            pass
+        self.assertEquals(self._callFUT((Meta,)), type)
+
+    @_skip_under_py3k
     def test_meta_of_class(self):
-        from zope.interface.advice import determineMetaclass
-
         class Metameta(type):
             pass
 
         class Meta(type):
             __metaclass__ = Metameta
 
-        self.assertEquals(determineMetaclass((Meta, type)), Metameta)
+        self.assertEquals(self._callFUT((Meta, type)), Metameta)
 
+    @_skip_under_py2
+    def test_meta_of_class_py3k(self):
+        # Work around SyntaxError under Python2.
+        EXEC = '\n'.join([
+        'class Metameta(type):',
+        '    pass',
+        'class Meta(type, metaclass=Metameta):',
+        '    pass',
+        ])
+        globs = {}
+        exec(EXEC, globs)
+        Meta = globs['Meta']
+        Metameta = globs['Metameta']
 
+        self.assertEquals(self._callFUT((Meta, type)), Metameta)
+
+    @_skip_under_py3k
+    def test_multiple_in_hierarchy(self):
+        class Meta_A(type):
+            pass
+        class Meta_B(Meta_A):
+            pass
+        class A(type):
+            __metaclass__ = Meta_A
+        class B(type):
+            __metaclass__ = Meta_B
+        self.assertEquals(self._callFUT((A, B,)), Meta_B)
+
+    @_skip_under_py2
+    def test_multiple_in_hierarchy_py3k(self):
+        # Work around SyntaxError under Python2.
+        EXEC = '\n'.join([
+        'class Meta_A(type):',
+        '    pass',
+        'class Meta_B(Meta_A):',
+        '    pass',
+        'class A(type, metaclass=Meta_A):',
+        '    pass',
+        'class B(type, metaclass=Meta_B):',
+        '    pass',
+        ])
+        globs = {}
+        exec(EXEC, globs)
+        Meta_A = globs['Meta_A']
+        Meta_B = globs['Meta_B']
+        A = globs['A']
+        B = globs['B']
+        self.assertEquals(self._callFUT((A, B)), Meta_B)
+
+    @_skip_under_py3k
+    def test_multiple_not_in_hierarchy(self):
+        class Meta_A(type):
+            pass
+        class Meta_B(type):
+            pass
+        class A(type):
+            __metaclass__ = Meta_A
+        class B(type):
+            __metaclass__ = Meta_B
+        self.assertRaises(TypeError, self._callFUT, (A, B,))
+
+    @_skip_under_py2
+    def test_multiple_not_in_hierarchy_py3k(self):
+        # Work around SyntaxError under Python2.
+        EXEC = '\n'.join([
+        'class Meta_A(type):',
+        '    pass',
+        'class Meta_B(type):',
+        '    pass',
+        'class A(type, metaclass=Meta_A):',
+        '    pass',
+        'class B(type, metaclass=Meta_B):',
+        '    pass',
+        ])
+        globs = {}
+        exec(EXEC, globs)
+        Meta_A = globs['Meta_A']
+        Meta_B = globs['Meta_B']
+        A = globs['A']
+        B = globs['B']
+        self.assertRaises(TypeError, self._callFUT, (A, B))
+
+
 class Test_minimalBases(unittest.TestCase):
 
     def _callFUT(self, klasses):
@@ -252,12 +375,10 @@
 
 
 def test_suite():
-    if sys.version[0] == '2':
-        return unittest.TestSuite((
-            unittest.makeSuite(FrameInfoTest),
-            unittest.makeSuite(AdviceTests),
-            unittest.makeSuite(Test_minimalBases),
-        ))
-    else:
-        # Advise metaclasses doesn't work in Python 3
-        return unittest.TestSuite([])
+    return unittest.TestSuite((
+        unittest.makeSuite(FrameInfoTest),
+        unittest.makeSuite(AdviceTests),
+        unittest.makeSuite(Test_isClassAdvisor),
+        unittest.makeSuite(Test_determineMetaclass),
+        unittest.makeSuite(Test_minimalBases),
+    ))

Modified: zope.interface/branches/tseaver-no_2to3/src/zope/interface/tests/test_declarations.py
===================================================================
--- zope.interface/branches/tseaver-no_2to3/src/zope/interface/tests/test_declarations.py	2012-04-06 04:14:27 UTC (rev 124986)
+++ zope.interface/branches/tseaver-no_2to3/src/zope/interface/tests/test_declarations.py	2012-04-06 04:14:32 UTC (rev 124987)
@@ -641,6 +641,31 @@
         from zope.interface.declarations import implementsOnly
         return implementsOnly
 
+    def test_simple(self):
+        from zope.interface.declarations import implementsOnly
+        from zope.interface._compat import PYTHON3
+        from zope.interface.interface import InterfaceClass
+        IFoo = InterfaceClass("IFoo")
+        globs = {'implementsOnly': implementsOnly,
+                 'IFoo': IFoo,
+                }
+        locs = {}
+        CODE = "\n".join([
+            'class Foo(object):'
+            '    implementsOnly(IFoo)',
+            ])
+        try:
+            exec(CODE, globs, locs)
+        except TypeError:
+            if not PYTHON3:
+                raise
+        else:
+            if PYTHON3:
+                self.fail("Didn't raise TypeError")
+            Foo = locs['Foo']
+            spec = Foo.__implemented__
+            self.assertEqual(list(spec), [IFoo])
+
     def test_called_once_from_class_w_bases(self):
         from zope.interface.declarations import implements
         from zope.interface.declarations import implementsOnly



More information about the checkins mailing list