Mercurial > public > mercurial-scm > hg
view mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c @ 37176:943d77fc07a3
thirdparty: vendor zope.interface 4.4.3
I've been trying to formalize interfaces for various components
of Mercurial. So far, we've been using the "abc" package. This
package is "good enough" for a lot of tasks. But it quickly
falls over. For example, if you declare an @abc.abstractproperty,
you must implement that attribute with a @property or the class
compile time checking performed by abc will complain. This often
forces you to implement dumb @property wrappers to return a
_ prefixed attribute of the sane name. That's ugly.
I've also wanted to implement automated checking that classes
conform to various interfaces and don't expose other "public"
attributes.
After doing a bit of research and asking around, the general
consensus seems to be that zope.interface is the best package for
doing interface-based programming in Python. It has built-in
support for verifying classes and objects conform to interfaces.
It allows an interface's properties to be defined during __init__.
There's even an "adapter registry" that allow you to register
interfaces and look up which classes implement them. That could
potentially be useful for places where our custom registry.py
modules currently facilitates central registrations, but at a
type level. Imagine extensions providing alternate implementations
of things like the local repository interface to allow opening
repositories with custom requirements.
Anyway, this commit vendors zope.interface 4.4.3. The contents of
the source tarball have been copied into mercurial/thirdparty/zope/
without modifications.
Test modules have been removed because they are not interesting
to us.
The LICENSE.txt file has been copied so it lives next to the
source.
The Python modules don't use relative imports. zope/__init__.py
defines a namespace package. So we'll need to modify the source
code before this package is usable inside Mercurial. This will
be done in subsequent commits.
# no-check-commit for various style failures
Differential Revision: https://phab.mercurial-scm.org/D2928
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Wed, 21 Mar 2018 19:48:50 -0700 |
parents | |
children | 68ee61822182 |
line wrap: on
line source
/*########################################################################### # # 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("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