[Zope3-checkins] CVS: Zope3/src/zope/interface - _zope_interface_ospec.c:1.1 declarations.py:1.7

Jim Fulton jim@zope.com
Thu, 15 May 2003 15:07:45 -0400


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

Modified Files:
	declarations.py 
Added Files:
	_zope_interface_ospec.c 
Log Message:
Converted some interface introspection code to C for performance.
The change reduced execution time for / and
/++etc++site/services.html by about 20%.


=== Added File Zope3/src/zope/interface/_zope_interface_ospec.c ===
/*****************************************************************************

 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.

 *****************************************************************************/
 

#include "Python.h"
#include "structmember.h"

static PyObject *str___provides__, *str___implements__, *str___class__;
static PyObject *str___dict__, *str___signature__;
static PyObject *_implements_reg, *classImplements, *proxySig, *oldSpecSig;

#define TYPE(O) ((PyTypeObject*)(O))
#define OBJECT(O) ((PyObject*)(O))
#define CLASSIC(O) ((PyClassObject*)(O))

typedef struct {
  PyObject_HEAD
  PyObject *__signature__;
} ISB;

static PyMemberDef ISB_members[] = {
  { "__signature__", T_OBJECT_EX, offsetof(ISB, __signature__), 0 },
  {NULL}	/* Sentinel */
};

static char ISBtype__doc__[] = 
"InterfaceSpecification base class that provides a __signature__ slot"
;

static PyTypeObject ISBType = {
	PyObject_HEAD_INIT(NULL)
	/* ob_size           */ 0,
	/* tp_name           */ "zope.interface._zope_interface_ospec."
                                "InterfaceSpecificationBase",
	/* tp_basicsize      */ sizeof(ISB),
	/* tp_itemsize       */ 0,
	/* tp_dealloc        */ (destructor)0,
	/* tp_print          */ (printfunc)0,
	/* tp_getattr        */ (getattrfunc)0,
	/* tp_setattr        */ (setattrfunc)0,
	/* tp_compare        */ (cmpfunc)0,
	/* tp_repr           */ (reprfunc)0,
	/* tp_as_number      */ 0,
	/* tp_as_sequence    */ 0,
	/* tp_as_mapping     */ 0,
	/* tp_hash           */ (hashfunc)0,
	/* tp_call           */ (ternaryfunc)0,
	/* tp_str            */ (reprfunc)0,
        /* tp_getattro       */ (getattrofunc)0,
        /* tp_setattro       */ (setattrofunc)0,
        /* tp_as_buffer      */ 0,
        /* tp_flags          */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
	/* tp_doc            */ ISBtype__doc__,
        /* tp_traverse       */ (traverseproc)0,
        /* tp_clear          */ (inquiry)0,
        /* tp_richcompare    */ (richcmpfunc)0,
        /* tp_weaklistoffset */ (long)0,
        /* tp_iter           */ (getiterfunc)0,
        /* tp_iternext       */ (iternextfunc)0,
        /* tp_methods        */ 0,
        /* tp_members        */ ISB_members,
        /* tp_getset         */ 0,
        /* tp_base           */ 0,
        /* tp_dict           */ 0, /* internal use */
        /* tp_descr_get      */ (descrgetfunc)0,
        /* tp_descr_set      */ (descrsetfunc)0,
        /* tp_dictoffset     */ 0,
        /* tp_init           */ (initproc)0,
        /* tp_alloc          */ (allocfunc)0,
        /* tp_new            */ (newfunc)PyType_GenericNew,
};

typedef struct {
  PyObject_HEAD
  PyObject *ob;
} OSpec;

static PyObject *
OSpec_init(OSpec *self, PyObject *args, PyObject *kwds)
{
	static char *kwlist[] = {"ob", NULL};
        PyObject *ob;

        if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, 
                                          &ob))
        	return NULL; 

        Py_INCREF(ob);
        self->ob = ob;

    	Py_INCREF(Py_None);
    	return Py_None;
}

static void
OSpec_dealloc(OSpec *self)
{
  Py_XDECREF(self->ob);
  self->ob_type->tp_free((PyObject*)self);
}

static PyObject *
OSpec_getob(OSpec *self, void *closure)
{
  if (self->ob == NULL) {
    PyErr_SetString(PyExc_AttributeError, "No ob attribute set");
    return NULL;
  }

  Py_INCREF(self->ob);
  return self->ob;
}

static PyObject *
getsig(PyObject *spec, PyObject *cls)
{
  PyObject *sig;

  if (PyObject_TypeCheck(spec, &ISBType))
    {
      sig = ((ISB*)spec)->__signature__;
      if (sig == NULL)
        {
          PyErr_SetString(PyExc_TypeError, 
                          "Specification has no __signature__");
          return NULL;
        }
      Py_INCREF(sig);
    }
  else
    { /* Wrong type of specification */
      if (cls == NULL)
        {

          /* This isn't the right kind of thing. Check for a
             __signature__ anyway. */

          sig = PyObject_GetAttr(spec, str___signature__);
        }
      else
        /* Maybe it's an old style declaration */
        sig = PyObject_CallFunctionObjArgs(oldSpecSig, cls, spec, NULL);
    }

  return sig;
}

static PyObject *
OSpec_getsig(OSpec *self, void *closure)
{
  PyObject *provides, *psig=0, *cls, *key, *dict, *implements, *sig=0, *result;

  if (self->ob == NULL) {
    PyErr_SetString(PyExc_AttributeError, "No ob attribute set");
    return NULL;
  }

  provides = PyObject_GetAttr(self->ob, str___provides__);
  if (provides == NULL)
    PyErr_Clear();
  else 
    {
      psig = getsig(provides, NULL);
      Py_DECREF(provides);
      if (psig == NULL)
        return NULL;
    }

  /* Own: psig */

  /* Whimper. We have to do a getattr, because ob may be a proxy */
  cls = PyObject_GetAttr(self->ob, str___class__);
  if (cls == NULL)
    {
      PyErr_Clear();
      goto done;
    }

  /* Own: psig, cls */

  /* Ultimately, we get the implementation spec from a dict with some
     key, where the dict is normally the class dict and the key is
     normally '__implements__'. */

  key = str___implements__;
  
  if (PyClass_Check(cls))
    {
      dict = CLASSIC(cls)->cl_dict;
      Py_INCREF(dict);
    }
  else if (PyType_Check(cls))
    {
      if (TYPE(cls)->tp_flags & Py_TPFLAGS_HEAPTYPE)
        dict = TYPE(cls)->tp_dict;
      else
        {
          dict = _implements_reg;
          key = cls;
        }
      Py_INCREF(dict);
    }
  else
    dict = PyObject_GetAttr(cls, str___dict__);

  /* Own: psig, cls, dict */

  if (dict == NULL)
    {
      /* We couldn't get a dict. Must be a proxy */
      PyErr_Clear();
      sig = PyObject_CallFunctionObjArgs(proxySig, cls, NULL);
    }
  else
    {
      if (! PyDict_Check(dict))
        {
          PyErr_SetObject(PyExc_TypeError, dict); 
          return NULL;
        }
      implements = PyDict_GetItem(dict, key);
      if (implements == NULL)
        {
          result = PyObject_CallFunctionObjArgs(classImplements, cls, NULL);
          if (result != NULL)
            {
              Py_DECREF(result);
              implements = PyDict_GetItem(dict, key);
              if (implements == NULL)
                PyErr_SetObject(PyExc_KeyError, key); 
            }
        }

      if (implements != NULL)
        sig = getsig(implements, cls);
      
      Py_DECREF(dict);
    }

  Py_DECREF(cls);


  /* Own: psig */


  if (sig == NULL)
    {
      Py_XDECREF(psig);
      return NULL;
    }

 done:
  if (sig == Py_None && psig != NULL)
    {
      /* We have a provided sig, but the class sig was None, so make class
         sig NULL  */
      Py_DECREF(sig);
      sig == NULL;
    }

  if (sig != NULL)
    if (psig != NULL)
      {
        result = PyTuple_New(2);
        if (result == NULL)
          {
            Py_DECREF(psig);
            Py_DECREF(sig);
            return NULL;
          }
        PyTuple_SET_ITEM(result, 0, psig);
        PyTuple_SET_ITEM(result, 1, sig);
        return result;
      }
    else
      return sig;
  else if (psig != NULL)
    return psig;
  else
    {
      Py_INCREF(Py_None);
      return Py_None;
    }
}    

static PyGetSetDef OSpec_getset[] = {
    {"ob", 
     (getter)OSpec_getob, (setter)0,
     "Subject of the object specification",
     NULL},
    {"__signature__", 
     (getter)OSpec_getsig, (setter)0,
     "Specification signature",
     NULL},
    {NULL}  /* Sentinel */
};




static char OSpecType__doc__[] = 
"Base type for object specifications computed via descriptors (no wrappers)"
;

static PyTypeObject OSpecType = {
	PyObject_HEAD_INIT(NULL)
	/* ob_size           */ 0,
	/* tp_name           */ "zope.interface._zope_interface_ospec."
                                "ObjectSpecificationBase",
	/* tp_basicsize      */ sizeof(OSpec),
	/* tp_itemsize       */ 0,
	/* tp_dealloc        */ (destructor)OSpec_dealloc,
	/* tp_print          */ (printfunc)0,
	/* tp_getattr        */ (getattrfunc)0,
	/* tp_setattr        */ (setattrfunc)0,
	/* tp_compare        */ (cmpfunc)0,
	/* tp_repr           */ (reprfunc)0,
	/* tp_as_number      */ 0,
	/* tp_as_sequence    */ 0,
	/* tp_as_mapping     */ 0,
	/* tp_hash           */ (hashfunc)0,
	/* tp_call           */ (ternaryfunc)0,
	/* tp_str            */ (reprfunc)0,
        /* tp_getattro       */ (getattrofunc)0,
        /* tp_setattro       */ (setattrofunc)0,
        /* tp_as_buffer      */ 0,
        /* tp_flags          */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
	/* tp_doc            */ OSpecType__doc__,
        /* tp_traverse       */ (traverseproc)0,
        /* tp_clear          */ (inquiry)0,
        /* tp_richcompare    */ (richcmpfunc)0,
        /* tp_weaklistoffset */ (long)0,
        /* tp_iter           */ (getiterfunc)0,
        /* tp_iternext       */ (iternextfunc)0,
        /* tp_methods        */ 0,
        /* tp_members        */ 0,
        /* tp_getset         */ OSpec_getset,
        /* tp_base           */ 0,
        /* tp_dict           */ 0, /* internal use */
        /* tp_descr_get      */ (descrgetfunc)0,
        /* tp_descr_set      */ (descrsetfunc)0,
        /* tp_dictoffset     */ 0,
        /* tp_init           */ (initproc)OSpec_init,
        /* tp_alloc          */ (allocfunc)0,
        /* tp_new            */ (newfunc)PyType_GenericNew,
};

/* List of methods defined in the module */

static struct PyMethodDef module_methods[] = {

	{NULL,	 (PyCFunction)NULL, 0, NULL}		/* sentinel */
};


static char _zope_interface_ospec_module_documentation[] = 
""
;

#ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
init_zope_interface_ospec(void)
{
  PyObject *module;
  
  str___implements__ = PyString_FromString("__implements__");
  if (str___implements__ == NULL)
    return;
  
  str___provides__ = PyString_FromString("__provides__");
  if (str___provides__ == NULL)
    return;
  
  str___class__ = PyString_FromString("__class__");
  if (str___class__ == NULL)
    return;
  
  str___dict__ = PyString_FromString("__dict__");
  if (str___dict__ == NULL)
    return;
  
  str___signature__ = PyString_FromString("__signature__");
  if (str___signature__ == NULL)
    return;
  
  _implements_reg = PyDict_New();
  if (_implements_reg == NULL)
    return;

  module = PyImport_ImportModule("zope.interface.declarations");
  if (module == NULL) 
    return;

  classImplements = PyObject_GetAttrString(module, "classImplements");
  if (classImplements == NULL)
    return;

  proxySig = PyObject_GetAttrString(module, "proxySig");
  if (proxySig == NULL)
    return;

  oldSpecSig = PyObject_GetAttrString(module, "oldSpecSig");
  if (oldSpecSig == NULL)
    return;

  Py_DECREF(module);
  
  /* Initialize types: */  
  if (PyType_Ready(&ISBType) < 0)
    return;
  if (PyType_Ready(&OSpecType) < 0)
    return;

  /* Create the module and add the functions */
  module = Py_InitModule3("_zope_interface_ospec", module_methods,
                          _zope_interface_ospec_module_documentation);
  
  if (module == NULL)
    return;
  
  /* Add types: */
  if (PyModule_AddObject(module, "InterfaceSpecificationBase", 
                         (PyObject *)&ISBType) < 0)
    return;
  if (PyModule_AddObject(module, "ObjectSpecificationBase", 
                         (PyObject *)&OSpecType) < 0)
    return;
  if (PyModule_AddObject(module, "_implements_reg", _implements_reg) < 0)
    return;
}



=== Zope3/src/zope/interface/declarations.py 1.6 => 1.7 ===
--- Zope3/src/zope/interface/declarations.py:1.6	Tue May 13 15:48:23 2003
+++ Zope3/src/zope/interface/declarations.py	Thu May 15 15:07:44 2003
@@ -15,15 +15,16 @@
 """
 
 import sys
-import weakref
 from zope.interface.interface import InterfaceClass, mergeOrderings
 import exceptions
 from types import ClassType
 
-DescriptorAwareMetaClasses = ClassType, type
+# There are imports from _zope_interface_ospec later in the file
+# because _zope_interface_ospec depends on some functions defined
+# here.
 
-# implementation info for immutable classes (heap flag clear)
-_implements_reg = weakref.WeakKeyDictionary()
+
+DescriptorAwareMetaClasses = ClassType, type
 
 __metaclass__ = type
 
@@ -34,20 +35,190 @@
 # We have 3 implementations of interface specifications:
 #
 # ImplementsSpecification
-#   Holds implements specification. 
+#   Holds specifications of interfaces of instances of classes. 
 #
 # ProvidesSpecification
-#   Holds provides specification. This is a descriptor that assures
+#   These are specifications for interfaces directly provided by
+#   objects.   This is a descriptor that assures
 #   that if we get it from a class for an instance, we get an attribute
 #   error.
 #
 # ObjectSpecification
 #   Holds the specification for all of the interfaces of an object.
+#   These are computed on the floy based on provides and implements
+#   specs.
 #
 # We also have a descriptor to support providedBy
 
 
-class InterfaceSpecification:
+# implementation info for immutable classes (heap flag clear)
+# This is overridden by _zope_interface_ospec.
+_implements_reg = {}
+
+# This is overridden by _zope_interface_ospec.
+class InterfaceSpecificationBase:
+    __slots__ = ['__signature__']
+
+
+# This function is needed by _zope_interface_ospec and, so, must be
+# defined before _zope_interface_ospec is imported. 
+def classImplements(cls, *interfaces):
+    """Declare additional interfaces implemented for instances of a class
+
+    The arguments after the class are one or more interfaces or
+    interface specifications (IInterfaceSpecification objects).
+
+    The interfaces given (including the interfaces in the
+    specifications) are added to any interfaces previously
+    declared.
+
+    Consider the following example::
+
+
+    for example:
+
+    >>> from zope.interface import Interface
+    >>> class I1(Interface): pass
+    ...
+    >>> class I2(Interface): pass
+    ...
+    >>> class I3(Interface): pass
+    ...
+    >>> class I4(Interface): pass
+    ...
+    >>> class I5(Interface): pass
+    ...
+    >>> class A:
+    ...   implements(I3)
+    >>> class B:
+    ...   implements(I4)
+    >>> class C(A, B):
+    ...   pass
+    >>> classImplements(C, I1, I2)
+    >>> [i.__name__ for i in implementedBy(C)]
+    ['I1', 'I2', 'I3', 'I4']
+    >>> classImplements(C, I5)
+    >>> [i.__name__ for i in implementedBy(C)]
+    ['I1', 'I2', 'I5', 'I3', 'I4']
+
+    Instances of ``C`` provide ``I1``, ``I2``, ``I5``, and whatever interfaces
+    instances of ``A`` and ``B`` provide.
+
+    """
+
+    _setImplements(cls,
+                   _getImplements(cls) + ImplementsSpecification(*interfaces)
+                   )
+
+# This function is needed by _zope_interface_ospec and, so, must be
+# defined before _zope_interface_ospec is imported. 
+def proxySig(cls):
+    # Get an implementation signature from a proxied class
+
+    # XXX If we got here, we must have a
+    # security-proxied class. This introduces an
+    # indirect dependency on security proxies,
+    # which we don't want. This is necessary to
+    # support old-style __implements__ interface
+    # declarations.
+
+    # If we got here, we must have an old-style
+    # declaration, so we'll just look for an
+    # __implements__.  We can't fix it because the class
+    # is probably security proxied.
+
+    implements = getattr(cls, '__implements__', None)
+    if implements is not None:
+        assert ((implements.__class__ == tuple)
+                or
+                (InterfaceClass in
+                 implements.__class__.__mro__)
+                )
+        sig = `implements`
+
+        return sig
+
+# This function is needed by _zope_interface_ospec and, so, must be
+# defined before _zope_interface_ospec is imported. 
+def oldSpecSig(cls, implements):
+    implements = OnlyImplementsSpecification(implements)
+    _setImplements(cls, implements)
+    return implements.__signature__
+
+# This is overridden by _zope_interface_ospec.
+class ObjectSpecificationBase:
+
+    __slots__ = ['ob']
+
+    def __init__(self, ob):
+        self.ob = ob
+
+    def __signature__(self):
+        ob = self.ob
+
+        provides = getattr(ob, '__provides__', None)
+        if provides is not None:
+            provides = provides.__signature__
+        else:
+            provides = ''
+        sig = ''
+
+        try:
+            cls = ob.__class__
+        except AttributeError:
+            # If there's no class, we'll just use the instance spec
+            pass
+        else:
+
+            try:
+                flags = cls.__flags__
+            except AttributeError:
+                flags = heap
+
+            if flags & heap:
+                try:
+                    dict = cls.__dict__
+                except AttributeError:
+                    sig = proxySig(cls)
+
+                else:
+                    # Normal case
+                    implements = dict.get('__implements__')
+                    if implements is None:
+                        # No implements spec, lets add one:
+                        classImplements(cls)
+                        implements = dict['__implements__']
+
+                    try:
+                        sig = implements.__signature__
+                    except AttributeError:
+                        # Old-style implements!  Fix it up.
+                        sig = oldSpecSig(cls, implements)
+
+            else:
+                # Look in reg
+                implements = _implements_reg.get(cls)
+                if implements is None:
+                        # No implements spec, lets add one:
+                        classImplements(cls)
+                        implements = _implements_reg[cls]
+                sig = implements.__signature__
+
+        if sig:
+            if provides:
+                return provides, sig
+            return sig
+        else:
+            return provides
+
+    __signature__ = property(__signature__)
+
+from _zope_interface_ospec import _implements_reg
+from _zope_interface_ospec import InterfaceSpecificationBase
+from _zope_interface_ospec import ObjectSpecificationBase
+
+
+class InterfaceSpecification(InterfaceSpecificationBase):
     """Create an interface specification
 
     The arguments are one or more interfaces or interface
@@ -116,7 +287,6 @@
           1
         """
         return interface in self.interfaces
-
     def __iter__(self):
         """Return an iterator for the interfaces in the specification
 
@@ -179,7 +349,6 @@
         """
 
         return iter(self.__iro__)
-
     def extends(self, interface):
         """Does the specification extend the given interface?
 
@@ -214,7 +383,6 @@
 
         """
         return interface in self.set
-
     def __add__(self, other):
         """Add twp specifications or a specification and an interface
 
@@ -420,7 +588,7 @@
 
 _objectSpecificationDescriptor = ObjectSpecificationDescriptor()
 
-class ObjectSpecification:
+class ObjectSpecification(ObjectSpecificationBase):
     """Provide object specifications
 
     These combine information for the object and for it's classes.
@@ -486,153 +654,14 @@
         1
     """
 
+    __slots__ = ['_specslot']
     only = True
 
-    def __init__(self, ob):
-        self.ob = ob
-
-    def _gathersig(self, c, result):
-        flags = getattr(c, '__flags__', heap)
-
-        if flags & heap:
-            try:
-                dict = c.__dict__
-            except AttributeError:
-
-                # XXX If we got here, we must have a
-                # security-proxied class. This introduces an
-                # indirect dependency on security proxies,
-                # which we don't want. This is necessary to
-                # support old-style __implements__ interface
-                # declarations.
-
-                # If we got here, we must have an old-style
-                # declaration, so we'll just look for an
-                # __implements__.  We can't fix it because the class
-                # is probably security proxied.
-
-                implements = getattr(c, '__implements__', None)
-                if implements is not None:
-                    assert ((implements.__class__ == tuple)
-                            or
-                            (InterfaceClass in
-                             implements.__class__.__mro__)
-                            )
-                    result.append(`implements`)
-
-            else:
-                # Normal case
-                implements = dict.get('__implements__')
-                if implements is None:
-                    # No implements spec, lets add one:
-                    classImplements(c)
-                    implements = dict['__implements__']
-
-                try:
-                    sig = implements.__signature__
-                except AttributeError:
-                    # Old-style implements!  Fix it up.
-                    implements = OnlyImplementsSpecification(
-                        implements)
-                    _setImplements(c, implements)
-                    sig = implements.__signature__
-
-                if sig:
-                    result.append(sig)
-                
-        else:
-            # Look in reg
-            implements = _implements_reg.get(c)
-            if implements is None:
-                    # No implements spec, lets add one:
-                    classImplements(c)
-                    implements = _implements_reg[c]
-            sig = implements.__signature__
-            if sig:
-                result.append(sig)
-
-
-    def __signature__(self):
-        ob = self.ob
-
-        provides = getattr(ob, '__provides__', None)
-        if provides is not None:
-            provides = provides.__signature__
-        else:
-            provides = ''
-        sig = ''
-
-        try:
-            cls = ob.__class__
-        except AttributeError:
-            # If there's no class, we'll just use the instance spec
-            pass
-        else:
-
-            flags = getattr(cls, '__flags__', heap)
-
-            if flags & heap:
-                try:
-                    dict = cls.__dict__
-                except AttributeError:
-
-                    # XXX If we got here, we must have a
-                    # security-proxied class. This introduces an
-                    # indirect dependency on security proxies,
-                    # which we don't want. This is necessary to
-                    # support old-style __implements__ interface
-                    # declarations.
-
-                    # If we got here, we must have an old-style
-                    # declaration, so we'll just look for an
-                    # __implements__.  We can't fix it because the class
-                    # is probably security proxied.
-
-                    implements = getattr(cls, '__implements__', None)
-                    if implements is not None:
-                        assert ((implements.__class__ == tuple)
-                                or
-                                (InterfaceClass in
-                                 implements.__class__.__mro__)
-                                )
-                        sig = `implements`
-
-                else:
-                    # Normal case
-                    implements = dict.get('__implements__')
-                    if implements is None:
-                        # No implements spec, lets add one:
-                        classImplements(cls)
-                        implements = dict['__implements__']
-
-                    try:
-                        sig = implements.__signature__
-                    except AttributeError:
-                        # Old-style implements!  Fix it up.
-                        implements = OnlyImplementsSpecification(
-                            implements)
-                        _setImplements(cls, implements)
-                        sig = implements.__signature__
-
-            else:
-                # Look in reg
-                implements = _implements_reg.get(cls)
-                if implements is None:
-                        # No implements spec, lets add one:
-                        classImplements(cls)
-                        implements = _implements_reg[cls]
-                sig = implements.__signature__
-
-        if sig:
-            if provides:
-                return provides, sig
-            return sig
-        else:
-            return provides
-
-    __signature__ = property(__signature__)
-
     def _v_spec(self):
+        spec = getattr(self, '_specslot', self)
+        if spec is not self:
+            return spec
+        
         ob = self.ob
         provides = getattr(ob, '__provides__', None)
         if provides is not None:
@@ -647,7 +676,7 @@
         else:
             _gatherSpecs(cls, result)
 
-        self.__dict__['_v_spec'] = spec = InterfaceSpecification(*result)
+        self._specslot = spec = InterfaceSpecification(*result)
 
         return spec
 
@@ -692,54 +721,6 @@
         
     return r
 
-def classImplements(cls, *interfaces):
-    """Declare additional interfaces implemented for instances of a class
-
-    The arguments after the class are one or more interfaces or
-    interface specifications (IInterfaceSpecification objects).
-
-    The interfaces given (including the interfaces in the
-    specifications) are added to any interfaces previously
-    declared.
-
-    Consider the following example::
-
-
-    for example:
-
-    >>> from zope.interface import Interface
-    >>> class I1(Interface): pass
-    ...
-    >>> class I2(Interface): pass
-    ...
-    >>> class I3(Interface): pass
-    ...
-    >>> class I4(Interface): pass
-    ...
-    >>> class I5(Interface): pass
-    ...
-    >>> class A:
-    ...   implements(I3)
-    >>> class B:
-    ...   implements(I4)
-    >>> class C(A, B):
-    ...   pass
-    >>> classImplements(C, I1, I2)
-    >>> [i.__name__ for i in implementedBy(C)]
-    ['I1', 'I2', 'I3', 'I4']
-    >>> classImplements(C, I5)
-    >>> [i.__name__ for i in implementedBy(C)]
-    ['I1', 'I2', 'I5', 'I3', 'I4']
-
-    Instances of ``C`` provide ``I1``, ``I2``, ``I5``, and whatever interfaces
-    instances of ``A`` and ``B`` provide.
-
-    """
-
-    _setImplements(cls,
-                   _getImplements(cls) + ImplementsSpecification(*interfaces)
-                   )
-
 def classImplementsOnly(cls, *interfaces):
     """Declare the only interfaces implemented by instances of a class
 
@@ -1182,7 +1163,11 @@
 
 
 def _getImplements(cls):
-    flags = getattr(cls, '__flags__', heap)
+
+    try:
+        flags = cls.__flags__
+    except AttributeError:
+        flags = heap
 
     if flags & heap:
         try: