[Zope-Checkins] CVS: Zope3/lib/python/Zope/ContextWrapper - proxy.c:1.1.2.1 proxy.h:1.1.2.1
Fred L. Drake, Jr.
fdrake@acm.org
Thu, 25 Apr 2002 15:10:30 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/ContextWrapper
In directory cvs.zope.org:/tmp/cvs-serv322
Added Files:
Tag: SecurityProxy-branch
proxy.c proxy.h
Log Message:
First cut at a proxy base class.
=== Added File Zope3/lib/python/Zope/ContextWrapper/proxy.c ===
#include "Python.h"
#include "modsupport.h"
#define PROXY_MODULE
#include "proxy.h"
staticforward PyTypeObject ProxyType;
#define Proxy_Check(wrapper) \
(((wrapper)->ob_type == &ProxyType) \
|| (PyObject_TypeCheck(wrapper, &ProxyType)))
static PyObject *
empty_tuple = NULL;
/*
* Slot methods.
*/
static int
wrap_init(PyObject *self, PyObject *args, PyObject *kwds)
{
int result = -1;
PyObject *object;
if (PyArg_UnpackTuple(args, "__init__", 1, 1, &object)) {
ProxyObject *wrapper = (ProxyObject *)self;
if (PyType_Type.tp_init(self, empty_tuple, NULL) < 0)
goto finally;
Py_INCREF(object);
wrapper->proxy_object = object;
result = 0;
}
finally:
return result;
}
static int
wrap_traverse(PyObject *self, visitproc visit, void *arg)
{
PyObject *ob = Proxy_GET_OBJECT(self);
if (ob != NULL)
return visit(ob, arg);
else
return 0;
}
static int
wrap_clear(PyObject *self)
{
ProxyObject *proxy = (ProxyObject *)self;
PyObject *temp = proxy->proxy_object;
if (temp != NULL) {
proxy->proxy_object = NULL;
Py_DECREF(temp);
}
return 0;
}
static PyObject *
wrap_richcompare(PyObject* self, PyObject* other, int op)
{
if (Proxy_Check(self)) {
self = Proxy_GET_OBJECT(self);
}
else {
other = Proxy_GET_OBJECT(other);
}
return PyObject_RichCompare(self, other, op);
}
static PyObject *
wrap_iter(PyObject *self)
{
return PyObject_GetIter(Proxy_GET_OBJECT(self));
}
static void
wrap_dealloc(PyObject *self)
{
(void) wrap_clear(self);
self->ob_type->tp_free(self);
}
static PyObject *
wrap_getattro(PyObject *self, PyObject *name)
{
return PyObject_GetAttr(Proxy_GET_OBJECT(self), name);
}
static int
wrap_setattro(PyObject *self, PyObject *name, PyObject *value)
{
if (Proxy_GET_OBJECT(self) != NULL)
return PyObject_SetAttr(Proxy_GET_OBJECT(self), name, value);
PyErr_Format(PyExc_RuntimeError,
"object is NULL; requested to set attribute '%s'",
PyString_AS_STRING(name));
return -1;
}
static int
wrap_print(PyObject *wrapper, FILE *fp, int flags)
{
return PyObject_Print(Proxy_GET_OBJECT(wrapper), fp, flags);
}
static PyObject *
wrap_str(PyObject *wrapper) {
return PyObject_Str(Proxy_GET_OBJECT(wrapper));
}
static PyObject *
wrap_repr(PyObject *wrapper)
{
return PyObject_Repr(Proxy_GET_OBJECT(wrapper));
}
static int
wrap_setattr(PyObject *wrapper, PyObject *name, PyObject *value)
{
return PyObject_SetAttr(Proxy_GET_OBJECT(wrapper), name, value);
}
static int
wrap_compare(PyObject *wrapper, PyObject *v)
{
return PyObject_Compare(Proxy_GET_OBJECT(wrapper), v);
}
static long
wrap_hash(PyObject *self)
{
return PyObject_Hash(Proxy_GET_OBJECT(self));
}
static PyObject *
wrap_call(PyObject *self, PyObject *args, PyObject *kw)
{
if (kw)
return PyEval_CallObjectWithKeywords(Proxy_GET_OBJECT(self),
args, kw);
else
return PyObject_CallObject(Proxy_GET_OBJECT(self), args);
}
/*
* Number methods
*/
static int
wrap_nonzero(PyObject *self)
{
return PyObject_IsTrue(Proxy_GET_OBJECT(self));
}
/*
* Sequence methods
*/
static int
wrap_length(PyObject *self)
{
return PyObject_Length(Proxy_GET_OBJECT(self));
}
static PyObject *
wrap_slice(PyObject *self, int start, int end)
{
return PySequence_GetSlice(Proxy_GET_OBJECT(self), start, end);
}
static int
wrap_ass_slice(PyObject *self, int i, int j, PyObject *value)
{
return PySequence_SetSlice(Proxy_GET_OBJECT(self), i, j, value);
}
static int
wrap_contains(PyObject *self, PyObject *value)
{
return PySequence_Contains(Proxy_GET_OBJECT(self), value);
}
/*
* Mapping methods
*/
static PyObject *
wrap_getitem(PyObject *wrapper, PyObject *v) {
return PyObject_GetItem(Proxy_GET_OBJECT(wrapper), v);
}
static int
wrap_setitem(PyObject *self, PyObject *key, PyObject *value)
{
return PyObject_SetItem(Proxy_GET_OBJECT(self), key, value);
}
/*
* Normal methods
*/
static char
reduce__doc__[] =
"__reduce__()\n"
"Raise an exception; this prevents proxies from being picklable by\n"
"default, even if the underlying object is picklable.";
static PyObject *
wrap_reduce(PyObject *self)
{
PyObject *pickle_error = NULL;
PyObject *pickle = PyImport_ImportModule("pickle");
if (pickle == NULL)
PyErr_Clear();
else {
pickle_error = PyObject_GetAttrString(pickle, "PicklingError");
if (pickle_error == NULL)
PyErr_Clear();
}
if (pickle_error == NULL) {
pickle_error = PyExc_RuntimeError;
Py_INCREF(pickle_error);
}
PyErr_SetString(pickle_error,
"proxy instances cannot be pickled");
Py_DECREF(pickle_error);
return NULL;
}
static PyNumberMethods
wrap_as_number = {
0, /* nb_add */
0, /* nb_subtract */
0, /* nb_multiply */
0, /* nb_divide */
0, /* nb_remainder */
0, /* nb_divmod */
0, /* nb_power */
0, /* nb_negative */
0, /* nb_positive */
0, /* nb_absolute */
wrap_nonzero, /* nb_nonzero */
};
static PySequenceMethods
wrap_as_sequence = {
wrap_length, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
0, /* sq_item */
wrap_slice, /* sq_slice */
0, /* sq_ass_item */
wrap_ass_slice, /* sq_ass_slice */
wrap_contains, /* sq_contains */
};
static PyMappingMethods
wrap_as_mapping = {
wrap_length, /* mp_length */
wrap_getitem, /* mp_subscript */
wrap_setitem, /* mp_ass_subscript */
};
static PyMethodDef
wrap_methods[] = {
{"__reduce__", (PyCFunction)wrap_reduce, METH_NOARGS, reduce__doc__},
{NULL, NULL},
};
/*
* Note that the numeric methods are not supported. This is primarily
* because of the way coercion-less operations are performed with
* new-style numbers; since we can't tell which side of the operation
* is 'self', we can't ensure we'd unwrap the right thing to perform
* the actual operation. We also can't afford to just unwrap both
* sides the way weakrefs do, since we don't know what semantics will
* be associated with the wrapper itself.
*/
statichere PyTypeObject
ProxyType = {
PyObject_HEAD_INIT(NULL)
0,
"proxy.proxy",
sizeof(ProxyObject),
0,
wrap_dealloc, /* tp_dealloc */
wrap_print, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
wrap_compare, /* tp_compare */
wrap_repr, /* tp_repr */
&wrap_as_number, /* tp_as_number */
&wrap_as_sequence, /* tp_as_sequence */
&wrap_as_mapping, /* tp_as_mapping */
wrap_hash, /* tp_hash */
wrap_call, /* tp_call */
wrap_str, /* tp_str */
wrap_getattro, /* tp_getattro */
wrap_setattro, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
| Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
wrap_traverse, /* tp_traverse */
wrap_clear, /* tp_clear */
wrap_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
wrap_iter, /* tp_iter */
0, /* tp_iternext */
wrap_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
wrap_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
_PyObject_GC_Del, /* tp_free */
};
static PyObject *
create_proxy(PyObject *object)
{
PyObject *result = NULL;
PyObject *args;
args = PyTuple_New(1);
if (args != NULL) {
Py_INCREF(object);
PyTuple_SET_ITEM(args, 0, object);
result = PyObject_CallObject((PyObject *)&ProxyType, args);
Py_DECREF(args);
}
return result;
}
static int
api_check(PyObject *obj)
{
return obj ? Proxy_Check(obj) : 0;
}
static PyObject *
api_create(PyObject *object)
{
if (object == NULL) {
PyErr_SetString(PyExc_ValueError,
"cannot create proxy around NULL");
return NULL;
}
return create_proxy(object);
}
static PyObject *
api_getobject(PyObject *proxy)
{
if (proxy == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"cannot pass NULL to ProxyAPI.getobject()");
return NULL;
}
if (Proxy_Check(proxy))
return Proxy_GET_OBJECT(proxy);
else {
PyErr_Format(PyExc_TypeError, "expected proxy object, got %s",
proxy->ob_type->tp_name);
return NULL;
}
}
static ProxyInterface
wrapper_capi = {
&ProxyType,
api_check,
api_create,
api_getobject,
};
static PyObject *api_object = NULL;
static char
getobject__doc__[] =
"getobject(proxy) --> object\n"
"\n"
"Return the underlying object for proxy, or raise TypeError if it is\n"
"not a proxy.";
static PyObject *
wrapper_getobject(PyObject *unused, PyObject *obj)
{
PyObject *result = NULL;
if (Proxy_Check(obj)) {
result = Proxy_GET_OBJECT(obj);
Py_INCREF(result);
}
else
PyErr_Format(PyExc_TypeError,
"expected proxy, got %s", obj->ob_type->tp_name);
return result;
}
static PyMethodDef
module_functions[] = {
{"getobject", wrapper_getobject, METH_O, getobject__doc__},
{NULL}
};
static char
module___doc__[] =
"Association between an object, a context object, and a dictionary.\n\
\n\
The context object and dictionary give additional context information\n\
associated with a reference to the basic object. The wrapper objects\n\
act as proxies for the original object.";
void
initproxy(void)
{
PyObject *m = Py_InitModule3("proxy", module_functions, module___doc__);
if (m == NULL)
return;
if (empty_tuple == NULL)
empty_tuple = PyTuple_New(0);
ProxyType.ob_type = &PyType_Type;
if (PyType_Ready(&ProxyType) < 0)
return;
Py_INCREF(&ProxyType);
PyModule_AddObject(m, "proxy", (PyObject *)&ProxyType);
if (api_object == NULL) {
api_object = PyCObject_FromVoidPtr(&wrapper_capi, NULL);
if (api_object == NULL)
return;
}
Py_INCREF(api_object);
PyModule_AddObject(m, "_CAPI", api_object);
}
=== Added File Zope3/lib/python/Zope/ContextWrapper/proxy.h ===
#ifndef _proxy_H_
#define _proxy_H_ 1
typedef struct {
PyObject_HEAD
PyObject *proxy_object;
} ProxyObject;
#define Proxy_GET_OBJECT(ob) (((ProxyObject *)(ob))->proxy_object)
typedef struct {
PyTypeObject *proxytype;
int (*check)(PyObject *obj);
PyObject *(*create)(PyObject *obj);
PyObject *(*getobject)(PyObject *proxy);
} ProxyInterface;
#ifndef PROXY_MODULE
/* These are only defined in the public interface, and are not
* available within the module implementation. There we use the
* classic Python/C API only.
*/
static ProxyInterface *_proxy_api = NULL;
static int
Proxy_Import(void)
{
if (_proxy_api == NULL) {
PyObject *m = PyImport_ImportModule("Zope.ContextWrapper.proxy");
if (m != NULL) {
PyObject *tmp = PyObject_GetAttrString(m, "_CAPI");
if (tmp != NULL) {
if (PyCObject_Check(tmp))
_proxy_api = (ProxyInterface *)
PyCObject_AsVoidPtr(tmp);
Py_DECREF(tmp);
}
}
}
return (_proxy_api == NULL) ? -1 : 0;
}
#define ProxyType (_proxy_api->proxytype)
#define Proxy_Check(obj) (_proxy_api->check((obj)))
#define Proxy_New(obj) (_proxy_api->create((obj)))
#define Proxy_GetObject(proxy) (_proxy_api->getobject((proxy)))
#endif /* PROXY_MODULE */
#endif /* _proxy_H_ */