[Zope3-checkins] CVS: Zope3/src/zope/proxy/context - decorator.c:1.1 decorator.h:1.1

Steve Alexander steve@cat-box.net
Thu, 8 May 2003 06:57:00 -0400


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

Added Files:
	decorator.c decorator.h 
Log Message:
Add new decorator type, with tests.
Add this to the build directives in setup.py.



=== Added File Zope3/src/zope/proxy/context/decorator.c === (1003/1103 lines abridged)
#include <Python.h>
#include "structmember.h"
#include "modsupport.h"
#include "zope/proxy/proxy.h"
#include "zope/proxy/context/wrapper.h"
#define DECORATOR_MODULE
#include "zope/proxy/context/decorator.h"

/* XXX perhaps all these wrapper args should be renamed to decorator? */
/* XXX provides should probably be renamed to providedBy */
#define Decorator_Check(wrapper)  (PyObject_TypeCheck(wrapper, &DecoratorType))

#define Decorator_GetObject(wrapper) Proxy_GET_OBJECT((wrapper))

#define Decorator_GetMixinFactory(wrapper) \
    (((DecoratorObject *)wrapper)->mixin_factory)

#define Decorator_GetMixin(wrapper) \
    (((DecoratorObject *)wrapper)->mixin)

#define Decorator_GetNames(wrapper) \
    (((DecoratorObject *)wrapper)->names)

#define Decorator_GetNamesDict(wrapper) \
    (((DecoratorObject *)wrapper)->names_dict)

#define Decorator_GetProvides(wrapper) \
    (((DecoratorObject *)wrapper)->provides)

static PyTypeObject DecoratorType;

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[10];
#define LEN_IDX 0
#define NONZERO_IDX 1
#define GETITEM_IDX 2
#define SETITEM_IDX 3
#define DELITEM_IDX 4
#define ITER_IDX 5
#define NEXT_IDX 6
#define CONTAINS_IDX 7
#define CALL_IDX 8
#define STR_IDX 9

/* Helper for decorate_new/decorate_init; return the base class args tuple

[-=- -=- -=- 1003 lines omitted -=- -=- -=-]

";

static PyObject *api_object = NULL;

void
initdecorator(void)
{
    PyObject *m;

    if (Proxy_Import() < 0)
        return;

    if (Wrapper_Import() < 0)
        return;

    m = Py_InitModule3("decorator", module_functions, module___doc__);
    if (m == NULL)
        return;

    SlotStrings[LEN_IDX] = PyString_InternFromString("__len__");
    SlotStrings[NONZERO_IDX] = PyString_InternFromString("__nonzero__");
    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__");

    DecoratorType.tp_base = &WrapperType;
    DecoratorType.tp_alloc = PyType_GenericAlloc;
    DecoratorType.tp_free = _PyObject_GC_Del;
    if (PyType_Ready(&DecoratorType) < 0)
        return;

    Py_INCREF(&DecoratorType);
    PyModule_AddObject(m, "Decorator", (PyObject *)&DecoratorType);

    if (api_object == NULL) {
        api_object = PyCObject_FromVoidPtr(&decorator_capi, NULL);
        if (api_object == NULL)
            return;
    }
    Py_INCREF(api_object);
    PyModule_AddObject(m, "_CAPI", api_object);

    if (empty_tuple == NULL)
        empty_tuple = PyTuple_New(0);
}


=== Added File Zope3/src/zope/proxy/context/decorator.h ===
/* Decorator objects.
 *
 * This is intended for use with Python 2.2.
 *
 * Created by Steve Alexander and Marius Gedminas, 2003-May-7.
 */

#ifndef _decorator_H_
#define _decorator_H_

#ifndef _wrapper_H_
#include "zope/proxy/context/wrapper.h"
#endif

typedef struct {
    WrapperObject wrapperobject;
    PyObject *mixin_factory;
    PyObject *mixin;
    PyObject *names;
    PyObject *names_dict;
    PyObject *provides;
} DecoratorObject;

typedef struct {
    int (*check)(PyObject *obj);
    PyObject *(*create)(PyObject *object, PyObject *context,
        PyObject *mixin_factory, PyObject *names, PyObject *provides);
    PyObject *(*getmixin)(PyObject *wrapper);
    PyObject *(*getmixinfactory)(PyObject *wrapper);
    PyObject *(*getnames)(PyObject *wrapper);
    PyObject *(*getprovides)(PyObject *wrapper);
    int (*setprovides)(PyObject *wrapper, PyObject *provides);
} DecoratorInterface;


#ifndef DECORATOR_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 DecoratorInterface *_decorator_api = NULL;

static int
Decorator_Import(void)
{
    if (_decorator_api == NULL) {
        PyObject *m = PyImport_ImportModule("zope.proxy.context.decorator");
        if (m != NULL) {
            PyObject *tmp = PyObject_GetAttrString(m, "_CAPI");
            if (tmp != NULL) {
                if (PyCObject_Check(tmp))
                    _decorator_api = (DecoratorInterface *)
                        PyCObject_AsVoidPtr(tmp);
                Py_DECREF(tmp);
            }
        }
    }
    return (_decorator_api == NULL) ? -1 : 0;
}

#define Decorator_Check(obj)                                           \
        (_decorator_api->check((obj)))
#define Decorator_New(object, context, mixin_factory, names, provides) \
        (_decorator_api->create((object), (context), (mixin_factory),  \
                                (names), (provides)))
#define Decorator_GetMixin(wrapper)                                    \
        (_decorator_api->getmixin((wrapper)))
#define Decorator_GetMixinFactory(wrapper)                             \
        (_decorator_api->getmixinfactory((wrapper)))
#define Decorator_GetNames(wrapper)                                    \
        (_decorator_api->getnames((wrapper)))
#define Decorator_GetProvides(wrapper)                                 \
        (_decorator_api->getprovides((wrapper)))
#define Decorator_SetProvides(wrapper, provides)                       \
        (_decorator_api->setprovides((wrapper), (provides)))

#endif

#endif