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

Jim Fulton jim@zope.com
Sat, 31 May 2003 18:12:18 -0400


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

Modified Files:
	_zope_interface_ospec.c declarations.py 
Log Message:
Refactored the way object specifications get created to make it easier
to create nested object specifications, to support things like
wrapper-object specifications.

Moved some more code to C.


=== Zope3/src/zope/interface/_zope_interface_ospec.c 1.5 => 1.6 === (485/585 lines abridged)
--- Zope3/src/zope/interface/_zope_interface_ospec.c:1.5	Wed May 28 12:44:59 2003
+++ Zope3/src/zope/interface/_zope_interface_ospec.c	Sat May 31 18:12:17 2003
@@ -17,8 +17,10 @@
 #include "structmember.h"
 
 static PyObject *str___provides__, *str___implements__, *str___class__;
-static PyObject *str___dict__, *str___signature__;
+static PyObject *str___dict__, *str___signature__, *str_flattened;
 static PyObject *_implements_reg, *classImplements, *proxySig, *oldSpecSig;
+static PyObject *combinedSpec, *str_extends, *declarations;
+static PyObject *str___providedBy__, *str_only;
 
 #define TYPE(O) ((PyTypeObject*)(O))
 #define OBJECT(O) ((PyObject*)(O))
@@ -67,7 +69,9 @@
         /* tp_getattro       */ (getattrofunc)0,
         /* tp_setattro       */ (setattrofunc)0,
         /* tp_as_buffer      */ 0,
-        /* tp_flags          */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+        /* tp_flags          */ Py_TPFLAGS_DEFAULT 
+                                | Py_TPFLAGS_BASETYPE
+                                ,
 	/* tp_doc            */ ISBtype__doc__,
         /* tp_traverse       */ (traverseproc)0,
         /* tp_clear          */ (inquiry)0,
@@ -90,42 +94,58 @@
 
 typedef struct {
   PyObject_HEAD
-  PyObject *ob;
+  PyObject *provides;
+  PyObject *cls;
+  PyObject *spec;
 } OSpec;
 
+static PyTypeObject OSpecType;
+
 static int
 OSpec_init(OSpec *self, PyObject *args, PyObject *kwds)
 {
-	static char *kwlist[] = {"ob", NULL};
-        PyObject *ob;
-
-        if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, 
-                                          &ob))
-        	return 0; 
+	static char *kwlist[] = {"provides", "cls", NULL};
+        PyObject *provides, *cls;
 
-        Py_INCREF(ob);

[-=- -=- -=- 485 lines omitted -=- -=- -=-]

 
-  oldSpecSig = PyObject_GetAttrString(module, "oldSpecSig");
+  oldSpecSig = PyObject_GetAttrString(declarations, "oldSpecSig");
   if (oldSpecSig == NULL)
     return;
 
-  Py_DECREF(module);
+  combinedSpec = PyObject_GetAttrString(declarations, "combinedSpec");
+  if (combinedSpec == NULL)
+    return;
  
-  OSpecType.tp_new = PyType_GenericNew;
-  ISBType.tp_new = PyType_GenericNew;
   
   /* Initialize types: */  
+
+  ISBType.tp_new = PyType_GenericNew;
   if (PyType_Ready(&ISBType) < 0)
     return;
+
+
+  OSpecType.tp_new = PyType_GenericNew;
+  OSpecType.tp_free = _PyObject_GC_Del;
   if (PyType_Ready(&OSpecType) < 0)
     return;
+  if (OSpecType.tp_dict && 
+      PyMapping_SetItemString(OSpecType.tp_dict, "only", Py_True) < 0
+      )
+    return;
+
+ 
+  OSpecDescrType.tp_new = PyType_GenericNew;
+    if (PyType_Ready(&OSpecDescrType) < 0)
+    return;
 
 
   /* Create the module and add the functions */
@@ -445,8 +707,11 @@
   if (PyModule_AddObject(module, "InterfaceSpecificationBase", 
                          (PyObject *)&ISBType) < 0)
     return;
-  if (PyModule_AddObject(module, "ObjectSpecificationBase", 
+  if (PyModule_AddObject(module, "ObjectSpecification", 
                          (PyObject *)&OSpecType) < 0)
+    return;
+  if (PyModule_AddObject(module, "ObjectSpecificationDescriptor", 
+                         (PyObject *)&OSpecDescrType) < 0)
     return;
   if (PyModule_AddObject(module, "_implements_reg", _implements_reg) < 0)
     return;


=== Zope3/src/zope/interface/declarations.py 1.8 => 1.9 === (520/620 lines abridged)
--- Zope3/src/zope/interface/declarations.py:1.8	Wed May 21 13:26:39 2003
+++ Zope3/src/zope/interface/declarations.py	Sat May 31 18:12:17 2003
@@ -146,63 +146,137 @@
     return implements.__signature__
 
 # This is overridden by _zope_interface_ospec.
-class ObjectSpecificationBase:
 
-    __slots__ = ['ob']
+def combinedSpec(provides, cls):
+    if provides is not None:
+        result = [provides]
+    else:
+        result = []
+
+    _gatherSpecs(cls, result)
 
-    def __init__(self, ob):
-        self.ob = ob
+    return InterfaceSpecification(*result)
+
+class ObjectSpecification_py:
+    """Provide object specifications
+
+    These combine information for the object and for it's classes.
+
+    For example::
+
+        >>> from zope.interface import Interface
+        >>> 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 A: implements(I1)
+        ...
+        >>> class B: __implements__ = I2
+        ...
+        >>> class C(A, B): implements(I31)
+        ...
+        >>> c = C()
+        >>> directlyProvides(c, I4)
+        >>> [i.__name__ for i in providedBy(c)]

[-=- -=- -=- 520 lines omitted -=- -=- -=-]

+                for c in mro:
+                    pb = c.__dict__.get("__providedBy__", c)
+                    if pb is not c:
+                        break
+                else: # no break
+                    pb = None
+                    
+            if not isinstance(pb, ObjectSpecificationDescriptor):
+                raise TypeError(
+                    cls,
+                    "has a __providedBy__ descriptor of the wrong type",
+                    pb)
 
-    """
-    try:
-        # catch bad spec by seeing if we can iterate over it
-        ispecs = iter(specs)
-    except TypeError:
-        # Must be a bad spec
-        raise exceptions.BadImplements(specs)
+            if "__providedBy__" not in cls.__dict__:
+                cls.__providedBy__ = pb
 
-    for spec in ispecs:
-        # We do this rather than isinstance because it works w proxies classes
-        if InterfaceClass in spec.__class__.__mro__:
-            if spec not in result:
-                result.append(spec)
-        elif spec is specs:
-            # Try to avoid an infinate loop by getting a string!
-            raise TypeError("Bad interface specification", spec)
-        else:
-            _flattenSpecs(spec, result)
+    else:
+        _implements_reg[cls] = v
 
-    return result
+    v.setClass(cls)
 
 def _getmro(C, r):
   if C not in r: r.append(C)
@@ -1310,8 +1376,6 @@
         _gatherSpecs(b, result)
 
     return result
-
-_empty = InterfaceSpecification()
 
 
 # DocTest: