diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-08-28 17:49:28 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2024-08-28 17:58:46 +0300 |
commit | 05f1a7bca5400633bcb52b58affe23880df1fd0e (patch) | |
tree | 87744c3c5cb786fddbe15004779b941988a0b7d7 /contrib/python/zope.interface/py3/zope/interface | |
parent | dc1a94ab8d6985d2dcf888fa1881e7b80f7042b1 (diff) | |
download | ydb-05f1a7bca5400633bcb52b58affe23880df1fd0e.tar.gz |
Intermediate changes
Diffstat (limited to 'contrib/python/zope.interface/py3/zope/interface')
21 files changed, 2914 insertions, 2014 deletions
diff --git a/contrib/python/zope.interface/py3/zope/interface/__init__.py b/contrib/python/zope.interface/py3/zope/interface/__init__.py index 8be812dd6c..2b8e7eb45b 100644 --- a/contrib/python/zope.interface/py3/zope/interface/__init__.py +++ b/contrib/python/zope.interface/py3/zope/interface/__init__.py @@ -58,7 +58,7 @@ from zope.interface.interface import _wire _wire() del _wire -from zope.interface.declarations import Declaration +from zope.interface.declarations import Declaration # isort: skip # The following are to make spec pickles cleaner from zope.interface.declarations import Provides from zope.interface.declarations import alsoProvides diff --git a/contrib/python/zope.interface/py3/zope/interface/_compat.py b/contrib/python/zope.interface/py3/zope/interface/_compat.py index 2ff8d83eaf..bc3f867114 100644 --- a/contrib/python/zope.interface/py3/zope/interface/_compat.py +++ b/contrib/python/zope.interface/py3/zope/interface/_compat.py @@ -29,6 +29,7 @@ def _normalize_name(name): return name raise TypeError("name must be a string or ASCII-only bytes") + PYPY = hasattr(sys, 'pypy_version_info') @@ -57,7 +58,7 @@ def _c_optimizations_available(): try: from zope.interface import _zope_interface_coptimizations as c_opt return c_opt - except catch: # pragma: no cover (only Jython doesn't build extensions) + except catch: # pragma: no cover (only Jython doesn't build extensions) return False @@ -120,7 +121,7 @@ def _use_c_impl(py_impl, name=None, globs=None): return py_impl c_opt = _c_optimizations_available() - if not c_opt: # pragma: no cover (only Jython doesn't build extensions) + if not c_opt: # pragma: no cover (Jython doesn't build extensions) return py_impl __traceback_info__ = c_opt diff --git a/contrib/python/zope.interface/py3/zope/interface/_flatten.py b/contrib/python/zope.interface/py3/zope/interface/_flatten.py index 68b490db1c..a2cb86b781 100644 --- a/contrib/python/zope.interface/py3/zope/interface/_flatten.py +++ b/contrib/python/zope.interface/py3/zope/interface/_flatten.py @@ -24,7 +24,7 @@ def _flatten(implements, include_None=0): r = implements.flattened() except AttributeError: if implements is None: - r=() + r = () else: r = Declaration(implements).flattened() diff --git a/contrib/python/zope.interface/py3/zope/interface/_zope_interface_coptimizations.c b/contrib/python/zope.interface/py3/zope/interface/_zope_interface_coptimizations.c index 2cf453a7e6..453057a4d6 100644 --- a/contrib/python/zope.interface/py3/zope/interface/_zope_interface_coptimizations.c +++ b/contrib/python/zope.interface/py3/zope/interface/_zope_interface_coptimizations.c @@ -24,299 +24,197 @@ #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 #define PyNative_FromString PyUnicode_FromString -static PyObject *str__dict__, *str__implemented__, *strextends; -static PyObject *BuiltinImplementationSpecifications, *str__provides__; -static PyObject *str__class__, *str__providedBy__; -static PyObject *empty, *fallback; -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 PyObject *str__self__; -static PyObject *str__module__; -static PyObject *str__name__; -static PyObject *str__adapt__; -static PyObject *str_CALL_CUSTOM_ADAPT; - -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; +#define ASSURE_DICT(N) \ + if (N == NULL) { \ + N = PyDict_New(); \ + if (N == NULL) \ + return NULL; \ } - Implements = (PyTypeObject *)i; - - Py_DECREF(declarations); - - imported_declarations = 1; - return 0; -} - +/* + * Don't use heap-allocated types for Python < 3.11: the API needed + * to find the dynamic module, 'PyType_GetModuleByDef', was added then. + */ +#if PY_VERSION_HEX < 0x030b0000 +#define USE_STATIC_TYPES 1 +#define USE_HEAP_TYPES 0 +#else +#define USE_STATIC_TYPES 0 +#define USE_HEAP_TYPES 1 +#endif -static PyTypeObject SpecificationBaseType; /* Forward */ +#if PY_VERSION_HEX >= 0x030c0000 +/* Add MANAGED_WEAKREF flag for Python >= 3.12, and don't define + * the '.tp_weaklistoffset' slot. + * + * See: https://docs.python.org/3/c-api/typeobj.html + * #c.PyTypeObject.tp_weaklistoffset + */ +#define USE_EXPLICIT_WEAKREFLIST 0 +#define BASETYPE_FLAGS \ + Py_TPFLAGS_DEFAULT | \ + Py_TPFLAGS_BASETYPE | \ + Py_TPFLAGS_MANAGED_WEAKREF | \ + Py_TPFLAGS_HAVE_GC +#else +/* No MANAGED_WEAKREF flag for Python < 3.12, and therefore define + * the '.tp_weaklistoffset' slot, and the member whose offset it holds. + * + * See: https://docs.python.org/3/c-api/typeobj.html + * #c.PyTypeObject.tp_weaklistoffset + */ +#define USE_EXPLICIT_WEAKREFLIST 1 +#define BASETYPE_FLAGS \ + Py_TPFLAGS_DEFAULT | \ + Py_TPFLAGS_BASETYPE | \ + Py_TPFLAGS_HAVE_GC +#endif -static PyObject * -implementedByFallback(PyObject *cls) -{ - if (imported_declarations == 0 && import_declarations() < 0) - return NULL; +/* Static strings, used to invoke PyObject_GetAttr (only in hot paths) */ +static PyObject *str__class__ = NULL; +static PyObject *str__conform__ = NULL; +static PyObject *str__dict__ = NULL; +static PyObject *str__module__ = NULL; +static PyObject *str__name__ = NULL; +static PyObject *str__providedBy__ = NULL; +static PyObject *str__provides__ = NULL; +static PyObject *str__self__ = NULL; +static PyObject *str_generation = NULL; +static PyObject *str_registry = NULL; +static PyObject *strro = NULL; + +/* Static strings, used to invoke PyObject_CallMethodObjArgs */ +static PyObject *str_call_conform = NULL; +static PyObject *str_uncached_lookup = NULL; +static PyObject *str_uncached_lookupAll = NULL; +static PyObject *str_uncached_subscriptions = NULL; +static PyObject *strchanged = NULL; +static PyObject *str__adapt__ = NULL; + +/* Static strings, used to invoke PyObject_GetItem + * + * We cannot use PyDict_GetItemString, because the '__dict__' we get + * from our types can be a 'types.mappingproxy', which causes a segfault. + */ +static PyObject* str__implemented__; - return PyObject_CallFunctionObjArgs(fallback, cls, NULL); -} -static PyObject * -implementedBy(PyObject *ignored, PyObject *cls) +static int +define_static_strings() { - /* Fast retrieval of implements spec, if possible, to optimize - common case. Use fallback code if we get stuck. - */ - - PyObject *dict = NULL, *spec; - - if (PyObject_TypeCheck(cls, &PySuper_Type)) - { - // Let merging be handled by Python. - return implementedByFallback(cls); - } - - if (PyType_Check(cls)) - { - dict = TYPE(cls)->tp_dict; - Py_XINCREF(dict); + if (str__class__ != NULL) { + return 0; } - if (dict == NULL) - dict = PyObject_GetAttr(cls, str__dict__); +#define DEFINE_STATIC_STRING(S) \ + if (!(str##S = PyUnicode_FromString(#S))) \ + return -1 + + DEFINE_STATIC_STRING(__class__); + DEFINE_STATIC_STRING(__conform__); + DEFINE_STATIC_STRING(__dict__); + DEFINE_STATIC_STRING(__module__); + DEFINE_STATIC_STRING(__name__); + DEFINE_STATIC_STRING(__providedBy__); + DEFINE_STATIC_STRING(__provides__); + DEFINE_STATIC_STRING(__self__); + DEFINE_STATIC_STRING(_generation); + DEFINE_STATIC_STRING(_registry); + DEFINE_STATIC_STRING(ro); + DEFINE_STATIC_STRING(__implemented__); + DEFINE_STATIC_STRING(_call_conform); + DEFINE_STATIC_STRING(_uncached_lookup); + DEFINE_STATIC_STRING(_uncached_lookupAll); + DEFINE_STATIC_STRING(_uncached_subscriptions); + DEFINE_STATIC_STRING(changed); + DEFINE_STATIC_STRING(__adapt__); +#undef DEFINE_STATIC_STRING - 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; + return 0; +} - if (PyObject_TypeCheck(spec, Implements)) - return spec; +/* Public module-scope functions, forward-declared here for type methods. */ +static PyObject *implementedBy(PyObject* module, PyObject *cls); +static PyObject *getObjectSpecification(PyObject *module, PyObject *ob); +static PyObject *providedBy(PyObject *module, PyObject *ob); - /* Old-style declaration, use more expensive fallback code */ - Py_DECREF(spec); - return implementedByFallback(cls); - } +/* + * Utility functions, forward-declared here for type methods. + */ +static PyObject* _get_module(PyTypeObject *typeobj); +static PyObject* _get_adapter_hooks(PyTypeObject *typeobj); +static PyTypeObject* _get_specification_base_class(PyTypeObject *typeobj); +static PyTypeObject* _get_interface_base_class(PyTypeObject *typeobj); + +#if USE_STATIC_TYPES +/* + * Global used by static IB__adapt + */ +static PyObject* adapter_hooks = NULL; - PyErr_Clear(); +/* + * Globals imported from 'zope.interface.declarations' + */ +static int imported_declarations = 0; +static PyObject* BuiltinImplementationSpecifications; +static PyObject* empty; +static PyObject* fallback; +static PyTypeObject *Implements; - /* Maybe we have a builtin */ - if (imported_declarations == 0 && import_declarations() < 0) - return NULL; +/* Import zope.interface.declarations and store results in global statics. + * + * Static alternative to '_zic_state_load_declarations' below. + */ +static int +import_declarations(void) +{ + PyObject *declarations, *i; - spec = PyDict_GetItem(BuiltinImplementationSpecifications, cls); - if (spec != NULL) - { - Py_INCREF(spec); - return spec; - } + declarations = PyImport_ImportModule("zope.interface.declarations"); + if (declarations == NULL) { return -1; } - /* 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) - { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) - { - /* Propagate non AttributeError exceptions. */ - return NULL; - } - PyErr_Clear(); - } - else - { - int is_instance = -1; - is_instance = PyObject_IsInstance(result, (PyObject*)&SpecificationBaseType); - if (is_instance < 0) - { - /* Propagate all errors */ - return NULL; - } - if (is_instance) - { - return result; - } - } - - /* We do a getattr here so as not to be defeated by proxies */ - cls = PyObject_GetAttr(ob, str__class__); - if (cls == NULL) - { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) - { - /* Propagate non-AttributeErrors */ - return 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; - int is_instance = -1; - result = NULL; - - is_instance = PyObject_IsInstance(ob, (PyObject*)&PySuper_Type); - if (is_instance < 0) - { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) - { - /* Propagate non-AttributeErrors */ - return NULL; - } - PyErr_Clear(); - } - if (is_instance) - { - return implementedBy(NULL, ob); - } - - result = PyObject_GetAttr(ob, str__providedBy__); - - if (result == NULL) - { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) - { - return 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, &SpecificationBaseType) - || - PyObject_HasAttr(result, strextends) - ) - return result; + BuiltinImplementationSpecifications = PyObject_GetAttrString( + declarations, "BuiltinImplementationSpecifications"); + if (BuiltinImplementationSpecifications == NULL) { return -1; } - /* - 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); + empty = PyObject_GetAttrString(declarations, "_empty"); + if (empty == NULL) { return -1; } - cls = PyObject_GetAttr(ob, str__class__); - if (cls == NULL) - return NULL; + fallback = PyObject_GetAttrString(declarations, "implementedByFallback"); + if (fallback == NULL) { return -1;} - 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; - } + i = PyObject_GetAttrString(declarations, "Implements"); + if (i == NULL) { return -1; } - 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 (! PyType_Check(i)) { + PyErr_SetString( + PyExc_TypeError, + "zope.interface.declarations.Implements is not a type"); + return -1; } - 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); - } + Implements = (PyTypeObject *)i; - Py_DECREF(cls); - Py_DECREF(cp); + Py_DECREF(declarations); - return result; + imported_declarations = 1; + return 0; } -typedef struct { +#endif + +/* + * SpecificationBase class + */ +typedef struct +{ PyObject_HEAD - PyObject* weakreflist; /* In the past, these fields were stored in the __dict__ and were technically allowed to contain any Python object, though @@ -325,6 +223,9 @@ typedef struct { make any assumptions about contents. */ PyObject* _implied; +#if USE_EXPLICIT_WEAKREFLIST + PyObject* weakreflist; +#endif /* The remainder aren't used in C code but must be stored here to prevent instance layout conflicts. @@ -334,15 +235,22 @@ typedef struct { PyObject* _v_attrs; PyObject* __iro__; PyObject* __sro__; -} Spec; +} SB; /* We know what the fields are *supposed* to define, but they could have anything, so we need to traverse them. */ static int -Spec_traverse(Spec* self, visitproc visit, void* arg) +SB_traverse(SB* self, visitproc visit, void* arg) { +/* Visit our 'tp_type' only on Python >= 3.9, per + * https://docs.python.org/3/howto/isolating-extensions.html + * #tp-traverse-in-python-3-8-and-lower + */ +#if USE_HEAP_TYPES && PY_VERSION_HEX > 0x03090000 + Py_VISIT(Py_TYPE(self)); +#endif Py_VISIT(self->_implied); Py_VISIT(self->_dependents); Py_VISIT(self->_bases); @@ -353,7 +261,7 @@ Spec_traverse(Spec* self, visitproc visit, void* arg) } static int -Spec_clear(Spec* self) +SB_clear(SB* self) { Py_CLEAR(self->_implied); Py_CLEAR(self->_dependents); @@ -365,246 +273,295 @@ Spec_clear(Spec* self) } static void -Spec_dealloc(Spec* self) +SB_dealloc(SB* self) { - /* PyType_GenericAlloc that you get when you don't - specify a tp_alloc always tracks the object. */ - PyObject_GC_UnTrack((PyObject *)self); + PyObject_GC_UnTrack((PyObject*)self); + PyTypeObject* tp = Py_TYPE(self); +#if USE_EXPLICIT_WEAKREFLIST if (self->weakreflist != NULL) { PyObject_ClearWeakRefs(OBJECT(self)); } - Spec_clear(self); - Py_TYPE(self)->tp_free(OBJECT(self)); +#endif + SB_clear(self); + tp->tp_free(OBJECT(self)); +#if USE_HEAP_TYPES + Py_DECREF(tp); +#endif } -static PyObject * -Spec_extends(Spec *self, PyObject *other) +static char SB_extends__doc__[] = + "Test whether a specification is or extends another"; + +static PyObject* +SB_extends(SB* self, PyObject* other) { - PyObject *implied; + PyObject* implied; - implied = self->_implied; - if (implied == NULL) { - return NULL; - } + implied = self->_implied; + if (implied == NULL) { + return NULL; + } - if (PyDict_GetItem(implied, other) != NULL) - Py_RETURN_TRUE; - Py_RETURN_FALSE; + if (PyDict_GetItem(implied, other) != NULL) + Py_RETURN_TRUE; + Py_RETURN_FALSE; } -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(Spec *self, PyObject *args, PyObject *kw) +static PyObject* +SB__call__(SB* self, PyObject* args, PyObject* kw) { - PyObject *spec; + PyObject* spec; - if (! PyArg_ParseTuple(args, "O", &spec)) - return NULL; - return Spec_extends(self, spec); + if (!PyArg_ParseTuple(args, "O", &spec)) + return NULL; + return SB_extends(self, spec); } -static PyObject * -Spec_providedBy(PyObject *self, PyObject *ob) +static char SB_providedBy__doc__[] = + "Test whether an interface is implemented by the specification"; + +static PyObject* +SB_providedBy(PyObject* self, PyObject* ob) { - PyObject *decl, *item; + PyObject *decl; + PyObject *item; + PyObject *module; + PyTypeObject *specification_base_class; - decl = providedBy(NULL, ob); - if (decl == NULL) - return NULL; + module = _get_module(Py_TYPE(self)); + specification_base_class = _get_specification_base_class(Py_TYPE(self)); - if (PyObject_TypeCheck(decl, &SpecificationBaseType)) - item = Spec_extends((Spec*)decl, self); - else - /* decl is probably a security proxy. We have to go the long way - around. - */ - item = PyObject_CallFunctionObjArgs(decl, self, NULL); + decl = providedBy(module, ob); + if (decl == NULL) + return NULL; - Py_DECREF(decl); - return item; -} + if (PyObject_TypeCheck(decl, specification_base_class)) + item = SB_extends((SB*)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 char SB_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) +static PyObject* +SB_implementedBy(PyObject* self, PyObject* cls) { - PyObject *decl, *item; + PyObject *decl; + PyObject *item; + PyObject *module; + PyTypeObject *specification_base_class; - decl = implementedBy(NULL, cls); - if (decl == NULL) - return NULL; + module = _get_module(Py_TYPE(self)); + specification_base_class = _get_specification_base_class(Py_TYPE(self)); - if (PyObject_TypeCheck(decl, &SpecificationBaseType)) - item = Spec_extends((Spec*)decl, self); - else - item = PyObject_CallFunctionObjArgs(decl, self, NULL); + decl = implementedBy(module, cls); + if (decl == NULL) + return NULL; + + if (PyObject_TypeCheck(decl, specification_base_class)) + item = SB_extends((SB*)decl, self); + else + item = PyObject_CallFunctionObjArgs(decl, self, NULL); - Py_DECREF(decl); - return item; + 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__}, +static struct PyMethodDef SB_methods[] = { + { "providedBy", + (PyCFunction)SB_providedBy, + METH_O, + SB_providedBy__doc__ }, + { "implementedBy", + (PyCFunction)SB_implementedBy, + METH_O, + SB_implementedBy__doc__ }, + { "isOrExtends", + (PyCFunction)SB_extends, + METH_O, + SB_extends__doc__ }, + + { NULL, NULL } /* sentinel */ +}; - {NULL, NULL} /* sentinel */ +static PyMemberDef SB_members[] = { + { "_implied", T_OBJECT_EX, offsetof(SB, _implied), 0, "" }, + { "_dependents", T_OBJECT_EX, offsetof(SB, _dependents), 0, "" }, + { "_bases", T_OBJECT_EX, offsetof(SB, _bases), 0, "" }, + { "_v_attrs", T_OBJECT_EX, offsetof(SB, _v_attrs), 0, "" }, + { "__iro__", T_OBJECT_EX, offsetof(SB, __iro__), 0, "" }, + { "__sro__", T_OBJECT_EX, offsetof(SB, __sro__), 0, "" }, +#if USE_EXPLICIT_WEAKREFLIST + { "__weaklistoffset__", T_PYSSIZET, offsetof(SB, weakreflist), READONLY, "" }, +#endif + { NULL }, }; -static PyMemberDef Spec_members[] = { - {"_implied", T_OBJECT_EX, offsetof(Spec, _implied), 0, ""}, - {"_dependents", T_OBJECT_EX, offsetof(Spec, _dependents), 0, ""}, - {"_bases", T_OBJECT_EX, offsetof(Spec, _bases), 0, ""}, - {"_v_attrs", T_OBJECT_EX, offsetof(Spec, _v_attrs), 0, ""}, - {"__iro__", T_OBJECT_EX, offsetof(Spec, __iro__), 0, ""}, - {"__sro__", T_OBJECT_EX, offsetof(Spec, __sro__), 0, ""}, - {NULL}, +static char SB__name__[] = "_zope_interface_coptimizations.SpecificationBase"; +static char SB__doc__[] = "Base type for Specification objects"; + +#if USE_STATIC_TYPES + +/* + * Static type: SpecificationBase + */ + +static PyTypeObject SB_type_def = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = SB__name__, + .tp_doc = SB__doc__, + .tp_basicsize = sizeof(SB), + .tp_flags = BASETYPE_FLAGS, + .tp_call = (ternaryfunc)SB__call__, + .tp_traverse = (traverseproc)SB_traverse, + .tp_clear = (inquiry)SB_clear, + .tp_dealloc = (destructor)SB_dealloc, +#if USE_EXPLICIT_WEAKREFLIST + .tp_weaklistoffset = offsetof(SB, weakreflist), +#endif + .tp_methods = SB_methods, + .tp_members = SB_members, }; +#else -static PyTypeObject SpecificationBaseType = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ "_interface_coptimizations." - "SpecificationBase", - /* tp_basicsize */ sizeof(Spec), - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor)Spec_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)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 | Py_TPFLAGS_HAVE_GC, - "Base type for Specification objects", - /* tp_traverse */ (traverseproc)Spec_traverse, - /* tp_clear */ (inquiry)Spec_clear, - /* tp_richcompare */ (richcmpfunc)0, - /* tp_weaklistoffset */ offsetof(Spec, weakreflist), - /* tp_iter */ (getiterfunc)0, - /* tp_iternext */ (iternextfunc)0, - /* tp_methods */ Spec_methods, - /* tp_members */ Spec_members, +/* + * Heap-based type: SpecificationBase + */ +static PyType_Slot SB_type_slots[] = { + {Py_tp_doc, SB__doc__}, + {Py_tp_call, SB__call__}, + {Py_tp_traverse, SB_traverse}, + {Py_tp_clear, SB_clear}, + {Py_tp_dealloc, SB_dealloc}, + {Py_tp_methods, SB_methods}, + {Py_tp_members, SB_members}, + {0, NULL} }; -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__); - /* Return __provides__ if we got it, or return NULL and propagate non-AttributeError. */ - if (provides != NULL || !PyErr_ExceptionMatches(PyExc_AttributeError)) - 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 PyType_Spec SB_type_spec = { + .name = SB__name__, + .basicsize = sizeof(SB), + .flags = BASETYPE_FLAGS, + .slots = SB_type_slots }; -typedef struct { - Spec spec; - /* These members are handled generically, as for Spec members. */ - PyObject* _cls; - PyObject* _implements; -} CPB; +#endif -static PyObject * -CPB_descr_get(CPB *self, PyObject *inst, PyObject *cls) +/* + * ObjectSpecificationDescriptor class + */ +#if USE_HEAP_TYPES +static int +OSD_traverse(PyObject* self, visitproc visit, void* arg) { - PyObject *implements; + Py_VISIT(Py_TYPE(self)); + return 0; +} - if (self->_cls == NULL) - return NULL; +static void +OSD_dealloc(PyObject* self) +{ + PyObject_GC_UnTrack(self); + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free(OBJECT(self)); + Py_DECREF(tp); +} +#endif - if (cls == self->_cls) - { - if (inst == NULL) - { - Py_INCREF(self); - return OBJECT(self); - } +static PyObject* +OSD_descr_get(PyObject* self, PyObject* inst, PyObject* cls) +{ + PyObject* provides; + PyObject *module; + + module = _get_module(Py_TYPE(self)); - implements = self->_implements; - Py_XINCREF(implements); - return implements; + if (inst == NULL) { + return getObjectSpecification(module, cls); } - PyErr_SetObject(PyExc_AttributeError, str__provides__); - return NULL; + provides = PyObject_GetAttr(inst, str__provides__); + /* Return __provides__ if we got it, or return NULL and propagate + * non-AttributeError. */ + if (provides != NULL || !PyErr_ExceptionMatches(PyExc_AttributeError)) { + return provides; + } + + PyErr_Clear(); + + return implementedBy(module, cls); } +static char OSD__name__[] = ( + "_zope_interface_coptimizations.ObjectSpecificationDescriptor"); +static char OSD__doc__[] = "Object Specification Descriptor"; + +#if USE_STATIC_TYPES + +/* + * Static type: ObjectSpecificationDescriptor + */ + +static PyTypeObject OSD_type_def = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = OSD__name__, + .tp_doc = OSD__doc__, + /* No GC for the static version */ + .tp_flags = Py_TPFLAGS_DEFAULT | + Py_TPFLAGS_BASETYPE, + .tp_descr_get = (descrgetfunc)OSD_descr_get, + /*.tp_traverse, = OSD_traverse}, not reqd for static */ + /*.tp_dealloc, = OSD_dealloc}, not reqd for static */ +}; + +#else + +/* + * Heap type: ObjectSpecificationDescriptor + */ +static PyType_Slot OSD_type_slots[] = { + {Py_tp_doc, OSD__doc__}, + {Py_tp_descr_get, OSD_descr_get}, + {Py_tp_traverse, OSD_traverse}, + {Py_tp_dealloc, OSD_dealloc}, + {0, NULL} +}; + +static PyType_Spec OSD_type_spec = { + .name = OSD__name__, + .basicsize = 0, + .flags = BASETYPE_FLAGS, + .slots = OSD_type_slots +}; + +#endif + +/* + * ClassProvidesBase class + */ +typedef struct +{ + SB spec; + /* These members are handled generically, as for SB members. */ + PyObject* _cls; + PyObject* _implements; +} CPB; + static int CPB_traverse(CPB* self, visitproc visit, void* arg) { Py_VISIT(self->_cls); Py_VISIT(self->_implements); - return Spec_traverse((Spec*)self, visit, arg); + return SB_traverse((SB*)self, visit, arg); } static int @@ -612,68 +569,153 @@ CPB_clear(CPB* self) { Py_CLEAR(self->_cls); Py_CLEAR(self->_implements); - Spec_clear((Spec*)self); + SB_clear((SB*)self); return 0; } static void CPB_dealloc(CPB* self) { - PyObject_GC_UnTrack((PyObject *)self); + PyObject_GC_UnTrack((PyObject*)self); CPB_clear(self); - Spec_dealloc((Spec*)self); + SB_dealloc((SB*)self); /* handles decrefing tp */ +} + +static PyObject* +CPB_descr_get(CPB* self, PyObject* inst, PyObject* cls) +{ + PyObject* implements; + + if (self->_cls == NULL) + return NULL; + + if (cls == self->_cls) { + if (inst == NULL) { + Py_INCREF(self); + return OBJECT(self); + } + + implements = self->_implements; + Py_XINCREF(implements); + return implements; + } + + PyErr_SetString(PyExc_AttributeError, "__provides__"); + return NULL; } static PyMemberDef CPB_members[] = { - {"_cls", T_OBJECT_EX, offsetof(CPB, _cls), 0, "Defining class."}, - {"_implements", T_OBJECT_EX, offsetof(CPB, _implements), 0, "Result of implementedBy."}, - {NULL} + { "_cls", T_OBJECT_EX, offsetof(CPB, _cls), 0, "Defining class." }, + { "_implements", + T_OBJECT_EX, + offsetof(CPB, _implements), + 0, + "Result of implementedBy." }, + { NULL } }; -static PyTypeObject CPBType = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ "_interface_coptimizations." - "ClassProvidesBase", - /* tp_basicsize */ sizeof(CPB), - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor)CPB_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, - "C Base class for ClassProvides", - /* tp_traverse */ (traverseproc)CPB_traverse, - /* tp_clear */ (inquiry)CPB_clear, - /* tp_richcompare */ (richcmpfunc)0, - /* tp_weaklistoffset */ (long)0, - /* tp_iter */ (getiterfunc)0, - /* tp_iternext */ (iternextfunc)0, - /* tp_methods */ 0, - /* tp_members */ CPB_members, - /* tp_getset */ 0, - /* tp_base */ &SpecificationBaseType, - /* tp_dict */ 0, /* internal use */ - /* tp_descr_get */ (descrgetfunc)CPB_descr_get, - /* tp_descr_set */ 0, - /* tp_dictoffset */ 0, - /* tp_init */ 0, - /* tp_alloc */ 0, - /* tp_new */ 0, +static char CPB__name__[] = "_zope_interface_coptimizations.ClassProvidesBase"; +static char CPB__doc__[] = "C Base class for ClassProvides"; + +#if USE_STATIC_TYPES + +/* + * Static type: ClassProvidesBase + */ + +static PyTypeObject CPB_type_def = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = CPB__name__, + .tp_doc = CPB__doc__, + .tp_base = &SB_type_def, + .tp_basicsize = sizeof(CPB), + .tp_flags = BASETYPE_FLAGS, + .tp_descr_get = (descrgetfunc)CPB_descr_get, + .tp_traverse = (traverseproc)CPB_traverse, + .tp_clear = (inquiry)CPB_clear, + .tp_dealloc = (destructor)CPB_dealloc, + .tp_members = CPB_members, }; -/* ==================================================================== */ -/* ========== Begin: __call__ and __adapt__ =========================== */ +#else + +/* + * Heap type: ClassProvidesBase + */ +static PyType_Slot CPB_type_slots[] = { + {Py_tp_doc, CPB__doc__}, + {Py_tp_descr_get, CPB_descr_get}, + {Py_tp_traverse, CPB_traverse}, + {Py_tp_clear, CPB_clear}, + {Py_tp_dealloc, CPB_dealloc}, + {Py_tp_members, CPB_members}, + /* tp_base cannot be set as a slot -- pass to PyType_FromModuleAndSpec */ + {0, NULL} +}; + +static PyType_Spec CPB_type_spec = { + .name = CPB__name__, + .basicsize = sizeof(CPB), + .flags = BASETYPE_FLAGS, + .slots = CPB_type_slots +}; + +#endif + +/* + * InterfaceBase class + */ + +typedef struct +{ + SB spec; + PyObject* __name__; + PyObject* __module__; + Py_hash_t _v_cached_hash; +} IB; + +static int +IB_traverse(IB* self, visitproc visit, void* arg) +{ + Py_VISIT(self->__name__); + Py_VISIT(self->__module__); + return SB_traverse((SB*)self, visit, arg); +} + +static int +IB_clear(IB* self) +{ + Py_CLEAR(self->__name__); + Py_CLEAR(self->__module__); + return SB_clear((SB*)self); +} + +static void +IB_dealloc(IB* self) +{ + PyObject_GC_UnTrack((PyObject*)self); + IB_clear(self); + SB_dealloc((SB*)self); /* handles decrefing tp */ +} + +static int +IB__init__(IB* self, PyObject* args, PyObject* kwargs) +{ + static char* kwlist[] = { "__name__", "__module__", NULL }; + PyObject* module = NULL; + PyObject* name = NULL; + + if (!PyArg_ParseTupleAndKeywords( + args, kwargs, "|OO:InterfaceBase.__init__", kwlist, &name, &module)) { + return -1; + } + IB_clear(self); + self->__module__ = module ? module : Py_None; + Py_INCREF(self->__module__); + self->__name__ = name ? name : Py_None; + Py_INCREF(self->__name__); + return 0; +} /* def __adapt__(self, obj): @@ -689,88 +731,84 @@ static PyTypeObject CPBType = { */ -static PyObject * -__adapt__(PyObject *self, PyObject *obj) +const char IB__adapt____doc__[] = "Adapt an object to the receiver"; + +static PyObject* +IB__adapt__(PyObject* self, PyObject* obj) { - PyObject *decl, *args, *adapter; - int implements, i, l; + PyObject *decl; + PyObject *args; + PyObject *adapter; + PyObject *module; + PyObject *adapter_hooks; + PyTypeObject *specification_base_class; + int implements; + int i; + int l; + + module = _get_module(Py_TYPE(self)); + + decl = providedBy(module, obj); + if (decl == NULL) + return NULL; - decl = providedBy(NULL, obj); - if (decl == NULL) - return NULL; + specification_base_class = _get_specification_base_class(Py_TYPE(self)); - if (PyObject_TypeCheck(decl, &SpecificationBaseType)) - { - PyObject *implied; + if (PyObject_TypeCheck(decl, specification_base_class)) { + PyObject* implied; - implied = ((Spec*)decl)->_implied; - if (implied == NULL) - { - Py_DECREF(decl); - return NULL; + implied = ((SB*)decl)->_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); + 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; + 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; + 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); + + adapter_hooks = _get_adapter_hooks(Py_TYPE(self)); + l = PyList_GET_SIZE(adapter_hooks); + 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(adapter); } - Py_DECREF(args); + Py_DECREF(args); - Py_INCREF(Py_None); - return Py_None; + Py_INCREF(Py_None); + return Py_None; } -typedef struct { - Spec spec; - PyObject* __name__; - PyObject* __module__; - Py_hash_t _v_cached_hash; -} IB; - -static struct PyMethodDef ib_methods[] = { - {"__adapt__", (PyCFunction)__adapt__, METH_O, - "Adapt an object to the receiver"}, - {NULL, NULL} /* sentinel */ -}; - /* def __call__(self, obj, alternate=_marker): try: @@ -792,120 +830,74 @@ static struct PyMethodDef ib_methods[] = { raise TypeError("Could not adapt", obj, self) */ -static PyObject * -IB_call(PyObject *self, PyObject *args, PyObject *kwargs) +static PyObject* +IB__call__(PyObject* self, PyObject* args, PyObject* kwargs) { - PyObject *conform, *obj, *alternate, *adapter; - static char *kwlist[] = {"obj", "alternate", NULL}; - conform = obj = alternate = adapter = NULL; + PyObject *conform, *obj, *alternate, *adapter; + static char* kwlist[] = { "obj", "alternate", NULL }; + conform = obj = alternate = adapter = NULL; + if (!PyArg_ParseTupleAndKeywords( + args, kwargs, "O|O", kwlist, &obj, &alternate)) + return NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist, - &obj, &alternate)) - return NULL; + conform = PyObject_GetAttr(obj, str__conform__); + if (conform == NULL) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + /* Propagate non-AttributeErrors */ + return NULL; + } + PyErr_Clear(); - conform = PyObject_GetAttr(obj, str__conform__); - if (conform == NULL) - { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) - { - /* Propagate non-AttributeErrors */ - return NULL; - } - PyErr_Clear(); - - Py_INCREF(Py_None); - conform = Py_None; - } - - if (conform != Py_None) - { - adapter = PyObject_CallMethodObjArgs(self, str_call_conform, - conform, NULL); - Py_DECREF(conform); - if (adapter == NULL || adapter != Py_None) - return adapter; - Py_DECREF(adapter); - } - else - { - Py_DECREF(conform); - } - - /* We differ from the Python code here. For speed, instead of always calling - self.__adapt__(), we check to see if the type has defined it. Checking in - the dict for __adapt__ isn't sufficient because there's no cheap way to - tell if it's the __adapt__ that InterfaceBase itself defines (our type - will *never* be InterfaceBase, we're always subclassed by - InterfaceClass). Instead, we cooperate with InterfaceClass in Python to - set a flag in a new subclass when this is necessary. */ - if (PyDict_GetItem(self->ob_type->tp_dict, str_CALL_CUSTOM_ADAPT)) - { - /* Doesn't matter what the value is. Simply being present is enough. */ - adapter = PyObject_CallMethodObjArgs(self, str__adapt__, obj, NULL); - } - else - { - 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; -} + Py_INCREF(Py_None); + conform = Py_None; + } + if (conform != Py_None) { + adapter = + PyObject_CallMethodObjArgs(self, str_call_conform, conform, NULL); + Py_DECREF(conform); + if (adapter == NULL || adapter != Py_None) + return adapter; + Py_DECREF(adapter); + } else { + Py_DECREF(conform); + } -static int -IB_traverse(IB* self, visitproc visit, void* arg) -{ - Py_VISIT(self->__name__); - Py_VISIT(self->__module__); - return Spec_traverse((Spec*)self, visit, arg); -} + /* We differ from the Python code here. For speed, instead of always calling + self.__adapt__(), we check to see if the type has defined it. Checking in + the dict for __adapt__ isn't sufficient because there's no cheap way to + tell if it's the __adapt__ that InterfaceBase itself defines (our type + will *never* be InterfaceBase, we're always subclassed by + InterfaceClass). Instead, we cooperate with InterfaceClass in Python to + set a flag in a new subclass when this is necessary. */ + if (PyDict_GetItemString(self->ob_type->tp_dict, "_CALL_CUSTOM_ADAPT")) { + /* Doesn't matter what the value is. Simply being present is enough. */ + adapter = PyObject_CallMethodObjArgs(self, str__adapt__, obj, NULL); + } else { + adapter = IB__adapt__(self, obj); + } -static int -IB_clear(IB* self) -{ - Py_CLEAR(self->__name__); - Py_CLEAR(self->__module__); - return Spec_clear((Spec*)self); -} + if (adapter == NULL || adapter != Py_None) { + return adapter; + } + Py_DECREF(adapter); -static void -IB_dealloc(IB* self) -{ - PyObject_GC_UnTrack((PyObject *)self); - IB_clear(self); - Spec_dealloc((Spec*)self); -} + if (alternate != NULL) { + Py_INCREF(alternate); + return alternate; + } -static PyMemberDef IB_members[] = { - {"__name__", T_OBJECT_EX, offsetof(IB, __name__), 0, ""}, - // The redundancy between __module__ and __ibmodule__ is because - // __module__ is often shadowed by subclasses. - {"__module__", T_OBJECT_EX, offsetof(IB, __module__), READONLY, ""}, - {"__ibmodule__", T_OBJECT_EX, offsetof(IB, __module__), 0, ""}, - {NULL} -}; + adapter = Py_BuildValue("sOO", "Could not adapt", obj, self); + if (adapter != NULL) { + PyErr_SetObject(PyExc_TypeError, adapter); + Py_DECREF(adapter); + } + return NULL; +} static Py_hash_t -IB_hash(IB* self) +IB__hash__(IB* self) { PyObject* tuple; if (!self->__module__) { @@ -930,14 +922,13 @@ IB_hash(IB* self) return self->_v_cached_hash; } -static PyTypeObject InterfaceBaseType; - static PyObject* IB_richcompare(IB* self, PyObject* other, int op) { PyObject* othername; PyObject* othermod; PyObject* oresult; + PyTypeObject* interface_base_class; IB* otherib; int result; @@ -945,42 +936,48 @@ IB_richcompare(IB* self, PyObject* other, int op) oresult = othername = othermod = NULL; if (OBJECT(self) == other) { - switch(op) { - case Py_EQ: - case Py_LE: - case Py_GE: - Py_RETURN_TRUE; - break; - case Py_NE: - Py_RETURN_FALSE; + switch (op) { + case Py_EQ: + case Py_LE: + case Py_GE: + Py_RETURN_TRUE; + break; + case Py_NE: + Py_RETURN_FALSE; } } if (other == Py_None) { - switch(op) { - case Py_LT: - case Py_LE: - case Py_NE: - Py_RETURN_TRUE; - default: - Py_RETURN_FALSE; + switch (op) { + case Py_LT: + case Py_LE: + case Py_NE: + Py_RETURN_TRUE; + default: + Py_RETURN_FALSE; } } - if (PyObject_TypeCheck(other, &InterfaceBaseType)) { + interface_base_class = _get_interface_base_class(Py_TYPE(self)); + if (interface_base_class == NULL) { + oresult = Py_NotImplemented; + goto cleanup; + } + + if (PyObject_TypeCheck(other, interface_base_class)) { // This branch borrows references. No need to clean // up if otherib is not null. otherib = (IB*)other; othername = otherib->__name__; othermod = otherib->__module__; - } - else { - othername = PyObject_GetAttrString(other, "__name__"); + } else { + othername = PyObject_GetAttr(other, str__name__); if (othername) { - othermod = PyObject_GetAttrString(other, "__module__"); + othermod = PyObject_GetAttr(other, str__module__); } if (!othername || !othermod) { - if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_AttributeError)) { + if (PyErr_Occurred() && + PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Clear(); oresult = Py_NotImplemented; } @@ -998,8 +995,7 @@ IB_richcompare(IB* self, PyObject* other, int op) result = PyObject_RichCompareBool(self->__name__, othername, Py_EQ); if (result == 0) { result = PyObject_RichCompareBool(self->__name__, othername, op); - } - else if (result == 1) { + } else if (result == 1) { result = PyObject_RichCompareBool(self->__module__, othermod, op); } // If either comparison failed, we have an error set. @@ -1010,7 +1006,6 @@ IB_richcompare(IB* self, PyObject* other, int op) oresult = result ? Py_True : Py_False; - cleanup: Py_XINCREF(oresult); @@ -1019,133 +1014,126 @@ cleanup: Py_XDECREF(othermod); } return oresult; - -} - -static int -IB_init(IB* self, PyObject* args, PyObject* kwargs) -{ - static char *kwlist[] = {"__name__", "__module__", NULL}; - PyObject* module = NULL; - PyObject* name = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO:InterfaceBase.__init__", kwlist, - &name, &module)) { - return -1; - } - IB_clear(self); - self->__module__ = module ? module : Py_None; - Py_INCREF(self->__module__); - self->__name__ = name ? name : Py_None; - Py_INCREF(self->__name__); - return 0; } +static PyMemberDef IB_members[] = { + { "__name__", T_OBJECT_EX, offsetof(IB, __name__), 0, "" }, + // The redundancy between __module__ and __ibmodule__ is because + // __module__ is often shadowed by subclasses. + { "__module__", T_OBJECT_EX, offsetof(IB, __module__), READONLY, "" }, + { "__ibmodule__", T_OBJECT_EX, offsetof(IB, __module__), 0, "" }, + { NULL } +}; -static PyTypeObject InterfaceBaseType = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ "_zope_interface_coptimizations." - "InterfaceBase", - /* tp_basicsize */ sizeof(IB), - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor)IB_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)IB_hash, - /* 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 | Py_TPFLAGS_HAVE_GC, - /* tp_doc */ "Interface base type providing __call__ and __adapt__", - /* tp_traverse */ (traverseproc)IB_traverse, - /* tp_clear */ (inquiry)IB_clear, - /* tp_richcompare */ (richcmpfunc)IB_richcompare, - /* tp_weaklistoffset */ (long)0, - /* tp_iter */ (getiterfunc)0, - /* tp_iternext */ (iternextfunc)0, - /* tp_methods */ ib_methods, - /* tp_members */ IB_members, - /* tp_getset */ 0, - /* tp_base */ &SpecificationBaseType, - /* tp_dict */ 0, - /* tp_descr_get */ 0, - /* tp_descr_set */ 0, - /* tp_dictoffset */ 0, - /* tp_init */ (initproc)IB_init, +static struct PyMethodDef IB_methods[] = { + { "__adapt__", (PyCFunction)IB__adapt__, METH_O, IB__adapt____doc__}, + { NULL, NULL } /* sentinel */ }; -/* =================== End: __call__ and __adapt__ ==================== */ -/* ==================================================================== */ +static char IB__name__[] ="_zope_interface_coptimizations.InterfaceBase"; +static char IB__doc__[] = ( + "Interface base type providing __call__ and __adapt__" +); -/* ==================================================================== */ -/* ========================== Begin: Lookup Bases ===================== */ +#if USE_STATIC_TYPES -typedef struct { - PyObject_HEAD - PyObject *_cache; - PyObject *_mcache; - PyObject *_scache; -} lookup; +/* + * Static type: InterfaceBase + */ + +static PyTypeObject IB_type_def = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = IB__name__, + .tp_doc = IB__doc__, + .tp_base = &SB_type_def, + .tp_basicsize = sizeof(IB), + .tp_flags = BASETYPE_FLAGS, + .tp_init = (initproc)IB__init__, + .tp_hash = (hashfunc)IB__hash__, + .tp_richcompare = (richcmpfunc)IB_richcompare, + .tp_call = (ternaryfunc)IB__call__, + .tp_traverse = (traverseproc)IB_traverse, + .tp_clear = (inquiry)IB_clear, + .tp_dealloc = (destructor)IB_dealloc, + .tp_methods = IB_methods, + .tp_members = IB_members, +}; -typedef struct { - PyObject_HEAD - PyObject *_cache; - PyObject *_mcache; - PyObject *_scache; - PyObject *_verify_ro; - PyObject *_verify_generations; -} verify; +#else -static int -lookup_traverse(lookup *self, visitproc visit, void *arg) -{ - int vret; +/* + * Heap type: InterfaceBase + */ +static PyType_Slot IB_type_slots[] = { + {Py_tp_doc, IB__doc__}, + {Py_tp_init, IB__init__}, + {Py_tp_hash, IB__hash__}, + {Py_tp_richcompare, IB_richcompare}, + {Py_tp_call, IB__call__}, + {Py_tp_traverse, IB_traverse}, + {Py_tp_clear, IB_clear}, + {Py_tp_dealloc, IB_dealloc}, + {Py_tp_methods, IB_methods}, + {Py_tp_members, IB_members}, + /* tp_base cannot be set as a slot -- pass to PyType_FromModuleAndSpec */ + {0, NULL} +}; - if (self->_cache) { - vret = visit(self->_cache, arg); - if (vret != 0) - return vret; - } +static PyType_Spec IB_type_spec = { + .name = IB__name__, + .basicsize = sizeof(IB), + .flags = BASETYPE_FLAGS, + .slots = IB_type_slots +}; - if (self->_mcache) { - vret = visit(self->_mcache, arg); - if (vret != 0) - return vret; - } +#endif - if (self->_scache) { - vret = visit(self->_scache, arg); - if (vret != 0) - return vret; - } +/* + * LookupBase class + */ +typedef struct +{ + PyObject_HEAD + PyObject* _cache; + PyObject* _mcache; + PyObject* _scache; +} LB; - return 0; +static int +LB_traverse(LB* self, visitproc visit, void* arg) +{ +/* Visit our 'tp_type' only on Python >= 3.9, per + * https://docs.python.org/3/howto/isolating-extensions.html + * #tp-traverse-in-python-3-8-and-lower + */ +#if USE_HEAP_TYPES && PY_VERSION_HEX > 0x03090000 + Py_VISIT(Py_TYPE(self)); +#endif + Py_VISIT(self->_cache); + Py_VISIT(self->_mcache); + Py_VISIT(self->_scache); + return 0; } static int -lookup_clear(lookup *self) +LB_clear(LB* self) { - Py_CLEAR(self->_cache); - Py_CLEAR(self->_mcache); - Py_CLEAR(self->_scache); - return 0; + Py_CLEAR(self->_cache); + Py_CLEAR(self->_mcache); + Py_CLEAR(self->_scache); + return 0; } static void -lookup_dealloc(lookup *self) +LB_dealloc(LB* self) { - PyObject_GC_UnTrack((PyObject *)self); - lookup_clear(self); - Py_TYPE(self)->tp_free((PyObject*)self); + PyObject_GC_UnTrack((PyObject*)self); + PyTypeObject* tp = Py_TYPE(self); + LB_clear(self); + tp->tp_free((PyObject*)self); +#if USE_HEAP_TYPES + Py_DECREF(tp); +#endif } /* @@ -1154,18 +1142,14 @@ lookup_dealloc(lookup *self) self._mcache.clear() self._scache.clear() */ -static PyObject * -lookup_changed(lookup *self, PyObject *ignored) +static PyObject* +LB_changed(LB* self, PyObject* ignored) { - lookup_clear(self); - Py_INCREF(Py_None); - return Py_None; + LB_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) @@ -1180,43 +1164,43 @@ lookup_changed(lookup *self, PyObject *ignored) cache = c return cache */ -static PyObject * -_subcache(PyObject *cache, PyObject *key) +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; + 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; + return subcache; } -static PyObject * -_getcache(lookup *self, PyObject *provided, PyObject *name) + +static PyObject* +_getcache(LB* self, PyObject* provided, PyObject* name) { - PyObject *cache; + PyObject* cache; - ASSURE_DICT(self->_cache); - cache = _subcache(self->_cache, provided); - if (cache == NULL) - return NULL; + ASSURE_DICT(self->_cache); - if (name != NULL && PyObject_IsTrue(name)) - cache = _subcache(cache, name); + cache = _subcache(self->_cache, provided); + if (cache == NULL) + return NULL; - return cache; -} + if (name != NULL && PyObject_IsTrue(name)) + cache = _subcache(cache, name); + return cache; +} /* def lookup(self, required, provided, name=u'', default=None): @@ -1239,86 +1223,85 @@ _getcache(lookup *self, PyObject *provided, PyObject *name) return result */ -static PyObject * -_lookup(lookup *self, - PyObject *required, PyObject *provided, PyObject *name, - PyObject *default_) -{ - PyObject *result, *key, *cache; - result = key = cache = NULL; - if ( name && !PyUnicode_Check(name) ) - { - PyErr_SetString(PyExc_ValueError, - "name is not a string or unicode"); - return NULL; - } +static PyObject* +_lookup(LB* self, + PyObject* required, + PyObject* provided, + PyObject* name, + PyObject* default_) +{ + PyObject *result, *key, *cache; + result = key = cache = NULL; + if (name && !PyUnicode_Check(name)) { + PyErr_SetString(PyExc_ValueError, "name is not a string"); + return NULL; + } - /* If `required` is a lazy sequence, it could have arbitrary side-effects, - such as clearing our caches. So we must not retrieve the cache until - after resolving it. */ - required = PySequence_Tuple(required); - if (required == NULL) - return NULL; + /* If `required` is a lazy sequence, it could have arbitrary side-effects, + such as clearing our caches. So we must not retrieve the cache until + after resolving it. */ + required = PySequence_Tuple(required); + if (required == NULL) + return NULL; + cache = _getcache(self, provided, name); + if (cache == NULL) + return NULL; - cache = _getcache(self, provided, name); - if (cache == 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; - 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; + 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; + status = PyDict_SetItem(cache, key, result); + Py_DECREF(required); + if (status < 0) { + Py_DECREF(result); + return NULL; } - } - else - { - Py_INCREF(result); - Py_DECREF(required); + } else { + Py_INCREF(result); + Py_DECREF(required); } - if (result == Py_None && default_ != NULL) - { - Py_DECREF(Py_None); - Py_INCREF(default_); - return default_; + if (result == Py_None && default_ != NULL) { + Py_DECREF(Py_None); + Py_INCREF(default_); + return default_; } - return result; + 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:LookupBase.lookup", kwlist, - &required, &provided, &name, &default_)) - return NULL; +static PyObject* +LB_lookup(LB* 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:LookupBase.lookup", + kwlist, + &required, + &provided, + &name, + &default_)) + return NULL; - return _lookup(self, required, provided, name, default_); + return _lookup(self, required, provided, name, default_); } - /* def lookup1(self, required, provided, name=u'', default=None): cache = self._getcache(provided, name) @@ -1331,59 +1314,61 @@ lookup_lookup(lookup *self, PyObject *args, PyObject *kwds) return result */ -static PyObject * -_lookup1(lookup *self, - PyObject *required, PyObject *provided, PyObject *name, - PyObject *default_) +static PyObject* +_lookup1(LB* self, + PyObject* required, + PyObject* provided, + PyObject* name, + PyObject* default_) { - PyObject *result, *cache; - - if ( name && !PyUnicode_Check(name) ) - { - 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; + PyObject *result, *cache; - tup = PyTuple_New(1); - if (tup == NULL) + if (name && !PyUnicode_Check(name)) { + PyErr_SetString(PyExc_ValueError, "name is not a string"); 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_; + + 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); + Py_INCREF(result); } - return result; + return result; } -static PyObject * -lookup_lookup1(lookup *self, PyObject *args, PyObject *kwds) +static PyObject* +LB_lookup1(LB* 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:LookupBase.lookup1", kwlist, - &required, &provided, &name, &default_)) - return NULL; + static char* kwlist[] = { "required", "provided", "name", "default", NULL }; + PyObject *required, *provided, *name = NULL, *default_ = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, + kwds, + "OO|OO:LookupBase.lookup1", + kwlist, + &required, + &provided, + &name, + &default_)) + return NULL; - return _lookup1(self, required, provided, name, default_); + return _lookup1(self, required, provided, name, default_); } /* @@ -1403,82 +1388,97 @@ lookup_lookup1(lookup *self, PyObject *args, PyObject *kwds) return default */ -static PyObject * -_adapter_hook(lookup *self, - PyObject *provided, PyObject *object, PyObject *name, - PyObject *default_) +static PyObject* +_adapter_hook(LB* self, + PyObject* provided, + PyObject* object, + PyObject* name, + PyObject* default_) { - PyObject *required, *factory, *result; + PyObject *required; + PyObject *factory; + PyObject *result; + PyObject *module; - if ( name && !PyUnicode_Check(name) ) - { - PyErr_SetString(PyExc_ValueError, - "name is not a string or unicode"); - return NULL; - } + module = _get_module(Py_TYPE(self)); - required = providedBy(NULL, object); - if (required == NULL) - return NULL; + if (name && !PyUnicode_Check(name)) { + PyErr_SetString(PyExc_ValueError, "name is not a string"); + return NULL; + } - factory = _lookup1(self, required, provided, name, Py_None); - Py_DECREF(required); - if (factory == NULL) - return NULL; + required = providedBy(module, object); + if (required == NULL) + return NULL; - if (factory != Py_None) - { - if (PyObject_TypeCheck(object, &PySuper_Type)) { - PyObject* self = PyObject_GetAttr(object, str__self__); - if (self == NULL) - { - Py_DECREF(factory); - return NULL; - } - // Borrow the reference to self - Py_DECREF(self); - object = self; - } - result = PyObject_CallFunctionObjArgs(factory, object, NULL); - Py_DECREF(factory); - if (result == NULL || result != Py_None) - return result; - } - else - result = factory; /* None */ + factory = _lookup1(self, required, provided, name, Py_None); + Py_DECREF(required); + if (factory == NULL) + return NULL; - if (default_ == NULL || default_ == result) /* No default specified, */ - return result; /* Return None. result is owned None */ + if (factory != Py_None) { + if (PyObject_TypeCheck(object, &PySuper_Type)) { + PyObject* self = PyObject_GetAttr(object, str__self__); + if (self == NULL) { + Py_DECREF(factory); + return NULL; + } + // Borrow the reference to self + Py_DECREF(self); + object = self; + } + result = PyObject_CallFunctionObjArgs(factory, object, NULL); + Py_DECREF(factory); + if (result == NULL || result != Py_None) + return result; + } else + result = factory; /* None */ - Py_DECREF(result); - Py_INCREF(default_); + if (default_ == NULL || default_ == result) /* No default specified, */ + return result; /* Return None. result is owned None */ - return default_; + 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:LookupBase.adapter_hook", kwlist, - &provided, &object, &name, &default_)) - return NULL; +static PyObject* +LB_adapter_hook(LB* 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:LookupBase.adapter_hook", + kwlist, + &provided, + &object, + &name, + &default_)) + return NULL; - return _adapter_hook(self, provided, object, name, default_); + return _adapter_hook(self, provided, object, name, default_); } -static PyObject * -lookup_queryAdapter(lookup *self, PyObject *args, PyObject *kwds) +static PyObject* +LB_queryAdapter(LB* 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:LookupBase.queryAdapter", kwlist, - &object, &provided, &name, &default_)) - return NULL; + static char* kwlist[] = { "object", "provided", "name", "default", NULL }; + PyObject *object, *provided, *name = NULL, *default_ = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, + kwds, + "OO|OO:LookupBase.queryAdapter", + kwlist, + &object, + &provided, + &name, + &default_)) + return NULL; - return _adapter_hook(self, provided, object, name, default_); + return _adapter_hook(self, provided, object, name, default_); } /* @@ -1496,60 +1496,57 @@ lookup_queryAdapter(lookup *self, PyObject *args, PyObject *kwds) return result */ -static PyObject * -_lookupAll(lookup *self, PyObject *required, PyObject *provided) +static PyObject* +_lookupAll(LB* self, PyObject* required, PyObject* provided) { - PyObject *cache, *result; + PyObject *cache, *result; - /* resolve before getting cache. See note in _lookup. */ - required = PySequence_Tuple(required); - if (required == NULL) - return NULL; + /* resolve before getting cache. See note in _lookup. */ + required = PySequence_Tuple(required); + if (required == NULL) + return NULL; - ASSURE_DICT(self->_mcache); - cache = _subcache(self->_mcache, provided); - if (cache == NULL) - return NULL; + ASSURE_DICT(self->_mcache); + + cache = _subcache(self->_mcache, provided); + if (cache == 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; + 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; + status = PyDict_SetItem(cache, required, result); + Py_DECREF(required); + if (status < 0) { + Py_DECREF(result); + return NULL; } - } - else - { - Py_INCREF(result); - Py_DECREF(required); + } else { + Py_INCREF(result); + Py_DECREF(required); } - return result; + return result; } -static PyObject * -lookup_lookupAll(lookup *self, PyObject *args, PyObject *kwds) + +static PyObject* +LB_lookupAll(LB* self, PyObject* args, PyObject* kwds) { - static char *kwlist[] = {"required", "provided", NULL}; - PyObject *required, *provided; + static char* kwlist[] = { "required", "provided", NULL }; + PyObject *required, *provided; - if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO:LookupBase.lookupAll", kwlist, - &required, &provided)) - return NULL; + if (!PyArg_ParseTupleAndKeywords( + args, kwds, "OO:LookupBase.lookupAll", kwlist, &required, &provided)) + return NULL; - return _lookupAll(self, required, provided); + return _lookupAll(self, required, provided); } /* @@ -1567,147 +1564,163 @@ lookup_lookupAll(lookup *self, PyObject *args, PyObject *kwds) return result */ -static PyObject * -_subscriptions(lookup *self, PyObject *required, PyObject *provided) +static PyObject* +_subscriptions(LB* self, PyObject* required, PyObject* provided) { - PyObject *cache, *result; + PyObject *cache, *result; - /* resolve before getting cache. See note in _lookup. */ - required = PySequence_Tuple(required); - if (required == NULL) - return NULL; + /* resolve before getting cache. See note in _lookup. */ + required = PySequence_Tuple(required); + if (required == NULL) + return NULL; - ASSURE_DICT(self->_scache); - cache = _subcache(self->_scache, provided); - if (cache == NULL) - return NULL; + ASSURE_DICT(self->_scache); + + cache = _subcache(self->_scache, provided); + if (cache == 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; + 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; + status = PyDict_SetItem(cache, required, result); + Py_DECREF(required); + if (status < 0) { + Py_DECREF(result); + return NULL; } - } - else - { - Py_INCREF(result); - Py_DECREF(required); + } else { + Py_INCREF(result); + Py_DECREF(required); } - return result; + return result; } -static PyObject * -lookup_subscriptions(lookup *self, PyObject *args, PyObject *kwds) + +static PyObject* +LB_subscriptions(LB* self, PyObject* args, PyObject* kwds) { - static char *kwlist[] = {"required", "provided", NULL}; - PyObject *required, *provided; + static char* kwlist[] = { "required", "provided", NULL }; + PyObject *required, *provided; - if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, - &required, &provided)) - return NULL; + if (!PyArg_ParseTupleAndKeywords( + args, kwds, "OO", kwlist, &required, &provided)) + return NULL; - return _subscriptions(self, required, provided); + 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 struct PyMethodDef LB_methods[] = { + { "changed", (PyCFunction)LB_changed, METH_O, "" }, + { "lookup", (PyCFunction)LB_lookup, METH_KEYWORDS | METH_VARARGS, "" }, + { "lookup1", + (PyCFunction)LB_lookup1, + METH_KEYWORDS | METH_VARARGS, + "" }, + { "queryAdapter", + (PyCFunction)LB_queryAdapter, + METH_KEYWORDS | METH_VARARGS, + "" }, + { "adapter_hook", + (PyCFunction)LB_adapter_hook, + METH_KEYWORDS | METH_VARARGS, + "" }, + { "lookupAll", + (PyCFunction)LB_lookupAll, + METH_KEYWORDS | METH_VARARGS, + "" }, + { "subscriptions", + (PyCFunction)LB_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 char LB__name__[] = "_zope_interface_coptimizations.LookupBase"; +static char LB__doc__[] = "Base class for adapter registries"; + + +#if USE_STATIC_TYPES + +/* + * Static type: LookupBase + */ + +static PyTypeObject LB_type_def = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = LB__name__, + .tp_doc = LB__doc__, + .tp_basicsize = sizeof(LB), + .tp_flags = BASETYPE_FLAGS, + .tp_traverse = (traverseproc)LB_traverse, + .tp_clear = (inquiry)LB_clear, + .tp_dealloc = (destructor)&LB_dealloc, + .tp_methods = LB_methods, }; -static int -verifying_traverse(verify *self, visitproc visit, void *arg) -{ - int vret; +#else - vret = lookup_traverse((lookup *)self, visit, arg); - if (vret != 0) - return vret; +/* + * Heap type: LookupBase + */ +static PyType_Slot LB_type_slots[] = { + {Py_tp_doc, LB__doc__}, + {Py_tp_traverse, LB_traverse}, + {Py_tp_clear, LB_clear}, + {Py_tp_dealloc, LB_dealloc}, + {Py_tp_methods, LB_methods}, + {0, NULL} +}; - 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; - } +static PyType_Spec LB_type_spec = { + .name = LB__name__, + .basicsize = sizeof(LB), + .flags = BASETYPE_FLAGS, + .slots = LB_type_slots +}; - return 0; -} +#endif + +typedef struct +{ + LB lookup; + PyObject* _verify_ro; + PyObject* _verify_generations; +} VB; static int -verifying_clear(verify *self) +VB_traverse(VB* self, visitproc visit, void* arg) { - lookup_clear((lookup *)self); - Py_CLEAR(self->_verify_generations); - Py_CLEAR(self->_verify_ro); - return 0; + Py_VISIT(self->_verify_ro); + Py_VISIT(self->_verify_generations); + return LB_traverse((LB*)self, visit, arg); } +static int +VB_clear(VB* self) +{ + Py_CLEAR(self->_verify_generations); + Py_CLEAR(self->_verify_ro); + return LB_clear((LB*)self); +} static void -verifying_dealloc(verify *self) +VB_dealloc(VB* self) { - PyObject_GC_UnTrack((PyObject *)self); - verifying_clear(self); - Py_TYPE(self)->tp_free((PyObject*)self); + PyObject_GC_UnTrack((PyObject*)self); + PyTypeObject *tp = Py_TYPE(self); + VB_clear(self); + tp->tp_free((PyObject*)self); +#if USE_HEAP_TYPES + Py_DECREF(tp); +#endif } /* @@ -1716,65 +1729,63 @@ verifying_dealloc(verify *self) 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; +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); + PyTuple_SET_ITEM(generations, i, generation); } - return generations; + return generations; } -static PyObject * -verifying_changed(verify *self, PyObject *ignored) +static PyObject* +verify_changed(VB* self, PyObject* ignored) { - PyObject *t, *ro; + PyObject *t, *ro; - verifying_clear(self); + VB_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_GetAttr(OBJECT(self), str_registry); + if (t == NULL) + return NULL; - t = PyObject_CallFunctionObjArgs(OBJECT(&PyTuple_Type), ro, NULL); - Py_DECREF(ro); - if (t == NULL) - return NULL; + ro = PyObject_GetAttr(t, strro); + Py_DECREF(t); + if (ro == NULL) + return NULL; - ro = PyTuple_GetSlice(t, 1, PyTuple_GET_SIZE(t)); - 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_generations = _generations_tuple(ro); + if (self->_verify_generations == NULL) { + Py_DECREF(ro); + return NULL; } - self->_verify_ro = ro; + self->_verify_ro = ro; - Py_INCREF(Py_None); - return Py_None; + Py_INCREF(Py_None); + return Py_None; } /* @@ -1784,296 +1795,880 @@ verifying_changed(verify *self, PyObject *ignored) self.changed(None) */ static int -_verify(verify *self) +_verify(VB* self) { - PyObject *changed_result; + PyObject* changed_result; - if (self->_verify_ro != NULL && self->_verify_generations != NULL) - { - PyObject *generations; - int changed; + if (self->_verify_ro != NULL && self->_verify_generations != NULL) { + PyObject* generations; + int changed; - generations = _generations_tuple(self->_verify_ro); - if (generations == NULL) - return -1; + 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; + changed = PyObject_RichCompareBool( + self->_verify_generations, generations, Py_NE); + Py_DECREF(generations); + if (changed == -1) + return -1; - if (changed == 0) - return 0; + if (changed == 0) + return 0; } - changed_result = PyObject_CallMethodObjArgs(OBJECT(self), strchanged, - Py_None, NULL); - if (changed_result == NULL) - return -1; + changed_result = + PyObject_CallMethodObjArgs(OBJECT(self), strchanged, Py_None, NULL); + if (changed_result == NULL) + return -1; - Py_DECREF(changed_result); - return 0; + Py_DECREF(changed_result); + return 0; } -static PyObject * -verifying_lookup(verify *self, PyObject *args, PyObject *kwds) +static PyObject* +VB_lookup(VB* self, PyObject* args, PyObject* kwds) { - static char *kwlist[] = {"required", "provided", "name", "default", NULL}; - PyObject *required, *provided, *name=NULL, *default_=NULL; + 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 (!PyArg_ParseTupleAndKeywords( + args, kwds, "OO|OO", kwlist, &required, &provided, &name, &default_)) + return NULL; - if (_verify(self) < 0) - return NULL; + if (_verify(self) < 0) + return NULL; - return _lookup((lookup *)self, required, provided, name, default_); + return _lookup((LB*)self, required, provided, name, default_); } -static PyObject * -verifying_lookup1(verify *self, PyObject *args, PyObject *kwds) +static PyObject* +VB_lookup1(VB* self, PyObject* args, PyObject* kwds) { - static char *kwlist[] = {"required", "provided", "name", "default", NULL}; - PyObject *required, *provided, *name=NULL, *default_=NULL; + 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 (!PyArg_ParseTupleAndKeywords( + args, kwds, "OO|OO", kwlist, &required, &provided, &name, &default_)) + return NULL; - if (_verify(self) < 0) - return NULL; + if (_verify(self) < 0) + return NULL; - return _lookup1((lookup *)self, required, provided, name, default_); + return _lookup1((LB*)self, required, provided, name, default_); } -static PyObject * -verifying_adapter_hook(verify *self, PyObject *args, PyObject *kwds) +static PyObject* +VB_adapter_hook(VB* self, PyObject* args, PyObject* kwds) { - static char *kwlist[] = {"provided", "object", "name", "default", NULL}; - PyObject *object, *provided, *name=NULL, *default_=NULL; + 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 (!PyArg_ParseTupleAndKeywords( + args, kwds, "OO|OO", kwlist, &provided, &object, &name, &default_)) + return NULL; - if (_verify(self) < 0) - return NULL; + if (_verify(self) < 0) + return NULL; - return _adapter_hook((lookup *)self, provided, object, name, default_); + return _adapter_hook((LB*)self, provided, object, name, default_); } -static PyObject * -verifying_queryAdapter(verify *self, PyObject *args, PyObject *kwds) +static PyObject* +VB_queryAdapter(VB* self, PyObject* args, PyObject* kwds) { - static char *kwlist[] = {"object", "provided", "name", "default", NULL}; - PyObject *object, *provided, *name=NULL, *default_=NULL; + 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 (!PyArg_ParseTupleAndKeywords( + args, kwds, "OO|OO", kwlist, &object, &provided, &name, &default_)) + return NULL; - if (_verify(self) < 0) - return NULL; + if (_verify(self) < 0) + return NULL; - return _adapter_hook((lookup *)self, provided, object, name, default_); + return _adapter_hook((LB*)self, provided, object, name, default_); } -static PyObject * -verifying_lookupAll(verify *self, PyObject *args, PyObject *kwds) +static PyObject* +VB_lookupAll(VB* self, PyObject* args, PyObject* kwds) { - static char *kwlist[] = {"required", "provided", NULL}; - PyObject *required, *provided; + static char* kwlist[] = { "required", "provided", NULL }; + PyObject *required, *provided; - if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, - &required, &provided)) - return NULL; + if (!PyArg_ParseTupleAndKeywords( + args, kwds, "OO", kwlist, &required, &provided)) + return NULL; - if (_verify(self) < 0) - return NULL; + if (_verify(self) < 0) + return NULL; - return _lookupAll((lookup *)self, required, provided); + return _lookupAll((LB*)self, required, provided); } -static PyObject * -verifying_subscriptions(verify *self, PyObject *args, PyObject *kwds) +static PyObject* +VB_subscriptions(VB* self, PyObject* args, PyObject* kwds) { - static char *kwlist[] = {"required", "provided", NULL}; - PyObject *required, *provided; + static char* kwlist[] = { "required", "provided", NULL }; + PyObject *required, *provided; - if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, - &required, &provided)) - return NULL; + if (!PyArg_ParseTupleAndKeywords( + args, kwds, "OO", kwlist, &required, &provided)) + return NULL; - if (_verify(self) < 0) - return NULL; + if (_verify(self) < 0) + return NULL; - return _subscriptions((lookup *)self, required, provided); + return _subscriptions((LB*)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 struct PyMethodDef VB_methods[] = { + { "changed", (PyCFunction)verify_changed, METH_O, "" }, + { "lookup", + (PyCFunction)VB_lookup, + METH_KEYWORDS | METH_VARARGS, + "" }, + { "lookup1", + (PyCFunction)VB_lookup1, + METH_KEYWORDS | METH_VARARGS, + "" }, + { "queryAdapter", + (PyCFunction)VB_queryAdapter, + METH_KEYWORDS | METH_VARARGS, + "" }, + { "adapter_hook", + (PyCFunction)VB_adapter_hook, + METH_KEYWORDS | METH_VARARGS, + "" }, + { "lookupAll", + (PyCFunction)VB_lookupAll, + METH_KEYWORDS | METH_VARARGS, + "" }, + { "subscriptions", + (PyCFunction)VB_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, -}; +static char VB__name__[] = "_zope_interface_coptimizations.VerifyingBase"; +static char VB__doc__[] = "Base class for verifying adapter registries."; -/* ========================== End: Lookup Bases ======================= */ -/* ==================================================================== */ +#if USE_STATIC_TYPES +/* + * Static type: VerifyingBase + */ + +static PyTypeObject VB_type_def = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = VB__name__, + .tp_doc = VB__doc__, + .tp_base = &LB_type_def, + .tp_basicsize = sizeof(VB), + .tp_flags = BASETYPE_FLAGS, + .tp_traverse = (traverseproc)VB_traverse, + .tp_clear = (inquiry)VB_clear, + .tp_dealloc = (destructor)&VB_dealloc, + .tp_methods = VB_methods, +}; -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"}, +#else - {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */ +/* + * Heap type: VerifyingBase + */ +static PyType_Slot VB_type_slots[] = { + {Py_tp_doc, VB__doc__}, + {Py_tp_traverse, VB_traverse}, + {Py_tp_clear, VB_clear}, + {Py_tp_dealloc, VB_dealloc}, + {Py_tp_methods, VB_methods}, + /* tp_base cannot be set as a slot -- pass to PyType_FromModuleAndSpec */ + {0, NULL} }; -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 +static PyType_Spec VB_type_spec = { + .name = VB__name__, + .basicsize = sizeof(VB), + .flags = BASETYPE_FLAGS, + .slots = VB_type_slots }; -static PyObject * -init(void) +#endif + + +/* + * Module state struct: holds all data formerly kept as static globals. + */ +typedef struct { - PyObject *m; - -#define DEFINE_STRING(S) \ - if(! (str ## S = PyUnicode_FromString(# S))) return NULL - - DEFINE_STRING(__dict__); - DEFINE_STRING(__implemented__); - DEFINE_STRING(__provides__); - DEFINE_STRING(__class__); - DEFINE_STRING(__providedBy__); - DEFINE_STRING(extends); - 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); - DEFINE_STRING(__self__); - DEFINE_STRING(__name__); - DEFINE_STRING(__module__); - DEFINE_STRING(__adapt__); - DEFINE_STRING(_CALL_CUSTOM_ADAPT); -#undef DEFINE_STRING - adapter_hooks = PyList_New(0); - if (adapter_hooks == NULL) - return NULL; + /* our globals (exposed to Python) */ + PyTypeObject* specification_base_class; + PyTypeObject* object_specification_descriptor_class; + PyTypeObject* class_provides_base_class; + PyTypeObject* interface_base_class; + PyTypeObject* lookup_base_class; + PyTypeObject* verifying_base_class; + PyObject* adapter_hooks; + /* members imported from 'zope.interface.declarations' + */ + PyObject* empty; + PyObject* fallback; + PyObject* builtin_impl_specs; + PyTypeObject* implements_class; + /* flag: have we imported the next set of members yet from + * 'zope.interface.declarations? + */ + int decl_imported; +} _zic_module_state; - /* Initialize types: */ - SpecificationBaseType.tp_new = PyBaseObject_Type.tp_new; - if (PyType_Ready(&SpecificationBaseType) < 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; +/* + * Macro to speed lookup of state members + */ +#define _zic_state(o) ((_zic_module_state*)PyModule_GetState(o)) - InterfaceBaseType.tp_new = PyBaseObject_Type.tp_new; - if (PyType_Ready(&InterfaceBaseType) < 0) - return NULL; +static _zic_module_state* +_zic_state_init(PyObject* module) +{ + _zic_module_state* rec = _zic_state(module); + + rec->specification_base_class = NULL; + rec->object_specification_descriptor_class = NULL; + rec->class_provides_base_class = NULL; + rec->interface_base_class = NULL; + rec->lookup_base_class = NULL; + rec->verifying_base_class = NULL; + rec->adapter_hooks = NULL; + + rec->builtin_impl_specs = NULL; + rec->empty = NULL; + rec->fallback = NULL; + rec->implements_class = NULL; + rec->decl_imported = 0; + + return rec; +} - LookupBase.tp_new = PyBaseObject_Type.tp_new; - if (PyType_Ready(&LookupBase) < 0) - return NULL; +static int +_zic_state_traverse(PyObject* module, visitproc visit, void* arg) +{ + _zic_module_state* rec = _zic_state(module); - VerifyingBase.tp_new = PyBaseObject_Type.tp_new; - if (PyType_Ready(&VerifyingBase) < 0) - return NULL; + Py_VISIT(rec->specification_base_class); + Py_VISIT(rec->object_specification_descriptor_class); + Py_VISIT(rec->class_provides_base_class); + Py_VISIT(rec->interface_base_class); + Py_VISIT(rec->lookup_base_class); + Py_VISIT(rec->verifying_base_class); + Py_VISIT(rec->adapter_hooks); - m = PyModule_Create(&_zic_module); - if (m == NULL) - return NULL; + Py_VISIT(rec->builtin_impl_specs); + Py_VISIT(rec->empty); + Py_VISIT(rec->fallback); + Py_VISIT(rec->implements_class); - /* Add types: */ - if (PyModule_AddObject(m, "SpecificationBase", OBJECT(&SpecificationBaseType)) < 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(&InterfaceBaseType)) < 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 0; +} + +static int +_zic_state_clear(PyObject* module) +{ + _zic_module_state* rec = _zic_state(module); + + Py_CLEAR(rec->specification_base_class); + Py_CLEAR(rec->object_specification_descriptor_class); + Py_CLEAR(rec->class_provides_base_class); + Py_CLEAR(rec->interface_base_class); + Py_CLEAR(rec->lookup_base_class); + Py_CLEAR(rec->verifying_base_class); + Py_CLEAR(rec->adapter_hooks); + + Py_CLEAR(rec->builtin_impl_specs); + Py_CLEAR(rec->empty); + Py_CLEAR(rec->fallback); + Py_CLEAR(rec->implements_class); + + return 0; +} + +#if USE_HEAP_TYPES +/* Import zope.interface.declarations and store results in module state. + * + * Dynamic alternative to 'import_declarations' above. + */ +static _zic_module_state* +_zic_state_load_declarations(PyObject* module) +{ + PyObject* declarations; + PyObject* builtin_impl_specs; + PyObject* empty; + PyObject* fallback; + PyObject* implements; + + _zic_module_state* rec = _zic_state(module); + + if (!rec->decl_imported) { + declarations = PyImport_ImportModule("zope.interface.declarations"); + if (declarations == NULL) { + return NULL; + } + + builtin_impl_specs = PyObject_GetAttrString( + declarations, "BuiltinImplementationSpecifications"); + if (builtin_impl_specs == NULL) { + return NULL; + } + + empty = PyObject_GetAttrString(declarations, "_empty"); + if (empty == NULL) { + return NULL; + } + + fallback = + PyObject_GetAttrString(declarations, "implementedByFallback"); + if (fallback == NULL) { + return NULL; + } + + implements = PyObject_GetAttrString(declarations, "Implements"); + if (implements == NULL) { + return NULL; + } + + if (!PyType_Check(implements)) { + PyErr_SetString( + PyExc_TypeError, + "zope.interface.declarations.Implements is not a type"); + return NULL; + } + + Py_DECREF(declarations); + + rec->builtin_impl_specs = builtin_impl_specs; + rec->empty = empty; + rec->fallback = fallback; + rec->implements_class = (PyTypeObject*)implements; + rec->decl_imported = 1; + } + return rec; +} + +#endif + +/* + * Provide access to the current module given the type. + */ + +static struct PyModuleDef _zic_module_def; + +static PyObject* +_get_module(PyTypeObject *typeobj) +{ +#if USE_STATIC_TYPES + return (PyObject*)&_zic_module_def; +#else + if (PyType_Check(typeobj)) { + /* Only added in Python 3.11 */ + return PyType_GetModuleByDef(typeobj, &_zic_module_def); + } + + PyErr_SetString(PyExc_TypeError, "_get_module: called w/ non-type"); return NULL; - return m; +#endif +} + +/* + * Fetch the adapter hooks for the current type's module. + */ +static PyObject* +_get_adapter_hooks(PyTypeObject *typeobj) +{ +#if USE_STATIC_TYPES + return adapter_hooks; +#else + PyObject* module; + _zic_module_state* rec; + + module = _get_module(typeobj); + if (module == NULL) { return NULL; } + + rec = _zic_state(module); + return rec->adapter_hooks; +#endif +} + +/* + * Fetch the 'SpecificationBase' class for the current type's module. + */ +static PyTypeObject* +_get_specification_base_class(PyTypeObject *typeobj) +{ +#if USE_STATIC_TYPES + return &SB_type_def; +#else + PyObject* module; + _zic_module_state* rec; + + module = _get_module(typeobj); + if (module == NULL) { return NULL; } + + rec = _zic_state(module); + return rec->specification_base_class; +#endif +} + +/* + * Fetch the 'InterfaceBase' class for the current type's module. + */ +static PyTypeObject* +_get_interface_base_class(PyTypeObject *typeobj) +{ +#if USE_STATIC_TYPES + return &IB_type_def; +#else + PyObject* module; + _zic_module_state* rec; + + module = _get_module(typeobj); + if (module == NULL) { return NULL; } + + rec = _zic_state(module); + return rec->interface_base_class; +#endif +} + +static PyObject* +implementedByFallback(PyObject* module, PyObject* cls) +{ +#if USE_STATIC_TYPES + if (imported_declarations == 0 && import_declarations() < 0) { + return NULL; + } + /* now use static 'fallback' */ +#else + PyObject* fallback; + + _zic_module_state* rec = _zic_state_load_declarations(module); + if (rec == NULL) { return NULL; } + + fallback = rec->fallback; +#endif + + return PyObject_CallFunctionObjArgs(fallback, cls, NULL); +} + +static char implementedBy___doc__[] = + ("Interfaces implemented by a class or factory.\n" + "Raises TypeError if argument is neither a class nor a callable."); + +static PyObject* +implementedBy(PyObject* module, PyObject* cls) +{ + /* Fast retrieval of implements spec, if possible, to optimize + common case. Use fallback code if we get stuck. + */ + PyObject *dict = NULL; + PyObject *spec; + PyTypeObject *implements_class; + PyObject *builtin_impl_specs; + +#if USE_STATIC_TYPES + if (imported_declarations == 0 && import_declarations() < 0) { + return NULL; + } + + implements_class = Implements; + builtin_impl_specs = BuiltinImplementationSpecifications; +#else + _zic_module_state* rec = _zic_state_load_declarations(module); + if (rec == NULL) { return NULL; } + + implements_class = rec->implements_class; + builtin_impl_specs = rec->builtin_impl_specs; +#endif + + if (PyObject_TypeCheck(cls, &PySuper_Type)) { + // Let merging be handled by Python. + return implementedByFallback(module, cls); + } + + 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(module, cls); + } + + spec = PyObject_GetItem(dict, str__implemented__); + Py_DECREF(dict); + if (spec) { + + if (PyObject_TypeCheck(spec, implements_class)) + return spec; + + /* Old-style declaration, use more expensive fallback code */ + Py_DECREF(spec); + return implementedByFallback(module, cls); + } + + PyErr_Clear(); + + /* Maybe we have a builtin */ + spec = PyDict_GetItem(builtin_impl_specs, cls); + if (spec != NULL) { + Py_INCREF(spec); + return spec; + } + + /* We're stuck, use fallback */ + return implementedByFallback(module, cls); +} + +static char getObjectSpecification___doc__[] = + ("Get an object's interfaces (internal api)"); + +static PyObject* +getObjectSpecification(PyObject* module, PyObject* ob) +{ + PyObject *cls; + PyObject *result; + PyTypeObject *specification_base_class; + PyObject *empty_; + +#if USE_STATIC_TYPES + specification_base_class = &SB_type_def; + + if (imported_declarations == 0 && import_declarations() < 0) { + return NULL; + } + empty_ = empty; /* global from import */ + +#else + _zic_module_state* rec = _zic_state_load_declarations(module); + if (rec == NULL) { return NULL; } + + specification_base_class = rec->specification_base_class; + empty_ = rec->empty; +#endif + + result = PyObject_GetAttr(ob, str__provides__); + if (!result) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + /* Propagate non AttributeError exceptions. */ + return NULL; + } + PyErr_Clear(); + } else { + int is_instance = -1; + is_instance = + PyObject_IsInstance(result, OBJECT(specification_base_class)); + if (is_instance < 0) { + /* Propagate all errors */ + return NULL; + } + if (is_instance) { + return result; + } + } + + /* We do a getattr here so as not to be defeated by proxies */ + cls = PyObject_GetAttr(ob, str__class__); + if (cls == NULL) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + /* Propagate non-AttributeErrors */ + return NULL; + } + PyErr_Clear(); + + Py_INCREF(empty_); + return empty_; + } + result = implementedBy(module, cls); + Py_DECREF(cls); + + return result; +} + +static char providedBy___doc__[] = ("Get an object's interfaces"); + +static PyObject* +providedBy(PyObject* module, PyObject* ob) +{ + PyObject *result = NULL; + PyObject *cls; + PyObject *cp; + PyTypeObject *specification_base_class; + int is_instance = -1; + + is_instance = PyObject_IsInstance(ob, (PyObject*)&PySuper_Type); + if (is_instance < 0) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + /* Propagate non-AttributeErrors */ + return NULL; + } + PyErr_Clear(); + } + if (is_instance) { + return implementedBy(module, ob); + } + + result = PyObject_GetAttr(ob, str__providedBy__); + + if (result == NULL) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + return NULL; + } + + PyErr_Clear(); + return getObjectSpecification(module, 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 USE_STATIC_TYPES + specification_base_class = &SB_type_def; +#else + _zic_module_state* rec = _zic_state(module); + specification_base_class = rec->specification_base_class; +#endif + if (PyObject_TypeCheck(result, specification_base_class) || + PyObject_HasAttrString(result, "extends")) + 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(module, 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(module, cls); + } + + Py_DECREF(cls); + Py_DECREF(cp); + + return result; +} + +static struct PyMethodDef _zic_module_methods[] = { + { "implementedBy", + (PyCFunction)implementedBy, + METH_O, + implementedBy___doc__ }, + { "getObjectSpecification", + (PyCFunction)getObjectSpecification, + METH_O, + getObjectSpecification___doc__ }, + { "providedBy", (PyCFunction)providedBy, METH_O, providedBy___doc__ }, + + { NULL, (PyCFunction)NULL, 0, NULL } /* sentinel */ +}; + + +/* Handler for the 'execute' phase of multi-phase initialization + * + * See: https://docs.python.org/3/c-api/module.html#multi-phase-initialization + * and: https://peps.python.org/pep-0489/#module-execution-phase + */ +static int +_zic_module_exec(PyObject* module) +{ + _zic_module_state* rec = _zic_state_init(module); + + rec->adapter_hooks = PyList_New(0); + if (rec->adapter_hooks == NULL) + return -1; + Py_INCREF(rec->adapter_hooks); + +#if USE_STATIC_TYPES + + /* Initialize static global */ + adapter_hooks = rec->adapter_hooks; + + /* Initialize types: */ + SB_type_def.tp_new = PyBaseObject_Type.tp_new; + if (PyType_Ready(&SB_type_def) < 0) { return -1; } + Py_INCREF(&SB_type_def); + rec->specification_base_class = &SB_type_def; + + OSD_type_def.tp_new = PyBaseObject_Type.tp_new; + if (PyType_Ready(&OSD_type_def) < 0) { return -1; } + Py_INCREF(&OSD_type_def); + rec->object_specification_descriptor_class = &OSD_type_def; + + CPB_type_def.tp_new = PyBaseObject_Type.tp_new; + if (PyType_Ready(&CPB_type_def) < 0) { return -1; } + Py_INCREF(&CPB_type_def); + rec->class_provides_base_class = &CPB_type_def; + + IB_type_def.tp_new = PyBaseObject_Type.tp_new; + if (PyType_Ready(&IB_type_def) < 0) { return -1; } + Py_INCREF(&IB_type_def); + rec->interface_base_class = &IB_type_def; + + LB_type_def.tp_new = PyBaseObject_Type.tp_new; + if (PyType_Ready(&LB_type_def) < 0) { return -1; } + Py_INCREF(&LB_type_def); + rec->lookup_base_class = &LB_type_def; + + VB_type_def.tp_new = PyBaseObject_Type.tp_new; + if (PyType_Ready(&VB_type_def) < 0) { return -1; } + Py_INCREF(&VB_type_def); + rec->verifying_base_class = &VB_type_def; + +#else + + PyObject *sb_class; + PyObject *osd_class; + PyObject *cpb_class; + PyObject *ib_class; + PyObject *lb_class; + PyObject *vb_class; + + /* Initialize types: + */ + sb_class = PyType_FromModuleAndSpec(module, &SB_type_spec, NULL); + if (sb_class == NULL) { return -1; } + Py_INCREF(sb_class); + rec->specification_base_class = TYPE(sb_class); + + osd_class = PyType_FromModuleAndSpec(module, &OSD_type_spec, NULL); + if (osd_class == NULL) { return -1; } + Py_INCREF(osd_class); + rec->object_specification_descriptor_class = TYPE(osd_class); + + cpb_class = PyType_FromModuleAndSpec(module, &CPB_type_spec, sb_class); + if (cpb_class == NULL) { return -1; } + Py_INCREF(cpb_class); + rec->class_provides_base_class = TYPE(cpb_class); + + ib_class = PyType_FromModuleAndSpec(module, &IB_type_spec, sb_class); + if (ib_class == NULL) { return -1; } + Py_INCREF(ib_class); + rec->interface_base_class = TYPE(ib_class); + + lb_class = PyType_FromModuleAndSpec(module, &LB_type_spec, NULL); + if (lb_class == NULL) { return -1; } + Py_INCREF(lb_class); + rec->lookup_base_class = TYPE(lb_class); + + vb_class = PyType_FromModuleAndSpec(module, &VB_type_spec, lb_class); + if (vb_class == NULL) { return -1; } + Py_INCREF(vb_class); + rec->verifying_base_class = TYPE(vb_class); + +#endif + + /* Add types to our dict FBO python; also the adapter hooks */ + if (PyModule_AddObject(module, + "SpecificationBase", OBJECT(rec->specification_base_class)) < 0) + return -1; + + if (PyModule_AddObject(module, + "ObjectSpecificationDescriptor", + OBJECT(rec->object_specification_descriptor_class)) < + 0) + return -1; + + if (PyModule_AddObject(module, + "ClassProvidesBase", OBJECT(rec->class_provides_base_class)) < 0) + return -1; + + if (PyModule_AddObject(module, + "InterfaceBase", OBJECT(rec->interface_base_class)) < 0) + return -1; + + if (PyModule_AddObject(module, + "LookupBase", OBJECT(rec->lookup_base_class)) < 0) + return -1; + + if (PyModule_AddObject(module, + "VerifyingBase", OBJECT(rec->verifying_base_class)) < 0) + return -1; + + if (PyModule_AddObject(module, "adapter_hooks", rec->adapter_hooks) < 0) + return -1; + + return 0; +} + + +/* Slot definitions for multi-phase initialization + * + * See: https://docs.python.org/3/c-api/module.html#multi-phase-initialization + * and: https://peps.python.org/pep-0489 + */ +static PyModuleDef_Slot _zic_module_slots[] = { + {Py_mod_exec, _zic_module_exec}, + {0, NULL} +}; + +static char _zic_module__doc__[] = "C optimizations for zope.interface\n\n"; + +static struct PyModuleDef _zic_module_def = { + PyModuleDef_HEAD_INIT, + .m_name = "_zope_interface_coptimizations", + .m_doc = _zic_module__doc__, + .m_size = sizeof(_zic_module_state), + .m_methods = _zic_module_methods, + .m_slots=_zic_module_slots, + .m_traverse = _zic_state_traverse, + .m_clear = _zic_state_clear, +}; + +static PyObject* +init(void) +{ + if (define_static_strings() < 0) { return NULL; } + + return PyModuleDef_Init(&_zic_module_def); } PyMODINIT_FUNC PyInit__zope_interface_coptimizations(void) { - return init(); + return init(); } #ifdef __clang__ diff --git a/contrib/python/zope.interface/py3/zope/interface/adapter.py b/contrib/python/zope.interface/py3/zope/interface/adapter.py index b02f19d562..a35c3f90c1 100644 --- a/contrib/python/zope.interface/py3/zope/interface/adapter.py +++ b/contrib/python/zope.interface/py3/zope/interface/adapter.py @@ -59,7 +59,7 @@ __all__ = [ # ``tuple([t fon t in range(10)])`` -> 82ns # ``tuple(t for t in range(10))`` -> 177ns # ``tuple(map(lambda t: t, range(10)))`` -> 168ns -# + class BaseAdapterRegistry: """ @@ -68,36 +68,40 @@ class BaseAdapterRegistry: Subclasses can set the following attributes to control how the data is stored; in particular, these hooks can be helpful for ZODB - persistence. They can be class attributes that are the named (or similar) type, or - they can be methods that act as a constructor for an object that behaves - like the types defined here; this object will not assume that they are type - objects, but subclasses are free to do so: + persistence. They can be class attributes that are the named + (or similar) type, or they can be methods that act as a constructor + for an object that behaves like the types defined here; this object + will not assume that they are type objects, but subclasses are free + to do so: _sequenceType = list This is the type used for our two mutable top-level "byorder" sequences. - Must support mutation operations like ``append()`` and ``del seq[index]``. - These are usually small (< 10). Although at least one of them is - accessed when performing lookups or queries on this object, the other - is untouched. In many common scenarios, both are only required when - mutating registrations and subscriptions (like what + Must support mutation operations like ``append()`` and ``del + seq[index]``. These are usually small (< 10). Although at least one of + them is accessed when performing lookups or queries on this object, the + other is untouched. In many common scenarios, both are only required + when mutating registrations and subscriptions (like what :meth:`zope.interface.interfaces.IComponents.registerUtility` does). This use pattern makes it an ideal candidate to be a :class:`~persistent.list.PersistentList`. + _leafSequenceType = tuple This is the type used for the leaf sequences of subscribers. It could be set to a ``PersistentList`` to avoid many unnecessary data - loads when subscribers aren't being used. Mutation operations are directed - through :meth:`_addValueToLeaf` and :meth:`_removeValueFromLeaf`; if you use - a mutable type, you'll need to override those. + loads when subscribers aren't being used. Mutation operations are + directed through :meth:`_addValueToLeaf` and + :meth:`_removeValueFromLeaf`; if you use a mutable type, you'll need to + override those. + _mappingType = dict - This is the mutable mapping type used for the keyed mappings. - A :class:`~persistent.mapping.PersistentMapping` - could be used to help reduce the number of data loads when the registry is large - and parts of it are rarely used. Further reductions in data loads can come from - using a :class:`~BTrees.OOBTree.OOBTree`, but care is required - to be sure that all required/provided - values are fully ordered (e.g., no required or provided values that are classes - can be used). + This is the mutable mapping type used for the keyed mappings. A + :class:`~persistent.mapping.PersistentMapping` could be used to help + reduce the number of data loads when the registry is large and parts of + it are rarely used. Further reductions in data loads can come from using + a :class:`~BTrees.OOBTree.OOBTree`, but care is required to be sure that + all required/provided values are fully ordered (e.g., no required or + provided values that are classes can be used). + _providedType = dict This is the mutable mapping type used for the ``_provided`` mapping. This is separate from the generic mapping type because the values @@ -106,9 +110,10 @@ class BaseAdapterRegistry: The same caveats regarding key types apply as for ``_mappingType``. - It is possible to also set these on an instance, but because of the need to - potentially also override :meth:`_addValueToLeaf` and :meth:`_removeValueFromLeaf`, - this may be less useful in a persistent scenario; using a subclass is recommended. + It is possible to also set these on an instance, but because of the need + to potentially also override :meth:`_addValueToLeaf` and + :meth:`_removeValueFromLeaf`, this may be less useful in a persistent + scenario; using a subclass is recommended. .. versionchanged:: 5.3.0 Add support for customizing the way internal data @@ -209,18 +214,20 @@ class BaseAdapterRegistry: Add the value *new_item* to the *existing_leaf_sequence*, which may be ``None``. - Subclasses that redefine `_leafSequenceType` should override this method. + Subclasses that redefine `_leafSequenceType` should override this + method. :param existing_leaf_sequence: If *existing_leaf_sequence* is not *None*, it will be an instance - of `_leafSequenceType`. (Unless the object has been unpickled - from an old pickle and the class definition has changed, in which case - it may be an instance of a previous definition, commonly a `tuple`.) + of `_leafSequenceType`. (Unless the object has been unpickled from + an old pickle and the class definition has changed, in which case + it may be an instance of a previous definition, commonly a + `tuple`.) :return: This method returns the new value to be stored. It may mutate the - sequence in place if it was not ``None`` and the type is mutable, but - it must also return it. + sequence in place if it was not ``None`` and the type is mutable, + but it must also return it. .. versionadded:: 5.3.0 """ @@ -337,9 +344,9 @@ class BaseAdapterRegistry: def _all_entries(self, byorder): # Recurse through the mapping levels of the `byorder` sequence, - # reconstructing a flattened sequence of ``(required, provided, name, value)`` - # tuples that can be used to reconstruct the sequence with the appropriate - # registration methods. + # reconstructing a flattened sequence of ``(required, provided, name, + # value)`` tuples that can be used to reconstruct the sequence with + # the appropriate registration methods. # # Locally reference the `byorder` data; it might be replaced while # this method is running (see ``rebuild``). @@ -461,7 +468,9 @@ class BaseAdapterRegistry: .. versionadded:: 5.3.0 """ - for required, provided, _name, value in self._all_entries(self._subscribers): + for required, provided, _name, value in self._all_entries( + self._subscribers, + ): for v in value: yield (required, provided, v) @@ -570,7 +579,6 @@ class BaseAdapterRegistry: registrations = buffer(registrations) subscriptions = buffer(subscriptions) - # Replace the base data structures as well as _v_lookup. self.__init__(self.__bases__) # Re-register everything previously registered and subscribed. @@ -584,12 +592,13 @@ class BaseAdapterRegistry: # part of passing that notification to the change of objects.) for args in registrations: self.register(*args) + for args in subscriptions: self.subscribe(*args) - # XXX hack to fake out twisted's use of a private api. We need to get them - # to use the new registered method. - def get(self, _): # pragma: no cover + # XXX hack to fake out twisted's use of a private api. + # We need to get them to use the new registered method. + def get(self, _): # pragma: no cover class XXXTwistedFakeOut: selfImplied = {} return XXXTwistedFakeOut @@ -597,6 +606,7 @@ class BaseAdapterRegistry: _not_in_mapping = object() + @_use_c_impl class LookupBase: @@ -693,7 +703,6 @@ class LookupBase: return result - def subscriptions(self, required, provided): cache = self._scache.get(provided) if cache is None: @@ -710,33 +719,42 @@ class LookupBase: @_use_c_impl -class VerifyingBase(LookupBaseFallback): +class VerifyingBase(LookupBaseFallback): # noqa F821 # Mixin for lookups against registries which "chain" upwards, and # whose lookups invalidate their own caches whenever a parent registry # bumps its own '_generation' counter. E.g., used by # zope.component.persistentregistry def changed(self, originally_changed): - LookupBaseFallback.changed(self, originally_changed) + LookupBaseFallback.changed(self, originally_changed) # noqa F821 self._verify_ro = self._registry.ro[1:] self._verify_generations = [r._generation for r in self._verify_ro] def _verify(self): - if ([r._generation for r in self._verify_ro] - != self._verify_generations): + if ( + [ + r._generation for r in self._verify_ro + ] != self._verify_generations + ): self.changed(None) def _getcache(self, provided, name): self._verify() - return LookupBaseFallback._getcache(self, provided, name) + return LookupBaseFallback._getcache( # noqa F821 + self, provided, name, + ) def lookupAll(self, required, provided): self._verify() - return LookupBaseFallback.lookupAll(self, required, provided) + return LookupBaseFallback.lookupAll( # noqa F821 + self, required, provided, + ) def subscriptions(self, required, provided): self._verify() - return LookupBaseFallback.subscriptions(self, required, provided) + return LookupBaseFallback.subscriptions( # noqa F821 + self, required, provided, + ) class AdapterLookupBase: @@ -755,7 +773,6 @@ class AdapterLookupBase: r.unsubscribe(self) self._required.clear() - # Extendors # --------- @@ -778,7 +795,7 @@ class AdapterLookupBase: # the interface's __iro__ has changed. This is unlikely enough that # we'll take our chances for now. - def init_extendors(self): + def init_extendors(self): # noqa E301 self._extendors = {} for p in self._registry._provided: self.add_extendor(p) @@ -788,12 +805,14 @@ class AdapterLookupBase: for i in provided.__iro__: extendors = _extendors.get(i, ()) _extendors[i] = ( - [e for e in extendors if provided.isOrExtends(e)] - + - [provided] - + - [e for e in extendors if not provided.isOrExtends(e)] - ) + [ + e for e in extendors if provided.isOrExtends(e) + ] + [ + provided + ] + [ + e for e in extendors if not provided.isOrExtends(e) + ] + ) def remove_extendor(self, provided): _extendors = self._extendors @@ -801,7 +820,6 @@ class AdapterLookupBase: _extendors[i] = [e for e in _extendors.get(i, ()) if e != provided] - def _subscribe(self, *required): _refs = self._required for r in required: @@ -838,7 +856,9 @@ class AdapterLookupBase: if factory is None: return default - result = factory(*[o.__self__ if isinstance(o, super) else o for o in objects]) + result = factory(*[ + o.__self__ if isinstance(o, super) else o for o in objects + ]) if result is None: return default @@ -889,7 +909,9 @@ class AdapterLookupBase: return result def subscribers(self, objects, provided): - subscriptions = self.subscriptions([providedBy(o) for o in objects], provided) + subscriptions = self.subscriptions( + [providedBy(o) for o in objects], provided + ) if provided is None: result = () for subscription in subscriptions: @@ -902,9 +924,11 @@ class AdapterLookupBase: result.append(subscriber) return result + class AdapterLookup(AdapterLookupBase, LookupBase): pass + @implementer(IAdapterRegistry) class AdapterRegistry(BaseAdapterRegistry): """ @@ -949,6 +973,7 @@ class AdapterRegistry(BaseAdapterRegistry): class VerifyingAdapterLookup(AdapterLookupBase, VerifyingBase): pass + @implementer(IAdapterRegistry) class VerifyingAdapterRegistry(BaseAdapterRegistry): """ @@ -957,13 +982,15 @@ class VerifyingAdapterRegistry(BaseAdapterRegistry): LookupClass = VerifyingAdapterLookup + def _convert_None_to_Interface(x): if x is None: return Interface else: return x -def _lookup(components, specs, provided, name, i, l): + +def _lookup(components, specs, provided, name, i, l): # noqa: E741 # this function is called very often. # The components.get in loops is executed 100 of 1000s times. # by loading get into a local variable the bytecode @@ -973,7 +1000,7 @@ def _lookup(components, specs, provided, name, i, l): for spec in specs[i].__sro__: comps = components_get(spec) if comps: - r = _lookup(comps, specs, provided, name, i+1, l) + r = _lookup(comps, specs, provided, name, i + 1, l) if r is not None: return r else: @@ -986,26 +1013,32 @@ def _lookup(components, specs, provided, name, i, l): return None -def _lookupAll(components, specs, provided, result, i, l): + +def _lookupAll(components, specs, provided, result, i, l): # noqa: E741 components_get = components.get # see _lookup above if i < l: for spec in reversed(specs[i].__sro__): comps = components_get(spec) if comps: - _lookupAll(comps, specs, provided, result, i+1, l) + _lookupAll(comps, specs, provided, result, i + 1, l) else: for iface in reversed(provided): comps = components_get(iface) if comps: result.update(comps) -def _subscriptions(components, specs, provided, name, result, i, l): + +def _subscriptions( + components, specs, provided, name, result, i, l # noqa: E741 +): components_get = components.get # see _lookup above if i < l: for spec in reversed(specs[i].__sro__): comps = components_get(spec) if comps: - _subscriptions(comps, specs, provided, name, result, i+1, l) + _subscriptions( + comps, specs, provided, name, result, i + 1, l + ) else: for iface in reversed(provided): comps = components_get(iface) diff --git a/contrib/python/zope.interface/py3/zope/interface/advice.py b/contrib/python/zope.interface/py3/zope/interface/advice.py index 5a8e377737..f577d42ab8 100644 --- a/contrib/python/zope.interface/py3/zope/interface/advice.py +++ b/contrib/python/zope.interface/py3/zope/interface/advice.py @@ -52,7 +52,7 @@ def getFrameInfo(frame): hasName = '__name__' in f_globals sameName = hasModule and hasName - sameName = sameName and f_globals['__name__']==f_locals['__module__'] + sameName = sameName and f_globals['__name__'] == f_locals['__module__'] module = hasName and sys.modules.get(f_globals['__name__']) or None @@ -67,35 +67,36 @@ def getFrameInfo(frame): kind = "class" elif not sameNamespace: kind = "function call" - else: # pragma: no cover - # How can you have f_locals is f_globals, and have '__module__' set? - # This is probably module-level code, but with a '__module__' variable. + else: # pragma: no cover + # How can you have f_locals is f_globals, and have '__module__' + # set? # This is probably module-level code, but with a + # '__module__' variable. kind = "unknown" return kind, module, f_locals, f_globals def isClassAdvisor(ob): """True if 'ob' is a class advisor function""" - return isinstance(ob,FunctionType) and hasattr(ob,'previousMetaclass') + return isinstance(ob, FunctionType) and hasattr(ob, 'previousMetaclass') def determineMetaclass(bases, explicit_mc=None): """Determine metaclass from 1+ bases and optional explicit __metaclass__""" - meta = [getattr(b,'__class__',type(b)) for b in bases] + meta = [getattr(b, '__class__', type(b)) for b in bases] if explicit_mc is not None: # The explicit metaclass needs to be verified for compatibility # as well, and allowed to resolve the incompatible bases, if any meta.append(explicit_mc) - if len(meta)==1: + if len(meta) == 1: # easy case return meta[0] - candidates = minimalBases(meta) # minimal set of metaclasses + candidates = minimalBases(meta) # minimal set of metaclasses - if len(candidates)>1: + if len(candidates) > 1: # We could auto-combine, but for now we won't... raise TypeError("Incompatible metatypes", bases) @@ -109,7 +110,7 @@ def minimalBases(classes): for m in classes: for n in classes: - if issubclass(n,m) and m is not n: + if issubclass(n, m) and m is not n: break else: # m has no subclasses in 'classes' diff --git a/contrib/python/zope.interface/py3/zope/interface/common/__init__.py b/contrib/python/zope.interface/py3/zope/interface/common/__init__.py index f308f9edd6..256ddc9178 100644 --- a/contrib/python/zope.interface/py3/zope/interface/common/__init__.py +++ b/contrib/python/zope.interface/py3/zope/interface/common/__init__.py @@ -24,11 +24,11 @@ __all__ = [ # Nothing public here. ] - # pylint:disable=inherit-non-class, # pylint:disable=no-self-argument,no-method-argument # pylint:disable=unexpected-special-method-signature + class optional: # Apply this decorator to a method definition to make it # optional (remove it from the list of required names), overriding @@ -115,8 +115,9 @@ class ABCInterfaceClass(InterfaceClass): """ # If we could figure out invalidation, and used some special - # Specification/Declaration instances, and override the method ``providedBy`` here, - # perhaps we could more closely integrate with ABC virtual inheritance? + # Specification/Declaration instances, and override the method + # ``providedBy`` here, perhaps we could more closely integrate with ABC + # virtual inheritance? def __init__(self, name, bases, attrs): # go ahead and give us a name to ease debugging. @@ -128,7 +129,9 @@ class ABCInterfaceClass(InterfaceClass): # Something like ``IList(ISequence)``: We're extending # abc interfaces but not an ABC interface ourself. InterfaceClass.__init__(self, name, bases, attrs) - ABCInterfaceClass.__register_classes(self, extra_classes, ignored_classes) + ABCInterfaceClass.__register_classes( + self, extra_classes, ignored_classes, + ) self.__class__ = InterfaceClass return @@ -143,8 +146,9 @@ class ABCInterfaceClass(InterfaceClass): # e.g., ``__ror__ = __or__``. k: self.__method_from_function(v, k) for k, v in vars(based_on).items() - if isinstance(v, FunctionType) and not self.__is_private_name(k) - and not self.__is_reverse_protocol_name(k) + if isinstance(v, FunctionType) and + not self.__is_private_name(k) and + not self.__is_reverse_protocol_name(k) } methods['__doc__'] = self.__create_class_doc(attrs) @@ -163,12 +167,13 @@ class ABCInterfaceClass(InterfaceClass): return '' docs = "\n\nThe following methods are optional:\n - " + "\n-".join( - "{}\n{}".format(k, v.__doc__) for k, v in optionals.items() + f"{k}\n{v.__doc__}" for k, v in optionals.items() ) return docs def __create_class_doc(self, attrs): based_on = self.__abc + def ref(c): mod = c.__module__ name = c.__name__ @@ -176,13 +181,16 @@ class ABCInterfaceClass(InterfaceClass): return "`%s`" % name if mod == '_io': mod = 'io' - return "`{}.{}`".format(mod, name) + return f"`{mod}.{name}`" + implementations_doc = "\n - ".join( ref(c) for c in sorted(self.getRegisteredConformers(), key=ref) ) if implementations_doc: - implementations_doc = "\n\nKnown implementations are:\n\n - " + implementations_doc + implementations_doc = ( + "\n\nKnown implementations are:\n\n - " + implementations_doc + ) based_on_doc = (based_on.__doc__ or '') based_on_doc = based_on_doc.splitlines() @@ -196,7 +204,6 @@ class ABCInterfaceClass(InterfaceClass): ) return doc - @staticmethod def __is_private_name(name): if name.startswith('__') and name.endswith('__'): @@ -221,8 +228,14 @@ class ABCInterfaceClass(InterfaceClass): def __register_classes(self, conformers=None, ignored_classes=None): # Make the concrete classes already present in our ABC's registry # declare that they implement this interface. - conformers = conformers if conformers is not None else self.getRegisteredConformers() - ignored = ignored_classes if ignored_classes is not None else self.__ignored_classes + conformers = ( + conformers if conformers is not None + else self.getRegisteredConformers() + ) + ignored = ( + ignored_classes if ignored_classes is not None + else self.__ignored_classes + ) for cls in conformers: if cls in ignored: continue @@ -246,7 +259,9 @@ class ABCInterfaceClass(InterfaceClass): # of checking that, so its quite possible that registrations # are in fact ignored, winding up just in the _abc_cache. try: - registered = list(based_on._abc_registry) + list(based_on._abc_cache) + registered = ( + list(based_on._abc_registry) + list(based_on._abc_cache) + ) except AttributeError: # Rewritten in C in CPython 3.7. # These expose the underlying weakref. @@ -261,13 +276,16 @@ class ABCInterfaceClass(InterfaceClass): def _create_ABCInterface(): - # It's a two-step process to create the root ABCInterface, because - # without specifying a corresponding ABC, using the normal constructor - # gets us a plain InterfaceClass object, and there is no ABC to associate with the + # It's a two-step process to create the root ABCInterface, because without + # specifying a corresponding ABC, using the normal constructor gets us a + # plain InterfaceClass object, and there is no ABC to associate with the # root. abc_name_bases_attrs = ('ABCInterface', (Interface,), {}) - instance = ABCInterfaceClass.__new__(ABCInterfaceClass, *abc_name_bases_attrs) + instance = ABCInterfaceClass.__new__( + ABCInterfaceClass, *abc_name_bases_attrs, + ) InterfaceClass.__init__(instance, *abc_name_bases_attrs) return instance + ABCInterface = _create_ABCInterface() diff --git a/contrib/python/zope.interface/py3/zope/interface/common/builtins.py b/contrib/python/zope.interface/py3/zope/interface/common/builtins.py index 6e13e06482..09de5b3b2f 100644 --- a/contrib/python/zope.interface/py3/zope/interface/common/builtins.py +++ b/contrib/python/zope.interface/py3/zope/interface/common/builtins.py @@ -35,6 +35,7 @@ __all__ = [ 'IFile', ] + # pylint:disable=no-self-argument class IList(collections.IMutableSequence): """ @@ -86,6 +87,8 @@ class INativeString(ITextString): On all Python versions, this is :class:`str`. Tt extends :class:`ITextString`. """ + + # We're not extending ABCInterface so extra_classes won't work classImplements(str, INativeString) @@ -108,8 +111,8 @@ class IFile(io.IIOBase): """ Interface for :class:`file`. - It is recommended to use the interfaces from :mod:`zope.interface.common.io` - instead of this interface. + It is recommended to use the interfaces from + :mod:`zope.interface.common.io` instead of this interface. On Python 3, there is no single implementation of this interface; depending on the arguments, the :func:`open` builtin can return diff --git a/contrib/python/zope.interface/py3/zope/interface/common/collections.py b/contrib/python/zope.interface/py3/zope/interface/common/collections.py index 3c751c05c8..543266d9cf 100644 --- a/contrib/python/zope.interface/py3/zope/interface/common/collections.py +++ b/contrib/python/zope.interface/py3/zope/interface/common/collections.py @@ -13,10 +13,10 @@ Interface definitions paralleling the abstract base classes defined in :mod:`collections.abc`. -After this module is imported, the standard library types will declare -that they implement the appropriate interface. While most standard -library types will properly implement that interface (that -is, ``verifyObject(ISequence, list()))`` will pass, for example), a few might not: +After this module is imported, the standard library types will declare that +they implement the appropriate interface. While most standard library types +will properly implement that interface (that is, ``verifyObject(ISequence, +list()))`` will pass, for example), a few might not: - `memoryview` doesn't feature all the defined methods of ``ISequence`` such as ``count``; it is still declared to provide @@ -67,6 +67,7 @@ def _new_in_ver(name, ver, return missing + __all__ = [ 'IAsyncGenerator', 'IAsyncIterable', @@ -93,6 +94,7 @@ __all__ = [ 'IValuesView', ] + class IContainer(ABCInterface): abc = abc.Container @@ -104,9 +106,11 @@ class IContainer(ABCInterface): to implement ``in``. """ + class IHashable(ABCInterface): abc = abc.Hashable + class IIterable(ABCInterface): abc = abc.Iterable @@ -117,9 +121,11 @@ class IIterable(ABCInterface): implement `iter` using the old ``__getitem__`` protocol. """ + class IIterator(IIterable): abc = abc.Iterator + class IReversible(IIterable): abc = _new_in_ver('Reversible', True, (IIterable.getABC(),)) @@ -131,6 +137,7 @@ class IReversible(IIterable): `reversed` builtin. """ + class IGenerator(IIterator): # New in Python 3.5 abc = _new_in_ver('Generator', True, (IIterator.getABC(),)) @@ -142,21 +149,25 @@ class ISized(ABCInterface): # ICallable is not defined because there's no standard signature. + class ICollection(ISized, IIterable, IContainer): - abc = _new_in_ver('Collection', True, - (ISized.getABC(), IIterable.getABC(), IContainer.getABC())) + abc = _new_in_ver( + 'Collection', + True, + (ISized.getABC(), IIterable.getABC(), IContainer.getABC()) + ) class ISequence(IReversible, ICollection): abc = abc.Sequence extra_classes = (UserString,) - # On Python 2, basestring is registered as an ISequence, and + # On Python 2, basestring was registered as an ISequence, and # its subclass str is an IByteString. If we also register str as # an ISequence, that tends to lead to inconsistent resolution order. - ignored_classes = (basestring,) if str is bytes else () # pylint:disable=undefined-variable + ignored_classes = () @optional def __reversed__(): @@ -173,6 +184,7 @@ class ISequence(IReversible, implement `iter` using the old ``__getitem__`` protocol. """ + class IMutableSequence(ISequence): abc = abc.MutableSequence extra_classes = (UserList,) @@ -182,9 +194,9 @@ class IByteString(ISequence): """ This unifies `bytes` and `bytearray`. """ - abc = _new_in_ver('ByteString', True, - (ISequence.getABC(),), - (bytes, bytearray)) + abc = _new_in_ver( + 'ByteString', True, (ISequence.getABC(),), (bytes, bytearray), + ) class ISet(ICollection): @@ -210,6 +222,7 @@ class IMutableMapping(IMapping): extra_classes = (dict, UserDict,) ignored_classes = (OrderedDict,) + class IMappingView(ISized): abc = abc.MappingView @@ -233,6 +246,7 @@ class IValuesView(IMappingView, ICollection): to implement ``in``. """ + class IAwaitable(ABCInterface): abc = _new_in_ver('Awaitable', True) diff --git a/contrib/python/zope.interface/py3/zope/interface/common/idatetime.py b/contrib/python/zope.interface/py3/zope/interface/common/idatetime.py index aeda07aa0e..24b2606e80 100644 --- a/contrib/python/zope.interface/py3/zope/interface/common/idatetime.py +++ b/contrib/python/zope.interface/py3/zope/interface/common/idatetime.py @@ -89,10 +89,10 @@ class IDateClass(Interface): """Return the local date from a POSIX timestamp (like time.time()) This may raise `ValueError`, if the timestamp is out of the range of - values supported by the platform C ``localtime()`` function. It's common - for this to be restricted to years from 1970 through 2038. Note that - on non-POSIX systems that include leap seconds in their notion of a - timestamp, leap seconds are ignored by `fromtimestamp`. + values supported by the platform C ``localtime()`` function. It's + common for this to be restricted to years from 1970 through 2038. Note + that on non-POSIX systems that include leap seconds in their notion of + a timestamp, leap seconds are ignored by `fromtimestamp`. """ def fromordinal(ordinal): @@ -122,13 +122,17 @@ class IDate(IDateClass): month = Attribute("Between 1 and 12 inclusive") day = Attribute( - "Between 1 and the number of days in the given month of the given year.") + "Between 1 and the number of days " + "in the given month of the given year." + ) def replace(year, month, day): """Return a date with the same value. Except for those members given new values by whichever keyword - arguments are specified. For example, if ``d == date(2002, 12, 31)``, then + arguments are specified. + + For example, if ``d == date(2002, 12, 31)``, then ``d.replace(day=26) == date(2000, 12, 26)``. """ @@ -238,10 +242,10 @@ class IDateTimeClass(Interface): def now(tz=None): """Return the current local date and time. - If optional argument *tz* is None or not specified, this is like `today`, - but, if possible, supplies more precision than can be gotten from going - through a `time.time` timestamp (for example, this may be possible on - platforms supplying the C ``gettimeofday()`` function). + If optional argument *tz* is None or not specified, this is like + `today`, but, if possible, supplies more precision than can be gotten + from going through a `time.time` timestamp (for example, this may be + possible on platforms supplying the C ``gettimeofday()`` function). Else tz must be an instance of a class tzinfo subclass, and the current date and time are converted to tz's time zone. In this case the result @@ -269,7 +273,7 @@ class IDateTimeClass(Interface): Else tz must be an instance of a class tzinfo subclass, and the timestamp is converted to tz's time zone. In this case the result is equivalent to - ``tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz))``. + ``tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz))`` fromtimestamp() may raise `ValueError`, if the timestamp is out of the range of values supported by the platform C localtime() or gmtime() @@ -286,8 +290,8 @@ class IDateTimeClass(Interface): """Return the UTC datetime from the POSIX timestamp with tzinfo None. This may raise `ValueError`, if the timestamp is out of the range of - values supported by the platform C ``gmtime()`` function. It's common for - this to be restricted to years in 1970 through 2038. + values supported by the platform C ``gmtime()`` function. It's common + for this to be restricted to years in 1970 through 2038. .. seealso:: `fromtimestamp`. """ @@ -312,7 +316,7 @@ class IDateTimeClass(Interface): class IDateTime(IDate, IDateTimeClass): - """Object contains all the information from a date object and a time object. + """Contains all the information from a date object and a time object. Implemented by `datetime.datetime`. """ @@ -337,7 +341,7 @@ class IDateTime(IDate, IDateTimeClass): or None if none was passed""") def date(): - """Return date object with same year, month and day.""" + """Return date object with same year, month and day.""" def time(): """Return time object with same hour, minute, second, microsecond. @@ -358,8 +362,8 @@ class IDateTime(IDate, IDateTimeClass): """Return a datetime with the same members, except for those members given new values by whichever keyword arguments are specified. - Note that ``tzinfo=None`` can be specified to create a naive datetime from - an aware datetime with no conversion of date and time members. + Note that ``tzinfo=None`` can be specified to create a naive datetime + from an aware datetime with no conversion of date and time members. """ def astimezone(tz): @@ -377,13 +381,16 @@ class IDateTime(IDate, IDateTimeClass): after astz = dt.astimezone(tz), astz - astz.utcoffset() - will usually have the same date and time members as dt - dt.utcoffset(). - The discussion of class `datetime.tzinfo` explains the cases at Daylight Saving - Time transition boundaries where this cannot be achieved (an issue only - if tz models both standard and daylight time). + will usually have the same date and time members as dt - + dt.utcoffset(). The discussion of class `datetime.tzinfo` explains + the cases at Daylight Saving Time transition boundaries where this + cannot be achieved (an issue only if tz models both standard and + daylight time). + + If you merely want to attach a time zone object *tz* to a datetime + *dt* without adjustment of date and time members, use + ``dt.replace(tzinfo=tz)``. - If you merely want to attach a time zone object *tz* to a datetime *dt* - without adjustment of date and time members, use ``dt.replace(tzinfo=tz)``. If you merely want to remove the time zone object from an aware datetime dt without conversion of date and time members, use ``dt.replace(tzinfo=None)``. @@ -405,7 +412,7 @@ class IDateTime(IDate, IDateTimeClass): """Return the timezone name.""" def timetuple(): - """Return a 9-element tuple of the form returned by `time.localtime`.""" + """Return a 9-tuple of the form returned by `time.localtime`.""" def utctimetuple(): """Return UTC time tuple compatilble with `time.gmtime`.""" @@ -453,17 +460,21 @@ class IDateTime(IDate, IDateTimeClass): """ def __str__(): - """For a datetime instance *d*, ``str(d)`` is equivalent to ``d.isoformat(' ')``. + """Convert to a stirng + + For a datetime instance *d*, ``str(d)`` is equivalent to + ``d.isoformat(' ')``. """ def ctime(): """Return a string representing the date and time. - ``datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'``. - ``d.ctime()`` is equivalent to ``time.ctime(time.mktime(d.timetuple()))`` on - platforms where the native C ``ctime()`` function (which `time.ctime` - invokes, but which `datetime.ctime` does not invoke) conforms to the - C standard. + ``datetime(2002, 12, 4, 20, 30, 40).ctime()`` yields + ``'Wed Dec 4 20:30:40 2002'``. + ``d.ctime()`` is equivalent to + ``time.ctime(time.mktime(d.timetuple()))`` on platforms where the + native C ``ctime()`` function (which `time.ctime` invokes, but which + `datetime.ctime` does not invoke) conforms to the C standard. """ def strftime(format): @@ -605,7 +616,7 @@ classImplements(datetime, IDateTime) classImplements(time, ITime) classImplements(tzinfo, ITZInfo) -## directlyProvides(timedelta, ITimeDeltaClass) -## directlyProvides(date, IDateClass) -## directlyProvides(datetime, IDateTimeClass) -## directlyProvides(time, ITimeClass) +# directlyProvides(timedelta, ITimeDeltaClass) +# directlyProvides(date, IDateClass) +# directlyProvides(datetime, IDateTimeClass) +# directlyProvides(time, ITimeClass) diff --git a/contrib/python/zope.interface/py3/zope/interface/common/interfaces.py b/contrib/python/zope.interface/py3/zope/interface/common/interfaces.py index 688e323a97..74386de024 100644 --- a/contrib/python/zope.interface/py3/zope/interface/common/interfaces.py +++ b/contrib/python/zope.interface/py3/zope/interface/common/interfaces.py @@ -19,7 +19,7 @@ from zope.interface import classImplements class IException(Interface): "Interface for `Exception`" -classImplements(Exception, IException) +classImplements(Exception, IException) # noqa E305 class IStandardError(IException): @@ -28,117 +28,117 @@ class IStandardError(IException): class IWarning(IException): "Interface for `Warning`" -classImplements(Warning, IWarning) +classImplements(Warning, IWarning) # noqa E305 class ISyntaxError(IStandardError): "Interface for `SyntaxError`" -classImplements(SyntaxError, ISyntaxError) +classImplements(SyntaxError, ISyntaxError) # noqa E305 class ILookupError(IStandardError): "Interface for `LookupError`" -classImplements(LookupError, ILookupError) +classImplements(LookupError, ILookupError) # noqa E305 class IValueError(IStandardError): "Interface for `ValueError`" -classImplements(ValueError, IValueError) +classImplements(ValueError, IValueError) # noqa E305 class IRuntimeError(IStandardError): "Interface for `RuntimeError`" -classImplements(RuntimeError, IRuntimeError) +classImplements(RuntimeError, IRuntimeError) # noqa E305 class IArithmeticError(IStandardError): "Interface for `ArithmeticError`" -classImplements(ArithmeticError, IArithmeticError) +classImplements(ArithmeticError, IArithmeticError) # noqa E305 class IAssertionError(IStandardError): "Interface for `AssertionError`" -classImplements(AssertionError, IAssertionError) +classImplements(AssertionError, IAssertionError) # noqa E305 class IAttributeError(IStandardError): "Interface for `AttributeError`" -classImplements(AttributeError, IAttributeError) +classImplements(AttributeError, IAttributeError) # noqa E305 class IDeprecationWarning(IWarning): "Interface for `DeprecationWarning`" -classImplements(DeprecationWarning, IDeprecationWarning) +classImplements(DeprecationWarning, IDeprecationWarning) # noqa E305 class IEOFError(IStandardError): "Interface for `EOFError`" -classImplements(EOFError, IEOFError) +classImplements(EOFError, IEOFError) # noqa E305 class IEnvironmentError(IStandardError): "Interface for `EnvironmentError`" -classImplements(EnvironmentError, IEnvironmentError) +classImplements(EnvironmentError, IEnvironmentError) # noqa E305 class IFloatingPointError(IArithmeticError): "Interface for `FloatingPointError`" -classImplements(FloatingPointError, IFloatingPointError) +classImplements(FloatingPointError, IFloatingPointError) # noqa E305 class IIOError(IEnvironmentError): "Interface for `IOError`" -classImplements(IOError, IIOError) +classImplements(IOError, IIOError) # noqa E305 class IImportError(IStandardError): "Interface for `ImportError`" -classImplements(ImportError, IImportError) +classImplements(ImportError, IImportError) # noqa E305 class IIndentationError(ISyntaxError): "Interface for `IndentationError`" -classImplements(IndentationError, IIndentationError) +classImplements(IndentationError, IIndentationError) # noqa E305 class IIndexError(ILookupError): "Interface for `IndexError`" -classImplements(IndexError, IIndexError) +classImplements(IndexError, IIndexError) # noqa E305 class IKeyError(ILookupError): "Interface for `KeyError`" -classImplements(KeyError, IKeyError) +classImplements(KeyError, IKeyError) # noqa E305 class IKeyboardInterrupt(IStandardError): "Interface for `KeyboardInterrupt`" -classImplements(KeyboardInterrupt, IKeyboardInterrupt) +classImplements(KeyboardInterrupt, IKeyboardInterrupt) # noqa E305 class IMemoryError(IStandardError): "Interface for `MemoryError`" -classImplements(MemoryError, IMemoryError) +classImplements(MemoryError, IMemoryError) # noqa E305 class INameError(IStandardError): "Interface for `NameError`" -classImplements(NameError, INameError) +classImplements(NameError, INameError) # noqa E305 class INotImplementedError(IRuntimeError): "Interface for `NotImplementedError`" -classImplements(NotImplementedError, INotImplementedError) +classImplements(NotImplementedError, INotImplementedError) # noqa E305 class IOSError(IEnvironmentError): "Interface for `OSError`" -classImplements(OSError, IOSError) +classImplements(OSError, IOSError) # noqa E305 class IOverflowError(IArithmeticError): "Interface for `ArithmeticError`" -classImplements(OverflowError, IOverflowError) +classImplements(OverflowError, IOverflowError) # noqa E305 class IOverflowWarning(IWarning): @@ -151,59 +151,59 @@ class IOverflowWarning(IWarning): class IReferenceError(IStandardError): "Interface for `ReferenceError`" -classImplements(ReferenceError, IReferenceError) +classImplements(ReferenceError, IReferenceError) # noqa E305 class IRuntimeWarning(IWarning): "Interface for `RuntimeWarning`" -classImplements(RuntimeWarning, IRuntimeWarning) +classImplements(RuntimeWarning, IRuntimeWarning) # noqa E305 class IStopIteration(IException): "Interface for `StopIteration`" -classImplements(StopIteration, IStopIteration) +classImplements(StopIteration, IStopIteration) # noqa E305 class ISyntaxWarning(IWarning): "Interface for `SyntaxWarning`" -classImplements(SyntaxWarning, ISyntaxWarning) +classImplements(SyntaxWarning, ISyntaxWarning) # noqa E305 class ISystemError(IStandardError): "Interface for `SystemError`" -classImplements(SystemError, ISystemError) +classImplements(SystemError, ISystemError) # noqa E305 class ISystemExit(IException): "Interface for `SystemExit`" -classImplements(SystemExit, ISystemExit) +classImplements(SystemExit, ISystemExit) # noqa E305 class ITabError(IIndentationError): "Interface for `TabError`" -classImplements(TabError, ITabError) +classImplements(TabError, ITabError) # noqa E305 class ITypeError(IStandardError): "Interface for `TypeError`" -classImplements(TypeError, ITypeError) +classImplements(TypeError, ITypeError) # noqa E305 class IUnboundLocalError(INameError): "Interface for `UnboundLocalError`" -classImplements(UnboundLocalError, IUnboundLocalError) +classImplements(UnboundLocalError, IUnboundLocalError) # noqa E305 class IUnicodeError(IValueError): "Interface for `UnicodeError`" -classImplements(UnicodeError, IUnicodeError) +classImplements(UnicodeError, IUnicodeError) # noqa E305 class IUserWarning(IWarning): "Interface for `UserWarning`" -classImplements(UserWarning, IUserWarning) +classImplements(UserWarning, IUserWarning) # noqa E305 class IZeroDivisionError(IArithmeticError): "Interface for `ZeroDivisionError`" -classImplements(ZeroDivisionError, IZeroDivisionError) +classImplements(ZeroDivisionError, IZeroDivisionError) # noqa E305 diff --git a/contrib/python/zope.interface/py3/zope/interface/common/mapping.py b/contrib/python/zope.interface/py3/zope/interface/common/mapping.py index eb9a2900b7..d8ea074826 100644 --- a/contrib/python/zope.interface/py3/zope/interface/common/mapping.py +++ b/contrib/python/zope.interface/py3/zope/interface/common/mapping.py @@ -96,9 +96,11 @@ class IEnumerableMapping(collections.ISized, IReadMapping): """Return the items of the mapping object. """ + class IMapping(IWriteMapping, IEnumerableMapping): ''' Simple mapping interface ''' + class IIterableMapping(IEnumerableMapping): """A mapping that has distinct methods for iterating without copying. @@ -115,6 +117,7 @@ class IClonableMapping(Interface): def copy(): "return copy of dict" + class IExtendedReadMapping(IIterableMapping): """ Something with a particular method equivalent to ``__contains__``. @@ -154,9 +157,14 @@ class IExtendedWriteMapping(IWriteMapping): """remove and return some (key, value) pair as a 2-tuple; but raise KeyError if mapping is empty""" + class IFullMapping( - collections.IMutableMapping, - IExtendedReadMapping, IExtendedWriteMapping, IClonableMapping, IMapping,): + collections.IMutableMapping, + IExtendedReadMapping, + IExtendedWriteMapping, + IClonableMapping, + IMapping, +): """ Full mapping interface. diff --git a/contrib/python/zope.interface/py3/zope/interface/common/sequence.py b/contrib/python/zope.interface/py3/zope/interface/common/sequence.py index 738f76d42a..c63f5a477a 100644 --- a/contrib/python/zope.interface/py3/zope/interface/common/sequence.py +++ b/contrib/python/zope.interface/py3/zope/interface/common/sequence.py @@ -55,6 +55,7 @@ class IMinimalSequence(collections.IIterable): Declaring this interface does not specify whether `__getitem__` supports slice objects.""" + class IFiniteSequence(collections.ISized, IMinimalSequence): """ A sequence of bound size. @@ -63,6 +64,7 @@ class IFiniteSequence(collections.ISized, IMinimalSequence): Extend ``ISized`` """ + class IReadSequence(collections.IContainer, IFiniteSequence): """ read interface shared by tuple and list @@ -120,6 +122,7 @@ class IExtendedReadSequence(IReadSequence): Return first index of *value* """ + class IUniqueMemberWriteSequence(Interface): """The write contract for a sequence that may enforce unique members""" @@ -161,12 +164,14 @@ class IUniqueMemberWriteSequence(Interface): def extend(iterable): """Extend list by appending elements from the iterable""" + class IWriteSequence(IUniqueMemberWriteSequence): """Full write contract for sequences""" def __imul__(n): """``x.__imul__(n) <==> x *= n``""" + class ISequence(IReadSequence, IWriteSequence): """ Full sequence contract. diff --git a/contrib/python/zope.interface/py3/zope/interface/declarations.py b/contrib/python/zope.interface/py3/zope/interface/declarations.py index 87e625203c..a9b983da81 100644 --- a/contrib/python/zope.interface/py3/zope/interface/declarations.py +++ b/contrib/python/zope.interface/py3/zope/interface/declarations.py @@ -34,6 +34,7 @@ from types import ModuleType from zope.interface._compat import _use_c_impl from zope.interface.interface import Interface +from zope.interface.interface import InterfaceBase from zope.interface.interface import InterfaceClass from zope.interface.interface import NameAndModuleComparisonMixin from zope.interface.interface import Specification @@ -61,6 +62,7 @@ def _next_super_class(ob): next_class = complete_mro[complete_mro.index(class_that_invoked_super) + 1] return next_class + class named: def __init__(self, name): @@ -103,7 +105,7 @@ class Declaration(Specification): if not [ j for j in other.interfaces() - if i.extends(j, 0) # non-strict extends + if i.extends(j, 0) # non-strict extends ] ]) @@ -114,10 +116,10 @@ class Declaration(Specification): .. versionchanged:: 5.4.0 Now tries to preserve a consistent resolution order. Interfaces - being added to this object are added to the front of the resulting resolution - order if they already extend an interface in this object. Previously, - they were always added to the end of the order, which easily resulted in - invalid orders. + being added to this object are added to the front of the resulting + resolution order if they already extend an interface in this + object. Previously, they were always added to the end of the order, + which easily resulted in invalid orders. """ before = [] result = list(self.interfaces()) @@ -171,9 +173,11 @@ class Declaration(Specification): # classes.) this_name = iface.__name__ duplicate_transform = _implements_name - elif (isinstance(iface, Implements) - and not iface.declared - and iface.inherit in interfaces): + elif ( + isinstance(iface, Implements) and + not iface.declared and + iface.inherit in interfaces + ): # If nothing is declared, there's no need to even print this; # it would just show as ``classImplements(Class)``, and the # ``Class`` has typically already. @@ -216,13 +220,15 @@ class _ImmutableDeclaration(Declaration): @__bases__.setter def __bases__(self, new_bases): # We expect the superclass constructor to set ``self.__bases__ = ()``. - # Rather than attempt to special case that in the constructor and allow - # setting __bases__ only at that time, it's easier to just allow setting - # the empty tuple at any time. That makes ``x.__bases__ = x.__bases__`` a nice - # no-op too. (Skipping the superclass constructor altogether is a recipe - # for maintenance headaches.) + # Rather than attempt to special case that in the constructor and + # allow setting __bases__ only at that time, it's easier to just allow + # setting the empty tuple at any time. That makes ``x.__bases__ = + # x.__bases__`` a nice no-op too. (Skipping the superclass constructor + # altogether is a recipe for maintenance headaches.) if new_bases != (): - raise TypeError("Cannot set non-empty bases on shared empty Declaration.") + raise TypeError( + "Cannot set non-empty bases on shared empty Declaration." + ) # As the immutable empty declaration, we cannot be changed. # This means there's no logical reason for us to have dependents @@ -246,20 +252,20 @@ class _ImmutableDeclaration(Declaration): def weakref(self, callback=None): # We're a singleton, we never go away. So there's no need to return - # distinct weakref objects here; their callbacks will never - # be called. Instead, we only need to return a callable that - # returns ourself. The easiest one is to return _ImmutableDeclaration - # itself; testing on Python 3.8 shows that's faster than a function that - # returns _empty. (Remember, one goal is to avoid allocating any - # object, and that includes a method.) + # distinct weakref objects here; their callbacks will never be called. + # Instead, we only need to return a callable that returns ourself. The + # easiest one is to return _ImmutableDeclaration itself; testing on + # Python 3.8 shows that's faster than a function that returns _empty. + # (Remember, one goal is to avoid allocating any object, and that + # includes a method.) return _ImmutableDeclaration @property def _v_attrs(self): # _v_attrs is not a public, documented property, but some client code # uses it anyway as a convenient place to cache things. To keep the - # empty declaration truly immutable, we must ignore that. That includes - # ignoring assignments as well. + # empty declaration truly immutable, we must ignore that. That + # includes ignoring assignments as well. return {} @_v_attrs.setter @@ -275,26 +281,28 @@ class _ImmutableDeclaration(Declaration): class Implements(NameAndModuleComparisonMixin, Declaration): - # Inherit from NameAndModuleComparisonMixin to be - # mutually comparable with InterfaceClass objects. - # (The two must be mutually comparable to be able to work in e.g., BTrees.) - # Instances of this class generally don't have a __module__ other than - # `zope.interface.declarations`, whereas they *do* have a __name__ that is the - # fully qualified name of the object they are representing. + # Inherit from NameAndModuleComparisonMixin to be mutually comparable with + # InterfaceClass objects. (The two must be mutually comparable to be able + # to work in e.g., BTrees.) Instances of this class generally don't have a + # __module__ other than `zope.interface.declarations`, whereas they *do* + # have a __name__ that is the fully qualified name of the object they are + # representing. # Note, though, that equality and hashing are still identity based. This - # accounts for things like nested objects that have the same name (typically - # only in tests) and is consistent with pickling. As far as comparisons to InterfaceClass - # goes, we'll never have equal name and module to those, so we're still consistent there. - # Instances of this class are essentially intended to be unique and are - # heavily cached (note how our __reduce__ handles this) so having identity - # based hash and eq should also work. - - # We want equality and hashing to be based on identity. However, we can't actually - # implement __eq__/__ne__ to do this because sometimes we get wrapped in a proxy. - # We need to let the proxy types implement these methods so they can handle unwrapping - # and then rely on: (1) the interpreter automatically changing `implements == proxy` into - # `proxy == implements` (which will call proxy.__eq__ to do the unwrapping) and then + # accounts for things like nested objects that have the same name + # (typically only in tests) and is consistent with pickling. As far as + # comparisons to InterfaceClass goes, we'll never have equal name and + # module to those, so we're still consistent there. Instances of this + # class are essentially intended to be unique and are heavily cached (note + # how our __reduce__ handles this) so having identity based hash and eq + # should also work. + + # We want equality and hashing to be based on identity. However, we can't + # actually implement __eq__/__ne__ to do this because sometimes we get + # wrapped in a proxy. We need to let the proxy types implement these + # methods so they can handle unwrapping and then rely on: (1) the + # interpreter automatically changing `implements == proxy` into `proxy == + # implements` (which will call proxy.__eq__ to do the unwrapping) and then # (2) the default equality and hashing semantics being identity based. # class whose specification should be used as additional base @@ -313,11 +321,11 @@ class Implements(NameAndModuleComparisonMixin, @classmethod def named(cls, name, *bases): - # Implementation method: Produce an Implements interface with - # a fully fleshed out __name__ before calling the constructor, which - # sets bases to the given interfaces and which may pass this object to - # other objects (e.g., to adjust dependents). If they're sorting or comparing - # by name, this needs to be set. + # Implementation method: Produce an Implements interface with a fully + # fleshed out __name__ before calling the constructor, which sets + # bases to the given interfaces and which may pass this object to + # other objects (e.g., to adjust dependents). If they're sorting or + # comparing by name, this needs to be set. inst = cls.__new__(cls) inst.__name__ = name inst.__init__(*bases) @@ -332,13 +340,16 @@ class Implements(NameAndModuleComparisonMixin, def __repr__(self): if self.inherit: - name = getattr(self.inherit, '__name__', None) or _implements_name(self.inherit) + name = ( + getattr(self.inherit, '__name__', None) or + _implements_name(self.inherit) + ) else: name = self.__name__ declared_names = self._argument_names_for_repr(self.declared) if declared_names: declared_names = ', ' + declared_names - return 'classImplements({}{})'.format(name, declared_names) + return f'classImplements({name}{declared_names})' def __reduce__(self): return implementedBy, (self.inherit, ) @@ -353,6 +364,12 @@ def _implements_name(ob): # equality and hashing is still based on identity. # It might be nice to use __qualname__ on Python 3, but that would produce # different values between Py2 and Py3. + + # Special-case 'InterfaceBase': its '__module__' member descriptor + # behaves differently across Python 3.x versions. + if ob is InterfaceBase: + return 'zope.interface.interface.InterfaceBase' + return (getattr(ob, '__module__', '?') or '?') + \ '.' + (getattr(ob, '__name__', '?') or '?') @@ -370,7 +387,7 @@ def _implementedBy_super(sup): # that excludes the classes being skipped over but # includes everything else. implemented_by_self = implementedBy(sup.__self_class__) - cache = implemented_by_self._super_cache # pylint:disable=protected-access + cache = implemented_by_self._super_cache # pylint:disable=protected-access if cache is None: cache = implemented_by_self._super_cache = weakref.WeakKeyDictionary() @@ -405,7 +422,9 @@ def _implementedBy_super(sup): @_use_c_impl -def implementedBy(cls): # pylint:disable=too-many-return-statements,too-many-branches +def implementedBy( + cls +): # pylint:disable=too-many-return-statements,too-many-branches """Return the interfaces implemented for a class' instances The value returned is an `~zope.interface.interfaces.IDeclaration`. @@ -459,10 +478,10 @@ def implementedBy(cls): # pylint:disable=too-many-return-statements,too-many-bra spec_name = _implements_name(cls) if spec is not None: # old-style __implemented__ = foo declaration - spec = (spec, ) # tuplefy, as it might be just an int + spec = (spec, ) # tuplefy, as it might be just an int spec = Implements.named(spec_name, *_normalizeargs(spec)) - spec.inherit = None # old-style implies no inherit - del cls.__implemented__ # get rid of the old-style declaration + spec.inherit = None # old-style implies no inherit + del cls.__implemented__ # get rid of the old-style declaration else: try: bases = cls.__bases__ @@ -482,9 +501,8 @@ def implementedBy(cls): # pylint:disable=too-many-return-statements,too-many-bra if isinstance(cls, type) and '__provides__' not in cls.__dict__: # Make sure we get a __provides__ descriptor cls.__provides__ = ClassProvides( - cls, - getattr(cls, '__class__', type(cls)), - ) + cls, getattr(cls, '__class__', type(cls)), + ) except TypeError: if not isinstance(cls, type): @@ -502,9 +520,10 @@ def classImplementsOnly(cls, *interfaces): specifications (`~zope.interface.interfaces.IDeclaration` objects). The interfaces given (including the interfaces in the specifications) - replace any previous declarations, *including* inherited definitions. If you - wish to preserve inherited declarations, you can pass ``implementedBy(cls)`` - in *interfaces*. This can be used to alter the interface resolution order. + replace any previous declarations, *including* inherited definitions. If + you wish to preserve inherited declarations, you can pass + ``implementedBy(cls)`` in *interfaces*. This can be used to alter the + interface resolution order. """ spec = implementedBy(cls) # Clear out everything inherited. It's important to @@ -521,8 +540,8 @@ def classImplements(cls, *interfaces): """ Declare additional interfaces implemented for instances of a class - The arguments after the class are one or more interfaces or - interface specifications (`~zope.interface.interfaces.IDeclaration` objects). + The arguments after the class are one or more interfaces or interface + specifications (`~zope.interface.interfaces.IDeclaration` objects). The interfaces given (including the interfaces in the specifications) are added to any interfaces previously declared. An effort is made to @@ -534,13 +553,14 @@ def classImplements(cls, *interfaces): based on inheritance, in order to try to maintain a consistent resolution order. Previously, all interfaces were added to the end. .. versionchanged:: 5.1.0 - If *cls* is already declared to implement an interface (or derived interface) - in *interfaces* through inheritance, the interface is ignored. Previously, it - would redundantly be made direct base of *cls*, which often produced inconsistent - interface resolution orders. Now, the order will be consistent, but may change. - Also, if the ``__bases__`` of the *cls* are later changed, the *cls* will no - longer be considered to implement such an interface (changing the ``__bases__`` of *cls* - has never been supported). + If *cls* is already declared to implement an interface (or derived + interface) in *interfaces* through inheritance, the interface is + ignored. Previously, it would redundantly be made direct base of *cls*, + which often produced inconsistent interface resolution orders. Now, the + order will be consistent, but may change. Also, if the ``__bases__`` + of the *cls* are later changed, the *cls* will no longer be considered + to implement such an interface (changing the ``__bases__`` of *cls* has + never been supported). """ spec = implementedBy(cls) interfaces = tuple(_normalizeargs(interfaces)) @@ -578,9 +598,9 @@ def classImplementsFirst(cls, iface): def _classImplements_ordered(spec, before=(), after=()): # Elide everything already inherited. # Except, if it is the root, and we don't already declare anything else - # that would imply it, allow the root through. (TODO: When we disallow non-strict - # IRO, this part of the check can be removed because it's not possible to re-declare - # like that.) + # that would imply it, allow the root through. (TODO: When we disallow + # non-strict IRO, this part of the check can be removed because it's not + # possible to re-declare like that.) before = [ x for x in before @@ -595,8 +615,8 @@ def _classImplements_ordered(spec, before=(), after=()): # eliminate duplicates new_declared = [] seen = set() - for l in before, spec.declared, after: - for b in l: + for lst in before, spec.declared, after: + for b in lst: if b not in seen: new_declared.append(b) seen.add(b) @@ -604,7 +624,7 @@ def _classImplements_ordered(spec, before=(), after=()): spec.declared = tuple(new_declared) # compute the bases - bases = new_declared # guaranteed no dupes + bases = new_declared # guaranteed no dupes if spec.inherit is not None: for c in spec.inherit.__bases__: @@ -629,19 +649,18 @@ class implementer: This function is called as a class decorator. - The arguments are one or more interfaces or interface - specifications (`~zope.interface.interfaces.IDeclaration` - objects). + The arguments are one or more interfaces or interface specifications + (`~zope.interface.interfaces.IDeclaration` objects). - The interfaces given (including the interfaces in the - specifications) are added to any interfaces previously declared, - unless the interface is already implemented. + The interfaces given (including the interfaces in the specifications) are + added to any interfaces previously declared, unless the interface is + already implemented. Previous declarations include declarations for base classes unless implementsOnly was used. - This function is provided for convenience. It provides a more - convenient way to call `classImplements`. For example:: + This function is provided for convenience. It provides a more convenient + way to call `classImplements`. For example:: @implementer(I1) class C(object): @@ -675,6 +694,7 @@ class implementer: raise TypeError("Can't declare implements", ob) return ob + class implementer_only: """Declare the only interfaces implemented by instances of a class @@ -728,22 +748,23 @@ class Provides(Declaration): # Really named ProvidesClass def __init__(self, cls, *interfaces): self.__args = (cls, ) + interfaces self._cls = cls - Declaration.__init__(self, *self._add_interfaces_to_cls(interfaces, cls)) + Declaration.__init__( + self, *self._add_interfaces_to_cls(interfaces, cls) + ) # Added to by ``moduleProvides``, et al _v_module_names = () def __repr__(self): - # The typical way to create instances of this - # object is via calling ``directlyProvides(...)`` or ``alsoProvides()``, - # but that's not the only way. Proxies, for example, - # directly use the ``Provides(...)`` function (which is the - # more generic method, and what we pickle as). We're after the most - # readable, useful repr in the common case, so we use the most - # common name. + # The typical way to create instances of this object is via calling + # ``directlyProvides(...)`` or ``alsoProvides()``, but that's not the + # only way. Proxies, for example, directly use the ``Provides(...)`` + # function (which is the more generic method, and what we pickle as). + # We're after the most readable, useful repr in the common case, so we + # use the most common name. # - # We also cooperate with ``moduleProvides`` to attempt to do the - # right thing for that API. See it for details. + # We also cooperate with ``moduleProvides`` to attempt to do the right + # thing for that API. See it for details. function_name = 'directlyProvides' if self._cls is ModuleType and self._v_module_names: # See notes in ``moduleProvides``/``directlyProvides`` @@ -758,7 +779,7 @@ class Provides(Declaration): # Really named ProvidesClass if len(mod_names) == 1: mod_names = "sys.modules[%r]" % mod_names[0] ordered_names = ( - '{}, '.format(mod_names) + f'{mod_names}, ' ) + ordered_names return "{}({})".format( function_name, @@ -783,13 +804,16 @@ class Provides(Declaration): # Really named ProvidesClass raise AttributeError('__provides__') + ProvidesClass = Provides + # Registry of instance declarations # This is a memory optimization to allow objects to share specifications. InstanceDeclarations = weakref.WeakValueDictionary() -def Provides(*interfaces): # pylint:disable=function-redefined + +def Provides(*interfaces): # pylint:disable=function-redefined """Declaration for an instance of *cls*. The correct signature is ``cls, *interfaces``. @@ -806,10 +830,11 @@ def Provides(*interfaces): # pylint:disable=function-redefined return spec + Provides.__safe_for_unpickling__ = True -def directlyProvides(object, *interfaces): # pylint:disable=redefined-builtin +def directlyProvides(object, *interfaces): # pylint:disable=redefined-builtin """Declare interfaces declared directly for an object The arguments after the object are one or more interfaces or interface @@ -842,8 +867,7 @@ def directlyProvides(object, *interfaces): # pylint:disable=redefined-builtin provides._v_module_names += (object.__name__,) - -def alsoProvides(object, *interfaces): # pylint:disable=redefined-builtin +def alsoProvides(object, *interfaces): # pylint:disable=redefined-builtin """Declare interfaces declared directly for an object The arguments after the object are one or more interfaces or interface @@ -855,7 +879,7 @@ def alsoProvides(object, *interfaces): # pylint:disable=redefined-builtin directlyProvides(object, directlyProvidedBy(object), *interfaces) -def noLongerProvides(object, interface): # pylint:disable=redefined-builtin +def noLongerProvides(object, interface): # pylint:disable=redefined-builtin """ Removes a directly provided interface from an object. """ directlyProvides(object, directlyProvidedBy(object) - interface) @@ -903,22 +927,24 @@ class ClassProvides(Declaration, ClassProvidesBase): self._cls = cls self._implements = implementedBy(cls) self.__args = (cls, metacls, ) + interfaces - Declaration.__init__(self, *self._add_interfaces_to_cls(interfaces, metacls)) + Declaration.__init__( + self, *self._add_interfaces_to_cls(interfaces, metacls) + ) def __repr__(self): - # There are two common ways to get instances of this object: - # The most interesting way is calling ``@provider(..)`` as a decorator - # of a class; this is the same as calling ``directlyProvides(cls, ...)``. + # There are two common ways to get instances of this object: The most + # interesting way is calling ``@provider(..)`` as a decorator of a + # class; this is the same as calling ``directlyProvides(cls, ...)``. # - # The other way is by default: anything that invokes ``implementedBy(x)`` - # will wind up putting an instance in ``type(x).__provides__``; this includes - # the ``@implementer(...)`` decorator. Those instances won't have any - # interfaces. + # The other way is by default: anything that invokes + # ``implementedBy(x)`` will wind up putting an instance in + # ``type(x).__provides__``; this includes the ``@implementer(...)`` + # decorator. Those instances won't have any interfaces. # # Thus, as our repr, we go with the ``directlyProvides()`` syntax. interfaces = (self._cls, ) + self.__args[2:] ordered_names = self._argument_names_for_repr(interfaces) - return "directlyProvides({})".format(ordered_names) + return f"directlyProvides({ordered_names})" def __reduce__(self): return self.__class__, self.__args @@ -927,18 +953,18 @@ class ClassProvides(Declaration, ClassProvidesBase): __get__ = ClassProvidesBase.__get__ -def directlyProvidedBy(object): # pylint:disable=redefined-builtin +def directlyProvidedBy(object): # pylint:disable=redefined-builtin """Return the interfaces directly provided by the given object The value returned is an `~zope.interface.interfaces.IDeclaration`. """ provides = getattr(object, "__provides__", None) if ( - provides is None # no spec + provides is None # no spec # We might have gotten the implements spec, as an # optimization. If so, it's like having only one base, that we # lop off to exclude class-supplied declarations: - or isinstance(provides, Implements) + or isinstance(provides, Implements) # noqa W503 ): return _empty @@ -1008,8 +1034,8 @@ def moduleProvides(*interfaces): directlyProvides(sys.modules[__name__], I1) """ - frame = sys._getframe(1) # pylint:disable=protected-access - locals = frame.f_locals # pylint:disable=redefined-builtin + frame = sys._getframe(1) # pylint:disable=protected-access + locals = frame.f_locals # pylint:disable=redefined-builtin # Try to make sure we were called from a module body if (locals is not frame.f_globals) or ('__name__' not in locals): @@ -1020,18 +1046,18 @@ def moduleProvides(*interfaces): raise TypeError( "moduleProvides can only be used once in a module definition.") - # Note: This is cached based on the key ``(ModuleType, *interfaces)``; - # One consequence is that any module that provides the same interfaces - # gets the same ``__repr__``, meaning that you can't tell what module - # such a declaration came from. Adding the module name to ``_v_module_names`` - # attempts to correct for this; it works in some common situations, but fails - # (1) after pickling (the data is lost) and (2) if declarations are - # actually shared and (3) if the alternate spelling of ``directlyProvides()`` - # is used. Problem (3) is fixed by cooperating with ``directlyProvides`` - # to maintain this information, and problem (2) is worked around by - # printing all the names, but (1) is unsolvable without introducing - # new classes or changing the stored data...but it doesn't actually matter, - # because ``ModuleType`` can't be pickled! + # Note: This is cached based on the key ``(ModuleType, *interfaces)``; One + # consequence is that any module that provides the same interfaces gets + # the same ``__repr__``, meaning that you can't tell what module such a + # declaration came from. Adding the module name to ``_v_module_names`` + # attempts to correct for this; it works in some common situations, but + # fails (1) after pickling (the data is lost) and (2) if declarations are + # actually shared and (3) if the alternate spelling of + # ``directlyProvides()`` is used. Problem (3) is fixed by cooperating + # with ``directlyProvides`` to maintain this information, and problem (2) + # is worked around by printing all the names, but (1) is unsolvable + # without introducing new classes or changing the stored data...but it + # doesn't actually matter, because ``ModuleType`` can't be pickled! p = locals["__provides__"] = Provides(ModuleType, *_normalizeargs(interfaces)) p._v_module_names += (locals['__name__'],) @@ -1050,7 +1076,8 @@ def ObjectSpecification(direct, cls): These combine information for the object and for it's classes. """ - return Provides(cls, direct) # pragma: no cover fossil + return Provides(cls, direct) # pragma: no cover fossil + @_use_c_impl def getObjectSpecification(ob): @@ -1086,7 +1113,7 @@ def providedBy(ob): # Try to get __providedBy__ try: - if isinstance(ob, super): # Some objects raise errors on isinstance() + if isinstance(ob, super): # Some objects raise errors on isinstance() return implementedBy(ob) r = ob.__providedBy__ @@ -1136,8 +1163,8 @@ def providedBy(ob): class ObjectSpecificationDescriptor: """Implement the ``__providedBy__`` attribute - The ``__providedBy__`` attribute computes the interfaces provided by - an object. If an object has an ``__provides__`` attribute, that is returned. + The ``__providedBy__`` attribute computes the interfaces provided by an + object. If an object has an ``__provides__`` attribute, that is returned. Otherwise, `implementedBy` the *cls* is returned. .. versionchanged:: 5.4.0 @@ -1184,6 +1211,7 @@ def _normalizeargs(sequence, output=None): return output + _empty = _ImmutableDeclaration() objectSpecificationDescriptor = ObjectSpecificationDescriptor() diff --git a/contrib/python/zope.interface/py3/zope/interface/document.py b/contrib/python/zope.interface/py3/zope/interface/document.py index 2595c569d2..3725037720 100644 --- a/contrib/python/zope.interface/py3/zope/interface/document.py +++ b/contrib/python/zope.interface/py3/zope/interface/document.py @@ -24,7 +24,8 @@ __all__ = [ 'asStructuredText', ] -def asStructuredText(I, munge=0, rst=False): + +def asStructuredText(iface, munge=0, rst=False): """ Output structured text format. Note, this will whack any existing 'structured' format of the text. @@ -33,19 +34,21 @@ def asStructuredText(I, munge=0, rst=False): """ if rst: - inline_literal = lambda s: "``{}``".format(s) + def inline_literal(s): + return f"``{s}``" else: - inline_literal = lambda s: s + def inline_literal(s): + return s - r = [inline_literal(I.getName())] + r = [inline_literal(iface.getName())] outp = r.append level = 1 - if I.getDoc(): - outp(_justify_and_indent(_trim_doc_string(I.getDoc()), level)) + if iface.getDoc(): + outp(_justify_and_indent(_trim_doc_string(iface.getDoc()), level)) bases = [base - for base in I.__bases__ + for base in iface.__bases__ if base is not zope.interface.Interface ] if bases: @@ -56,14 +59,16 @@ def asStructuredText(I, munge=0, rst=False): outp(_justify_and_indent(_trim_doc_string(item), level, munge)) level -= 1 - namesAndDescriptions = sorted(I.namesAndDescriptions()) + namesAndDescriptions = sorted(iface.namesAndDescriptions()) outp(_justify_and_indent("Attributes:", level, munge)) level += 1 for name, desc in namesAndDescriptions: if not hasattr(desc, 'getSignatureString'): # ugh... - item = "{} -- {}".format(inline_literal(desc.getName()), - desc.getDoc() or 'no documentation') + item = "{} -- {}".format( + inline_literal(desc.getName()), + desc.getDoc() or 'no documentation' + ) outp(_justify_and_indent(_trim_doc_string(item), level, munge)) level -= 1 @@ -71,18 +76,21 @@ def asStructuredText(I, munge=0, rst=False): level += 1 for name, desc in namesAndDescriptions: if hasattr(desc, 'getSignatureString'): # ugh... - _call = "{}{}".format(desc.getName(), desc.getSignatureString()) - item = "{} -- {}".format(inline_literal(_call), - desc.getDoc() or 'no documentation') + _call = f"{desc.getName()}{desc.getSignatureString()}" + item = "{} -- {}".format( + inline_literal(_call), + desc.getDoc() or 'no documentation' + ) outp(_justify_and_indent(_trim_doc_string(item), level, munge)) return "\n\n".join(r) + "\n\n" -def asReStructuredText(I, munge=0): - """ Output reStructuredText format. Note, this will whack any existing - 'structured' format of the text.""" - return asStructuredText(I, munge=munge, rst=True) +def asReStructuredText(iface, munge=0): + """ Output reStructuredText format. + + Note, this will whack any existing 'structured' format of the text.""" + return asStructuredText(iface, munge=munge, rst=True) def _trim_doc_string(text): diff --git a/contrib/python/zope.interface/py3/zope/interface/exceptions.py b/contrib/python/zope.interface/py3/zope/interface/exceptions.py index 0612eb230e..b86fb1e04c 100644 --- a/contrib/python/zope.interface/py3/zope/interface/exceptions.py +++ b/contrib/python/zope.interface/py3/zope/interface/exceptions.py @@ -26,6 +26,7 @@ __all__ = [ 'InvalidInterface', ] + class Invalid(Exception): """A specification is violated """ @@ -55,7 +56,7 @@ class _TargetInvalid(Invalid): def _get_arg_or_default(self, ix, default=None): try: - return self.args[ix] # pylint:disable=unsubscriptable-object + return self.args[ix] # pylint:disable=unsubscriptable-object except self._NOT_GIVEN_CATCH: return default @@ -92,7 +93,7 @@ class _TargetInvalid(Invalid): target = self.target if target is self._NOT_GIVEN: return "An object" - return "The object {!r}".format(target) + return f"The object {target!r}" @property def _str_description(self): @@ -146,7 +147,7 @@ class BrokenImplementation(_TargetInvalid): @property def name(self): - return self.args[1] # pylint:disable=unsubscriptable-object + return self.args[1] # pylint:disable=unsubscriptable-object @property def _str_details(self): @@ -157,7 +158,9 @@ class BrokenImplementation(_TargetInvalid): class BrokenMethodImplementation(_TargetInvalid): """ - BrokenMethodImplementation(method, message[, implementation, interface, target]) + BrokenMethodImplementation( + method, message[, implementation, interface, target] + ) The *target* (optional) has a *method* in *implementation* that violates its contract in a way described by *mess*. @@ -181,11 +184,11 @@ class BrokenMethodImplementation(_TargetInvalid): @property def method(self): - return self.args[0] # pylint:disable=unsubscriptable-object + return self.args[0] # pylint:disable=unsubscriptable-object @property def mess(self): - return self.args[1] # pylint:disable=unsubscriptable-object + return self.args[1] # pylint:disable=unsubscriptable-object @staticmethod def __implementation_str(impl): @@ -197,8 +200,7 @@ class BrokenMethodImplementation(_TargetInvalid): formatsig = str except AttributeError: sig = inspect.getargspec - f = inspect.formatargspec - formatsig = lambda sig: f(*sig) # pylint:disable=deprecated-method + formatsig = inspect.formatargspec try: sig = sig(impl) @@ -248,7 +250,7 @@ class MultipleInvalid(_TargetInvalid): @property def exceptions(self): - return self.args[2] # pylint:disable=unsubscriptable-object + return self.args[2] # pylint:disable=unsubscriptable-object @property def _str_details(self): @@ -259,7 +261,7 @@ class MultipleInvalid(_TargetInvalid): for x in self.exceptions ) - _str_conjunction = ':' # We don't want a trailing space, messes up doctests + _str_conjunction = ':' # no trailing space, messes up doctests _str_trailer = '' @@ -267,6 +269,7 @@ class InvalidInterface(Exception): """The interface has invalid contents """ + class BadImplements(TypeError): """An implementation assertion is invalid diff --git a/contrib/python/zope.interface/py3/zope/interface/interface.py b/contrib/python/zope.interface/py3/zope/interface/interface.py index 8e0d9ad2b7..575b6381e3 100644 --- a/contrib/python/zope.interface/py3/zope/interface/interface.py +++ b/contrib/python/zope.interface/py3/zope/interface/interface.py @@ -47,7 +47,6 @@ _decorator_non_return = object() _marker = object() - def invariant(call): f_locals = sys._getframe(1).f_locals tags = f_locals.setdefault(TAGGED_DATA, {}) @@ -72,9 +71,11 @@ class Element: # We can't say this yet because we don't have enough # infrastructure in place. # - #implements(IElement) + # implements(IElement) - def __init__(self, __name__, __doc__=''): # pylint:disable=redefined-builtin + def __init__( + self, __name__, __doc__='', + ): # pylint:disable=redefined-builtin if not __doc__ and __name__.find(' ') >= 0: __doc__ = __name__ __name__ = None @@ -108,7 +109,9 @@ class Element: def queryTaggedValue(self, tag, default=None): """ Returns the value associated with 'tag'. """ - return self.__tagged_values.get(tag, default) if self.__tagged_values else default + return self.__tagged_values.get( + tag, default, + ) if self.__tagged_values else default def getTaggedValueTags(self): """ Returns a collection of all tags. """ @@ -125,7 +128,7 @@ class Element: getDirectTaggedValueTags = getTaggedValueTags -SpecificationBasePy = object # filled by _use_c_impl. +SpecificationBasePy = object # filled by _use_c_impl. @_use_c_impl @@ -170,7 +173,7 @@ class SpecificationBase: def isOrExtends(self, interface): """Is the interface the same as or extend the given interface """ - return interface in self._implied # pylint:disable=no-member + return interface in self._implied # pylint:disable=no-member __call__ = isOrExtends @@ -181,10 +184,11 @@ class NameAndModuleComparisonMixin: # attributes. Subclasses will be mutually comparable; but because equality # and hashing semantics are missing from this class, take care in how # you define those two attributes: If you stick with the default equality - # and hashing (identity based) you should make sure that all possible ``__name__`` - # and ``__module__`` pairs are unique ACROSS ALL SUBCLASSES. (Actually, pretty - # much the same thing goes if you define equality and hashing to be based on - # those two attributes: they must still be consistent ACROSS ALL SUBCLASSES.) + # and hashing (identity based) you should make sure that all possible + # ``__name__`` and ``__module__`` pairs are unique ACROSS ALL SUBCLASSES. + # (Actually, pretty much the same thing goes if you define equality and + # hashing to be based on those two attributes: they must still be + # consistent ACROSS ALL SUBCLASSES.) # pylint:disable=assigning-non-slot __slots__ = () @@ -206,8 +210,8 @@ class NameAndModuleComparisonMixin: For example, ``class Foo(object)`` and ``class Foo(Interface)`` in the same file would compare equal, depending on the order of - operands. Writing code like this by hand would be unusual, but it could - happen with dynamic creation of types and interfaces. + operands. Writing code like this by hand would be unusual, but it + could happen with dynamic creation of types and interfaces. None is treated as a pseudo interface that implies the loosest contact possible, no contract. For that reason, all interfaces @@ -333,6 +337,7 @@ class InterfaceBase(NameAndModuleComparisonMixin, SpecificationBasePy): return c return c != 0 + adapter_hooks = _use_c_impl([], 'adapter_hooks') @@ -367,7 +372,7 @@ class Specification(SpecificationBase): # 4700 had 0 dependents, 1400 had 1, 382 had 2 and so on. Only one # for <type> had 1664. So there's savings to be had deferring # the creation of dependents. - self._dependents = None # type: weakref.WeakKeyDictionary + self._dependents = None # type: weakref.WeakKeyDictionary self._bases = () self._implied = {} self._v_attrs = None @@ -410,9 +415,8 @@ class Specification(SpecificationBase): self.changed(self) __bases__ = property( - lambda self: self._bases, - __setBases, - ) + lambda self: self._bases, __setBases, + ) # This method exists for tests to override the way we call # ro.calculate_ro(), usually by adding extra kwargs. We don't @@ -422,26 +426,25 @@ class Specification(SpecificationBase): _do_calculate_ro = calculate_ro def _calculate_sro(self): - """ - Calculate and return the resolution order for this object, using its ``__bases__``. + """Compute resolution order for this object using its ``__bases__``. - Ensures that ``Interface`` is always the last (lowest priority) element. + Ensures that ``Interface`` is always the last (lowest priority) + element. """ - # We'd like to make Interface the lowest priority as a - # property of the resolution order algorithm. That almost - # works out naturally, but it fails when class inheritance has - # some bases that DO implement an interface, and some that DO - # NOT. In such a mixed scenario, you wind up with a set of - # bases to consider that look like this: [[..., Interface], - # [..., object], ...]. Depending on the order of inheritance, - # Interface can wind up before or after object, and that can - # happen at any point in the tree, meaning Interface can wind - # up somewhere in the middle of the order. Since Interface is - # treated as something that everything winds up implementing - # anyway (a catch-all for things like adapters), having it high up - # the order is bad. It's also bad to have it at the end, just before - # some concrete class: concrete classes should be HIGHER priority than - # interfaces (because there's only one class, but many implementations). + # We'd like to make Interface the lowest priority as a property of the + # resolution order algorithm. That almost works out naturally, but it + # fails when class inheritance has some bases that DO implement an + # interface, and some that DO NOT. In such a mixed scenario, you wind + # up with a set of bases to consider that look like this: [[..., + # Interface], [..., object], ...]. Depending on the order of + # inheritance, Interface can wind up before or after object, and that + # can happen at any point in the tree, meaning Interface can wind up + # somewhere in the middle of the order. Since Interface is treated as + # something that everything winds up implementing anyway (a catch-all + # for things like adapters), having it high up the order is bad. It's + # also bad to have it at the end, just before some concrete class: + # concrete classes should be HIGHER priority than interfaces (because + # there's only one class, but many implementations). # # One technically nice way to fix this would be to have # ``implementedBy(object).__bases__ = (Interface,)`` @@ -462,9 +465,9 @@ class Specification(SpecificationBase): }) root = self._ROOT if root is not None and sro and sro[-1] is not root: - # In one dataset of 1823 Interface objects, 1117 ClassProvides objects, - # sro[-1] was root 4496 times, and only not root 118 times. So it's - # probably worth checking. + # In one dataset of 1823 Interface objects, 1117 ClassProvides + # objects, sro[-1] was root 4496 times, and only not root 118 + # times. So it's probably worth checking. # Once we don't have to deal with old-style classes, # we can add a check and only do this if base_count > 1, @@ -502,7 +505,9 @@ class Specification(SpecificationBase): # Now, advise our dependents of change # (being careful not to create the WeakKeyDictionary if not needed): - for dependent in tuple(self._dependents.keys() if self._dependents else ()): + for dependent in tuple( + self._dependents.keys() if self._dependents else () + ): dependent.changed(originally_changed) # Just in case something called get() at some point @@ -526,10 +531,11 @@ class Specification(SpecificationBase): Test whether an interface in the specification extends the given interface """ - return ((interface in self._implied) - and - ((not strict) or (self != interface)) - ) + return ( + (interface in self._implied) and ( + (not strict) or (self != interface) + ) + ) def weakref(self, callback=None): return weakref.ref(self, callback) @@ -552,14 +558,13 @@ class Specification(SpecificationBase): class _InterfaceMetaClass(type): - # Handling ``__module__`` on ``InterfaceClass`` is tricky. We need - # to be able to read it on a type and get the expected string. We - # also need to be able to set it on an instance and get the value - # we set. So far so good. But what gets tricky is that we'd like - # to store the value in the C structure (``InterfaceBase.__ibmodule__``) for - # direct access during equality, sorting, and hashing. "No - # problem, you think, I'll just use a property" (well, the C - # equivalents, ``PyMemberDef`` or ``PyGetSetDef``). + # Handling ``__module__`` on ``InterfaceClass`` is tricky. We need to be + # able to read it on a type and get the expected string. We also need to + # be able to set it on an instance and get the value we set. So far so + # good. But what gets tricky is that we'd like to store the value in the C + # structure (``InterfaceBase.__ibmodule__``) for direct access during + # equality, sorting, and hashing. "No problem, you think, I'll just use a + # property" (well, the C equivalents, ``PyMemberDef`` or ``PyGetSetDef``). # # Except there is a problem. When a subclass is created, the # metaclass (``type``) always automatically puts the expected @@ -578,13 +583,14 @@ class _InterfaceMetaClass(type): # (when implemented in C). Since that includes methods like # ``providedBy``, that's probably not acceptable. # - # All the other methods involve modifying subclasses. This can be - # done either on the fly in some cases, as instances are - # constructed, or by using a metaclass. These next few can be done on the fly. + # All the other methods involve modifying subclasses. This can be done + # either on the fly in some cases, as instances are constructed, or by + # using a metaclass. These next few can be done on the fly. # - # (2) Make ``__module__`` a descriptor in each subclass dictionary. - # It can't be a straight up ``@property`` descriptor, though, because accessing - # it on the class returns a ``property`` object, not the desired string. + # (2) Make ``__module__`` a descriptor in each subclass dictionary. It + # can't be a straight up ``@property`` descriptor, though, because + # accessing it on the class returns a ``property`` object, not the desired + # string. # # (3) Implement a data descriptor (``__get__`` and ``__set__``) # that is both a subclass of string, and also does the redirect of @@ -599,11 +605,12 @@ class _InterfaceMetaClass(type): # This works, preserves the ability to read and write # ``__module__``, and eliminates any penalty accessing other # attributes. But it slows down accessing ``__module__`` of - # instances by 200% (40ns to 124ns), requires editing class dicts on the fly - # (in InterfaceClass.__init__), thus slightly slowing down all interface creation, - # and is ugly. + # instances by 200% (40ns to 124ns), requires editing class dicts on the + # fly (in InterfaceClass.__init__), thus slightly slowing down all + # interface creation, and is ugly. # - # (4) As in the last step, but make it a non-data descriptor (no ``__set__``). + # (4) As in the last step, but make it a non-data descriptor (no + # ``__set__``). # # If you then *also* store a copy of ``__ibmodule__`` in # ``__module__`` in the instance's dict, reading works for both @@ -673,7 +680,8 @@ def interfacemethod(func): define the ``__adapt__`` method, but other interface methods can be overridden this way too. - .. seealso:: `zope.interface.interfaces.IInterfaceDeclaration.interfacemethod` + .. seealso:: + `zope.interface.interfaces.IInterfaceDeclaration.interfacemethod` """ f_locals = sys._getframe(1).f_locals methods = f_locals.setdefault(INTERFACE_METHODS, {}) @@ -692,10 +700,16 @@ class InterfaceClass(_InterfaceClassBase): # We can't say this yet because we don't have enough # infrastructure in place. # - #implements(IInterface) - - def __new__(cls, name=None, bases=(), attrs=None, __doc__=None, # pylint:disable=redefined-builtin - __module__=None): + # implements(IInterface) + + def __new__( + cls, + name=None, + bases=(), + attrs=None, + __doc__=None, # pylint:disable=redefined-builtin + __module__=None, + ): assert isinstance(bases, tuple) attrs = attrs or {} needs_custom_class = attrs.pop(INTERFACE_METHODS, None) @@ -716,7 +730,7 @@ class InterfaceClass(_InterfaceClassBase): else: cls_bases = (cls, _InterfaceClassWithCustomMethods) - cls = type(cls)( # pylint:disable=self-cls-assignment + cls = type(cls)( # pylint:disable=self-cls-assignment name + "<WithCustomMethods>", cls_bases, needs_custom_class @@ -724,8 +738,14 @@ class InterfaceClass(_InterfaceClassBase): return _InterfaceClassBase.__new__(cls) - def __init__(self, name, bases=(), attrs=None, __doc__=None, # pylint:disable=redefined-builtin - __module__=None): + def __init__( + self, + name, + bases=(), + attrs=None, + __doc__=None, # pylint:disable=redefined-builtin + __module__=None, + ): # We don't call our metaclass parent directly # pylint:disable=non-parent-init-called # pylint:disable=super-init-not-called @@ -745,7 +765,7 @@ class InterfaceClass(_InterfaceClassBase): # This is how cPython figures out the module of # a class, but of course it does it in C. :-/ __module__ = sys._getframe(1).f_globals['__name__'] - except (AttributeError, KeyError): # pragma: no cover + except (AttributeError, KeyError): # pragma: no cover pass InterfaceBase.__init__(self, name, __module__) @@ -773,7 +793,7 @@ class InterfaceClass(_InterfaceClassBase): Specification.__init__(self, bases) self.__attrs = self.__compute_attrs(attrs) - self.__identifier__ = "{}.{}".format(__module__, name) + self.__identifier__ = f"{__module__}.{name}" def __compute_attrs(self, attrs): # Make sure that all recorded attributes (and methods) are of type @@ -806,7 +826,7 @@ class InterfaceClass(_InterfaceClassBase): # https://github.com/python/cpython/pull/118475 '__firstlineno__', ) - and aval is not _decorator_non_return + and aval is not _decorator_non_return # noqa W503 } def interfaces(self): @@ -821,7 +841,7 @@ class InterfaceClass(_InterfaceClassBase): """Same interface or extends?""" return self == other or other.extends(self) - def names(self, all=False): # pylint:disable=redefined-builtin + def names(self, all=False): # pylint:disable=redefined-builtin """Return the attribute names defined by the interface.""" if not all: return self.__attrs.keys() @@ -836,7 +856,9 @@ class InterfaceClass(_InterfaceClassBase): def __iter__(self): return iter(self.names(all=True)) - def namesAndDescriptions(self, all=False): # pylint:disable=redefined-builtin + def namesAndDescriptions( + self, all=False # pylint:disable=redefined-builtin + ): """Return attribute names and descriptions defined by interface.""" if not all: return self.__attrs.items() @@ -886,8 +908,8 @@ class InterfaceClass(_InterfaceClassBase): def queryTaggedValue(self, tag, default=None): """ - Queries for the value associated with *tag*, returning it from the nearest - interface in the ``__iro__``. + Queries for the value associated with *tag*, returning it from the + nearest interface in the ``__iro__``. If not found, returns *default*. """ @@ -916,21 +938,21 @@ class InterfaceClass(_InterfaceClassBase): return self._v_repr except AttributeError: name = str(self) - r = "<{} {}>".format(self.__class__.__name__, name) - self._v_repr = r # pylint:disable=attribute-defined-outside-init + r = f"<{self.__class__.__name__} {name}>" + self._v_repr = r # pylint:disable=attribute-defined-outside-init return r def __str__(self): name = self.__name__ m = self.__ibmodule__ if m: - name = '{}.{}'.format(m, name) + name = f'{m}.{name}' return name def _call_conform(self, conform): try: return conform(self) - except TypeError: # pragma: no cover + except TypeError: # pragma: no cover # We got a TypeError. It might be an error raised by # the __conform__ implementation, or *we* may have # made the TypeError by calling an unbound method @@ -944,7 +966,7 @@ class InterfaceClass(_InterfaceClassBase): raise # This clever trick is from Phillip Eby - return None # pragma: no cover + return None # pragma: no cover def __reduce__(self): return self.__name__ @@ -957,6 +979,7 @@ class InterfaceClass(_InterfaceClassBase): """Allow type hinting syntax: None | Interface.""" return Union[other, self] + Interface = InterfaceClass("Interface", __module__='zope.interface') # Interface is the only member of its own SRO. Interface._calculate_sro = lambda: (Interface,) @@ -965,9 +988,11 @@ assert Interface.__sro__ == (Interface,) Specification._ROOT = Interface ro._ROOT = Interface + class _InterfaceClassWithCustomMethods(InterfaceClass): """ - Marker class for interfaces with custom methods that override InterfaceClass methods. + Marker class for interfaces with custom methods that override + InterfaceClass methods. """ @@ -989,7 +1014,12 @@ class Attribute(Element): def __str__(self): of = '' if self.interface is not None: - of = self.interface.__module__ + '.' + self.interface.__name__ + '.' + of = ( + self.interface.__module__ + + '.' + + self.interface.__name__ + + '.' + ) # self.__name__ may be None during construction (e.g., debugging) return of + (self.__name__ or '<unknown>') + self._get_str_info() @@ -1016,14 +1046,18 @@ class Method(Attribute): positional = required = () _optional = varargs = kwargs = None + def _get_optional(self): if self._optional is None: return {} return self._optional + def _set_optional(self, opt): self._optional = opt + def _del_optional(self): self._optional = None + optional = property(_get_optional, _set_optional, _del_optional) def __call__(self, *args, **kw): @@ -1144,5 +1178,6 @@ from zope.interface.exceptions import InvalidInterface # This ensures that ``Interface`` winds up in the flattened() # list of the immutable declaration. It correctly overrides changed() # as a no-op, so we bypass that. -from zope.interface.declarations import _empty +# pylint:disable=wrong-import-position +from zope.interface.declarations import _empty # isort: skip Specification.changed(_empty, _empty) diff --git a/contrib/python/zope.interface/py3/zope/interface/interfaces.py b/contrib/python/zope.interface/py3/zope/interface/interfaces.py index 0d315cb6a5..454fee893c 100644 --- a/contrib/python/zope.interface/py3/zope/interface/interfaces.py +++ b/contrib/python/zope.interface/py3/zope/interface/interfaces.py @@ -52,6 +52,7 @@ __all__ = [ # pylint:disable=unexpected-special-method-signature # pylint:disable=too-many-lines + class IElement(Interface): """ Objects that have basic documentation and tagged values. @@ -82,7 +83,8 @@ class IElement(Interface): # make ``IInterface`` define new methods # ``getIndirectTaggedValue``, etc, to include inheritance instead # of overriding ``getTaggedValue`` to do that, but that ship has sailed. - # So to keep things nice and symmetric, we define the ``Direct`` methods here. + # So to keep things nice and symmetric, we define the ``Direct`` methods + # here. ### def getTaggedValue(tag): @@ -100,7 +102,8 @@ class IElement(Interface): def queryTaggedValue(tag, default=None): """ - As for `getTaggedValue`, but instead of raising a `KeyError`, returns *default*. + As for `getTaggedValue`, but instead of raising a `KeyError`, returns + *default*. .. versionchanged:: 4.7.0 @@ -179,14 +182,15 @@ class IMethod(IAttribute): """Return a signature string suitable for inclusion in documentation. This method returns the function signature string. For example, if you - have ``def func(a, b, c=1, d='f')``, then the signature string is ``"(a, b, - c=1, d='f')"``. + have ``def func(a, b, c=1, d='f')``, then the signature string is + ``"(a, b, c=1, d='f')"``. """ + class ISpecification(Interface): """Object Behavioral specifications""" # pylint:disable=arguments-differ - def providedBy(object): # pylint:disable=redefined-builtin + def providedBy(object): # pylint:disable=redefined-builtin """Test whether the interface is implemented by the object Return true of the object asserts that it implements the @@ -346,7 +350,7 @@ class IInterface(ISpecification, IElement): """ # pylint:disable=arguments-differ - def names(all=False): # pylint:disable=redefined-builtin + def names(all=False): # pylint:disable=redefined-builtin """Get the interface attribute names Return a collection of the names of the attributes, including @@ -357,7 +361,7 @@ class IInterface(ISpecification, IElement): attributes defined by base classes will be included. """ - def namesAndDescriptions(all=False): # pylint:disable=redefined-builtin + def namesAndDescriptions(all=False): # pylint:disable=redefined-builtin """Get the interface attribute names and descriptions Return a collection of the names and descriptions of the @@ -461,6 +465,7 @@ class IDeclaration(ISpecification): """Return a true value of the interface specification is non-empty """ + class IInterfaceDeclaration(Interface): """ Declare and check the interfaces of objects. @@ -534,10 +539,10 @@ class IInterfaceDeclaration(Interface): A decorator that transforms a method specification into an implementation method. - This is used to override methods of ``Interface`` or provide new methods. - Definitions using this decorator will not appear in :meth:`IInterface.names()`. - It is possible to have an implementation method and a method specification - of the same name. + This is used to override methods of ``Interface`` or provide new + methods. Definitions using this decorator will not appear in + :meth:`IInterface.names()`. It is possible to have an implementation + method and a method specification of the same name. For example:: @@ -549,10 +554,10 @@ class IInterfaceDeclaration(Interface): return obj return super(type(IRange), self).__adapt__(obj) - You can use ``super`` to call the parent class functionality. Note that - the zero-argument version (``super().__adapt__``) works on Python 3.6 and above, but - prior to that the two-argument version must be used, and the class must be explicitly - passed as the first argument. + You can use ``super`` to call the parent class functionality. Note + that the zero-argument version (``super().__adapt__``) works on Python + 3.6 and above, but prior to that the two-argument version must be + used, and the class must be explicitly passed as the first argument. .. versionadded:: 5.1.0 .. seealso:: `zope.interface.interfacemethod` @@ -667,7 +672,7 @@ class IInterfaceDeclaration(Interface): .. seealso:: `zope.interface.implementer_only` """ - def directlyProvidedBy(object): # pylint:disable=redefined-builtin + def directlyProvidedBy(object): # pylint:disable=redefined-builtin """ Return the interfaces directly provided by the given object. @@ -676,7 +681,9 @@ class IInterfaceDeclaration(Interface): .. seealso:: `zope.interface.directlyProvidedBy` """ - def directlyProvides(object, *interfaces): # pylint:disable=redefined-builtin + def directlyProvides( + object, *interfaces, + ): # pylint:disable=redefined-builtin """ Declare interfaces declared directly for an object. @@ -720,7 +727,7 @@ class IInterfaceDeclaration(Interface): .. seealso:: `zope.interface.directlyProvides` """ - def alsoProvides(object, *interfaces): # pylint:disable=redefined-builtin + def alsoProvides(object, *interfaces): # pylint:disable=redefined-builtin """ Declare additional interfaces directly for an object. @@ -735,7 +742,9 @@ class IInterfaceDeclaration(Interface): .. seealso:: `zope.interface.alsoProvides` """ - def noLongerProvides(object, interface): # pylint:disable=redefined-builtin + def noLongerProvides( + object, interface, + ): # pylint:disable=redefined-builtin """ Remove an interface from the list of an object's directly provided interfaces. @@ -803,6 +812,7 @@ class IInterfaceDeclaration(Interface): .. seealso:: `zope.interface.Declaration` """ + class IAdapterRegistry(Interface): """Provide an interface-based registry for adapters @@ -856,11 +866,15 @@ class IAdapterRegistry(Interface): text. """ - def queryAdapter(object, provided, name='', default=None): # pylint:disable=redefined-builtin + def queryAdapter( + object, provided, name='', default=None, + ): # pylint:disable=redefined-builtin """Adapt an object using a registered adapter factory. """ - def adapter_hook(provided, object, name='', default=None): # pylint:disable=redefined-builtin + def adapter_hook( + provided, object, name='', default=None, + ): # pylint:disable=redefined-builtin """Adapt an object using a registered adapter factory. name must be text. @@ -872,11 +886,13 @@ class IAdapterRegistry(Interface): An iterable object is returned that provides name-value two-tuples. """ - def names(required, provided): # pylint:disable=arguments-differ + def names(required, provided): # pylint:disable=arguments-differ """Return the names for which there are registered objects """ - def subscribe(required, provided, subscriber): # pylint:disable=arguments-differ + def subscribe( + required, provided, subscriber, + ): # pylint:disable=arguments-differ """Register a subscriber A subscriber is registered for a *sequence* of required @@ -954,12 +970,15 @@ class IAdapterRegistry(Interface): # begin formerly in zope.component + class ComponentLookupError(LookupError): """A component could not be found.""" + class Invalid(Exception): """A component doesn't satisfy a promise.""" + class IObjectEvent(Interface): """An event related to an object. @@ -973,7 +992,7 @@ class IObjectEvent(Interface): @implementer(IObjectEvent) class ObjectEvent: - def __init__(self, object): # pylint:disable=redefined-builtin + def __init__(self, object): # pylint:disable=redefined-builtin self.object = object @@ -990,13 +1009,17 @@ class IComponentLookup(Interface): utilities = Attribute( "Adapter Registry to manage all registered utilities.") - def queryAdapter(object, interface, name='', default=None): # pylint:disable=redefined-builtin + def queryAdapter( + object, interface, name='', default=None + ): # pylint:disable=redefined-builtin """Look for a named adapter to an interface for an object If a matching adapter cannot be found, returns the default. """ - def getAdapter(object, interface, name=''): # pylint:disable=redefined-builtin + def getAdapter( + object, interface, name='' + ): # pylint:disable=redefined-builtin """Look for a named adapter to an interface for an object If a matching adapter cannot be found, a `ComponentLookupError` @@ -1058,6 +1081,7 @@ class IComponentLookup(Interface): returned. """ + class IRegistration(Interface): """A registration-information object """ @@ -1073,6 +1097,7 @@ class IRegistration(Interface): commentary or information about the source of the configuration. """) + class IUtilityRegistration(IRegistration): """Information about the registration of a utility """ @@ -1081,6 +1106,7 @@ class IUtilityRegistration(IRegistration): component = Attribute("The object registered") provided = Attribute("The interface provided by the component") + class _IBaseAdapterRegistration(IRegistration): """Information about the registration of an adapter """ @@ -1099,14 +1125,17 @@ class _IBaseAdapterRegistration(IRegistration): This interface is implemented by the factory """) + class IAdapterRegistration(_IBaseAdapterRegistration): """Information about the registration of an adapter """ + class ISubscriptionAdapterRegistration(_IBaseAdapterRegistration): """Information about the registration of a subscription adapter """ + class IHandlerRegistration(IRegistration): handler = Attribute("An object called used to handle an event") @@ -1118,6 +1147,7 @@ class IHandlerRegistration(IRegistration): positional arguments, that provide these interfaces. """) + class IRegistrationEvent(IObjectEvent): """An event that involves a registration""" @@ -1127,20 +1157,24 @@ class RegistrationEvent(ObjectEvent): """There has been a change in a registration """ def __repr__(self): - return "{} event:\n{!r}".format(self.__class__.__name__, self.object) + return f"{self.__class__.__name__} event:\n{self.object!r}" + class IRegistered(IRegistrationEvent): """A component or factory was registered """ + @implementer(IRegistered) class Registered(RegistrationEvent): pass + class IUnregistered(IRegistrationEvent): """A component or factory was unregistered """ + @implementer(IUnregistered) class Unregistered(RegistrationEvent): """A component or factory was unregistered diff --git a/contrib/python/zope.interface/py3/zope/interface/registry.py b/contrib/python/zope.interface/py3/zope/interface/registry.py index a6a24fdd80..37c4ec991b 100644 --- a/contrib/python/zope.interface/py3/zope/interface/registry.py +++ b/contrib/python/zope.interface/py3/zope/interface/registry.py @@ -18,8 +18,9 @@ from collections import defaultdict try: from zope.event import notify -except ImportError: # pragma: no cover - def notify(*arg, **kw): pass +except ImportError: # pragma: no cover + def notify(*arg, **kw): + pass from zope.interface.adapter import AdapterRegistry from zope.interface.declarations import implementedBy @@ -45,6 +46,7 @@ __all__ = [ 'Components', ] + class _UnhashableComponentCounter: # defaultdict(int)-like object for unhashable components @@ -70,11 +72,13 @@ class _UnhashableComponentCounter: if data[0] == component: del self._data[i] return - raise KeyError(component) # pragma: no cover + raise KeyError(component) # pragma: no cover + def _defaultdict_int(): return defaultdict(int) + class _UtilityRegistrations: def __init__(self, utilities, utility_registrations): @@ -94,18 +98,20 @@ class _UtilityRegistrations: try: self._cache[provided][component] += 1 except TypeError: - # The component is not hashable, and we have a dict. Switch to a strategy - # that doesn't use hashing. - prov = self._cache[provided] = _UnhashableComponentCounter(self._cache[provided]) + # The component is not hashable, and we have a dict. Switch to a + # strategy that doesn't use hashing. + prov = self._cache[provided] = _UnhashableComponentCounter( + self._cache[provided] + ) prov[component] += 1 def __uncache_utility(self, provided, component): provided = self._cache[provided] # It seems like this line could raise a TypeError if component isn't - # hashable and we haven't yet switched to _UnhashableComponentCounter. However, - # we can't actually get in that situation. In order to get here, we would - # have had to cache the utility already which would have switched - # the datastructure if needed. + # hashable and we haven't yet switched to _UnhashableComponentCounter. + # However, we can't actually get in that situation. In order to get + # here, we would have had to cache the utility already which would + # have switched the datastructure if needed. count = provided[component] count -= 1 if count == 0: @@ -124,7 +130,9 @@ class _UtilityRegistrations: def registerUtility(self, provided, name, component, info, factory): subscribed = self._is_utility_subscribed(provided, component) - self._utility_registrations[(provided, name)] = component, info, factory + self._utility_registrations[ + (provided, name) + ] = component, info, factory self._utilities.register((), provided, name, component) if not subscribed: @@ -158,7 +166,7 @@ class Components: self._v_utility_registrations_cache = None def __repr__(self): - return "<{} {}>".format(self.__class__.__name__, self.__name__) + return f"<{self.__class__.__name__} {self.__name__}>" def __reduce__(self): # Mimic what a persistent.Persistent object does and elide @@ -192,12 +200,16 @@ class Components: # We use a _v_ attribute internally so that data aren't saved in ZODB, # because this object cannot be pickled. cache = self._v_utility_registrations_cache - if (cache is None - or cache._utilities is not self.utilities - or cache._utility_registrations is not self._utility_registrations): - cache = self._v_utility_registrations_cache = _UtilityRegistrations( - self.utilities, - self._utility_registrations) + if ( + cache is None or + cache._utilities is not self.utilities or + cache._utility_registrations is not self._utility_registrations + ): + cache = self._v_utility_registrations_cache = ( + _UtilityRegistrations( + self.utilities, self._utility_registrations, + ) + ) return cache def _getBases(self): @@ -215,7 +227,7 @@ class Components: __bases__ = property( lambda self: self._getBases(), lambda self, bases: self._setBases(bases), - ) + ) def registerUtility(self, component=None, provided=None, name='', info='', event=True, factory=None): @@ -242,9 +254,9 @@ class Components: if event: notify(Registered( - UtilityRegistration(self, provided, name, component, info, - factory) - )) + UtilityRegistration( + self, provided, name, component, info, factory) + )) def unregisterUtility(self, component=None, provided=None, name='', factory=None): @@ -273,7 +285,7 @@ class Components: notify(Unregistered( UtilityRegistration(self, provided, name, component, *old[1:]) - )) + )) return True @@ -310,10 +322,10 @@ class Components: if event: notify(Registered( - AdapterRegistration(self, required, provided, name, - factory, info) - )) - + AdapterRegistration( + self, required, provided, name, factory, info + ) + )) def unregisterAdapter(self, factory=None, required=None, provided=None, name='', @@ -336,9 +348,8 @@ class Components: self.adapters.unregister(required, provided, name) notify(Unregistered( - AdapterRegistration(self, required, provided, name, - *old) - )) + AdapterRegistration(self, required, provided, name, *old) + )) return True @@ -370,8 +381,8 @@ class Components: def getAdapters(self, objects, provided): for name, factory in self.adapters.lookupAll( - list(map(providedBy, objects)), - provided): + list(map(providedBy, objects)), provided, + ): adapter = factory(*objects) if adapter is not None: yield name, adapter @@ -387,22 +398,23 @@ class Components: required = _getAdapterRequired(factory, required) self._subscription_registrations.append( (required, provided, name, factory, info) - ) + ) self.adapters.subscribe(required, provided, factory) if event: notify(Registered( - SubscriptionRegistration(self, required, provided, name, - factory, info) - )) + SubscriptionRegistration( + self, required, provided, name, factory, info, + ) + )) def registeredSubscriptionAdapters(self): for data in self._subscription_registrations: yield SubscriptionRegistration(self, *data) - def unregisterSubscriptionAdapter(self, factory=None, - required=None, provided=None, name='', - ): + def unregisterSubscriptionAdapter( + self, factory=None, required=None, provided=None, name='', + ): if name: raise TypeError("Named subscribers are not yet supported") if provided is None: @@ -431,14 +443,14 @@ class Components: if len(new) == len(self._subscription_registrations): return False - self._subscription_registrations[:] = new self.adapters.unsubscribe(required, provided, factory) notify(Unregistered( - SubscriptionRegistration(self, required, provided, name, - factory, '') - )) + SubscriptionRegistration( + self, required, provided, name, factory, '', + ) + )) return True @@ -454,13 +466,13 @@ class Components: required = _getAdapterRequired(factory, required) self._handler_registrations.append( (required, name, factory, info) - ) + ) self.adapters.subscribe(required, None, factory) if event: notify(Registered( HandlerRegistration(self, required, name, factory, info) - )) + )) def registeredHandlers(self): for data in self._handler_registrations: @@ -496,7 +508,7 @@ class Components: notify(Unregistered( HandlerRegistration(self, required, name, factory, '') - )) + )) return True @@ -520,9 +532,10 @@ class Components: in the registry as needed to synchronize with the local cache. :return: A dictionary that's meant as diagnostic data. The keys - and values may change over time. When called with a false *rebuild*, - the keys ``"needed_registered"`` and ``"needed_subscribed"`` will be - non-zero if any corruption was detected, but that will not be corrected. + and values may change over time. When called with a false + *rebuild*, the keys ``"needed_registered"`` and + ``"needed_subscribed"`` will be non-zero if any corruption was + detected, but that will not be corrected. .. versionadded:: 5.3.0 """ @@ -533,7 +546,6 @@ class Components: needed_subscribed = 0 did_not_subscribe = 0 - # Avoid the expensive change process during this; we'll call # it once at the end if needed. assert 'changed' not in utils.__dict__ @@ -570,19 +582,23 @@ class Components: 'did_not_subscribe': did_not_subscribe } + def _getName(component): try: return component.__component_name__ except AttributeError: return '' + def _getUtilityProvided(component): provided = list(providedBy(component)) if len(provided) == 1: return provided[0] raise TypeError( "The utility doesn't provide a single interface " - "and no provided interface was specified.") + "and no provided interface was specified." + ) + def _getAdapterProvided(factory): provided = list(implementedBy(factory)) @@ -590,7 +606,9 @@ def _getAdapterProvided(factory): return provided[0] raise TypeError( "The adapter factory doesn't implement a single interface " - "and no provided interface was specified.") + "and no provided interface was specified." + ) + def _getAdapterRequired(factory, required): if required is None: @@ -600,10 +618,12 @@ def _getAdapterRequired(factory, required): raise TypeError( "The adapter factory doesn't have a __component_adapts__ " "attribute and no required specifications were specified" - ) + ) elif ISpecification.providedBy(required): - raise TypeError("the required argument should be a list of " - "interfaces, not a single interface") + raise TypeError( + "the required argument should be a list of " + "interfaces, not a single interface" + ) result = [] for r in required: @@ -613,9 +633,10 @@ def _getAdapterRequired(factory, required): if isinstance(r, type): r = implementedBy(r) else: - raise TypeError("Required specification must be a " - "specification or class, not %r" % type(r) - ) + raise TypeError( + "Required specification must be a " + "specification or class, not %r" % type(r) + ) result.append(r) return tuple(result) @@ -624,18 +645,21 @@ def _getAdapterRequired(factory, required): class UtilityRegistration: def __init__(self, registry, provided, name, component, doc, factory=None): - (self.registry, self.provided, self.name, self.component, self.info, - self.factory - ) = registry, provided, name, component, doc, factory + self.registry = registry + self.provided = provided + self.name = name + self.component = component + self.info = doc + self.factory = factory def __repr__(self): return '{}({!r}, {}, {!r}, {}, {!r}, {!r})'.format( - self.__class__.__name__, - self.registry, - getattr(self.provided, '__name__', None), self.name, - getattr(self.component, '__name__', repr(self.component)), - self.factory, self.info, - ) + self.__class__.__name__, + self.registry, + getattr(self.provided, '__name__', None), self.name, + getattr(self.component, '__name__', repr(self.component)), + self.factory, self.info, + ) def __hash__(self): return id(self) @@ -658,6 +682,7 @@ class UtilityRegistration: def __ge__(self, other): return repr(self) >= repr(other) + @implementer(IAdapterRegistration) class AdapterRegistration: @@ -673,7 +698,7 @@ class AdapterRegistration: '[' + ", ".join([r.__name__ for r in self.required]) + ']', getattr(self.provided, '__name__', None), self.name, getattr(self.factory, '__name__', repr(self.factory)), self.info, - ) + ) def __hash__(self): return id(self) @@ -696,6 +721,7 @@ class AdapterRegistration: def __ge__(self, other): return repr(self) >= repr(other) + @implementer_only(ISubscriptionAdapterRegistration) class SubscriptionRegistration(AdapterRegistration): pass @@ -721,4 +747,4 @@ class HandlerRegistration(AdapterRegistration): '[' + ", ".join([r.__name__ for r in self.required]) + ']', self.name, getattr(self.factory, '__name__', repr(self.factory)), self.info, - ) + ) diff --git a/contrib/python/zope.interface/py3/zope/interface/ro.py b/contrib/python/zope.interface/py3/zope/interface/ro.py index 52986483c2..5233e49b16 100644 --- a/contrib/python/zope.interface/py3/zope/interface/ro.py +++ b/contrib/python/zope.interface/py3/zope/interface/ro.py @@ -28,37 +28,45 @@ Compute a resolution order for an object and its bases. .. rubric:: Environment Variables -Due to the change in 5.0, certain environment variables can be used to control errors -and warnings about inconsistent resolution orders. They are listed in priority order, with -variables at the bottom generally overriding variables above them. +Due to the change in 5.0, certain environment variables can be used to control +errors and warnings about inconsistent resolution orders. They are listed in +priority order, with variables at the bottom generally overriding variables +above them. ZOPE_INTERFACE_WARN_BAD_IRO - If this is set to "1", then if there is at least one inconsistent resolution - order discovered, a warning (:class:`InconsistentResolutionOrderWarning`) will - be issued. Use the usual warning mechanisms to control this behaviour. The warning - text will contain additional information on debugging. + If this is set to "1", then if there is at least one inconsistent + resolution order discovered, a warning + (:class:`InconsistentResolutionOrderWarning`) will be issued. Use the + usual warning mechanisms to control this behaviour. The warning text will + contain additional information on debugging. + ZOPE_INTERFACE_TRACK_BAD_IRO If this is set to "1", then zope.interface will log information about each - inconsistent resolution order discovered, and keep those details in memory in this module - for later inspection. + inconsistent resolution order discovered, and keep those details in memory + in this module for later inspection. + ZOPE_INTERFACE_STRICT_IRO - If this is set to "1", any attempt to use :func:`ro` that would produce a non-C3 - ordering will fail by raising :class:`InconsistentResolutionOrderError`. + If this is set to "1", any attempt to use :func:`ro` that would produce a + non-C3 ordering will fail by raising + :class:`InconsistentResolutionOrderError`. .. important:: - ``ZOPE_INTERFACE_STRICT_IRO`` is intended to become the default in the future. + ``ZOPE_INTERFACE_STRICT_IRO`` is intended to become the default in the + future. There are two environment variables that are independent. ZOPE_INTERFACE_LOG_CHANGED_IRO If this is set to "1", then if the C3 resolution order is different from - the legacy resolution order for any given object, a message explaining the differences - will be logged. This is intended to be used for debugging complicated IROs. + the legacy resolution order for any given object, a message explaining the + differences will be logged. This is intended to be used for debugging + complicated IROs. + ZOPE_INTERFACE_USE_LEGACY_IRO - If this is set to "1", then the C3 resolution order will *not* be used. The - legacy IRO will be used instead. This is a temporary measure and will be removed in the - future. It is intended to help during the transition. + If this is set to "1", then the C3 resolution order will *not* be used. + The legacy IRO will be used instead. This is a temporary measure and will + be removed in the future. It is intended to help during the transition. It implies ``ZOPE_INTERFACE_LOG_CHANGED_IRO``. .. rubric:: Debugging Behaviour Changes in zope.interface 5 @@ -82,6 +90,9 @@ positions of interfaces for which there are registered adapters. """ __docformat__ = 'restructuredtext' +import warnings + + __all__ = [ 'ro', 'InconsistentResolutionOrderError', @@ -90,13 +101,15 @@ __all__ = [ __logger = None + def _logger(): - global __logger # pylint:disable=global-statement + global __logger # pylint:disable=global-statement if __logger is None: import logging __logger = logging.getLogger(__name__) return __logger + def _legacy_mergeOrderings(orderings): """Merge multiple orderings so that within-ordering order is preserved @@ -106,7 +119,7 @@ def _legacy_mergeOrderings(orderings): For example: - >>> _mergeOrderings([ + >>> _legacy_mergeOrderings([ ... ['x', 'y', 'z'], ... ['q', 'z'], ... [1, 3, 5], @@ -126,6 +139,7 @@ def _legacy_mergeOrderings(orderings): return result + def _legacy_flatten(begin): result = [begin] i = 0 @@ -139,6 +153,7 @@ def _legacy_flatten(begin): result[i:i] = ob.__bases__ return result + def _legacy_ro(ob): return _legacy_mergeOrderings([_legacy_flatten(ob)]) @@ -156,6 +171,7 @@ class InconsistentResolutionOrderWarning(PendingDeprecationWarning): The warning issued when an invalid IRO is requested. """ + class InconsistentResolutionOrderError(TypeError): """ The error raised when an invalid IRO is requested in strict mode. @@ -177,7 +193,9 @@ class InconsistentResolutionOrderError(TypeError): def __str__(self): import pprint - return "{}: For object {!r}.\nBase ROs:\n{}\nConflict Location:\n{}".format( + return ( + "{}: For object {!r}.\nBase ROs:\n{}\nConflict Location:\n{}" + ).format( self.__class__.__name__, self.C, pprint.pformat(self.base_ros), @@ -185,7 +203,7 @@ class InconsistentResolutionOrderError(TypeError): ) -class _NamedBool(int): # cannot actually inherit bool +class _NamedBool(int): # cannot actually inherit bool def __new__(cls, val, name): inst = super(cls, _NamedBool).__new__(cls, val) @@ -209,7 +227,7 @@ class _ClassBoolFromEnv: break if my_name is not None: break - else: # pragma: no cover + else: # pragma: no cover raise RuntimeError("Unable to find self") env_name = 'ZOPE_INTERFACE_' + my_name @@ -224,7 +242,7 @@ class _StaticMRO: # A previously resolved MRO, supplied by the caller. # Used in place of calculating it. - had_inconsistency = None # We don't know... + had_inconsistency = None # We don't know... def __init__(self, C, mro): self.leaf = C @@ -234,6 +252,16 @@ class _StaticMRO: return list(self.__mro) +_INCONSISTENT_RESOLUTION_ORDER = """\ +An inconsistent resolution order is being requested. (Interfaces should +follow the Python class rules known as C3.) For backwards compatibility, +zope.interface will allow this, making the best guess it can to produce as +meaningful an order as possible. In the future this might be an error. Set +the warning filter to error, or set the environment variable +'ZOPE_INTERFACE_TRACK_BAD_IRO' to '1' and examine ro.C3.BAD_IROS to debug, or +set 'ZOPE_INTERFACE_STRICT_IRO' to raise exceptions.""" + + class C3: # Holds the shared state during computation of an MRO. @@ -278,7 +306,9 @@ class C3: list(C.__bases__) ] - self.bases_had_inconsistency = any(base.had_inconsistency for base in base_resolvers) + self.bases_had_inconsistency = any( + base.had_inconsistency for base in base_resolvers + ) if len(C.__bases__) == 1: self.__mro = [C] + memo[C.__bases__[0]].mro() @@ -306,15 +336,8 @@ class C3: # In the future (2021?) seeing at least the first warning will # be the default return - import warnings warnings.warn( - "An inconsistent resolution order is being requested. " - "(Interfaces should follow the Python class rules known as C3.) " - "For backwards compatibility, zope.interface will allow this, " - "making the best guess it can to produce as meaningful an order as possible. " - "In the future this might be an error. Set the warning filter to error, or set " - "the environment variable 'ZOPE_INTERFACE_TRACK_BAD_IRO' to '1' and examine " - "ro.C3.BAD_IROS to debug, or set 'ZOPE_INTERFACE_STRICT_IRO' to raise exceptions.", + _INCONSISTENT_RESOLUTION_ORDER, InconsistentResolutionOrderWarning, ) @@ -344,7 +367,8 @@ class C3: Return the next base. The return value will either fit the C3 constraints or be our best - guess about what to do. If we cannot guess, this may raise an exception. + guess about what to do. If we cannot guess, this may raise an + exception. """ base = self._find_next_C3_base(base_tree_remaining) if base is not None: @@ -352,8 +376,9 @@ class C3: return self._guess_next_base(base_tree_remaining) def _find_next_C3_base(self, base_tree_remaining): - """ - Return the next base that fits the constraints, or ``None`` if there isn't one. + """Return the next base that fits the constraints + + Return ``None`` if there isn't one. """ for bases in base_tree_remaining: base = bases[0] @@ -379,11 +404,12 @@ class C3: # However, older versions of zope.interface were fine with this order. # A good example is ``providedBy(IOError())``. Because of the way # ``classImplements`` works, it winds up with ``__bases__`` == - # ``[IEnvironmentError, IIOError, IOSError, <implementedBy Exception>]`` - # (on Python 3). But ``IEnvironmentError`` is a base of both ``IIOError`` - # and ``IOSError``. Previously, we would get a resolution order of - # ``[IIOError, IOSError, IEnvironmentError, IStandardError, IException, Interface]`` - # but the standard Python algorithm would forbid creating that order entirely. + # ``[IEnvironmentError, IIOError, IOSError, <implementedBy + # Exception>]`` (on Python 3). But ``IEnvironmentError`` is a base of + # both ``IIOError`` and ``IOSError``. Previously, we would get a + # resolution order of ``[IIOError, IOSError, IEnvironmentError, + # IStandardError, IException, Interface]`` but the standard Python + # algorithm would forbid creating that order entirely. # Unlike Python's MRO, we attempt to resolve the issue. A few # heuristics have been tried. One was: @@ -409,7 +435,9 @@ class C3: # # So now, we fall back to the old linearization (fast to compute). self._warn_iro() - self.direct_inconsistency = InconsistentResolutionOrderError(self, base_tree_remaining) + self.direct_inconsistency = InconsistentResolutionOrderError( + self, base_tree_remaining, + ) raise self._UseLegacyRO def _merge(self): @@ -422,7 +450,9 @@ class C3: # This differs slightly from the standard Python MRO and is needed # because we have no other step that prevents duplicates # from coming in (e.g., in the inconsistent fallback path) - base_tree_remaining = self._nonempty_bases_ignoring(base_tree_remaining, base) + base_tree_remaining = self._nonempty_bases_ignoring( + base_tree_remaining, base + ) if not base_tree_remaining: return result @@ -442,12 +472,14 @@ class C3: class _StrictC3(C3): __slots__ = () + def _guess_next_base(self, base_tree_remaining): raise InconsistentResolutionOrderError(self, base_tree_remaining) class _TrackingC3(C3): __slots__ = () + def _guess_next_base(self, base_tree_remaining): import traceback bad_iros = C3.BAD_IROS @@ -474,8 +506,10 @@ class _ROComparison: # Components we use to build up the comparison report class Item: prefix = ' ' + def __init__(self, item): self.item = item + def __str__(self): return "{}{}".format( self.prefix, @@ -490,9 +524,10 @@ class _ROComparison: Empty = str - class ReplacedBy: # pragma: no cover + class ReplacedBy: # pragma: no cover prefix = '- ' suffix = '' + def __init__(self, chunk, total_count): self.chunk = chunk self.total_count = total_count @@ -511,7 +546,6 @@ class _ROComparison: prefix = "+ " suffix = '' - _c3_report = None _legacy_report = None @@ -547,16 +581,23 @@ class _ROComparison: if opcode == 'delete': # Guaranteed same length assert not c3_chunk - self.__move(c3_report, legacy_report, legacy_chunk, self.Deleted) + self.__move( + c3_report, legacy_report, legacy_chunk, self.Deleted, + ) if opcode == 'insert': # Guaranteed same length assert not legacy_chunk - self.__move(legacy_report, c3_report, c3_chunk, self.Inserted) - if opcode == 'replace': # pragma: no cover (How do you make it output this?) + self.__move( + legacy_report, c3_report, c3_chunk, self.Inserted, + ) + if opcode == 'replace': # pragma: no cover + # (How do you make it output this?) # Either side could be longer. chunk_size = max(len(c3_chunk), len(legacy_chunk)) c3_report.extend(self.Replacing(c3_chunk, chunk_size)) - legacy_report.extend(self.ReplacedBy(legacy_chunk, chunk_size)) + legacy_report.extend( + self.ReplacedBy(legacy_chunk, chunk_size), + ) return self._c3_report, self._legacy_report @@ -584,14 +625,19 @@ class _ROComparison: max_left = max(len(x) for x in left_lines) max_right = max(len(x) for x in right_lines) - left_title = 'Legacy RO (len={})'.format(len(self.legacy_ro)) + left_title = f'Legacy RO (len={len(self.legacy_ro)})' right_title = 'C3 RO (len={}; inconsistent={})'.format( len(self.c3_ro), self._inconsistent_label, ) lines = [ - (padding + left_title.ljust(max_left) + padding + right_title.ljust(max_right)), + ( + padding + + left_title.ljust(max_left) + + padding + + right_title.ljust(max_right) + ), padding + '=' * (max_left + len(padding) + max_right) ] lines += [ @@ -606,7 +652,10 @@ class _ROComparison: # avoid logging false positives about changed ROs. _ROOT = None -def ro(C, strict=None, base_mros=None, log_changed_ro=None, use_legacy_ro=None): + +def ro( + C, strict=None, base_mros=None, log_changed_ro=None, use_legacy_ro=None, +): """ ro(C) -> list @@ -624,8 +673,14 @@ def ro(C, strict=None, base_mros=None, log_changed_ro=None, use_legacy_ro=None): resolver = C3.resolver(C, strict, base_mros) mro = resolver.mro() - log_changed = log_changed_ro if log_changed_ro is not None else resolver.LOG_CHANGED_IRO - use_legacy = use_legacy_ro if use_legacy_ro is not None else resolver.USE_LEGACY_IRO + log_changed = ( + log_changed_ro if log_changed_ro is not None + else resolver.LOG_CHANGED_IRO + ) + use_legacy = ( + use_legacy_ro if use_legacy_ro is not None + else resolver.USE_LEGACY_IRO + ) if log_changed or use_legacy: legacy_ro = resolver.legacy_ro @@ -660,8 +715,8 @@ def ro(C, strict=None, base_mros=None, log_changed_ro=None, use_legacy_ro=None): def is_consistent(C): - """ - Check if the resolution order for *C*, as computed by :func:`ro`, is consistent - according to C3. + """Is the resolution order for *C*, consistent according to C3. + + Order as computed by :func:`ro`. """ return not C3.resolver(C, False, None).had_inconsistency diff --git a/contrib/python/zope.interface/py3/zope/interface/verify.py b/contrib/python/zope.interface/py3/zope/interface/verify.py index 0894d2d2f7..5bee470be3 100644 --- a/contrib/python/zope.interface/py3/zope/interface/verify.py +++ b/contrib/python/zope.interface/py3/zope/interface/verify.py @@ -45,10 +45,11 @@ def _verify(iface, candidate, tentative=False, vtype=None): This involves: - Making sure the candidate claims that it provides the - interface using ``iface.providedBy`` (unless *tentative* is `True`, - in which case this step is skipped). This means that the candidate's class - declares that it `implements <zope.interface.implementer>` the interface, - or the candidate itself declares that it `provides <zope.interface.provider>` + interface using ``iface.providedBy`` (unless *tentative* is `True`, in + which case this step is skipped). This means that the candidate's class + declares that it `implements <zope.interface.implementer>` the + interface, or the candidate itself declares that it `provides + <zope.interface.provider>` the interface - Making sure the candidate defines all the necessary methods @@ -65,9 +66,9 @@ def _verify(iface, candidate, tentative=False, vtype=None): .. versionchanged:: 5.0 If multiple methods or attributes are invalid, all such errors - are collected and reported. Previously, only the first error was reported. - As a special case, if only one such error is present, it is raised - alone, like before. + are collected and reported. Previously, only the first error was + reported. As a special case, if only one such error is present, it is + raised alone, like before. """ if vtype == 'c': @@ -92,15 +93,18 @@ def _verify(iface, candidate, tentative=False, vtype=None): return True + def _verify_element(iface, name, desc, candidate, vtype): # Here the `desc` is either an `Attribute` or `Method` instance try: attr = getattr(candidate, name) except AttributeError: + if (not isinstance(desc, Method)) and vtype == 'c': # We can't verify non-methods on classes, since the # class may provide attrs in it's __init__. return + # TODO: This should use ``raise...from`` raise BrokenImplementation(iface, desc, candidate) @@ -118,11 +122,13 @@ def _verify_element(iface, name, desc, candidate, vtype): # ValueError: no signature found. The ``__text_signature__`` attribute # isn't typically populated either. # - # Note that on PyPy 2 or 3 (up through 7.3 at least), these are - # not true for things like ``dict.pop`` (but might be true for C extensions?) + # Note that on PyPy 2 or 3 (up through 7.3 at least), these are not + # true for things like ``dict.pop`` (but might be true for C + # extensions?) return if isinstance(attr, FunctionType): + if isinstance(candidate, type) and vtype == 'c': # This is an "unbound method". # Only unwrap this if we're verifying implementedBy; @@ -132,9 +138,13 @@ def _verify_element(iface, name, desc, candidate, vtype): else: # Nope, just a normal function meth = fromFunction(attr, iface, name=name) - elif (isinstance(attr, MethodTypes) - and type(attr.__func__) is FunctionType): + + elif ( + isinstance(attr, MethodTypes) and + type(attr.__func__) is FunctionType + ): meth = fromMethod(attr, iface, name) + elif isinstance(attr, property) and vtype == 'c': # Without an instance we cannot be sure it's not a # callable. @@ -144,8 +154,13 @@ def _verify_element(iface, name, desc, candidate, vtype): else: if not callable(attr): - raise BrokenMethodImplementation(desc, "implementation is not a method", - attr, iface, candidate) + raise BrokenMethodImplementation( + desc, + "implementation is not a method", + attr, + iface, + candidate + ) # sigh, it's callable, but we don't know how to introspect it, so # we have to give it a pass. return @@ -157,31 +172,38 @@ def _verify_element(iface, name, desc, candidate, vtype): raise BrokenMethodImplementation(desc, mess, attr, iface, candidate) - def verifyClass(iface, candidate, tentative=False): """ Verify that the *candidate* might correctly provide *iface*. """ return _verify(iface, candidate, tentative, vtype='c') + def verifyObject(iface, candidate, tentative=False): return _verify(iface, candidate, tentative, vtype='o') + verifyObject.__doc__ = _verify.__doc__ _MSG_TOO_MANY = 'implementation requires too many arguments' + def _incompat(required, implemented): - #if (required['positional'] != - # implemented['positional'][:len(required['positional'])] - # and implemented['kwargs'] is None): - # return 'imlementation has different argument names' + # if (required['positional'] != + # implemented['positional'][:len(required['positional'])] + # and implemented['kwargs'] is None): + # return 'imlementation has different argument names' if len(implemented['required']) > len(required['required']): return _MSG_TOO_MANY - if ((len(implemented['positional']) < len(required['positional'])) - and not implemented['varargs']): + + if ( + (len(implemented['positional']) < len(required['positional'])) and + not implemented['varargs'] + ): return "implementation doesn't allow enough arguments" + if required['kwargs'] and not implemented['kwargs']: return "implementation doesn't support keyword arguments" + if required['varargs'] and not implemented['varargs']: return "implementation doesn't support variable arguments" |