##// END OF EJS Templates
discovery: fix embarrassing typo in slice definition...
discovery: fix embarrassing typo in slice definition The code introduced in e514799e4e07 ended up having a silly bug. The indexing selected a single item slice picking only p1. The discovery result was still correct, but the sampling was hampered, sometime leading to much more round trips being performed. Fixing this issue restore the previous sampling behavior. This fix has a negative performance impact on the pathological case the previous test has been built. # parent of this changesets ! wall 5.313884 comb 5.310000 user 5.260000 sys 0.050000 (best of 5) ! wall 6.711860 comb 6.710000 user 6.670000 sys 0.040000 (max of 5) ! wall 5.844016 comb 5.842000 user 5.784000 sys 0.058000 (avg of 5) ! wall 5.778635 comb 5.780000 user 5.740000 sys 0.040000 (median of 5) # With this changesets. ! wall 6.350879 comb 6.350000 user 6.300000 sys 0.050000 (best of 5) ! wall 6.653647 comb 6.660000 user 6.480000 sys 0.180000 (max of 5) ! wall 6.492762 comb 6.494000 user 6.414000 sys 0.080000 (avg of 5) ! wall 6.547577 comb 6.550000 user 6.490000 sys 0.060000 (median of 5) Changeset e514799e4e07 raised the question of using the "_uncheckedparentrevs" instead of the current code. So I ran comparative timing: # old code: 55919b96c02a (e514799e4e07 parent) ! wall 64.078708 comb 64.080000 user 63.160000 sys 0.920000 (best of 5) ! wall 68.296300 comb 68.290000 user 67.410000 sys 0.880000 (max of 5) ! wall 65.899075 comb 65.894000 user 65.082000 sys 0.812000 (avg of 5) ! wall 66.140286 comb 66.130000 user 65.330000 sys 0.800000 (median of 5) # buggy code: e514799e4e07 ! wall 46.605362 comb 46.610000 user 45.880000 sys 0.730000 (best of 5) ! wall 48.619659 comb 48.620000 user 47.890000 sys 0.730000 (max of 5) ! wall 47.350247 comb 47.350000 user 46.672000 sys 0.678000 (avg of 5) ! wall 46.983224 comb 46.980000 user 46.350000 sys 0.630000 (median of 5) # fixed code: e514799e4e07 with this fix ! wall 55.858460 comb 55.850000 user 55.090000 sys 0.760000 (best of 5) ! wall 59.048805 comb 59.060000 user 58.110000 sys 0.950000 (max of 5) ! wall 57.192639 comb 57.192000 user 56.350000 sys 0.842000 (avg of 5) ! wall 57.056373 comb 57.060000 user 56.160000 sys 0.900000 (median of 5) # version using uncheckedparents ! wall 56.471916 comb 56.470000 user 55.630000 sys 0.840000 (best of 5) ! wall 58.228793 comb 58.230000 user 57.600000 sys 0.630000 (max of 5) ! wall 57.377583 comb 57.378000 user 56.674000 sys 0.704000 (avg of 5) ! wall 57.008843 comb 57.010000 user 56.330000 sys 0.680000 (median of 5) So it looks like the overhead from `_uncheckedparentrevs` is not that impactful. I'll investigate this shortly. I'm almost done updating our benchmark suite with more meaningful discovery cases.

File last commit:

r37195:68ee6182 default
r42145:0d467e4d default
Show More
_zope_interface_coptimizations.c
1727 lines | 44.9 KiB | text/x-c | CLexer
/ mercurial / thirdparty / zope / interface / _zope_interface_coptimizations.c
/*###########################################################################
#
# Copyright (c) 2003 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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 "structmember.h"
#define TYPE(O) ((PyTypeObject*)(O))
#define OBJECT(O) ((PyObject*)(O))
#define CLASSIC(O) ((PyClassObject*)(O))
#ifndef PyVarObject_HEAD_INIT
#define PyVarObject_HEAD_INIT(a, b) PyObject_HEAD_INIT(a) b,
#endif
#ifndef Py_TYPE
#define Py_TYPE(o) ((o)->ob_type)
#endif
#if PY_MAJOR_VERSION >= 3
#define PY3K
#endif
static PyObject *str__dict__, *str__implemented__, *strextends;
static PyObject *BuiltinImplementationSpecifications, *str__provides__;
static PyObject *str__class__, *str__providedBy__;
static PyObject *empty, *fallback, *str_implied, *str_cls, *str_implements;
static PyObject *str__conform__, *str_call_conform, *adapter_hooks;
static PyObject *str_uncached_lookup, *str_uncached_lookupAll;
static PyObject *str_uncached_subscriptions;
static PyObject *str_registry, *strro, *str_generation, *strchanged;
static PyTypeObject *Implements;
static int imported_declarations = 0;
static int
import_declarations(void)
{
PyObject *declarations, *i;
declarations = PyImport_ImportModule(
"mercurial.thirdparty.zope.interface.declarations");
if (declarations == NULL)
return -1;
BuiltinImplementationSpecifications = PyObject_GetAttrString(
declarations, "BuiltinImplementationSpecifications");
if (BuiltinImplementationSpecifications == NULL)
return -1;
empty = PyObject_GetAttrString(declarations, "_empty");
if (empty == NULL)
return -1;
fallback = PyObject_GetAttrString(declarations, "implementedByFallback");
if (fallback == NULL)
return -1;
i = PyObject_GetAttrString(declarations, "Implements");
if (i == NULL)
return -1;
if (! PyType_Check(i))
{
PyErr_SetString(PyExc_TypeError,
"zope.interface.declarations.Implements is not a type");
return -1;
}
Implements = (PyTypeObject *)i;
Py_DECREF(declarations);
imported_declarations = 1;
return 0;
}
static PyTypeObject SpecType; /* Forward */
static PyObject *
implementedByFallback(PyObject *cls)
{
if (imported_declarations == 0 && import_declarations() < 0)
return NULL;
return PyObject_CallFunctionObjArgs(fallback, cls, NULL);
}
static PyObject *
implementedBy(PyObject *ignored, PyObject *cls)
{
/* Fast retrieval of implements spec, if possible, to optimize
common case. Use fallback code if we get stuck.
*/
PyObject *dict = NULL, *spec;
if (PyType_Check(cls))
{
dict = TYPE(cls)->tp_dict;
Py_XINCREF(dict);
}
if (dict == NULL)
dict = PyObject_GetAttr(cls, str__dict__);
if (dict == NULL)
{
/* Probably a security proxied class, use more expensive fallback code */
PyErr_Clear();
return implementedByFallback(cls);
}
spec = PyObject_GetItem(dict, str__implemented__);
Py_DECREF(dict);
if (spec)
{
if (imported_declarations == 0 && import_declarations() < 0)
return NULL;
if (PyObject_TypeCheck(spec, Implements))
return spec;
/* Old-style declaration, use more expensive fallback code */
Py_DECREF(spec);
return implementedByFallback(cls);
}
PyErr_Clear();
/* Maybe we have a builtin */
if (imported_declarations == 0 && import_declarations() < 0)
return NULL;
spec = PyDict_GetItem(BuiltinImplementationSpecifications, cls);
if (spec != NULL)
{
Py_INCREF(spec);
return spec;
}
/* We're stuck, use fallback */
return implementedByFallback(cls);
}
static PyObject *
getObjectSpecification(PyObject *ignored, PyObject *ob)
{
PyObject *cls, *result;
result = PyObject_GetAttr(ob, str__provides__);
if (result != NULL && PyObject_TypeCheck(result, &SpecType))
return result;
PyErr_Clear();
/* We do a getattr here so as not to be defeated by proxies */
cls = PyObject_GetAttr(ob, str__class__);
if (cls == NULL)
{
PyErr_Clear();
if (imported_declarations == 0 && import_declarations() < 0)
return NULL;
Py_INCREF(empty);
return empty;
}
result = implementedBy(NULL, cls);
Py_DECREF(cls);
return result;
}
static PyObject *
providedBy(PyObject *ignored, PyObject *ob)
{
PyObject *result, *cls, *cp;
result = PyObject_GetAttr(ob, str__providedBy__);
if (result == NULL)
{
PyErr_Clear();
return getObjectSpecification(NULL, ob);
}
/* We want to make sure we have a spec. We can't do a type check
because we may have a proxy, so we'll just try to get the
only attribute.
*/
if (PyObject_TypeCheck(result, &SpecType)
||
PyObject_HasAttr(result, strextends)
)
return result;
/*
The object's class doesn't understand descriptors.
Sigh. We need to get an object descriptor, but we have to be
careful. We want to use the instance's __provides__,l if
there is one, but only if it didn't come from the class.
*/
Py_DECREF(result);
cls = PyObject_GetAttr(ob, str__class__);
if (cls == NULL)
return NULL;
result = PyObject_GetAttr(ob, str__provides__);
if (result == NULL)
{
/* No __provides__, so just fall back to implementedBy */
PyErr_Clear();
result = implementedBy(NULL, cls);
Py_DECREF(cls);
return result;
}
cp = PyObject_GetAttr(cls, str__provides__);
if (cp == NULL)
{
/* The the class has no provides, assume we're done: */
PyErr_Clear();
Py_DECREF(cls);
return result;
}
if (cp == result)
{
/*
Oops, we got the provides from the class. This means
the object doesn't have it's own. We should use implementedBy
*/
Py_DECREF(result);
result = implementedBy(NULL, cls);
}
Py_DECREF(cls);
Py_DECREF(cp);
return result;
}
/*
Get an attribute from an inst dict. Return a borrowed reference.
This has a number of advantages:
- It avoids layers of Python api
- It doesn't waste time looking for descriptors
- It fails wo raising an exception, although that shouldn't really
matter.
*/
static PyObject *
inst_attr(PyObject *self, PyObject *name)
{
PyObject **dictp, *v;
dictp = _PyObject_GetDictPtr(self);
if (dictp && *dictp && (v = PyDict_GetItem(*dictp, name)))
return v;
PyErr_SetObject(PyExc_AttributeError, name);
return NULL;
}
static PyObject *
Spec_extends(PyObject *self, PyObject *other)
{
PyObject *implied;
implied = inst_attr(self, str_implied);
if (implied == NULL)
return NULL;
#ifdef Py_True
if (PyDict_GetItem(implied, other) != NULL)
{
Py_INCREF(Py_True);
return Py_True;
}
Py_INCREF(Py_False);
return Py_False;
#else
return PyInt_FromLong(PyDict_GetItem(implied, other) != NULL);
#endif
}
static char Spec_extends__doc__[] =
"Test whether a specification is or extends another"
;
static char Spec_providedBy__doc__[] =
"Test whether an interface is implemented by the specification"
;
static PyObject *
Spec_call(PyObject *self, PyObject *args, PyObject *kw)
{
PyObject *spec;
if (! PyArg_ParseTuple(args, "O", &spec))
return NULL;
return Spec_extends(self, spec);
}
static PyObject *
Spec_providedBy(PyObject *self, PyObject *ob)
{
PyObject *decl, *item;
decl = providedBy(NULL, ob);
if (decl == NULL)
return NULL;
if (PyObject_TypeCheck(decl, &SpecType))
item = Spec_extends(decl, self);
else
/* decl is probably a security proxy. We have to go the long way
around.
*/
item = PyObject_CallFunctionObjArgs(decl, self, NULL);
Py_DECREF(decl);
return item;
}
static char Spec_implementedBy__doc__[] =
"Test whether the specification is implemented by a class or factory.\n"
"Raise TypeError if argument is neither a class nor a callable."
;
static PyObject *
Spec_implementedBy(PyObject *self, PyObject *cls)
{
PyObject *decl, *item;
decl = implementedBy(NULL, cls);
if (decl == NULL)
return NULL;
if (PyObject_TypeCheck(decl, &SpecType))
item = Spec_extends(decl, self);
else
item = PyObject_CallFunctionObjArgs(decl, self, NULL);
Py_DECREF(decl);
return item;
}
static struct PyMethodDef Spec_methods[] = {
{"providedBy",
(PyCFunction)Spec_providedBy, METH_O,
Spec_providedBy__doc__},
{"implementedBy",
(PyCFunction)Spec_implementedBy, METH_O,
Spec_implementedBy__doc__},
{"isOrExtends", (PyCFunction)Spec_extends, METH_O,
Spec_extends__doc__},
{NULL, NULL} /* sentinel */
};
static PyTypeObject SpecType = {
PyVarObject_HEAD_INIT(NULL, 0)
/* tp_name */ "_interface_coptimizations."
"SpecificationBase",
/* tp_basicsize */ 0,
/* tp_itemsize */ 0,
/* tp_dealloc */ (destructor)0,
/* tp_print */ (printfunc)0,
/* tp_getattr */ (getattrfunc)0,
/* tp_setattr */ (setattrfunc)0,
/* tp_compare */ 0,
/* tp_repr */ (reprfunc)0,
/* tp_as_number */ 0,
/* tp_as_sequence */ 0,
/* tp_as_mapping */ 0,
/* tp_hash */ (hashfunc)0,
/* tp_call */ (ternaryfunc)Spec_call,
/* tp_str */ (reprfunc)0,
/* tp_getattro */ (getattrofunc)0,
/* tp_setattro */ (setattrofunc)0,
/* tp_as_buffer */ 0,
/* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
"Base type for Specification objects",
/* tp_traverse */ (traverseproc)0,
/* tp_clear */ (inquiry)0,
/* tp_richcompare */ (richcmpfunc)0,
/* tp_weaklistoffset */ (long)0,
/* tp_iter */ (getiterfunc)0,
/* tp_iternext */ (iternextfunc)0,
/* tp_methods */ Spec_methods,
};
static PyObject *
OSD_descr_get(PyObject *self, PyObject *inst, PyObject *cls)
{
PyObject *provides;
if (inst == NULL)
return getObjectSpecification(NULL, cls);
provides = PyObject_GetAttr(inst, str__provides__);
if (provides != NULL)
return provides;
PyErr_Clear();
return implementedBy(NULL, cls);
}
static PyTypeObject OSDType = {
PyVarObject_HEAD_INIT(NULL, 0)
/* tp_name */ "_interface_coptimizations."
"ObjectSpecificationDescriptor",
/* tp_basicsize */ 0,
/* tp_itemsize */ 0,
/* tp_dealloc */ (destructor)0,
/* tp_print */ (printfunc)0,
/* tp_getattr */ (getattrfunc)0,
/* tp_setattr */ (setattrfunc)0,
/* tp_compare */ 0,
/* tp_repr */ (reprfunc)0,
/* tp_as_number */ 0,
/* tp_as_sequence */ 0,
/* tp_as_mapping */ 0,
/* tp_hash */ (hashfunc)0,
/* tp_call */ (ternaryfunc)0,
/* tp_str */ (reprfunc)0,
/* tp_getattro */ (getattrofunc)0,
/* tp_setattro */ (setattrofunc)0,
/* tp_as_buffer */ 0,
/* tp_flags */ Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE ,
"Object Specification Descriptor",
/* tp_traverse */ (traverseproc)0,
/* tp_clear */ (inquiry)0,
/* tp_richcompare */ (richcmpfunc)0,
/* tp_weaklistoffset */ (long)0,
/* tp_iter */ (getiterfunc)0,
/* tp_iternext */ (iternextfunc)0,
/* tp_methods */ 0,
/* tp_members */ 0,
/* tp_getset */ 0,
/* tp_base */ 0,
/* tp_dict */ 0, /* internal use */
/* tp_descr_get */ (descrgetfunc)OSD_descr_get,
};
static PyObject *
CPB_descr_get(PyObject *self, PyObject *inst, PyObject *cls)
{
PyObject *mycls, *implements;
mycls = inst_attr(self, str_cls);
if (mycls == NULL)
return NULL;
if (cls == mycls)
{
if (inst == NULL)
{
Py_INCREF(self);
return OBJECT(self);
}
implements = inst_attr(self, str_implements);
Py_XINCREF(implements);
return implements;
}
PyErr_SetObject(PyExc_AttributeError, str__provides__);
return NULL;
}
static PyTypeObject CPBType = {
PyVarObject_HEAD_INIT(NULL, 0)
/* tp_name */ "_interface_coptimizations."
"ClassProvidesBase",
/* tp_basicsize */ 0,
/* tp_itemsize */ 0,
/* tp_dealloc */ (destructor)0,
/* tp_print */ (printfunc)0,
/* tp_getattr */ (getattrfunc)0,
/* tp_setattr */ (setattrfunc)0,
/* tp_compare */ 0,
/* tp_repr */ (reprfunc)0,
/* tp_as_number */ 0,
/* tp_as_sequence */ 0,
/* tp_as_mapping */ 0,
/* tp_hash */ (hashfunc)0,
/* tp_call */ (ternaryfunc)0,
/* tp_str */ (reprfunc)0,
/* tp_getattro */ (getattrofunc)0,
/* tp_setattro */ (setattrofunc)0,
/* tp_as_buffer */ 0,
/* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
"C Base class for ClassProvides",
/* tp_traverse */ (traverseproc)0,
/* tp_clear */ (inquiry)0,
/* tp_richcompare */ (richcmpfunc)0,
/* tp_weaklistoffset */ (long)0,
/* tp_iter */ (getiterfunc)0,
/* tp_iternext */ (iternextfunc)0,
/* tp_methods */ 0,
/* tp_members */ 0,
/* tp_getset */ 0,
/* tp_base */ &SpecType,
/* tp_dict */ 0, /* internal use */
/* tp_descr_get */ (descrgetfunc)CPB_descr_get,
};
/* ==================================================================== */
/* ========== Begin: __call__ and __adapt__ =========================== */
/*
def __adapt__(self, obj):
"""Adapt an object to the reciever
"""
if self.providedBy(obj):
return obj
for hook in adapter_hooks:
adapter = hook(self, obj)
if adapter is not None:
return adapter
*/
static PyObject *
__adapt__(PyObject *self, PyObject *obj)
{
PyObject *decl, *args, *adapter;
int implements, i, l;
decl = providedBy(NULL, obj);
if (decl == NULL)
return NULL;
if (PyObject_TypeCheck(decl, &SpecType))
{
PyObject *implied;
implied = inst_attr(decl, str_implied);
if (implied == NULL)
{
Py_DECREF(decl);
return NULL;
}
implements = PyDict_GetItem(implied, self) != NULL;
Py_DECREF(decl);
}
else
{
/* decl is probably a security proxy. We have to go the long way
around.
*/
PyObject *r;
r = PyObject_CallFunctionObjArgs(decl, self, NULL);
Py_DECREF(decl);
if (r == NULL)
return NULL;
implements = PyObject_IsTrue(r);
Py_DECREF(r);
}
if (implements)
{
Py_INCREF(obj);
return obj;
}
l = PyList_GET_SIZE(adapter_hooks);
args = PyTuple_New(2);
if (args == NULL)
return NULL;
Py_INCREF(self);
PyTuple_SET_ITEM(args, 0, self);
Py_INCREF(obj);
PyTuple_SET_ITEM(args, 1, obj);
for (i = 0; i < l; i++)
{
adapter = PyObject_CallObject(PyList_GET_ITEM(adapter_hooks, i), args);
if (adapter == NULL || adapter != Py_None)
{
Py_DECREF(args);
return adapter;
}
Py_DECREF(adapter);
}
Py_DECREF(args);
Py_INCREF(Py_None);
return Py_None;
}
static struct PyMethodDef ib_methods[] = {
{"__adapt__", (PyCFunction)__adapt__, METH_O,
"Adapt an object to the reciever"},
{NULL, NULL} /* sentinel */
};
/*
def __call__(self, obj, alternate=_marker):
conform = getattr(obj, '__conform__', None)
if conform is not None:
adapter = self._call_conform(conform)
if adapter is not None:
return adapter
adapter = self.__adapt__(obj)
if adapter is not None:
return adapter
elif alternate is not _marker:
return alternate
else:
raise TypeError("Could not adapt", obj, self)
*/
static PyObject *
ib_call(PyObject *self, PyObject *args, PyObject *kwargs)
{
PyObject *conform, *obj, *alternate=NULL, *adapter;
static char *kwlist[] = {"obj", "alternate", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist,
&obj, &alternate))
return NULL;
conform = PyObject_GetAttr(obj, str__conform__);
if (conform != NULL)
{
adapter = PyObject_CallMethodObjArgs(self, str_call_conform,
conform, NULL);
Py_DECREF(conform);
if (adapter == NULL || adapter != Py_None)
return adapter;
Py_DECREF(adapter);
}
else
PyErr_Clear();
adapter = __adapt__(self, obj);
if (adapter == NULL || adapter != Py_None)
return adapter;
Py_DECREF(adapter);
if (alternate != NULL)
{
Py_INCREF(alternate);
return alternate;
}
adapter = Py_BuildValue("sOO", "Could not adapt", obj, self);
if (adapter != NULL)
{
PyErr_SetObject(PyExc_TypeError, adapter);
Py_DECREF(adapter);
}
return NULL;
}
static PyTypeObject InterfaceBase = {
PyVarObject_HEAD_INIT(NULL, 0)
/* tp_name */ "_zope_interface_coptimizations."
"InterfaceBase",
/* tp_basicsize */ 0,
/* tp_itemsize */ 0,
/* tp_dealloc */ (destructor)0,
/* tp_print */ (printfunc)0,
/* tp_getattr */ (getattrfunc)0,
/* tp_setattr */ (setattrfunc)0,
/* tp_compare */ 0,
/* tp_repr */ (reprfunc)0,
/* tp_as_number */ 0,
/* tp_as_sequence */ 0,
/* tp_as_mapping */ 0,
/* tp_hash */ (hashfunc)0,
/* tp_call */ (ternaryfunc)ib_call,
/* tp_str */ (reprfunc)0,
/* tp_getattro */ (getattrofunc)0,
/* tp_setattro */ (setattrofunc)0,
/* tp_as_buffer */ 0,
/* tp_flags */ Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE ,
/* tp_doc */ "Interface base type providing __call__ and __adapt__",
/* tp_traverse */ (traverseproc)0,
/* tp_clear */ (inquiry)0,
/* tp_richcompare */ (richcmpfunc)0,
/* tp_weaklistoffset */ (long)0,
/* tp_iter */ (getiterfunc)0,
/* tp_iternext */ (iternextfunc)0,
/* tp_methods */ ib_methods,
};
/* =================== End: __call__ and __adapt__ ==================== */
/* ==================================================================== */
/* ==================================================================== */
/* ========================== Begin: Lookup Bases ===================== */
typedef struct {
PyObject_HEAD
PyObject *_cache;
PyObject *_mcache;
PyObject *_scache;
} lookup;
typedef struct {
PyObject_HEAD
PyObject *_cache;
PyObject *_mcache;
PyObject *_scache;
PyObject *_verify_ro;
PyObject *_verify_generations;
} verify;
static int
lookup_traverse(lookup *self, visitproc visit, void *arg)
{
int vret;
if (self->_cache) {
vret = visit(self->_cache, arg);
if (vret != 0)
return vret;
}
if (self->_mcache) {
vret = visit(self->_mcache, arg);
if (vret != 0)
return vret;
}
if (self->_scache) {
vret = visit(self->_scache, arg);
if (vret != 0)
return vret;
}
return 0;
}
static int
lookup_clear(lookup *self)
{
Py_CLEAR(self->_cache);
Py_CLEAR(self->_mcache);
Py_CLEAR(self->_scache);
return 0;
}
static void
lookup_dealloc(lookup *self)
{
PyObject_GC_UnTrack((PyObject *)self);
lookup_clear(self);
Py_TYPE(self)->tp_free((PyObject*)self);
}
/*
def changed(self, ignored=None):
self._cache.clear()
self._mcache.clear()
self._scache.clear()
*/
static PyObject *
lookup_changed(lookup *self, PyObject *ignored)
{
lookup_clear(self);
Py_INCREF(Py_None);
return Py_None;
}
#define ASSURE_DICT(N) if (N == NULL) { N = PyDict_New(); \
if (N == NULL) return NULL; \
}
/*
def _getcache(self, provided, name):
cache = self._cache.get(provided)
if cache is None:
cache = {}
self._cache[provided] = cache
if name:
c = cache.get(name)
if c is None:
c = {}
cache[name] = c
cache = c
return cache
*/
static PyObject *
_subcache(PyObject *cache, PyObject *key)
{
PyObject *subcache;
subcache = PyDict_GetItem(cache, key);
if (subcache == NULL)
{
int status;
subcache = PyDict_New();
if (subcache == NULL)
return NULL;
status = PyDict_SetItem(cache, key, subcache);
Py_DECREF(subcache);
if (status < 0)
return NULL;
}
return subcache;
}
static PyObject *
_getcache(lookup *self, PyObject *provided, PyObject *name)
{
PyObject *cache;
ASSURE_DICT(self->_cache);
cache = _subcache(self->_cache, provided);
if (cache == NULL)
return NULL;
if (name != NULL && PyObject_IsTrue(name))
cache = _subcache(cache, name);
return cache;
}
/*
def lookup(self, required, provided, name=u'', default=None):
cache = self._getcache(provided, name)
if len(required) == 1:
result = cache.get(required[0], _not_in_mapping)
else:
result = cache.get(tuple(required), _not_in_mapping)
if result is _not_in_mapping:
result = self._uncached_lookup(required, provided, name)
if len(required) == 1:
cache[required[0]] = result
else:
cache[tuple(required)] = result
if result is None:
return default
return result
*/
static PyObject *
tuplefy(PyObject *v)
{
if (! PyTuple_Check(v))
{
v = PyObject_CallFunctionObjArgs(OBJECT(&PyTuple_Type), v, NULL);
if (v == NULL)
return NULL;
}
else
Py_INCREF(v);
return v;
}
static PyObject *
_lookup(lookup *self,
PyObject *required, PyObject *provided, PyObject *name,
PyObject *default_)
{
PyObject *result, *key, *cache;
#ifdef PY3K
if ( name && !PyUnicode_Check(name) )
#else
if ( name && !PyString_Check(name) && !PyUnicode_Check(name) )
#endif
{
PyErr_SetString(PyExc_ValueError,
"name is not a string or unicode");
return NULL;
}
cache = _getcache(self, provided, name);
if (cache == NULL)
return NULL;
required = tuplefy(required);
if (required == NULL)
return NULL;
if (PyTuple_GET_SIZE(required) == 1)
key = PyTuple_GET_ITEM(required, 0);
else
key = required;
result = PyDict_GetItem(cache, key);
if (result == NULL)
{
int status;
result = PyObject_CallMethodObjArgs(OBJECT(self), str_uncached_lookup,
required, provided, name, NULL);
if (result == NULL)
{
Py_DECREF(required);
return NULL;
}
status = PyDict_SetItem(cache, key, result);
Py_DECREF(required);
if (status < 0)
{
Py_DECREF(result);
return NULL;
}
}
else
{
Py_INCREF(result);
Py_DECREF(required);
}
if (result == Py_None && default_ != NULL)
{
Py_DECREF(Py_None);
Py_INCREF(default_);
return default_;
}
return result;
}
static PyObject *
lookup_lookup(lookup *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", "name", "default", NULL};
PyObject *required, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&required, &provided, &name, &default_))
return NULL;
return _lookup(self, required, provided, name, default_);
}
/*
def lookup1(self, required, provided, name=u'', default=None):
cache = self._getcache(provided, name)
result = cache.get(required, _not_in_mapping)
if result is _not_in_mapping:
return self.lookup((required, ), provided, name, default)
if result is None:
return default
return result
*/
static PyObject *
_lookup1(lookup *self,
PyObject *required, PyObject *provided, PyObject *name,
PyObject *default_)
{
PyObject *result, *cache;
#ifdef PY3K
if ( name && !PyUnicode_Check(name) )
#else
if ( name && !PyString_Check(name) && !PyUnicode_Check(name) )
#endif
{
PyErr_SetString(PyExc_ValueError,
"name is not a string or unicode");
return NULL;
}
cache = _getcache(self, provided, name);
if (cache == NULL)
return NULL;
result = PyDict_GetItem(cache, required);
if (result == NULL)
{
PyObject *tup;
tup = PyTuple_New(1);
if (tup == NULL)
return NULL;
Py_INCREF(required);
PyTuple_SET_ITEM(tup, 0, required);
result = _lookup(self, tup, provided, name, default_);
Py_DECREF(tup);
}
else
{
if (result == Py_None && default_ != NULL)
{
result = default_;
}
Py_INCREF(result);
}
return result;
}
static PyObject *
lookup_lookup1(lookup *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", "name", "default", NULL};
PyObject *required, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&required, &provided, &name, &default_))
return NULL;
return _lookup1(self, required, provided, name, default_);
}
/*
def adapter_hook(self, provided, object, name=u'', default=None):
required = providedBy(object)
cache = self._getcache(provided, name)
factory = cache.get(required, _not_in_mapping)
if factory is _not_in_mapping:
factory = self.lookup((required, ), provided, name)
if factory is not None:
result = factory(object)
if result is not None:
return result
return default
*/
static PyObject *
_adapter_hook(lookup *self,
PyObject *provided, PyObject *object, PyObject *name,
PyObject *default_)
{
PyObject *required, *factory, *result;
#ifdef PY3K
if ( name && !PyUnicode_Check(name) )
#else
if ( name && !PyString_Check(name) && !PyUnicode_Check(name) )
#endif
{
PyErr_SetString(PyExc_ValueError,
"name is not a string or unicode");
return NULL;
}
required = providedBy(NULL, object);
if (required == NULL)
return NULL;
factory = _lookup1(self, required, provided, name, Py_None);
Py_DECREF(required);
if (factory == NULL)
return NULL;
if (factory != Py_None)
{
result = PyObject_CallFunctionObjArgs(factory, object, NULL);
Py_DECREF(factory);
if (result == NULL || result != Py_None)
return result;
}
else
result = factory; /* None */
if (default_ == NULL || default_ == result) /* No default specified, */
return result; /* Return None. result is owned None */
Py_DECREF(result);
Py_INCREF(default_);
return default_;
}
static PyObject *
lookup_adapter_hook(lookup *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"provided", "object", "name", "default", NULL};
PyObject *object, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&provided, &object, &name, &default_))
return NULL;
return _adapter_hook(self, provided, object, name, default_);
}
static PyObject *
lookup_queryAdapter(lookup *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"object", "provided", "name", "default", NULL};
PyObject *object, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&object, &provided, &name, &default_))
return NULL;
return _adapter_hook(self, provided, object, name, default_);
}
/*
def lookupAll(self, required, provided):
cache = self._mcache.get(provided)
if cache is None:
cache = {}
self._mcache[provided] = cache
required = tuple(required)
result = cache.get(required, _not_in_mapping)
if result is _not_in_mapping:
result = self._uncached_lookupAll(required, provided)
cache[required] = result
return result
*/
static PyObject *
_lookupAll(lookup *self, PyObject *required, PyObject *provided)
{
PyObject *cache, *result;
ASSURE_DICT(self->_mcache);
cache = _subcache(self->_mcache, provided);
if (cache == NULL)
return NULL;
required = tuplefy(required);
if (required == NULL)
return NULL;
result = PyDict_GetItem(cache, required);
if (result == NULL)
{
int status;
result = PyObject_CallMethodObjArgs(OBJECT(self), str_uncached_lookupAll,
required, provided, NULL);
if (result == NULL)
{
Py_DECREF(required);
return NULL;
}
status = PyDict_SetItem(cache, required, result);
Py_DECREF(required);
if (status < 0)
{
Py_DECREF(result);
return NULL;
}
}
else
{
Py_INCREF(result);
Py_DECREF(required);
}
return result;
}
static PyObject *
lookup_lookupAll(lookup *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", NULL};
PyObject *required, *provided;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
&required, &provided))
return NULL;
return _lookupAll(self, required, provided);
}
/*
def subscriptions(self, required, provided):
cache = self._scache.get(provided)
if cache is None:
cache = {}
self._scache[provided] = cache
required = tuple(required)
result = cache.get(required, _not_in_mapping)
if result is _not_in_mapping:
result = self._uncached_subscriptions(required, provided)
cache[required] = result
return result
*/
static PyObject *
_subscriptions(lookup *self, PyObject *required, PyObject *provided)
{
PyObject *cache, *result;
ASSURE_DICT(self->_scache);
cache = _subcache(self->_scache, provided);
if (cache == NULL)
return NULL;
required = tuplefy(required);
if (required == NULL)
return NULL;
result = PyDict_GetItem(cache, required);
if (result == NULL)
{
int status;
result = PyObject_CallMethodObjArgs(
OBJECT(self), str_uncached_subscriptions,
required, provided, NULL);
if (result == NULL)
{
Py_DECREF(required);
return NULL;
}
status = PyDict_SetItem(cache, required, result);
Py_DECREF(required);
if (status < 0)
{
Py_DECREF(result);
return NULL;
}
}
else
{
Py_INCREF(result);
Py_DECREF(required);
}
return result;
}
static PyObject *
lookup_subscriptions(lookup *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", NULL};
PyObject *required, *provided;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
&required, &provided))
return NULL;
return _subscriptions(self, required, provided);
}
static struct PyMethodDef lookup_methods[] = {
{"changed", (PyCFunction)lookup_changed, METH_O, ""},
{"lookup", (PyCFunction)lookup_lookup, METH_KEYWORDS | METH_VARARGS, ""},
{"lookup1", (PyCFunction)lookup_lookup1, METH_KEYWORDS | METH_VARARGS, ""},
{"queryAdapter", (PyCFunction)lookup_queryAdapter, METH_KEYWORDS | METH_VARARGS, ""},
{"adapter_hook", (PyCFunction)lookup_adapter_hook, METH_KEYWORDS | METH_VARARGS, ""},
{"lookupAll", (PyCFunction)lookup_lookupAll, METH_KEYWORDS | METH_VARARGS, ""},
{"subscriptions", (PyCFunction)lookup_subscriptions, METH_KEYWORDS | METH_VARARGS, ""},
{NULL, NULL} /* sentinel */
};
static PyTypeObject LookupBase = {
PyVarObject_HEAD_INIT(NULL, 0)
/* tp_name */ "_zope_interface_coptimizations."
"LookupBase",
/* tp_basicsize */ sizeof(lookup),
/* tp_itemsize */ 0,
/* tp_dealloc */ (destructor)&lookup_dealloc,
/* tp_print */ (printfunc)0,
/* tp_getattr */ (getattrfunc)0,
/* tp_setattr */ (setattrfunc)0,
/* tp_compare */ 0,
/* tp_repr */ (reprfunc)0,
/* tp_as_number */ 0,
/* tp_as_sequence */ 0,
/* tp_as_mapping */ 0,
/* tp_hash */ (hashfunc)0,
/* tp_call */ (ternaryfunc)0,
/* tp_str */ (reprfunc)0,
/* tp_getattro */ (getattrofunc)0,
/* tp_setattro */ (setattrofunc)0,
/* tp_as_buffer */ 0,
/* tp_flags */ Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC,
/* tp_doc */ "",
/* tp_traverse */ (traverseproc)lookup_traverse,
/* tp_clear */ (inquiry)lookup_clear,
/* tp_richcompare */ (richcmpfunc)0,
/* tp_weaklistoffset */ (long)0,
/* tp_iter */ (getiterfunc)0,
/* tp_iternext */ (iternextfunc)0,
/* tp_methods */ lookup_methods,
};
static int
verifying_traverse(verify *self, visitproc visit, void *arg)
{
int vret;
vret = lookup_traverse((lookup *)self, visit, arg);
if (vret != 0)
return vret;
if (self->_verify_ro) {
vret = visit(self->_verify_ro, arg);
if (vret != 0)
return vret;
}
if (self->_verify_generations) {
vret = visit(self->_verify_generations, arg);
if (vret != 0)
return vret;
}
return 0;
}
static int
verifying_clear(verify *self)
{
lookup_clear((lookup *)self);
Py_CLEAR(self->_verify_generations);
Py_CLEAR(self->_verify_ro);
return 0;
}
static void
verifying_dealloc(verify *self)
{
PyObject_GC_UnTrack((PyObject *)self);
verifying_clear(self);
Py_TYPE(self)->tp_free((PyObject*)self);
}
/*
def changed(self, originally_changed):
super(VerifyingBasePy, self).changed(originally_changed)
self._verify_ro = self._registry.ro[1:]
self._verify_generations = [r._generation for r in self._verify_ro]
*/
static PyObject *
_generations_tuple(PyObject *ro)
{
int i, l;
PyObject *generations;
l = PyTuple_GET_SIZE(ro);
generations = PyTuple_New(l);
for (i=0; i < l; i++)
{
PyObject *generation;
generation = PyObject_GetAttr(PyTuple_GET_ITEM(ro, i), str_generation);
if (generation == NULL)
{
Py_DECREF(generations);
return NULL;
}
PyTuple_SET_ITEM(generations, i, generation);
}
return generations;
}
static PyObject *
verifying_changed(verify *self, PyObject *ignored)
{
PyObject *t, *ro;
verifying_clear(self);
t = PyObject_GetAttr(OBJECT(self), str_registry);
if (t == NULL)
return NULL;
ro = PyObject_GetAttr(t, strro);
Py_DECREF(t);
if (ro == NULL)
return NULL;
t = PyObject_CallFunctionObjArgs(OBJECT(&PyTuple_Type), ro, NULL);
Py_DECREF(ro);
if (t == NULL)
return NULL;
ro = PyTuple_GetSlice(t, 1, PyTuple_GET_SIZE(t));
Py_DECREF(t);
if (ro == NULL)
return NULL;
self->_verify_generations = _generations_tuple(ro);
if (self->_verify_generations == NULL)
{
Py_DECREF(ro);
return NULL;
}
self->_verify_ro = ro;
Py_INCREF(Py_None);
return Py_None;
}
/*
def _verify(self):
if ([r._generation for r in self._verify_ro]
!= self._verify_generations):
self.changed(None)
*/
static int
_verify(verify *self)
{
PyObject *changed_result;
if (self->_verify_ro != NULL && self->_verify_generations != NULL)
{
PyObject *generations;
int changed;
generations = _generations_tuple(self->_verify_ro);
if (generations == NULL)
return -1;
changed = PyObject_RichCompareBool(self->_verify_generations,
generations, Py_NE);
Py_DECREF(generations);
if (changed == -1)
return -1;
if (changed == 0)
return 0;
}
changed_result = PyObject_CallMethodObjArgs(OBJECT(self), strchanged,
Py_None, NULL);
if (changed_result == NULL)
return -1;
Py_DECREF(changed_result);
return 0;
}
static PyObject *
verifying_lookup(verify *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", "name", "default", NULL};
PyObject *required, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&required, &provided, &name, &default_))
return NULL;
if (_verify(self) < 0)
return NULL;
return _lookup((lookup *)self, required, provided, name, default_);
}
static PyObject *
verifying_lookup1(verify *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", "name", "default", NULL};
PyObject *required, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&required, &provided, &name, &default_))
return NULL;
if (_verify(self) < 0)
return NULL;
return _lookup1((lookup *)self, required, provided, name, default_);
}
static PyObject *
verifying_adapter_hook(verify *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"provided", "object", "name", "default", NULL};
PyObject *object, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&provided, &object, &name, &default_))
return NULL;
if (_verify(self) < 0)
return NULL;
return _adapter_hook((lookup *)self, provided, object, name, default_);
}
static PyObject *
verifying_queryAdapter(verify *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"object", "provided", "name", "default", NULL};
PyObject *object, *provided, *name=NULL, *default_=NULL;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
&object, &provided, &name, &default_))
return NULL;
if (_verify(self) < 0)
return NULL;
return _adapter_hook((lookup *)self, provided, object, name, default_);
}
static PyObject *
verifying_lookupAll(verify *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", NULL};
PyObject *required, *provided;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
&required, &provided))
return NULL;
if (_verify(self) < 0)
return NULL;
return _lookupAll((lookup *)self, required, provided);
}
static PyObject *
verifying_subscriptions(verify *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"required", "provided", NULL};
PyObject *required, *provided;
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
&required, &provided))
return NULL;
if (_verify(self) < 0)
return NULL;
return _subscriptions((lookup *)self, required, provided);
}
static struct PyMethodDef verifying_methods[] = {
{"changed", (PyCFunction)verifying_changed, METH_O, ""},
{"lookup", (PyCFunction)verifying_lookup, METH_KEYWORDS | METH_VARARGS, ""},
{"lookup1", (PyCFunction)verifying_lookup1, METH_KEYWORDS | METH_VARARGS, ""},
{"queryAdapter", (PyCFunction)verifying_queryAdapter, METH_KEYWORDS | METH_VARARGS, ""},
{"adapter_hook", (PyCFunction)verifying_adapter_hook, METH_KEYWORDS | METH_VARARGS, ""},
{"lookupAll", (PyCFunction)verifying_lookupAll, METH_KEYWORDS | METH_VARARGS, ""},
{"subscriptions", (PyCFunction)verifying_subscriptions, METH_KEYWORDS | METH_VARARGS, ""},
{NULL, NULL} /* sentinel */
};
static PyTypeObject VerifyingBase = {
PyVarObject_HEAD_INIT(NULL, 0)
/* tp_name */ "_zope_interface_coptimizations."
"VerifyingBase",
/* tp_basicsize */ sizeof(verify),
/* tp_itemsize */ 0,
/* tp_dealloc */ (destructor)&verifying_dealloc,
/* tp_print */ (printfunc)0,
/* tp_getattr */ (getattrfunc)0,
/* tp_setattr */ (setattrfunc)0,
/* tp_compare */ 0,
/* tp_repr */ (reprfunc)0,
/* tp_as_number */ 0,
/* tp_as_sequence */ 0,
/* tp_as_mapping */ 0,
/* tp_hash */ (hashfunc)0,
/* tp_call */ (ternaryfunc)0,
/* tp_str */ (reprfunc)0,
/* tp_getattro */ (getattrofunc)0,
/* tp_setattro */ (setattrofunc)0,
/* tp_as_buffer */ 0,
/* tp_flags */ Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC,
/* tp_doc */ "",
/* tp_traverse */ (traverseproc)verifying_traverse,
/* tp_clear */ (inquiry)verifying_clear,
/* tp_richcompare */ (richcmpfunc)0,
/* tp_weaklistoffset */ (long)0,
/* tp_iter */ (getiterfunc)0,
/* tp_iternext */ (iternextfunc)0,
/* tp_methods */ verifying_methods,
/* tp_members */ 0,
/* tp_getset */ 0,
/* tp_base */ &LookupBase,
};
/* ========================== End: Lookup Bases ======================= */
/* ==================================================================== */
static struct PyMethodDef m_methods[] = {
{"implementedBy", (PyCFunction)implementedBy, METH_O,
"Interfaces implemented by a class or factory.\n"
"Raises TypeError if argument is neither a class nor a callable."},
{"getObjectSpecification", (PyCFunction)getObjectSpecification, METH_O,
"Get an object's interfaces (internal api)"},
{"providedBy", (PyCFunction)providedBy, METH_O,
"Get an object's interfaces"},
{NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
};
#if PY_MAJOR_VERSION >= 3
static char module_doc[] = "C optimizations for zope.interface\n\n";
static struct PyModuleDef _zic_module = {
PyModuleDef_HEAD_INIT,
"_zope_interface_coptimizations",
module_doc,
-1,
m_methods,
NULL,
NULL,
NULL,
NULL
};
#endif
static PyObject *
init(void)
{
PyObject *m;
#if PY_MAJOR_VERSION < 3
#define DEFINE_STRING(S) \
if(! (str ## S = PyString_FromString(# S))) return NULL
#else
#define DEFINE_STRING(S) \
if(! (str ## S = PyUnicode_FromString(# S))) return NULL
#endif
DEFINE_STRING(__dict__);
DEFINE_STRING(__implemented__);
DEFINE_STRING(__provides__);
DEFINE_STRING(__class__);
DEFINE_STRING(__providedBy__);
DEFINE_STRING(extends);
DEFINE_STRING(_implied);
DEFINE_STRING(_implements);
DEFINE_STRING(_cls);
DEFINE_STRING(__conform__);
DEFINE_STRING(_call_conform);
DEFINE_STRING(_uncached_lookup);
DEFINE_STRING(_uncached_lookupAll);
DEFINE_STRING(_uncached_subscriptions);
DEFINE_STRING(_registry);
DEFINE_STRING(_generation);
DEFINE_STRING(ro);
DEFINE_STRING(changed);
#undef DEFINE_STRING
adapter_hooks = PyList_New(0);
if (adapter_hooks == NULL)
return NULL;
/* Initialize types: */
SpecType.tp_new = PyBaseObject_Type.tp_new;
if (PyType_Ready(&SpecType) < 0)
return NULL;
OSDType.tp_new = PyBaseObject_Type.tp_new;
if (PyType_Ready(&OSDType) < 0)
return NULL;
CPBType.tp_new = PyBaseObject_Type.tp_new;
if (PyType_Ready(&CPBType) < 0)
return NULL;
InterfaceBase.tp_new = PyBaseObject_Type.tp_new;
if (PyType_Ready(&InterfaceBase) < 0)
return NULL;
LookupBase.tp_new = PyBaseObject_Type.tp_new;
if (PyType_Ready(&LookupBase) < 0)
return NULL;
VerifyingBase.tp_new = PyBaseObject_Type.tp_new;
if (PyType_Ready(&VerifyingBase) < 0)
return NULL;
#if PY_MAJOR_VERSION < 3
/* Create the module and add the functions */
m = Py_InitModule3("_zope_interface_coptimizations", m_methods,
"C optimizations for zope.interface\n\n");
#else
m = PyModule_Create(&_zic_module);
#endif
if (m == NULL)
return NULL;
/* Add types: */
if (PyModule_AddObject(m, "SpecificationBase", OBJECT(&SpecType)) < 0)
return NULL;
if (PyModule_AddObject(m, "ObjectSpecificationDescriptor",
(PyObject *)&OSDType) < 0)
return NULL;
if (PyModule_AddObject(m, "ClassProvidesBase", OBJECT(&CPBType)) < 0)
return NULL;
if (PyModule_AddObject(m, "InterfaceBase", OBJECT(&InterfaceBase)) < 0)
return NULL;
if (PyModule_AddObject(m, "LookupBase", OBJECT(&LookupBase)) < 0)
return NULL;
if (PyModule_AddObject(m, "VerifyingBase", OBJECT(&VerifyingBase)) < 0)
return NULL;
if (PyModule_AddObject(m, "adapter_hooks", adapter_hooks) < 0)
return NULL;
return m;
}
PyMODINIT_FUNC
#if PY_MAJOR_VERSION < 3
init_zope_interface_coptimizations(void)
{
init();
}
#else
PyInit__zope_interface_coptimizations(void)
{
return init();
}
#endif