[Checkins] SVN: zc.twist/trunk/ fix bug with slot methods of persistent objects. Prepare for 1.0.1.

Gary Poster gary at zope.com
Fri Mar 14 18:21:56 EDT 2008


Log message for revision 84653:
  fix bug with slot methods of persistent objects.  Prepare for 1.0.1.

Changed:
  U   zc.twist/trunk/CHANGES.txt
  U   zc.twist/trunk/setup.py
  U   zc.twist/trunk/src/zc/twist/README.txt
  U   zc.twist/trunk/src/zc/twist/__init__.py
  A   zc.twist/trunk/src/zc/twist/_methodwrapper.c

-=-
Modified: zc.twist/trunk/CHANGES.txt
===================================================================
--- zc.twist/trunk/CHANGES.txt	2008-03-14 11:01:44 UTC (rev 84652)
+++ zc.twist/trunk/CHANGES.txt	2008-03-14 22:21:54 UTC (rev 84653)
@@ -1,3 +1,9 @@
+1.0.1 (2008-3-14)
+-----------------
+
+* Bugfix: if you passed a slot method like a BTree.__setitem__, bad things
+  would happen.
+
 1.0.0 (2008-3-13)
 -----------------
 

Modified: zc.twist/trunk/setup.py
===================================================================
--- zc.twist/trunk/setup.py	2008-03-14 11:01:44 UTC (rev 84652)
+++ zc.twist/trunk/setup.py	2008-03-14 22:21:54 UTC (rev 84653)
@@ -1,14 +1,19 @@
-import os
 
+from distutils.extension import Extension
 from setuptools import setup, find_packages
 
 long_description = (open("src/zc/twist/README.txt").read() +
                     '\n\n=======\nChanges\n=======\n\n' +
                     open("CHANGES.txt").read())
 
+methodwrapper = Extension(
+    name='zc.twist._methodwrapper',
+    sources=['src/zc/twist/_methodwrapper.c'],
+    )
+
 setup(
     name='zc.twist',
-    version='1.0',
+    version='1.0.1',
     packages=find_packages('src'),
     package_dir={'':'src'},
     zip_safe=False,
@@ -27,4 +32,5 @@
         'zope.testing',
         ],
     include_package_data=True,
+    ext_modules=[methodwrapper],
     )

Modified: zc.twist/trunk/src/zc/twist/README.txt
===================================================================
--- zc.twist/trunk/src/zc/twist/README.txt	2008-03-14 11:01:44 UTC (rev 84652)
+++ zc.twist/trunk/src/zc/twist/README.txt	2008-03-14 22:21:54 UTC (rev 84653)
@@ -81,6 +81,19 @@
     >>> demo.count
     0
 
+This also works for slot methods.
+
+    >>> import BTrees
+    >>> tree = root['tree'] = BTrees.family32.OO.BTree()
+    >>> transaction.commit()
+    >>> call = Partial(tree.__setitem__, 'foo', 'bar')
+    >>> deferred = call()
+    >>> len(tree)
+    0
+    >>> t = transaction.begin()
+    >>> tree['foo']
+    'bar'
+
 Arguments are passed through.
 
     >>> call = Partial(demo)

Modified: zc.twist/trunk/src/zc/twist/__init__.py
===================================================================
--- zc.twist/trunk/src/zc/twist/__init__.py	2008-03-14 11:01:44 UTC (rev 84652)
+++ zc.twist/trunk/src/zc/twist/__init__.py	2008-03-14 22:21:54 UTC (rev 84653)
@@ -15,6 +15,15 @@
 import zope.component
 import zope.interface
 
+import zc.twist._methodwrapper
+
+METHOD_WRAPPER_TYPE = type({}.__setitem__)
+
+def get_self(wrapper):
+    if not isinstance(wrapper, METHOD_WRAPPER_TYPE):
+        raise TypeError('unsupported type') # includes dict.__getitem__ :-/
+    return zc.twist._methodwrapper._get_self(wrapper)
+
 EXPLOSIVE_ERRORS = [SystemExit, KeyboardInterrupt,
                     ZODB.POSException.POSError]
 
@@ -35,6 +44,9 @@
         if isinstance(obj, types.MethodType):
             self.name = obj.__name__
             obj = obj.im_self
+        elif isinstance(obj, METHOD_WRAPPER_TYPE):
+            self.name = obj.__name__
+            obj = get_self(obj)
         conn = ZODB.interfaces.IConnection(obj)
         self.db = conn.db()
         self.id = obj._p_oid
@@ -54,6 +66,13 @@
             return DeferredReferenceToPersistent(obj)
         else:
             return obj
+    if isinstance(obj, METHOD_WRAPPER_TYPE):
+        obj_self = get_self(obj)
+        if (persistent.interfaces.IPersistent.providedBy(obj_self) and
+            obj_self._p_jar is not None):
+            return DeferredReferenceToPersistent(obj)
+        else:
+            return obj
     if (persistent.interfaces.IPersistent.providedBy(obj)
         and obj._p_jar is not None):
         return DeferredReferenceToPersistent(obj)

Added: zc.twist/trunk/src/zc/twist/_methodwrapper.c
===================================================================
--- zc.twist/trunk/src/zc/twist/_methodwrapper.c	                        (rev 0)
+++ zc.twist/trunk/src/zc/twist/_methodwrapper.c	2008-03-14 22:21:54 UTC (rev 84653)
@@ -0,0 +1,42 @@
+#include <Python.h>
+
+// wrapperobject is not in a header.  Also see wrappertype comment.
+typedef struct {
+	PyObject_HEAD
+	PyWrapperDescrObject *descr;
+	PyObject *self;
+} wrapperobject;
+
+
+#define Wrapper_Check(obj) \
+	PyObject_TypeCheck(obj, &wrapperobject)
+
+static PyObject *
+module_getSelf(PyObject *self, PyObject *args)
+{
+  PyObject *wrapper;
+  PyObject *result;
+
+  if (!PyArg_ParseTuple(args, "O", &wrapper))
+    return NULL;
+// wrappertype is not in a header. :-(
+//  if (!PyObject_TypeCheck(wrapper, &wrappertype))
+//    result = Py_None; // Exception might be nice
+//  else
+    result = (PyObject*)((wrapperobject*)wrapper)->self;
+  
+  Py_INCREF(result);
+  return result;
+}
+
+static PyMethodDef MethodWrapperMethods[] = { 
+    {"_get_self", module_getSelf, METH_VARARGS, 
+    "get im_self of method wrapper.  NO CHECKS!"}, 
+    {NULL, NULL, 0, NULL} /* Sentinel */ 
+}; 
+
+PyMODINIT_FUNC 
+init_methodwrapper(void) 
+{ 
+    (void) Py_InitModule("_methodwrapper", MethodWrapperMethods); 
+} 


Property changes on: zc.twist/trunk/src/zc/twist/_methodwrapper.c
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Checkins mailing list