[Zope-Checkins] CVS: Zope/lib/python/ExtensionClass - ExtensionClass.h:1.1.2.4 _ExtensionClass.c:1.1.2.4 tests.py:1.1.2.3

Jim Fulton cvs-admin at zope.org
Wed Oct 29 06:09:18 EST 2003


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

Modified Files:
      Tag: zodb33-devel-branch
	ExtensionClass.h _ExtensionClass.c tests.py 
Log Message:
allowe setting attributes of extension types if the attributes don't
seem to be slots.


=== Zope/lib/python/ExtensionClass/ExtensionClass.h 1.1.2.3 => 1.1.2.4 ===
--- Zope/lib/python/ExtensionClass/ExtensionClass.h:1.1.2.3	Tue Oct 28 13:46:51 2003
+++ Zope/lib/python/ExtensionClass/ExtensionClass.h	Wed Oct 29 06:09:17 2003
@@ -175,7 +175,7 @@
 
 /* The following macro checks whether a type is an extension class: */
 #define PyExtensionClass_Check(TYPE) \
-  ((PyObject*)(TYPE)->ob_type == ECExtensionClassType)
+  (((PyObject*)(TYPE))->ob_type == ECExtensionClassType)
 
 /* The following macro checks whether an instance is an extension instance: */
 #define PyExtensionInstance_Check(INST) \


=== Zope/lib/python/ExtensionClass/_ExtensionClass.c 1.1.2.3 => 1.1.2.4 ===
--- Zope/lib/python/ExtensionClass/_ExtensionClass.c:1.1.2.3	Tue Oct 28 13:46:51 2003
+++ Zope/lib/python/ExtensionClass/_ExtensionClass.c	Wed Oct 29 06:09:17 2003
@@ -551,6 +551,55 @@
   return 0;
 }
 
+static int
+EC_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
+{
+  /* We want to allow setting attributes of builti-in types, because
+     EC did in the past and there's code that relies on it.
+
+     We can't really set slots though, but I don't think we need to.
+     There's no good way to spot slots.  We could use a lame rule like
+     names that begin and end with __s and have just 4 _s smell too
+     much like slots.
+
+
+  */
+  if (! (type->tp_flags & Py_TPFLAGS_HEAPTYPE)) 
+    {
+      char *cname;
+      int l;
+
+      cname = PyString_AsString(name);
+      if (cname == NULL)
+        return -1;
+      l = PyString_GET_SIZE(name);
+      if (l > 4 
+          && cname[0] == '_' && cname[1] == '_'
+          && cname[l-1] == '_' && cname[l-2] == '_'
+          )
+        {
+          char *c;
+          
+          c = strchr(cname+2, '_');
+          if (c != NULL && (c - cname) >= (l-2))
+            {
+              PyErr_Format
+                (PyExc_TypeError,
+                 "can't set attributes of built-in/extension type '%s' if the "
+                 "attribute name begins and ends with __ and contains only "
+                 "4 _ characters",
+                 type->tp_name
+                 );
+              return -1;
+            }
+        }
+      
+      return PyObject_GenericSetAttr(OBJECT(type), name, value);
+    }
+  return PyType_Type.tp_setattro(OBJECT(type), name, value);
+}
+
+
 static PyObject *
 inheritedAttribute(PyTypeObject *self, PyObject *name)
 {
@@ -604,7 +653,7 @@
 	/* tp_call           */ (ternaryfunc)0,
 	/* tp_str            */ (reprfunc)0,
         /* tp_getattro       */ (getattrofunc)0,
-        /* tp_setattro       */ (setattrofunc)0,
+        /* tp_setattro       */ (setattrofunc)EC_setattro,
         /* tp_as_buffer      */ 0,
         /* tp_flags          */ Py_TPFLAGS_DEFAULT
                                 | Py_TPFLAGS_HAVE_GC
@@ -660,7 +709,7 @@
 }
 
 static PyObject *
-ec_new(PyTypeObject *type, PyObject *args, PyObject *kw)
+ec_new_for_custom_dealloc(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
@@ -748,7 +797,7 @@
                     | Py_TPFLAGS_BASETYPE;
 
       if (typ->tp_dealloc != NULL)
-          typ->tp_new = ec_new;
+          typ->tp_new = ec_new_for_custom_dealloc;
     }
 
   typ->ob_type = ECExtensionClassType; 


=== Zope/lib/python/ExtensionClass/tests.py 1.1.2.2 => 1.1.2.3 ===
--- Zope/lib/python/ExtensionClass/tests.py:1.1.2.2	Tue Oct 28 13:46:51 2003
+++ Zope/lib/python/ExtensionClass/tests.py	Wed Oct 29 06:09:17 2003
@@ -375,7 +375,49 @@
 
     """
     
+def test_setattr_on_extension_type():
+    """
+    >>> for name in 'x', '_x', 'x_', '__x_y__', '___x__', '__x___', '_x_':
+    ...     setattr(Base, name, 1)
+    ...     print getattr(Base, name)
+    ...     delattr(Base, name)
+    ...     print getattr(Base, name, 0)
+    1
+    0
+    1
+    0
+    1
+    0
+    1
+    0
+    1
+    0
+    1
+    0
+    1
+    0
 
+    >>> Base.__foo__ = 1
+    Traceback (most recent call last):
+    ...
+    TypeError: can't set attributes of built-in/extension type """ \
+        """'ExtensionClass.Base' if the attribute name begins """ \
+        """and ends with __ and contains only 4 _ characters
+
+    >>> Base.__foo__
+    Traceback (most recent call last):
+    ...
+    AttributeError: type object 'ExtensionClass.Base' """ \
+        """has no attribute '__foo__'
+
+    >>> del Base.__foo__
+    Traceback (most recent call last):
+    ...
+    TypeError: can't set attributes of built-in/extension type """ \
+        """'ExtensionClass.Base' if the attribute name begins """ \
+        """and ends with __ and contains only 4 _ characters
+
+    """
         
 
 from doctest import DocTestSuite




More information about the Zope-Checkins mailing list