← Back to team overview

beeseek-devs team mailing list archive

[Branch ~beeseek-devs/beeseek/trunk] Rev 187: * Resolve conflict in local attributes names in interfaces.py (LP: 311217)

 

------------------------------------------------------------
revno: 187
committer: Andrea Corbellini <andrea.corbellini@xxxxxxxxxxx>
branch nick: trunk
timestamp: Wed 2008-12-24 18:44:16 +0100
message:
  * Resolve conflict in local attributes names in interfaces.py (LP: 311217)
  * Improve comments in interfaces.py
modified:
  beeseek/interfaces.py

=== modified file 'beeseek/interfaces.py'
--- a/beeseek/interfaces.py	2008-11-13 13:42:08 +0000
+++ b/beeseek/interfaces.py	2008-12-24 17:44:16 +0000
@@ -71,6 +71,7 @@
     def __new__(cls):
         raise TypeError('Cannot instance an Interface')
 
+
 class ImplementationError(StandardError):
     """An error raised when an interface is not implemented correctly."""
 
@@ -92,22 +93,23 @@
         self.metaclass = metaclass
         self.interfaces = interfaces
 
-    def __call__(self, name, bases, origattrs):
-        # Get the original __metaclass__
-        metaclass = origattrs.get('__metaclass__', self)
+    def __call__(self, classname, bases, origattrs):
+        # Get the original __metaclass__ and restore it
+        metaclass = origattrs.pop('__metaclass__')
         if metaclass is self:
             metaclass = self.metaclass
-        del origattrs['__metaclass__']
+        if metaclass is not type and metaclass is not self:
+            origattrs['__metaclass__'] = metaclass
+        else:
+            metaclass = type
 
         # Sanity check
         interfaces = self.interfaces
         if origattrs['implements'] is not interfaces:
             raise ValueError('``implements`` changed in class definition')
 
-        commons = dir(Interface)
+        attrs = origattrs.copy()
         isbaseclass = origattrs.get('isbaseclass', False)
-
-        attrs = origattrs.copy()
         if not isbaseclass:
             # Get the whole attributes, including the ones declared in the
             # inherited classes
@@ -116,6 +118,8 @@
                     if name not in attrs:
                         attrs[name] = getattr(cls, name)
 
+
+        commons = dir(Interface)
         for interface in interfaces:
             for name in dir(interface):
                 if name in commons:
@@ -138,8 +142,9 @@
                         raise ImplementationError('Wrong number of arguments '
                                                   'for %s' % name)
                 else:
-                    # The attribute is a variable; it may be a tuple of types,
-                    # and the last element may be a doc string
+                    # The attribute is a variable
+                    # Its declaration in the interface may be a type or a
+                    # tuple of types and the last item may be a doc string
                     if isinstance(value, tuple):
                         if isinstance(value[-1], basestring):
                             value = value[:-1]
@@ -154,11 +159,12 @@
                     # Check if the variable type is correct
                     if not any(isinstance(attrs[name], cls or NoneType)
                                for cls in value):
+                        print attrs[name].__class__
                         raise ImplementationError('%s should be of type %r' %
                             (name, value))
 
         # Return a new class
-        return type.__new__(metaclass, name, bases, origattrs)
+        return metaclass.__new__(metaclass, classname, bases, origattrs)
 
 
 def implements(*interfaces, **kwargs):
@@ -180,32 +186,41 @@
     ...     cooking_time = 10
     ...
     """
-    # Get the locals of the caller
+    # Get the value of locals() of the caller that corresponds to the
+    # attributes of the class
     # TODO It should check if the caller is really a class
     attrs = sys._getframe(1).f_locals
 
     if 'implements' in attrs:
-        # ``implements`` is set at the end of this function; if present, it
-        # means that it has already been called
-        raise ValueError('This class has already called ``implements()``')
+        # ``implements`` is set at the end of this function; if it is present,
+        # it means that it has already been called
+        raise ValueError('implements() called twice')
 
+    # Some sanity checks
     for interface in interfaces:
-        # Some sanity checks
+        # Check if the given interfaces are subclasses of ``Interface``
         if not issubclass(interface, Interface) or interface is Interface:
             raise TypeError('The implemented class %r is not an interface' %
-                             interface)
+                            interface)
+        # Check if some of the given interfaces are not subclasses of other
+        # given interfaces
         if any(issubclass(interface, cls) for cls in interfaces
                if cls is not interface):
-            raise TypeError('%r is a subclass of an another interface' %
+            raise TypeError('%r is a subclass of an another given interface' %
                             interface)
 
-    # Set the callback for the class creation
+    # Set the callback for the class creation; this will check the class'
+    # attributes when its declaration is finished
     metaclass = attrs.get('__metaclass__', type)
     attrs['__metaclass__'] = _SignatureChecker(metaclass, interfaces)
 
-    # ``implements`` lists all the interfaces
+    # ``implements`` lists all the implemented interfaces; it is a tuple so
+    # it cannot be edited
     attrs['implements'] = interfaces
 
-    # Base classes shouldn't be initialized and so have special rights
+    # Base classes should never be initialized and so they can miss the
+    # declaration of some attributes
+    # Setting ``isbaseclass`` to True will tell _SignatureChecker not to raise
+    # errors about missing values
     if kwargs.get('isbase', False):
         attrs['isbaseclass'] = True



--
BeeSeek mainline
https://code.launchpad.net/~beeseek-devs/beeseek/trunk

You are receiving this branch notification because you are subscribed to it.