[Zope3-checkins] CVS: Zope3/src/zope/proxy/context - wrapper.c:1.5

Steve Alexander steve@cat-box.net
Wed, 9 Apr 2003 09:00:20 -0400


Update of /cvs-repository/Zope3/src/zope/proxy/context
In directory cvs.zope.org:/tmp/cvs-serv29791/src/zope/proxy/context

Modified Files:
	wrapper.c 
Log Message:
Fixed leaking string refcounts.
Now uses a fixed lookup-table of PyStrings for the python special method
names such as __getitem__ and next and __len__.


=== Zope3/src/zope/proxy/context/wrapper.c 1.4 => 1.5 ===
--- Zope3/src/zope/proxy/context/wrapper.c:1.4	Tue Apr  8 12:44:04 2003
+++ Zope3/src/zope/proxy/context/wrapper.c	Wed Apr  9 09:00:19 2003
@@ -22,6 +22,22 @@
 static PyObject *
 empty_tuple = NULL;
 
+/* We need to use PyStrings for the various python special method names,
+ * such as __len__ and next and __getitem__.
+ * At module initialisation, we create the strings, and cache them here.
+ */
+static PyObject *SlotStrings[9];
+#define LEN_IDX 0
+#define GETITEM_IDX 1
+#define SETITEM_IDX 2
+#define DELITEM_IDX 3
+#define ITER_IDX 4
+#define NEXT_IDX 5
+#define CONTAINS_IDX 6
+#define CALL_IDX 7
+#define STR_IDX 8
+
+
 /* ContextAware type
  *
  * This is a 'marker' type with no methods or members.
@@ -658,9 +674,10 @@
  */
 #define FILLSLOTDEFS \
     PyObject *wrapped; \
-    PyObject *descriptor;
+    PyObject *descriptor; \
+    PyObject *name;
 
-#define FILLSLOT(NAME, BADVAL) \
+#define FILLSLOT(NAME, IDX, BADVAL) \
     wrapped = Proxy_GET_OBJECT(self); \
     if (wrapped == NULL) { \
         PyErr_Format(PyExc_RuntimeError, \
@@ -668,21 +685,21 @@
                      (NAME)); \
             return (BADVAL); \
     } \
-    descriptor = _PyType_Lookup(wrapped->ob_type,\
-                    PyString_FromString((NAME))); \
+    name = SlotStrings[IDX]; \
+    descriptor = _PyType_Lookup(wrapped->ob_type, name);\
     if (descriptor != NULL && \
         descriptor->ob_type->tp_descr_get != NULL && \
         (PyObject_TypeCheck(descriptor, &ContextDescriptorType) || \
             PyObject_TypeCheck(wrapped, &ContextAwareType))\
         )
 
-#define FILLSLOTBASE(NAME) \
+#define FILLSLOTBASE(NAME, IDX) \
     FILLSLOTDEFS \
-    FILLSLOT(NAME, NULL)
+    FILLSLOT(NAME, IDX, NULL)
 
-#define FILLSLOTBASEINT(NAME) \
+#define FILLSLOTBASEINT(NAME, IDX) \
     FILLSLOTDEFS \
-    FILLSLOT(NAME, -1)
+    FILLSLOT(NAME, IDX, -1)
 
 #define REBOUNDDESCRIPTOR \
     descriptor->ob_type->tp_descr_get( \
@@ -697,7 +714,7 @@
 {
     PyObject *res;
     int len;
-    FILLSLOTBASEINT("__len__") {
+    FILLSLOTBASEINT("__len__", LEN_IDX) {
         res = PyObject_CallFunctionObjArgs(REBOUNDDESCRIPTOR, NULL);
         if (res == NULL)
             return -1;
@@ -710,7 +727,7 @@
 
 static PyObject *
 wrap_getitem(PyObject *self, PyObject *v) {
-    FILLSLOTBASE("__getitem__")
+    FILLSLOTBASE("__getitem__", GETITEM_IDX)
         return PyObject_CallFunctionObjArgs(REBOUNDDESCRIPTOR, v, NULL);
     return PyObject_GetItem(wrapped, v);
 }
@@ -722,7 +739,7 @@
     FILLSLOTDEFS
 
     if (value == NULL) {
-        FILLSLOT("__delitem__", -1) {
+        FILLSLOT("__delitem__", DELITEM_IDX, -1) {
             res = PyObject_CallFunctionObjArgs(REBOUNDDESCRIPTOR, key, NULL);
             if (res == NULL)
                 return -1;
@@ -731,7 +748,7 @@
         }
         return PyObject_DelItem(wrapped, key);
     } else {
-        FILLSLOT("__setitem__", -1) {
+        FILLSLOT("__setitem__", SETITEM_IDX, -1) {
             res = PyObject_CallFunctionObjArgs(
                             REBOUNDDESCRIPTOR, key, value, NULL);
             if (res == NULL)
@@ -749,7 +766,7 @@
 static PyObject *
 wrap_iter(PyObject *self)
 {
-    FILLSLOTBASE("__iter__")
+    FILLSLOTBASE("__iter__", ITER_IDX)
         return PyObject_CallFunctionObjArgs(REBOUNDDESCRIPTOR, NULL);
     return PyObject_GetIter(wrapped);
 }
@@ -757,7 +774,7 @@
 static PyObject *
 wrap_iternext(PyObject *self)
 {
-    FILLSLOTBASE("next")
+    FILLSLOTBASE("next", NEXT_IDX)
         return PyObject_CallFunctionObjArgs(REBOUNDDESCRIPTOR, NULL);
     return PyIter_Next(Proxy_GET_OBJECT(self));
 }
@@ -770,7 +787,7 @@
 {
     PyObject *res;
     int result;
-    FILLSLOTBASEINT("__contains__") {
+    FILLSLOTBASEINT("__contains__", CONTAINS_IDX) {
         res = PyObject_CallFunctionObjArgs(REBOUNDDESCRIPTOR, value, NULL);
         if (res == NULL)
             return -1;
@@ -790,11 +807,11 @@
     FILLSLOTDEFS
 
     if (kw) {
-        FILLSLOT("__call__", NULL)
+        FILLSLOT("__call__", CALL_IDX, NULL)
             return PyEval_CallObjectWithKeywords(REBOUNDDESCRIPTOR, args, kw);
         return PyEval_CallObjectWithKeywords(wrapped, args, kw);
     } else {
-        FILLSLOT("__call__", NULL)
+        FILLSLOT("__call__", CALL_IDX, NULL)
             return PyObject_CallObject(REBOUNDDESCRIPTOR, args);
         return PyObject_CallObject(wrapped, args);
     }
@@ -802,7 +819,7 @@
 
 static PyObject *
 wrap_str(PyObject *self) {
-    FILLSLOTBASE("__str__")
+    FILLSLOTBASE("__str__", STR_IDX)
         return PyObject_CallFunctionObjArgs(REBOUNDDESCRIPTOR, NULL);
     return PyObject_Str(wrapped);
 }
@@ -1353,6 +1370,16 @@
     m = Py_InitModule3("wrapper", module_functions, module___doc__);
     if (m == NULL)
         return;
+
+    SlotStrings[LEN_IDX] = PyString_InternFromString("__len__");
+    SlotStrings[GETITEM_IDX] = PyString_InternFromString("__getitem__");
+    SlotStrings[SETITEM_IDX] = PyString_InternFromString("__setitem__");
+    SlotStrings[DELITEM_IDX] = PyString_InternFromString("__delitem__");
+    SlotStrings[ITER_IDX] = PyString_InternFromString("__iter__");
+    SlotStrings[NEXT_IDX] = PyString_InternFromString("next");
+    SlotStrings[CONTAINS_IDX] = PyString_InternFromString("__contains__");
+    SlotStrings[CALL_IDX] = PyString_InternFromString("__call__");
+    SlotStrings[STR_IDX] = PyString_InternFromString("__str__");
 
     WrapperType.tp_base = ProxyType;
     WrapperType.tp_alloc = PyType_GenericAlloc;