[Zope-Checkins] CVS: Zope/lib/python/ExtensionClass - tests.py:1.1.2.1 ExtensionClass.h:1.1.2.2 _ExtensionClass.c:1.1.2.2 __init__.py:1.1.2.2 setup.py:1.1.2.2

Jim Fulton cvs-admin at zope.org
Thu Oct 23 09:03:36 EDT 2003


Update of /cvs-repository/Zope/lib/python/ExtensionClass
In directory cvs.zope.org:/tmp/cvs-serv17283/lib/python/ExtensionClass

Modified Files:
      Tag: zodb33-devel-branch
	ExtensionClass.h _ExtensionClass.c __init__.py setup.py 
Added Files:
      Tag: zodb33-devel-branch
	tests.py 
Log Message:
Updated substantially in the course of getting Acquisition, Missing,
and MethodObject.


=== Added File Zope/lib/python/ExtensionClass/tests.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.
#
##############################################################################
"""

$Id: tests.py,v 1.1.2.1 2003/10/23 13:03:04 jim Exp $
"""

from doctest import DocTestSuite
import unittest

def test_basic():
    """
    >>> from ExtensionClass import *

    Test creating basic classes and objects and test that class_init is called

    >>> class C(Base):
    ...   def __class_init__(self):
    ...      print 'class init called'
    ...      print self.__name__
    ...   def bar(self): pass
    ... 
    class init called
    C
    >>> c = C()
    >>> int(c.__class__ is C)
    1
    >>> int(c.__class__ is type(c))
    1

    Test that __of__ works

    >>> class O(Base):
    ...   def __of__(*a):
    ...      return a
    ... 
    >>> o1 = O()
    >>> o2 = O()
    >>> C.o1 = o1
    >>> c.o2 = o2
    >>> int(c.o1 == (o1, c))
    1
    >>> int(c.o2 == (o2, c))
    1

    Test inherited attribute:

    >>> class O2(O):
    ...   def __of__(*a):
    ...      return O2.inheritedAttribute('__of__')(*a), 42
    ... 
    >>> o2 = O2()
    >>> c.o2 = o2
    >>> int(c.o2 == ((o2, c), 42))
    1

    Test working with a classic class

    >>> class Classic: 
    ...   def x(self): 
    ...     return 42
    ... 
    >>> class O2(Classic, O):
    ...   def __of__(*a):
    ...      return (O2.inheritedAttribute('__of__')(*a), 
    ...              O2.inheritedAttribute('x')(a[0]))
    ... 
    >>> o2 = O2()
    >>> c.o2 = o2
    >>> int(c.o2 == ((o2, c), 42))
    1


    Test working with a ew style

    >>> class Modern(object): 
    ...   def x(self): 
    ...     return 42
    ... 
    >>> class O2(Modern, O):
    ...   def __of__(*a):
    ...      return (O2.inheritedAttribute('__of__')(*a), 
    ...              O2.inheritedAttribute('x')(a[0]))
    ... 
    >>> o2 = O2()
    >>> c.o2 = o2
    >>> int(c.o2 == ((o2, c), 42))
    1

    """

def test_class_creation_under_stress():
    """
    >>> from ExtensionClass import Base
    >>> for i in range(100): 
    ...   class B(Base):
    ...     print i,
    ...     if i and i%20 == 0:
    ...         print
    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
    21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
    41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
    61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
    81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

    >>> import gc
    >>> x = gc.collect()

    """

def old_test_add():
    """test_add.py from old EC
    
    >>> from ExtensionClass import Base

    >>> class foo(Base):
    ...     def __add__(self,other): print 'add called'

    
    >>> foo()+foo()
    add called
    """

def proper_error_on_deleattr():
    """
    Florent Guillaume wrote:

    ...

    Excellent.
    Will it also fix this particularity of ExtensionClass:
    
    
    >>> from ExtensionClass import Base
    >>> class A(Base):
    ...   def foo(self):
    ...     self.gee
    ...   def bar(self):
    ...     del self.gee
    
    >>> a=A()
    >>> a.foo()
    Traceback (most recent call last):
    ...
    AttributeError: gee
    
    >>> a.bar()
    Traceback (most recent call last):
    ...
    AttributeError: 'A' object has no attribute 'gee'
    
    I.e., the fact that KeyError is raised whereas a normal class would
    raise AttributeError.
    """


def test_suite():
    return DocTestSuite()

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


=== Zope/lib/python/ExtensionClass/ExtensionClass.h 1.1.2.1 => 1.1.2.2 ===
--- Zope/lib/python/ExtensionClass/ExtensionClass.h:1.1.2.1	Sun Oct 19 17:25:41 2003
+++ Zope/lib/python/ExtensionClass/ExtensionClass.h	Thu Oct 23 09:03:04 2003
@@ -74,18 +74,6 @@
 	  class library.  The macro 'PyExtensionClass_Export' imports the
 	  'ExtensionClass' module and uses objects imported from this module
 	  to initialize an extension class with necessary behavior.
- 
-  If you have questions regarding this software,
-  contact:
- 
-  
-  If you have questions regarding this software,
-  contact:
- 
-    Digital Creations L.C.  
-    info at digicool.com
- 
-    (540) 371-6909
 
 */
 
@@ -97,41 +85,156 @@
 
 /* Declarations for objects of type ExtensionClass */
 
+#define EC PyTypeObject
+#define PyExtensionClass PyTypeObject
+
 typedef struct {
-  PyHeapTypeObject tp;
-  long class_flags;  
-} PyExtensionClass;
+  PyObject_HEAD
+} _emptyobject;
 
-#define EC PyExtensionClass
+static struct ExtensionClassCAPIstruct {
+  PyObject *(*EC_findiattrs_)(PyObject *self, char *cname);
+  int (*PyExtensionClass_Export_)(PyObject *dict, char *name, 
+                                  PyTypeObject *typ);
+  PyObject *(*PyECMethod_New_)(PyObject *callable, PyObject *inst);
+  PyExtensionClass *ECBaseType_;
+  PyExtensionClass *ECExtensionClassType_;
+}  *PyExtensionClassCAPI = NULL;
+
+#define ECBaseType (PyExtensionClassCAPI->ECBaseType_)
+#define ECExtensionClassType (PyExtensionClassCAPI->ECExtensionClassType_)
+
+/* Following are macros that are needed or useful for defining extension
+   classes:
+   */
+
+/* This macro redefines Py_FindMethod to do attribute for an attribute
+   name given by a C string lookup using extension class meta-data.
+   This is used by older getattr implementations.
+
+   This macro is used in base class implementations of tp_getattr to
+   lookup methods or attributes that are not managed by the base type
+   directly.  The macro is generally used to search for attributes
+   after other attribute searches have failed.
+   
+   Note that in Python 1.4, a getattr operation may be provided that
+   uses an object argument. Classes that support this new operation
+   should use Py_FindAttr.
+   */
+
+#define EC_findiattrs(O, N) PyExtensionClassCAPI->EC_findiattrs_((O),(N))
+
+#define Py_FindMethod(M,SELF,NAME) (EC_findiattrs((SELF),(NAME)))
+
+/* Do method or attribute lookup for an attribute name given by a C
+   string using extension class meta-data.
+
+   This macro is used in base class implementations of tp_getattro to
+   lookup methods or attributes that are not managed by the base type
+   directly.  The macro is generally used to search for attributes
+   after other attribute searches have failed.
+   
+   Note that in Python 1.4, a getattr operation may be provided that
+   uses an object argument. Classes that support this new operation
+   should use Py_FindAttr.
+   */
+#define Py_FindAttrString(SELF,NAME)  (EC_findiattrs((SELF),(NAME)))
+
+/* Do method or attribute lookup using extension class meta-data.
+
+   This macro is used in base class implementations of tp_getattr to
+   lookup methods or attributes that are not managed by the base type
+   directly.  The macro is generally used to search for attributes
+   after other attribute searches have failed.  */
+#define Py_FindAttr(SELF,NAME) (ECBaseType->tp_getattro(SELF, NAME))
+
+/* Do attribute assignment for an attribute.
+
+   This macro is used in base class implementations of tp_setattro to
+   set attributes that are not managed by the base type directly.  The
+   macro is generally used to assign attributes after other attribute
+   attempts to assign attributes have failed.
+   */
+#define PyEC_SetAttr(SELF,NAME,V) (ECBaseType->tp_setattro(SELF, NAME, V))
 
-  /* The following flags are used by ExtensionClass */
-#define EXTENSIONCLASS_DYNAMIC_FLAG       1 << 0
 #define EXTENSIONCLASS_BINDABLE_FLAG      1 << 2
-#define EXTENSIONCLASS_METHODHOOK_FLAG    1 << 3
-#define EXTENSIONCLASS_INSTDICT_FLAG      1 << 4
-#define EXTENSIONCLASS_NOINSTDICT_FLAG    1 << 5
-#define EXTENSIONCLASS_BASICNEW_FLAG      1 << 6
-#define EXTENSIONCLASS_PYTHONICATTR_FLAG  1 << 7
-#define EXTENSIONCLASS_USERGETATTR_FLAG   1 << 8
-#define EXTENSIONCLASS_USERSETATTR_FLAG   1 << 9
-#define EXTENSIONCLASS_USERDELATTR_FLAG   1 << 10
-
-  /* The following flags are for use by extension class developers. */
-#define EXTENSIONCLASS_USER_FLAG1  	  1 << 16
-#define EXTENSIONCLASS_USER_FLAG2  	  1 << 17
-#define EXTENSIONCLASS_USER_FLAG3  	  1 << 18
-#define EXTENSIONCLASS_USER_FLAG4  	  1 << 19
-#define EXTENSIONCLASS_USER_FLAG5  	  1 << 20
-#define EXTENSIONCLASS_USER_FLAG6  	  1 << 21
-#define EXTENSIONCLASS_USER_FLAG7  	  1 << 22
-#define EXTENSIONCLASS_USER_FLAG8  	  1 << 23
-#define EXTENSIONCLASS_USER_FLAG9  	  1 << 24
-#define EXTENSIONCLASS_USER_FLAG10 	  1 << 25
-#define EXTENSIONCLASS_USER_FLAG11 	  1 << 26
-#define EXTENSIONCLASS_USER_FLAG12 	  1 << 27
-#define EXTENSIONCLASS_USER_FLAG13 	  1 << 28
-#define EXTENSIONCLASS_USER_FLAG14 	  1 << 29
-#define EXTENSIONCLASS_USER_FLAG15 	  1 << 30
-#define EXTENSIONCLASS_USER_FLAG16 	  1 << 31
+
+
+
+/* Convert a method list to a method chain.  */
+#define METHOD_CHAIN(DEF) (traverseproc)(DEF)
+
+/* The following macro checks whether a type is an extension class: */
+#define PyExtensionClass_Check(TYPE) \
+  ((PyObject*)(TYPE)->ob_type == ECExtensionClassType)
+
+/* The following macro checks whether an instance is an extension instance: */
+#define PyExtensionInstance_Check(INST) \
+  (((PyObject*)(INST))->ob_type->ob_type == ECExtensionClassType)
+
+#define CHECK_FOR_ERRORS(MESS) 
+
+/* The following macro can be used to define an extension base class
+   that only provides method and that is used as a pure mix-in class. */
+#define PURE_MIXIN_CLASS(NAME,DOC,METHODS) \
+static PyExtensionClass NAME ## Type = { PyObject_HEAD_INIT(NULL) 0, # NAME, \
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+   0 , DOC, (traverseproc)METHODS, }
+
+/* The following macros provide limited access to extension-class
+   method facilities. */
+
+/* Test for an ExtensionClass method: */
+#define PyECMethod_Check(O) PyMethod_Check((O))
+
+/* Create a method object that wraps a callable object and an
+   instance. Note that if the callable object is an extension class
+   method, then the new method will wrap the callable object that is
+   wrapped by the extension class method.  Also note that if the
+   callable object is an extension class method with a reference
+   count of 1, then the callable object will be rebound to the
+   instance and returned with an incremented reference count.
+   */
+#define PyECMethod_New(CALLABLE, INST) \
+  PyExtensionClassCAPI->PyECMethod_New_((CALLABLE),(INST))
+
+/* Return the instance that is bound by an extension class method. */
+#define PyECMethod_Self(M) \
+(PyMethod_Check((M)) ? ((PyMethodObject*)(M))->im_self : NULL)
+
+/* Check whether an object has an __of__ method for returning itself
+   in the context of it's container. */
+#define has__of__(O) ((O)->ob_type->ob_type == ECExtensionClassType \
+                      && (O)->ob_type->tp_descr_get != NULL)
+
+/* The following macros are used to check whether an instance
+   or a class' instanses have instance dictionaries: */
+#define HasInstDict(O) (_PyObject_GetDictPtr(O) != NULL)
+
+#define ClassHasInstDict(C) ((C)->tp_dictoffset > 0))
+
+/* Get an object's instance dictionary.  Use with caution */
+#define INSTANCE_DICT(inst) (_PyObject_GetDictPtr(O))
+
+/* Test whether an ExtensionClass, S, is a subclass of ExtensionClass C. */
+#define ExtensionClassSubclass_Check(S,C) PyType_IsSubtype((S), (C))
+
+/* Test whether an ExtensionClass instance , I, is a subclass of 
+   ExtensionClass C. */
+#define ExtensionClassSubclassInstance_Check(I,C) PyObject_TypeCheck((I), (C))
+
+
+/* Export an Extension Base class in a given module dictionary with a
+   given name and ExtensionClass structure.
+   */
+
+#define PyExtensionClass_Export(D,N,T) \
+  if (! ExtensionClassImported || \
+      PyExtensionClassCAPI->PyExtensionClass_Export_((D),(N),&(T)) < 0) return;
+
+
+#define ExtensionClassImported \
+  ((PyExtensionClassCAPI != NULL) || \
+   (PyExtensionClassCAPI = PyCObject_Import("ExtensionClass","CAPI2")))
 
 #endif /* EXTENSIONCLASS_H */


=== Zope/lib/python/ExtensionClass/_ExtensionClass.c 1.1.2.1 => 1.1.2.2 ===
--- Zope/lib/python/ExtensionClass/_ExtensionClass.c:1.1.2.1	Sun Oct 19 17:25:41 2003
+++ Zope/lib/python/ExtensionClass/_ExtensionClass.c	Thu Oct 23 09:03:04 2003
@@ -19,12 +19,15 @@
 
 #include "ExtensionClass.h"
 
-static PyObject *str__of__, *str__get__, *str__class_init__;
+#define EC PyTypeObject
+
+static PyObject *str__of__, *str__get__, *str__class_init__, *str__init__;
 
 #define OBJECT(O) ((PyObject *)(O))
 #define TYPE(O) ((PyTypeObject *)(O))
 
 extern PyTypeObject ExtensionClassType;
+extern PyTypeObject BaseType;
 
 static PyObject *
 of_get(PyObject *self, PyObject *inst, PyObject *cls)
@@ -138,11 +141,10 @@
                              If the tp_descr_get of res is of_get, 
                              then call it. */
 
-                          if (PyType_HasFeature(res->ob_type, 
-                                                Py_TPFLAGS_HAVE_CLASS)
-                              && res->ob_type->tp_descr_get == of_get
-                              ) 
-                            res = of_get(res, obj, NULL);
+                          if (res->ob_type->ob_type == &ExtensionClassType
+                              && res->ob_type->tp_descr_get != NULL)
+                            res = res->ob_type->tp_descr_get(
+                                                 res, obj, OBJECT(&BaseType));
                           else
                             Py_INCREF(res);
                           goto done;
@@ -161,20 +163,13 @@
 		goto done;
 	}
 
-	PyErr_Format(PyExc_AttributeError,
-		     "'%.50s' object has no attribute '%.400s'",
-		     tp->tp_name, PyString_AS_STRING(name));
+        PyErr_SetObject(PyExc_AttributeError, name);
   done:
 	Py_DECREF(name);
 	return res;
 }
 
-
-
-
 static EC BaseType = {
-  {
-    {
 	PyObject_HEAD_INIT(NULL)
 	/* ob_size           */ 0,
 	/* tp_name           */ "ExtensionClass."
@@ -197,18 +192,15 @@
         /* tp_setattro       */ (setattrofunc)0,
         /* tp_as_buffer      */ 0,
         /* tp_flags          */ Py_TPFLAGS_DEFAULT 
-                                | Py_TPFLAGS_HAVE_GC
 				| Py_TPFLAGS_BASETYPE
                                 ,
 	/* tp_doc            */ "Standard ExtensionClass base type",
-    },
-  },
 };
 
 static PyObject *
 EC_new(PyTypeObject *self, PyObject *args, PyObject *kw)
 {
-  PyObject *name, *bases=NULL, *dict=NULL, *__class_init__;
+  PyObject *name, *bases=NULL, *dict=NULL;
   PyObject *new_bases=NULL, *new_args, *result;
   int have_base = 0, i;
 
@@ -223,19 +215,6 @@
                         &PyTuple_Type, &bases, &PyDict_Type, &dict))
     return NULL;
 
-  /* Handle __class_init__ */
-  if (dict)
-    {
-      __class_init__ = PyDict_GetItem(dict, str__class_init__);
-      if (__class_init__)
-        {                       /* Convert to class meth */
-          __class_init__ = PyClassMethod_New(__class_init__);
-          if (! __class_init__)
-            return NULL;
-          PyDict_SetItem(dict, str__class_init__, __class_init__);
-        }
-    }
-
   /* Make sure Base is in bases */
   if (bases)
     {
@@ -320,21 +299,29 @@
 
   /* Call __class_init__ */
   __class_init__ = PyObject_GetAttr(OBJECT(self), str__class_init__);
-  if (__class_init__)
+  if (__class_init__ == NULL)
     {
-      r = PyObject_CallFunctionObjArgs(__class_init__, NULL);
-      Py_DECREF(__class_init__);
+      PyErr_Clear();
+      return 0;
+    }
 
-      if (r)
-        {
-          Py_DECREF(r);
-        }
-      else
-        return -1;
+  if (! (PyMethod_Check(__class_init__) 
+         && PyMethod_GET_FUNCTION(__class_init__)
+         )
+      )
+    {
+      Py_DECREF(__class_init__);
+      PyErr_SetString(PyExc_TypeError, "Invalid type for __class_init__");
+      return -1;
     }
-  else
-    PyErr_Clear();
 
+  r = PyObject_CallFunctionObjArgs(PyMethod_GET_FUNCTION(__class_init__),
+                                   OBJECT(self), NULL);
+  Py_DECREF(__class_init__);
+  if (! r)
+    return -1;
+  Py_DECREF(r);
+  
   return 0;
 }
 
@@ -367,7 +354,7 @@
 	/* ob_size           */ 0,
 	/* tp_name           */ "ExtensionClass."
                                 "ExtensionClass",
-	/* tp_basicsize      */ sizeof(EC),
+	/* tp_basicsize      */ 0,
 	/* tp_itemsize       */ 0,
 	/* tp_dealloc        */ (destructor)0,
 	/* tp_print          */ (printfunc)0,
@@ -416,7 +403,6 @@
   return Py_None;
 }
 
-
 /* List of methods defined in the module */
 
 static struct PyMethodDef ec_methods[] = {
@@ -424,13 +410,202 @@
   {NULL,	 (PyCFunction)NULL, 0, NULL}		/* sentinel */
   };
 
+
+static PyObject *
+EC_findiattrs_(PyObject *self, char *cname)
+{
+  PyObject *name, *r;
+  
+  name = PyString_FromString(cname);
+  if (name == NULL)
+    return NULL;
+  r = ECBaseType->tp_getattro(self, name);
+  Py_DECREF(name);
+  return r;
+}
+
+static PyObject *
+ec_new(PyTypeObject *type, PyObject *args, PyObject *kw)
+{
+  /* This is for EC's that have deallocs.  For these, we need to
+     incref the type when we create an instance, because the deallocs
+     will decref the type.
+  */
+
+  PyObject *r;
+
+  r = PyType_GenericNew(type, args, kw);
+  if (r)
+    {
+      Py_INCREF(type);
+    }
+  return r;
+}
+
+static int
+ec_init(PyObject *self, PyObject *args, PyObject *kw)
+{
+  PyObject *r, *__init__;
+
+  __init__ = PyObject_GetAttr(self, str__init__);
+  if (__init__ == NULL)
+    return -1;
+    
+  r = PyObject_Call(__init__, args, kw);
+  Py_DECREF(__init__);
+  if (r == NULL)
+    return -1;
+
+  Py_DECREF(r);
+  return 0;
+}
+
+static int
+PyExtensionClass_Export_(PyObject *dict, char *name, PyTypeObject *typ)
+{
+  int ecflags;
+  PyMethodDef *pure_methods = NULL, *mdef = NULL;
+  PyObject *m;
+
+  if (typ->tp_flags == 0) 
+    { 
+      /* Old-style EC */
+
+      if (typ->tp_traverse) 
+        { 
+          /* ExtensionClasses stick there methods in the tp_traverse slot */
+          mdef = (PyMethodDef *)typ->tp_traverse;
+
+          if (typ->tp_basicsize <= sizeof(_emptyobject))
+            /* Pure mixin. We want rebindable methods */
+            pure_methods = mdef;
+          else
+            typ->tp_methods = mdef;
+
+          typ->tp_traverse = NULL; 
+
+          /* Look for __init__ method  */
+          for (; mdef->ml_name; mdef++)
+            {
+              if (strcmp(mdef->ml_name, "__init__") == 0)
+                {
+                  /* we have an old-style __init__, install a special slot */
+                  typ->tp_init = ec_init;
+                  break;
+                }
+            }
+        } 
+
+      if (typ->tp_clear)
+        {
+          /* ExtensionClasses stick there flags in the tp_clear slot */
+          ecflags = (int)(typ->tp_clear);
+
+          /* Some old-style flags were set */
+
+          if ((ecflags & EXTENSIONCLASS_BINDABLE_FLAG)
+              && typ->tp_descr_get == NULL)
+            /* We have __of__-style binding */
+            typ->tp_descr_get = of_get; 
+        }
+      typ->tp_clear = NULL; 
+      typ->tp_flags = Py_TPFLAGS_DEFAULT 
+                    | Py_TPFLAGS_BASETYPE;
+      
+      if (typ->tp_dealloc != NULL)
+          typ->tp_new = ec_new;
+    }
+
+  typ->ob_type = ECExtensionClassType; 
+  typ->tp_base = ECBaseType; 
+  if (typ->tp_new == NULL)
+    typ->tp_new = PyType_GenericNew; 
+
+  if (PyType_Ready(typ) < 0) 
+    return -1; 
+
+  if (pure_methods)
+    {
+      /* We had pure methods. We want to be able to rebind these, so
+         we'll make them ordinary method wrappers around method descrs
+      */
+      for (; pure_methods->ml_name; pure_methods++)
+        {
+          m = PyDescr_NewMethod(ECBaseType, pure_methods);
+          if (! m)
+            return -1;
+          m = PyMethod_New((PyObject *)m, NULL, (PyObject *)ECBaseType);
+          if (! m)
+            return -1;
+          if (PyDict_SetItemString(typ->tp_dict, pure_methods->ml_name, m) 
+              < 0)
+            return -1;
+        }      
+    }
+  else if (mdef && mdef->ml_name)
+    {
+      /* Blast, we have to stick __init__ in the dict ourselves
+         because PyType_Ready probably stuck a wrapper for ec_init in
+         instead.
+      */
+      m = PyDescr_NewMethod(typ, mdef);
+      if (! m)
+        return -1;
+      if (PyDict_SetItemString(typ->tp_dict, mdef->ml_name, m) < 0)
+        return -1;
+    }
+
+  if (PyMapping_SetItemString(dict, name, (PyObject*)typ) < 0)  
+    return -1; 
+
+  return 0;
+}
+
+PyObject *
+PyECMethod_New_(PyObject *callable, PyObject *inst)
+{
+  if (! PyExtensionInstance_Check(inst))
+    {
+      PyErr_SetString(PyExc_TypeError, 
+                      "Can't bind non-ExtensionClass instance.");
+      return NULL;
+    }
+
+  if (PyMethod_Check(callable))
+    {
+      if (callable->ob_refcnt == 1)
+        {
+          Py_XDECREF(((PyMethodObject*)callable)->im_self);
+          Py_INCREF(inst);
+          ((PyMethodObject*)callable)->im_self = inst;
+          Py_INCREF(callable);
+          return callable;
+        }
+      else
+        return callable->ob_type->tp_descr_get(
+                   callable, inst, 
+                   ((PyMethodObject*)callable)->im_class);
+    }
+  else
+    return PyMethod_New(callable, inst, (PyObject*)(ECBaseType));
+}
+
+static struct ExtensionClassCAPIstruct
+TrueExtensionClassCAPI = {
+  EC_findiattrs_,
+  PyExtensionClass_Export_,
+  PyECMethod_New_,
+  &BaseType,
+  &ExtensionClassType,
+};
+
 #ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
 #define PyMODINIT_FUNC void
 #endif
 PyMODINIT_FUNC
 init_ExtensionClass(void)
 {
-  PyObject *m;
+  PyObject *m, *s;
 
 #define DEFINE_STRING(S) \
   if(! (str ## S = PyString_FromString(# S))) return
@@ -438,6 +613,9 @@
   DEFINE_STRING(__of__);
   DEFINE_STRING(__get__);
   DEFINE_STRING(__class_init__);
+  DEFINE_STRING(__init__);
+
+  PyExtensionClassCAPI = &TrueExtensionClassCAPI;
 
   ExtensionClassType.ob_type = &PyType_Type;
   ExtensionClassType.tp_base = &PyType_Type;
@@ -449,7 +627,6 @@
     return;
   
   
-  TYPE(&BaseType)->tp_basicsize = PyBaseObject_Type.tp_basicsize;
   TYPE(&BaseType)->ob_type = &ExtensionClassType;
   TYPE(&BaseType)->tp_base = &PyBaseObject_Type;
   TYPE(&BaseType)->tp_new = PyType_GenericNew;
@@ -464,6 +641,9 @@
   if (m == NULL)
     return;
 
+  s = PyCObject_FromVoidPtr(PyExtensionClassCAPI, NULL);
+  if (PyModule_AddObject(m, "CAPI2", s) < 0)
+    return;
         
   /* Add types: */
   if (PyModule_AddObject(m, "ExtensionClass", 


=== Zope/lib/python/ExtensionClass/__init__.py 1.1.2.1 => 1.1.2.2 ===
--- Zope/lib/python/ExtensionClass/__init__.py:1.1.2.1	Sun Oct 19 17:25:41 2003
+++ Zope/lib/python/ExtensionClass/__init__.py	Thu Oct 23 09:03:04 2003
@@ -16,4 +16,4 @@
 $Id$
 """
 
-from _ExtensionClass import ExtensionClass, Base
+from _ExtensionClass import *


=== Zope/lib/python/ExtensionClass/setup.py 1.1.2.1 => 1.1.2.2 ===
--- Zope/lib/python/ExtensionClass/setup.py:1.1.2.1	Sun Oct 19 17:25:41 2003
+++ Zope/lib/python/ExtensionClass/setup.py	Thu Oct 23 09:03:04 2003
@@ -1,6 +1,8 @@
 from distutils.core import setup, Extension
 setup(name="ExtensionClass", version="2.0",
       ext_modules=[
-         Extension("_ExtensionClass", ["_ExtensionClass.c"]),
+         Extension("_ExtensionClass", ["_ExtensionClass.c"],
+                   depends = ["ExtensionClass.h"],
+                   ),
          ])
 




More information about the Zope-Checkins mailing list