[Zope3-checkins] CVS: Zope3/src/zope/app/container - _zope_app_container_contained.c:1.2

Jim Fulton jim at zope.com
Sun Sep 21 13:31:29 EDT 2003


Update of /cvs-repository/Zope3/src/zope/app/container
In directory cvs.zope.org:/tmp/cvs-serv13174/src/zope/app/container

Added Files:
	_zope_app_container_contained.c 
Log Message:
New extension for implemementing container proxies. These are
persistent proxies that provide __parent__ and __name__ attributes.


=== Zope3/src/zope/app/container/_zope_app_container_contained.c 1.1 => 1.2 ===
--- /dev/null	Sun Sep 21 13:31:29 2003
+++ Zope3/src/zope/app/container/_zope_app_container_contained.c	Sun Sep 21 13:31:28 2003
@@ -0,0 +1,311 @@
+/*############################################################################
+#
+# 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.
+#
+############################################################################*/
+
+#include "Python.h"
+#include "persistence/persistence.h"
+#include "persistence/persistenceAPI.h"
+
+typedef struct {
+  PyPersist_HEAD                 
+  PyObject *po_serial;            
+  PyObject *po_weaklist;          
+  PyObject *proxy_object;
+  PyObject *__parent__;
+  PyObject *__name__;
+} ProxyObject;
+
+typedef struct {
+    PyTypeObject *proxytype;
+    int (*check)(PyObject *obj);
+    PyObject *(*create)(PyObject *obj);
+    PyObject *(*getobject)(PyObject *proxy);
+} ProxyInterface;
+
+#define Proxy_GET_OBJECT(ob)   (((ProxyObject *)(ob))->proxy_object)
+
+/* Supress inclusion of the original proxy.h */
+#define _proxy_H_ 1
+
+/* Incude the proxy C source */
+#include "zope/proxy/_zope_proxy_proxy.c"
+
+#define SPECIAL(NAME) (                        \
+    *(NAME) == '_' &&                          \
+      (((NAME)[1] == 'p' && (NAME)[2] == '_')  \
+       ||                                      \
+       ((NAME)[1] == '_' && (                  \
+         strcmp((NAME), "__parent__") == 0     \
+         ||                                    \
+         strcmp((NAME), "__name__") == 0       \
+         ||                                    \
+         strcmp((NAME), "__getstate__") == 0   \
+         ||                                    \
+         strcmp((NAME), "__setstate__") == 0   \
+         ||                                    \
+         strcmp((NAME), "__getnewargs__") == 0 \
+         ||                                    \
+         strcmp((NAME), "__reduce__") == 0     \
+         ||                                    \
+         strcmp((NAME), "__reduce_ex__") == 0  \
+         ))                                    \
+       ))
+      
+static PyObject *
+CP_getattro(PyObject *self, PyObject *name)
+{
+  char *cname;
+
+  cname = PyString_AsString(name);
+  if (cname == NULL)
+    return NULL;
+
+  if (SPECIAL(cname))
+    /* delegate to persistent */
+    return PyPersist_TYPE->tp_getattro(self, name);
+
+  /* Use the wrapper version to delegate */
+  return wrap_getattro(self, name);
+}
+
+static int
+CP_setattro(PyObject *self, PyObject *name, PyObject *v)
+{
+  char *cname;
+
+  cname = PyString_AsString(name);
+  if (cname == NULL)
+    return -1;
+
+  if (SPECIAL(cname))
+    /* delegate to persistent */
+    return PyPersist_TYPE->tp_setattro(self, name, v);
+
+  /* Use the wrapper version to delegate */
+  return wrap_setattro(self, name, v);
+}
+
+static PyObject *
+CP_getstate(ProxyObject *self)
+{
+  return Py_BuildValue("OO", 
+                       self->__parent__ ? self->__parent__ : Py_None,
+                       self->__name__   ? self->__name__   : Py_None
+                       );
+}
+
+static PyObject *
+CP_getnewargs(ProxyObject *self)
+{
+  return Py_BuildValue("(O)", self->proxy_object);
+}
+
+static PyObject *
+CP_setstate(ProxyObject *self, PyObject *state)
+{
+  if(! PyArg_ParseTuple(state, "OO", &self->__parent__, &self->__name__))
+    return NULL;
+  Py_INCREF(self->__parent__);
+  Py_INCREF(self->__name__);
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+
+static PyObject *
+CP_reduce(ProxyObject *self)
+{
+  return Py_BuildValue("O(O)(OO)",
+                       self->ob_type,
+                       self->proxy_object,
+                       self->__parent__ ? self->__parent__ : Py_None,
+                       self->__name__   ? self->__name__   : Py_None
+                       );
+}
+
+static PyObject *
+CP_reduce_ex(ProxyObject *self, PyObject *proto)
+{
+  return CP_reduce(self);
+}
+
+static PyObject *
+CP__p_deactivate(ProxyObject *self, PyObject *args, PyObject *keywords)
+{
+    int ghostify = 1;
+    PyObject *force = NULL;
+
+    if (args && PyTuple_GET_SIZE(args) > 0) {
+	PyErr_SetString(PyExc_TypeError, 
+			"_p_deactivate takes not positional arguments");
+	return NULL;
+    }
+    if (keywords) {
+	int size = PyDict_Size(keywords);
+	force = PyDict_GetItemString(keywords, "force");
+	if (force)
+	    size--;
+	if (size) {
+	    PyErr_SetString(PyExc_TypeError, 
+			    "_p_deactivate only accepts keyword arg force");
+	    return NULL;
+	}
+    }
+
+    if (self->po_dm && self->po_oid) {
+	ghostify = self->po_state == UPTODATE;
+	if (!ghostify && force) {
+	    if (PyObject_IsTrue(force))
+		ghostify = 1;
+	    if (PyErr_Occurred())
+		return NULL;
+	}
+	if (ghostify) {
+            Py_XDECREF(self->__parent__);
+            self->__parent__ = NULL;
+            Py_XDECREF(self->__name__);
+            self->__name__ = NULL;
+
+	    self->po_state = GHOST;
+	}
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+
+static PyMethodDef
+CP_methods[] = {
+  {"__getstate__", (PyCFunction)CP_getstate, METH_NOARGS, 
+   "Get the object state"},
+  {"__setstate__", (PyCFunction)CP_setstate, METH_O, 
+   "Set the object state"},
+  {"__getnewargs__", (PyCFunction)CP_getnewargs, METH_NOARGS, 
+   "Get the arguments that must be passed to __new__"},
+  {"__reduce__", (PyCFunction)CP_reduce, METH_NOARGS, 
+   "Reduce the object to constituent parts."},
+  {"__reduce_ex__", (PyCFunction)CP_reduce_ex, METH_O, 
+   "Reduce the object to constituent parts."},
+  {"_p_deactivate", (PyCFunction)CP__p_deactivate, METH_KEYWORDS, 
+   "Deactivate the object."},
+  {NULL, NULL},
+};
+
+
+/* Code to access structure members by accessing attributes */
+
+#include "structmember.h"
+
+static PyMemberDef CP_members[] = {
+  {"_p_serial", T_OBJECT, offsetof(ProxyObject, po_serial)},
+  {"__parent__", T_OBJECT, offsetof(ProxyObject, __parent__)},
+  {"__name__", T_OBJECT, offsetof(ProxyObject, __name__)},
+  {NULL}	/* Sentinel */
+};
+
+static int
+CP_traverse(ProxyObject *self, visitproc visit, void *arg)
+{
+  if (PyPersist_TYPE->tp_traverse((PyObject *)self, visit, arg) < 0)
+    return -1;
+  if (self->po_serial != NULL && visit(self->po_serial, arg) < 0)
+    return -1;
+  if (self->proxy_object != NULL && visit(self->proxy_object, arg) < 0)
+    return -1;
+  if (self->__parent__ != NULL && visit(self->__parent__, arg) < 0)
+    return -1;
+  if (self->__name__ != NULL && visit(self->__name__, arg) < 0)
+    return -1;
+  
+  return 0;
+}
+
+static int
+CP_clear(ProxyObject *self)
+{
+  /* XXXX Drop references that may have created reference
+     cycles. Immutable objects do not have to define this method
+     since they can never directly create reference cycles. Note
+     that the object must still be valid after calling this
+     method (don't just call Py_DECREF() on a reference). The
+     collector will call this method if it detects that this
+     object is involved in a reference cycle.
+  */
+  PyPersist_TYPE->tp_clear((PyObject*)self);
+
+  Py_XDECREF(self->po_serial);
+  self->po_serial = NULL;
+  Py_XDECREF(self->proxy_object);
+  self->proxy_object = NULL;
+  Py_XDECREF(self->__parent__);
+  self->__parent__ = NULL;
+  Py_XDECREF(self->__name__);
+  self->__name__ = NULL;
+  return 0;
+}
+
+static void
+CP_dealloc(ProxyObject *self)
+{
+  if (self->po_weaklist != NULL)
+    PyObject_ClearWeakRefs((PyObject *)self);
+
+  PyObject_GC_UnTrack((PyObject *)self);
+  CP_clear(self);
+  self->ob_type->tp_free((PyObject*)self);
+}
+
+#ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
+#define PyMODINIT_FUNC void
+#endif
+PyMODINIT_FUNC
+init_zope_app_container_contained(void)
+{
+  PyObject *m;
+        
+  /* Try to fake out compiler nag function */
+  if (0) init_zope_proxy_proxy();
+  
+  m = Py_InitModule3("_zope_app_container_contained", 
+                     module_functions, module___doc__);
+
+  if (m == NULL)
+    return;
+
+  if (empty_tuple == NULL)
+    empty_tuple = PyTuple_New(0);
+
+  /* Initialize the PyPersist_C_API and the type objects. */
+  PyPersist_C_API = PyCObject_Import("persistence._persistence", "C_API");
+  if (PyPersist_C_API == NULL)
+    return;
+
+  
+  ProxyType.tp_name = "zope.app.container.contained.ContainedProxyBase";
+  ProxyType.ob_type = &PyType_Type;
+  ProxyType.tp_base = PyPersist_TYPE;
+  ProxyType.tp_getattro = CP_getattro;
+  ProxyType.tp_setattro = CP_setattro;
+  ProxyType.tp_members = CP_members;
+  ProxyType.tp_methods = CP_methods;
+  ProxyType.tp_traverse = (traverseproc) CP_traverse;
+  ProxyType.tp_clear = (inquiry) CP_clear;
+  ProxyType.tp_dealloc = (destructor) CP_dealloc;
+  ProxyType.tp_weaklistoffset = offsetof(ProxyObject, po_weaklist);
+
+  if (PyType_Ready(&ProxyType) < 0)
+    return;
+
+  Py_INCREF(&ProxyType);
+  PyModule_AddObject(m, "ContainedProxyBase", (PyObject *)&ProxyType);
+}




More information about the Zope3-Checkins mailing list