[Zope3-checkins] CVS: Zope3/src/zope/interface/tests - odd.py:1.1.2.1 test_odd_declarations.py:1.1.2.1

Jim Fulton jim@zope.com
Sat, 3 May 2003 11:40:37 -0400


Update of /cvs-repository/Zope3/src/zope/interface/tests
In directory cvs.zope.org:/tmp/cvs-serv13110/tests

Added Files:
      Tag: interfacegeddon2-branch
	odd.py test_odd_declarations.py 
Log Message:
Added some support for ExtensionClass instances.

Old style declarations like:

  class C(ExtensionClass.Base):
     __implements__ = IFoo

work.

Also:

  class C(ExtensionClass.Base):
     pass

  classImplements(IFoo)

works.

But use of implements and classprovides will produce incorrect
behavior.  I'll be able to fix this in the next iteration.

Note, however, that we need to disallow declarations of interface
declarations for ExtensionClasses themselves until ExtensionClass is
rewritten to support descriptors.



=== Added File Zope3/src/zope/interface/tests/odd.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Odd meta class that doesn't subclass type.

This is used for testing support for ExtensionClass in new interfaces.

  >>> class A:
  ...     __metaclass__ = MetaClass
  ...     a = 1
  ...
  >>> A.__name__
  'A'
  >>> A.__bases__
  ()
  >>> class B:
  ...     __metaclass__ = MetaClass
  ...     b = 1
  ...
  >>> class C(A, B): pass
  ...
  >>> C.__name__
  'C'
  >>> int(C.__bases__ == (A, B))
  1
  >>> a = A()
  >>> aa = A()
  >>> a.a
  1
  >>> aa.a
  1
  >>> aa.a = 2
  >>> a.a
  1
  >>> aa.a
  2
  >>> c = C()
  >>> c.a
  1
  >>> c.b
  1
  >>> c.b = 2
  >>> c.b
  2
  >>> C.c = 1
  >>> c.c
  1
  >>> from types import ClassType
  >>> int(isinstance(C, (type, ClassType)))
  0
  >>> int(C.__class__.__class__ is C.__class__)
  1

$Id: odd.py,v 1.1.2.1 2003/05/03 15:40:37 jim Exp $
"""

# class OddClass is an odd meta class

class MetaMetaClass(type):

    def __getattribute__(self, name):
        if name == '__class__':
            return self
        return type.__getattribute__(self, name)
    

class MetaClass(object):
    """Odd classes
    """
    __metaclass__ = MetaMetaClass

    def __init__(self, name, bases, dict):
        self.__name__ = name
        self.__bases__ = bases
        self.__dict__.update(dict)

    def __call__(self):
        return OddInstance(self)

    def __getattr__(self, name):
        for b in self.__bases__:
            v = getattr(b, name, self)
            if v is not self:
                return v
        raise AttributeError, name

    def __repr__(self):
        return "<odd class %s at %s>" % (self.__name__, hex(id(self)))

class OddInstance(object):

    def __init__(self, cls):
        self.__dict__['__class__'] = cls

    def __getattribute__(self, name):
        dict = object.__getattribute__(self, '__dict__')
        if name == '__dict__':
            return dict
        v = dict.get(name, self)
        if v is not self:
            return v
        return getattr(dict['__class__'], name)

    def __setattr__(self, name, v):
        self.__dict__[name] = v

    def __delattr__(self, name):
        del self.__dict__[name]

    def __repr__(self):
        return "<odd %s instance at %s>" % (
            self.__class__.__name__, hex(id(self)))
        


# DocTest:
if __name__ == "__main__":
    import doctest, __main__
    doctest.testmod(__main__, isprivate=lambda *a: False)


=== Added File Zope3/src/zope/interface/tests/test_odd_declarations.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Test interface declarations against ExtensionClass-like classes.

These tests are to make sure we do something sane in the presense of
classic ExtensionClass classes and instances.

$Id: test_odd_declarations.py,v 1.1.2.1 2003/05/03 15:40:37 jim Exp $
"""

import unittest, odd
from zope.interface import Interface
from zope.interface import directlyProvides, providedBy, directlyProvidedBy
from zope.interface import classImplements, classImplementsOnly, implementedBy

class I1(Interface): pass
class I2(Interface): pass
class I3(Interface): pass
class I31(I3): pass
class I4(Interface): pass
class I5(Interface): pass

class Odd: __metaclass__ = odd.MetaClass

class B(Odd): __implements__ = I2


# XXX We are going to need more magic to make implements work with odd
#     classes. This will work in the next iteration. For now, we'll use
#     a different mechanism.

# from zope.interface import implements, classProvides

class A(Odd):
    # implements(I1)
    __implements__ = I1

class C(A, B):
    pass
    #implements(I31)
classImplements(C, I31)



class Test(unittest.TestCase):

    def test_ObjectSpecification(self):        
        c = C()
        directlyProvides(c, I4)
        self.assertEqual([i.__name__ for i in providedBy(c)],
                         ['I4', 'I31', 'I1', 'I2']
                         )
        self.assertEqual([i.__name__ for i in providedBy(c).flattened()],
                         ['I4', 'I31', 'I3', 'I1', 'I2', 'Interface']
                         )
        self.assert_(I1 in providedBy(c))
        self.failIf(I3 in providedBy(c))        
        self.assert_(providedBy(c).extends(I3))
        self.assert_(providedBy(c).extends(I31))
        self.failIf(providedBy(c).extends(I5))

        class COnly(A, B):
            # XXX implementsOnly(I31)
            __implements__ = I31
        class D(COnly):
            # XXX implements(I5)
            pass
        classImplements(D, I5)
        
        c = D()
        directlyProvides(c, I4)
        self.assertEqual([i.__name__ for i in providedBy(c)],
                         ['I4', 'I5', 'I31'])
        self.assertEqual([i.__name__ for i in providedBy(c).flattened()],
                         ['I4', 'I5', 'I31', 'I3', 'Interface'])
        self.failIf(I1 in providedBy(c))
        self.failIf(I3 in providedBy(c))
        self.assert_(providedBy(c).extends(I3))
        self.failIf(providedBy(c).extends(I1))
        self.assert_(providedBy(c).extends(I31))
        self.assert_(providedBy(c).extends(I5))

        class COnly(A, B): __implements__ = I31        
        class D(COnly):
            # XXX implements(I5)
            pass
        classImplements(D, I5)
        c = D()
        directlyProvides(c, I4)
        self.assertEqual([i.__name__ for i in providedBy(c)],
                         ['I4', 'I5', 'I31'])
        self.assertEqual([i.__name__ for i in providedBy(c).flattened()],
                         ['I4', 'I5', 'I31', 'I3', 'Interface'])
        self.failIf(I1 in providedBy(c))
        self.failIf(I3 in providedBy(c))
        self.assert_(providedBy(c).extends(I3))
        self.failIf(providedBy(c).extends(I1))
        self.assert_(providedBy(c).extends(I31))
        self.assert_(providedBy(c).extends(I5))
        
    def test_classImplements(self):
        class A(Odd):
          # XXX implements(I3)
          __implements__ = I3
        class B(Odd):
          # XXX implements(I4)
          __implements__ = I4
        class C(A, B):
          pass
        classImplements(C, I1, I2)
        self.assertEqual([i.__name__ for i in implementedBy(C)],
                         ['I1', 'I2', 'I3', 'I4'])
        classImplements(C, I5)
        self.assertEqual([i.__name__ for i in implementedBy(C)],
                         ['I1', 'I2', 'I5', 'I3', 'I4'])
        
    def test_classImplementsOnly(self):
        class A(Odd):
            # XXX implements(I3)
          __implements__ = I3
        class B(Odd):
            # XXX implements(I4)
          __implements__ = I4
        class C(A, B):
          pass
        classImplementsOnly(C, I1, I2)
        self.assertEqual([i.__name__ for i in implementedBy(C)],
                         ['I1', 'I2'])


    def test_directlyProvides(self):
        class IA1(Interface): pass        
        class IA2(Interface): pass
        class IB(Interface): pass
        class IC(Interface): pass
        class A(Odd):
            # XXX implements(IA1, IA2)
            __implements__ = IA1, IA2
        class B(Odd):
            # XXX implements(IB)
            __implements__ = IB
        class C(A, B):
            # XXX implements(IC)
            pass
        classImplements(C, IC)

        ob = C()
        directlyProvides(ob, I1, I2)
        self.assert_(I1 in providedBy(ob))
        self.assert_(I2 in providedBy(ob))
        self.assert_(IA1 in providedBy(ob))
        self.assert_(IA2 in providedBy(ob))
        self.assert_(IB in providedBy(ob))
        self.assert_(IC in providedBy(ob))
        
        directlyProvides(ob, directlyProvidedBy(ob)-I2)
        self.assert_(I1 in providedBy(ob))
        self.failIf(I2 in providedBy(ob))
        self.failIf(I2 in providedBy(ob))
        directlyProvides(ob, directlyProvidedBy(ob), I2)
        self.assert_(I2 in providedBy(ob))

    def test_directlyProvides_fails_for_odd_class(self):
        self.assertRaises(TypeError, directlyProvides, C, I5)

    # XXX see above
    def XXX_test_classProvides_fails_for_odd_class(self):
        try:
            class A(Odd):
                classProvides(I1)
        except TypeError:
            pass # Sucess
        self.assert_(False,
                     "Shouldn't be able to use directlyProvides on odd class."
                     )

    def test_implementedBy(self):
        class I2(I1): pass
        
        class C1(Odd):
          # XXX implements(I2)
          __implements__ = I2
        class C2(C1):
          # XXX implements(I3)
          pass
        classImplements(C2, I3)
        self.assertEqual([i.__name__ for i in implementedBy(C2)],
                         ['I3', 'I2'])

    
        

def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(Test))
    return suite


if __name__ == '__main__':
    unittest.main()