##// END OF EJS Templates
thirdparty: vendor zope.interface 4.4.3...
Gregory Szorc -
r37193:943d77fc default
parent child Browse files
Show More
@@ -0,0 +1,7 b''
1 # this is a namespace package
2 try:
3 import pkg_resources
4 pkg_resources.declare_namespace(__name__)
5 except ImportError:
6 import pkgutil
7 __path__ = pkgutil.extend_path(__path__, __name__)
@@ -0,0 +1,44 b''
1 Zope Public License (ZPL) Version 2.1
2
3 A copyright notice accompanies this license document that identifies the
4 copyright holders.
5
6 This license has been certified as open source. It has also been designated as
7 GPL compatible by the Free Software Foundation (FSF).
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
11
12 1. Redistributions in source code must retain the accompanying copyright
13 notice, this list of conditions, and the following disclaimer.
14
15 2. Redistributions in binary form must reproduce the accompanying copyright
16 notice, this list of conditions, and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
18
19 3. Names of the copyright holders must not be used to endorse or promote
20 products derived from this software without prior written permission from the
21 copyright holders.
22
23 4. The right to distribute this software or to use it for any purpose does not
24 give you the right to use Servicemarks (sm) or Trademarks (tm) of the
25 copyright
26 holders. Use of them is covered by separate agreement with the copyright
27 holders.
28
29 5. If any files are modified, you must cause the modified files to carry
30 prominent notices stating that you changed the files and the date of any
31 change.
32
33 Disclaimer
34
35 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED
36 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
38 EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
39 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
41 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
42 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
43 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
44 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,90 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Interfaces
15
16 This package implements the Python "scarecrow" proposal.
17
18 The package exports two objects, `Interface` and `Attribute` directly. It also
19 exports several helper methods. Interface is used to create an interface with
20 a class statement, as in:
21
22 class IMyInterface(Interface):
23 '''Interface documentation
24 '''
25
26 def meth(arg1, arg2):
27 '''Documentation for meth
28 '''
29
30 # Note that there is no self argument
31
32 To find out what you can do with interfaces, see the interface
33 interface, `IInterface` in the `interfaces` module.
34
35 The package has several public modules:
36
37 o `declarations` provides utilities to declare interfaces on objects. It
38 also provides a wide range of helpful utilities that aid in managing
39 declared interfaces. Most of its public names are however imported here.
40
41 o `document` has a utility for documenting an interface as structured text.
42
43 o `exceptions` has the interface-defined exceptions
44
45 o `interfaces` contains a list of all public interfaces for this package.
46
47 o `verify` has utilities for verifying implementations of interfaces.
48
49 See the module doc strings for more information.
50 """
51 __docformat__ = 'restructuredtext'
52
53 from zope.interface.interface import Interface
54 from zope.interface.interface import _wire
55
56 # Need to actually get the interface elements to implement the right interfaces
57 _wire()
58 del _wire
59
60 from zope.interface.declarations import Declaration
61 from zope.interface.declarations import alsoProvides
62 from zope.interface.declarations import classImplements
63 from zope.interface.declarations import classImplementsOnly
64 from zope.interface.declarations import classProvides
65 from zope.interface.declarations import directlyProvidedBy
66 from zope.interface.declarations import directlyProvides
67 from zope.interface.declarations import implementedBy
68 from zope.interface.declarations import implementer
69 from zope.interface.declarations import implementer_only
70 from zope.interface.declarations import implements
71 from zope.interface.declarations import implementsOnly
72 from zope.interface.declarations import moduleProvides
73 from zope.interface.declarations import named
74 from zope.interface.declarations import noLongerProvides
75 from zope.interface.declarations import providedBy
76 from zope.interface.declarations import provider
77 from zope.interface.exceptions import Invalid
78 from zope.interface.interface import Attribute
79 from zope.interface.interface import invariant
80 from zope.interface.interface import taggedValue
81
82 # The following are to make spec pickles cleaner
83 from zope.interface.declarations import Provides
84
85
86 from zope.interface.interfaces import IInterfaceDeclaration
87
88 moduleProvides(IInterfaceDeclaration)
89
90 __all__ = ('Interface', 'Attribute') + tuple(IInterfaceDeclaration)
@@ -0,0 +1,58 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2006 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Basic components support
15 """
16 import sys
17 import types
18
19 if sys.version_info[0] < 3:
20
21 def _normalize_name(name):
22 if isinstance(name, basestring):
23 return unicode(name)
24 raise TypeError("name must be a regular or unicode string")
25
26 CLASS_TYPES = (type, types.ClassType)
27 STRING_TYPES = (basestring,)
28
29 _BUILTINS = '__builtin__'
30
31 PYTHON3 = False
32 PYTHON2 = True
33
34 else:
35
36 def _normalize_name(name):
37 if isinstance(name, bytes):
38 name = str(name, 'ascii')
39 if isinstance(name, str):
40 return name
41 raise TypeError("name must be a string or ASCII-only bytes")
42
43 CLASS_TYPES = (type,)
44 STRING_TYPES = (str,)
45
46 _BUILTINS = 'builtins'
47
48 PYTHON3 = True
49 PYTHON2 = False
50
51 def _skip_under_py3k(test_method):
52 import unittest
53 return unittest.skipIf(sys.version_info[0] >= 3, "Only on Python 2")(test_method)
54
55
56 def _skip_under_py2(test_method):
57 import unittest
58 return unittest.skipIf(sys.version_info[0] < 3, "Only on Python 3")(test_method)
@@ -0,0 +1,35 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Adapter-style interface registry
15
16 See Adapter class.
17 """
18 from zope.interface import Declaration
19
20 def _flatten(implements, include_None=0):
21
22 try:
23 r = implements.flattened()
24 except AttributeError:
25 if implements is None:
26 r=()
27 else:
28 r = Declaration(implements).flattened()
29
30 if not include_None:
31 return r
32
33 r = list(r)
34 r.append(None)
35 return r
This diff has been collapsed as it changes many lines, (1726 lines changed) Show them Hide them
@@ -0,0 +1,1726 b''
1 /*###########################################################################
2 #
3 # Copyright (c) 2003 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ############################################################################*/
14
15 #include "Python.h"
16 #include "structmember.h"
17
18 #define TYPE(O) ((PyTypeObject*)(O))
19 #define OBJECT(O) ((PyObject*)(O))
20 #define CLASSIC(O) ((PyClassObject*)(O))
21 #ifndef PyVarObject_HEAD_INIT
22 #define PyVarObject_HEAD_INIT(a, b) PyObject_HEAD_INIT(a) b,
23 #endif
24 #ifndef Py_TYPE
25 #define Py_TYPE(o) ((o)->ob_type)
26 #endif
27
28 #if PY_MAJOR_VERSION >= 3
29 #define PY3K
30 #endif
31
32 static PyObject *str__dict__, *str__implemented__, *strextends;
33 static PyObject *BuiltinImplementationSpecifications, *str__provides__;
34 static PyObject *str__class__, *str__providedBy__;
35 static PyObject *empty, *fallback, *str_implied, *str_cls, *str_implements;
36 static PyObject *str__conform__, *str_call_conform, *adapter_hooks;
37 static PyObject *str_uncached_lookup, *str_uncached_lookupAll;
38 static PyObject *str_uncached_subscriptions;
39 static PyObject *str_registry, *strro, *str_generation, *strchanged;
40
41 static PyTypeObject *Implements;
42
43 static int imported_declarations = 0;
44
45 static int
46 import_declarations(void)
47 {
48 PyObject *declarations, *i;
49
50 declarations = PyImport_ImportModule("zope.interface.declarations");
51 if (declarations == NULL)
52 return -1;
53
54 BuiltinImplementationSpecifications = PyObject_GetAttrString(
55 declarations, "BuiltinImplementationSpecifications");
56 if (BuiltinImplementationSpecifications == NULL)
57 return -1;
58
59 empty = PyObject_GetAttrString(declarations, "_empty");
60 if (empty == NULL)
61 return -1;
62
63 fallback = PyObject_GetAttrString(declarations, "implementedByFallback");
64 if (fallback == NULL)
65 return -1;
66
67
68
69 i = PyObject_GetAttrString(declarations, "Implements");
70 if (i == NULL)
71 return -1;
72
73 if (! PyType_Check(i))
74 {
75 PyErr_SetString(PyExc_TypeError,
76 "zope.interface.declarations.Implements is not a type");
77 return -1;
78 }
79
80 Implements = (PyTypeObject *)i;
81
82 Py_DECREF(declarations);
83
84 imported_declarations = 1;
85 return 0;
86 }
87
88 static PyTypeObject SpecType; /* Forward */
89
90 static PyObject *
91 implementedByFallback(PyObject *cls)
92 {
93 if (imported_declarations == 0 && import_declarations() < 0)
94 return NULL;
95
96 return PyObject_CallFunctionObjArgs(fallback, cls, NULL);
97 }
98
99 static PyObject *
100 implementedBy(PyObject *ignored, PyObject *cls)
101 {
102 /* Fast retrieval of implements spec, if possible, to optimize
103 common case. Use fallback code if we get stuck.
104 */
105
106 PyObject *dict = NULL, *spec;
107
108 if (PyType_Check(cls))
109 {
110 dict = TYPE(cls)->tp_dict;
111 Py_XINCREF(dict);
112 }
113
114 if (dict == NULL)
115 dict = PyObject_GetAttr(cls, str__dict__);
116
117 if (dict == NULL)
118 {
119 /* Probably a security proxied class, use more expensive fallback code */
120 PyErr_Clear();
121 return implementedByFallback(cls);
122 }
123
124 spec = PyObject_GetItem(dict, str__implemented__);
125 Py_DECREF(dict);
126 if (spec)
127 {
128 if (imported_declarations == 0 && import_declarations() < 0)
129 return NULL;
130
131 if (PyObject_TypeCheck(spec, Implements))
132 return spec;
133
134 /* Old-style declaration, use more expensive fallback code */
135 Py_DECREF(spec);
136 return implementedByFallback(cls);
137 }
138
139 PyErr_Clear();
140
141 /* Maybe we have a builtin */
142 if (imported_declarations == 0 && import_declarations() < 0)
143 return NULL;
144
145 spec = PyDict_GetItem(BuiltinImplementationSpecifications, cls);
146 if (spec != NULL)
147 {
148 Py_INCREF(spec);
149 return spec;
150 }
151
152 /* We're stuck, use fallback */
153 return implementedByFallback(cls);
154 }
155
156 static PyObject *
157 getObjectSpecification(PyObject *ignored, PyObject *ob)
158 {
159 PyObject *cls, *result;
160
161 result = PyObject_GetAttr(ob, str__provides__);
162 if (result != NULL && PyObject_TypeCheck(result, &SpecType))
163 return result;
164
165 PyErr_Clear();
166
167 /* We do a getattr here so as not to be defeated by proxies */
168 cls = PyObject_GetAttr(ob, str__class__);
169 if (cls == NULL)
170 {
171 PyErr_Clear();
172 if (imported_declarations == 0 && import_declarations() < 0)
173 return NULL;
174 Py_INCREF(empty);
175 return empty;
176 }
177
178 result = implementedBy(NULL, cls);
179 Py_DECREF(cls);
180
181 return result;
182 }
183
184 static PyObject *
185 providedBy(PyObject *ignored, PyObject *ob)
186 {
187 PyObject *result, *cls, *cp;
188
189 result = PyObject_GetAttr(ob, str__providedBy__);
190 if (result == NULL)
191 {
192 PyErr_Clear();
193 return getObjectSpecification(NULL, ob);
194 }
195
196
197 /* We want to make sure we have a spec. We can't do a type check
198 because we may have a proxy, so we'll just try to get the
199 only attribute.
200 */
201 if (PyObject_TypeCheck(result, &SpecType)
202 ||
203 PyObject_HasAttr(result, strextends)
204 )
205 return result;
206
207 /*
208 The object's class doesn't understand descriptors.
209 Sigh. We need to get an object descriptor, but we have to be
210 careful. We want to use the instance's __provides__,l if
211 there is one, but only if it didn't come from the class.
212 */
213 Py_DECREF(result);
214
215 cls = PyObject_GetAttr(ob, str__class__);
216 if (cls == NULL)
217 return NULL;
218
219 result = PyObject_GetAttr(ob, str__provides__);
220 if (result == NULL)
221 {
222 /* No __provides__, so just fall back to implementedBy */
223 PyErr_Clear();
224 result = implementedBy(NULL, cls);
225 Py_DECREF(cls);
226 return result;
227 }
228
229 cp = PyObject_GetAttr(cls, str__provides__);
230 if (cp == NULL)
231 {
232 /* The the class has no provides, assume we're done: */
233 PyErr_Clear();
234 Py_DECREF(cls);
235 return result;
236 }
237
238 if (cp == result)
239 {
240 /*
241 Oops, we got the provides from the class. This means
242 the object doesn't have it's own. We should use implementedBy
243 */
244 Py_DECREF(result);
245 result = implementedBy(NULL, cls);
246 }
247
248 Py_DECREF(cls);
249 Py_DECREF(cp);
250
251 return result;
252 }
253
254 /*
255 Get an attribute from an inst dict. Return a borrowed reference.
256
257 This has a number of advantages:
258
259 - It avoids layers of Python api
260
261 - It doesn't waste time looking for descriptors
262
263 - It fails wo raising an exception, although that shouldn't really
264 matter.
265
266 */
267 static PyObject *
268 inst_attr(PyObject *self, PyObject *name)
269 {
270 PyObject **dictp, *v;
271
272 dictp = _PyObject_GetDictPtr(self);
273 if (dictp && *dictp && (v = PyDict_GetItem(*dictp, name)))
274 return v;
275 PyErr_SetObject(PyExc_AttributeError, name);
276 return NULL;
277 }
278
279
280 static PyObject *
281 Spec_extends(PyObject *self, PyObject *other)
282 {
283 PyObject *implied;
284
285 implied = inst_attr(self, str_implied);
286 if (implied == NULL)
287 return NULL;
288
289 #ifdef Py_True
290 if (PyDict_GetItem(implied, other) != NULL)
291 {
292 Py_INCREF(Py_True);
293 return Py_True;
294 }
295 Py_INCREF(Py_False);
296 return Py_False;
297 #else
298 return PyInt_FromLong(PyDict_GetItem(implied, other) != NULL);
299 #endif
300 }
301
302 static char Spec_extends__doc__[] =
303 "Test whether a specification is or extends another"
304 ;
305
306 static char Spec_providedBy__doc__[] =
307 "Test whether an interface is implemented by the specification"
308 ;
309
310 static PyObject *
311 Spec_call(PyObject *self, PyObject *args, PyObject *kw)
312 {
313 PyObject *spec;
314
315 if (! PyArg_ParseTuple(args, "O", &spec))
316 return NULL;
317 return Spec_extends(self, spec);
318 }
319
320 static PyObject *
321 Spec_providedBy(PyObject *self, PyObject *ob)
322 {
323 PyObject *decl, *item;
324
325 decl = providedBy(NULL, ob);
326 if (decl == NULL)
327 return NULL;
328
329 if (PyObject_TypeCheck(decl, &SpecType))
330 item = Spec_extends(decl, self);
331 else
332 /* decl is probably a security proxy. We have to go the long way
333 around.
334 */
335 item = PyObject_CallFunctionObjArgs(decl, self, NULL);
336
337 Py_DECREF(decl);
338 return item;
339 }
340
341
342 static char Spec_implementedBy__doc__[] =
343 "Test whether the specification is implemented by a class or factory.\n"
344 "Raise TypeError if argument is neither a class nor a callable."
345 ;
346
347 static PyObject *
348 Spec_implementedBy(PyObject *self, PyObject *cls)
349 {
350 PyObject *decl, *item;
351
352 decl = implementedBy(NULL, cls);
353 if (decl == NULL)
354 return NULL;
355
356 if (PyObject_TypeCheck(decl, &SpecType))
357 item = Spec_extends(decl, self);
358 else
359 item = PyObject_CallFunctionObjArgs(decl, self, NULL);
360
361 Py_DECREF(decl);
362 return item;
363 }
364
365 static struct PyMethodDef Spec_methods[] = {
366 {"providedBy",
367 (PyCFunction)Spec_providedBy, METH_O,
368 Spec_providedBy__doc__},
369 {"implementedBy",
370 (PyCFunction)Spec_implementedBy, METH_O,
371 Spec_implementedBy__doc__},
372 {"isOrExtends", (PyCFunction)Spec_extends, METH_O,
373 Spec_extends__doc__},
374
375 {NULL, NULL} /* sentinel */
376 };
377
378 static PyTypeObject SpecType = {
379 PyVarObject_HEAD_INIT(NULL, 0)
380 /* tp_name */ "_interface_coptimizations."
381 "SpecificationBase",
382 /* tp_basicsize */ 0,
383 /* tp_itemsize */ 0,
384 /* tp_dealloc */ (destructor)0,
385 /* tp_print */ (printfunc)0,
386 /* tp_getattr */ (getattrfunc)0,
387 /* tp_setattr */ (setattrfunc)0,
388 /* tp_compare */ 0,
389 /* tp_repr */ (reprfunc)0,
390 /* tp_as_number */ 0,
391 /* tp_as_sequence */ 0,
392 /* tp_as_mapping */ 0,
393 /* tp_hash */ (hashfunc)0,
394 /* tp_call */ (ternaryfunc)Spec_call,
395 /* tp_str */ (reprfunc)0,
396 /* tp_getattro */ (getattrofunc)0,
397 /* tp_setattro */ (setattrofunc)0,
398 /* tp_as_buffer */ 0,
399 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
400 "Base type for Specification objects",
401 /* tp_traverse */ (traverseproc)0,
402 /* tp_clear */ (inquiry)0,
403 /* tp_richcompare */ (richcmpfunc)0,
404 /* tp_weaklistoffset */ (long)0,
405 /* tp_iter */ (getiterfunc)0,
406 /* tp_iternext */ (iternextfunc)0,
407 /* tp_methods */ Spec_methods,
408 };
409
410 static PyObject *
411 OSD_descr_get(PyObject *self, PyObject *inst, PyObject *cls)
412 {
413 PyObject *provides;
414
415 if (inst == NULL)
416 return getObjectSpecification(NULL, cls);
417
418 provides = PyObject_GetAttr(inst, str__provides__);
419 if (provides != NULL)
420 return provides;
421 PyErr_Clear();
422 return implementedBy(NULL, cls);
423 }
424
425 static PyTypeObject OSDType = {
426 PyVarObject_HEAD_INIT(NULL, 0)
427 /* tp_name */ "_interface_coptimizations."
428 "ObjectSpecificationDescriptor",
429 /* tp_basicsize */ 0,
430 /* tp_itemsize */ 0,
431 /* tp_dealloc */ (destructor)0,
432 /* tp_print */ (printfunc)0,
433 /* tp_getattr */ (getattrfunc)0,
434 /* tp_setattr */ (setattrfunc)0,
435 /* tp_compare */ 0,
436 /* tp_repr */ (reprfunc)0,
437 /* tp_as_number */ 0,
438 /* tp_as_sequence */ 0,
439 /* tp_as_mapping */ 0,
440 /* tp_hash */ (hashfunc)0,
441 /* tp_call */ (ternaryfunc)0,
442 /* tp_str */ (reprfunc)0,
443 /* tp_getattro */ (getattrofunc)0,
444 /* tp_setattro */ (setattrofunc)0,
445 /* tp_as_buffer */ 0,
446 /* tp_flags */ Py_TPFLAGS_DEFAULT
447 | Py_TPFLAGS_BASETYPE ,
448 "Object Specification Descriptor",
449 /* tp_traverse */ (traverseproc)0,
450 /* tp_clear */ (inquiry)0,
451 /* tp_richcompare */ (richcmpfunc)0,
452 /* tp_weaklistoffset */ (long)0,
453 /* tp_iter */ (getiterfunc)0,
454 /* tp_iternext */ (iternextfunc)0,
455 /* tp_methods */ 0,
456 /* tp_members */ 0,
457 /* tp_getset */ 0,
458 /* tp_base */ 0,
459 /* tp_dict */ 0, /* internal use */
460 /* tp_descr_get */ (descrgetfunc)OSD_descr_get,
461 };
462
463 static PyObject *
464 CPB_descr_get(PyObject *self, PyObject *inst, PyObject *cls)
465 {
466 PyObject *mycls, *implements;
467
468 mycls = inst_attr(self, str_cls);
469 if (mycls == NULL)
470 return NULL;
471
472 if (cls == mycls)
473 {
474 if (inst == NULL)
475 {
476 Py_INCREF(self);
477 return OBJECT(self);
478 }
479
480 implements = inst_attr(self, str_implements);
481 Py_XINCREF(implements);
482 return implements;
483 }
484
485 PyErr_SetObject(PyExc_AttributeError, str__provides__);
486 return NULL;
487 }
488
489 static PyTypeObject CPBType = {
490 PyVarObject_HEAD_INIT(NULL, 0)
491 /* tp_name */ "_interface_coptimizations."
492 "ClassProvidesBase",
493 /* tp_basicsize */ 0,
494 /* tp_itemsize */ 0,
495 /* tp_dealloc */ (destructor)0,
496 /* tp_print */ (printfunc)0,
497 /* tp_getattr */ (getattrfunc)0,
498 /* tp_setattr */ (setattrfunc)0,
499 /* tp_compare */ 0,
500 /* tp_repr */ (reprfunc)0,
501 /* tp_as_number */ 0,
502 /* tp_as_sequence */ 0,
503 /* tp_as_mapping */ 0,
504 /* tp_hash */ (hashfunc)0,
505 /* tp_call */ (ternaryfunc)0,
506 /* tp_str */ (reprfunc)0,
507 /* tp_getattro */ (getattrofunc)0,
508 /* tp_setattro */ (setattrofunc)0,
509 /* tp_as_buffer */ 0,
510 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
511 "C Base class for ClassProvides",
512 /* tp_traverse */ (traverseproc)0,
513 /* tp_clear */ (inquiry)0,
514 /* tp_richcompare */ (richcmpfunc)0,
515 /* tp_weaklistoffset */ (long)0,
516 /* tp_iter */ (getiterfunc)0,
517 /* tp_iternext */ (iternextfunc)0,
518 /* tp_methods */ 0,
519 /* tp_members */ 0,
520 /* tp_getset */ 0,
521 /* tp_base */ &SpecType,
522 /* tp_dict */ 0, /* internal use */
523 /* tp_descr_get */ (descrgetfunc)CPB_descr_get,
524 };
525
526 /* ==================================================================== */
527 /* ========== Begin: __call__ and __adapt__ =========================== */
528
529 /*
530 def __adapt__(self, obj):
531 """Adapt an object to the reciever
532 """
533 if self.providedBy(obj):
534 return obj
535
536 for hook in adapter_hooks:
537 adapter = hook(self, obj)
538 if adapter is not None:
539 return adapter
540
541
542 */
543 static PyObject *
544 __adapt__(PyObject *self, PyObject *obj)
545 {
546 PyObject *decl, *args, *adapter;
547 int implements, i, l;
548
549 decl = providedBy(NULL, obj);
550 if (decl == NULL)
551 return NULL;
552
553 if (PyObject_TypeCheck(decl, &SpecType))
554 {
555 PyObject *implied;
556
557 implied = inst_attr(decl, str_implied);
558 if (implied == NULL)
559 {
560 Py_DECREF(decl);
561 return NULL;
562 }
563
564 implements = PyDict_GetItem(implied, self) != NULL;
565 Py_DECREF(decl);
566 }
567 else
568 {
569 /* decl is probably a security proxy. We have to go the long way
570 around.
571 */
572 PyObject *r;
573 r = PyObject_CallFunctionObjArgs(decl, self, NULL);
574 Py_DECREF(decl);
575 if (r == NULL)
576 return NULL;
577 implements = PyObject_IsTrue(r);
578 Py_DECREF(r);
579 }
580
581 if (implements)
582 {
583 Py_INCREF(obj);
584 return obj;
585 }
586
587 l = PyList_GET_SIZE(adapter_hooks);
588 args = PyTuple_New(2);
589 if (args == NULL)
590 return NULL;
591 Py_INCREF(self);
592 PyTuple_SET_ITEM(args, 0, self);
593 Py_INCREF(obj);
594 PyTuple_SET_ITEM(args, 1, obj);
595 for (i = 0; i < l; i++)
596 {
597 adapter = PyObject_CallObject(PyList_GET_ITEM(adapter_hooks, i), args);
598 if (adapter == NULL || adapter != Py_None)
599 {
600 Py_DECREF(args);
601 return adapter;
602 }
603 Py_DECREF(adapter);
604 }
605
606 Py_DECREF(args);
607
608 Py_INCREF(Py_None);
609 return Py_None;
610 }
611
612 static struct PyMethodDef ib_methods[] = {
613 {"__adapt__", (PyCFunction)__adapt__, METH_O,
614 "Adapt an object to the reciever"},
615 {NULL, NULL} /* sentinel */
616 };
617
618 /*
619 def __call__(self, obj, alternate=_marker):
620 conform = getattr(obj, '__conform__', None)
621 if conform is not None:
622 adapter = self._call_conform(conform)
623 if adapter is not None:
624 return adapter
625
626 adapter = self.__adapt__(obj)
627
628 if adapter is not None:
629 return adapter
630 elif alternate is not _marker:
631 return alternate
632 else:
633 raise TypeError("Could not adapt", obj, self)
634 */
635 static PyObject *
636 ib_call(PyObject *self, PyObject *args, PyObject *kwargs)
637 {
638 PyObject *conform, *obj, *alternate=NULL, *adapter;
639
640 static char *kwlist[] = {"obj", "alternate", NULL};
641
642 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist,
643 &obj, &alternate))
644 return NULL;
645
646 conform = PyObject_GetAttr(obj, str__conform__);
647 if (conform != NULL)
648 {
649 adapter = PyObject_CallMethodObjArgs(self, str_call_conform,
650 conform, NULL);
651 Py_DECREF(conform);
652 if (adapter == NULL || adapter != Py_None)
653 return adapter;
654 Py_DECREF(adapter);
655 }
656 else
657 PyErr_Clear();
658
659 adapter = __adapt__(self, obj);
660 if (adapter == NULL || adapter != Py_None)
661 return adapter;
662 Py_DECREF(adapter);
663
664 if (alternate != NULL)
665 {
666 Py_INCREF(alternate);
667 return alternate;
668 }
669
670 adapter = Py_BuildValue("sOO", "Could not adapt", obj, self);
671 if (adapter != NULL)
672 {
673 PyErr_SetObject(PyExc_TypeError, adapter);
674 Py_DECREF(adapter);
675 }
676 return NULL;
677 }
678
679 static PyTypeObject InterfaceBase = {
680 PyVarObject_HEAD_INIT(NULL, 0)
681 /* tp_name */ "_zope_interface_coptimizations."
682 "InterfaceBase",
683 /* tp_basicsize */ 0,
684 /* tp_itemsize */ 0,
685 /* tp_dealloc */ (destructor)0,
686 /* tp_print */ (printfunc)0,
687 /* tp_getattr */ (getattrfunc)0,
688 /* tp_setattr */ (setattrfunc)0,
689 /* tp_compare */ 0,
690 /* tp_repr */ (reprfunc)0,
691 /* tp_as_number */ 0,
692 /* tp_as_sequence */ 0,
693 /* tp_as_mapping */ 0,
694 /* tp_hash */ (hashfunc)0,
695 /* tp_call */ (ternaryfunc)ib_call,
696 /* tp_str */ (reprfunc)0,
697 /* tp_getattro */ (getattrofunc)0,
698 /* tp_setattro */ (setattrofunc)0,
699 /* tp_as_buffer */ 0,
700 /* tp_flags */ Py_TPFLAGS_DEFAULT
701 | Py_TPFLAGS_BASETYPE ,
702 /* tp_doc */ "Interface base type providing __call__ and __adapt__",
703 /* tp_traverse */ (traverseproc)0,
704 /* tp_clear */ (inquiry)0,
705 /* tp_richcompare */ (richcmpfunc)0,
706 /* tp_weaklistoffset */ (long)0,
707 /* tp_iter */ (getiterfunc)0,
708 /* tp_iternext */ (iternextfunc)0,
709 /* tp_methods */ ib_methods,
710 };
711
712 /* =================== End: __call__ and __adapt__ ==================== */
713 /* ==================================================================== */
714
715 /* ==================================================================== */
716 /* ========================== Begin: Lookup Bases ===================== */
717
718 typedef struct {
719 PyObject_HEAD
720 PyObject *_cache;
721 PyObject *_mcache;
722 PyObject *_scache;
723 } lookup;
724
725 typedef struct {
726 PyObject_HEAD
727 PyObject *_cache;
728 PyObject *_mcache;
729 PyObject *_scache;
730 PyObject *_verify_ro;
731 PyObject *_verify_generations;
732 } verify;
733
734 static int
735 lookup_traverse(lookup *self, visitproc visit, void *arg)
736 {
737 int vret;
738
739 if (self->_cache) {
740 vret = visit(self->_cache, arg);
741 if (vret != 0)
742 return vret;
743 }
744
745 if (self->_mcache) {
746 vret = visit(self->_mcache, arg);
747 if (vret != 0)
748 return vret;
749 }
750
751 if (self->_scache) {
752 vret = visit(self->_scache, arg);
753 if (vret != 0)
754 return vret;
755 }
756
757 return 0;
758 }
759
760 static int
761 lookup_clear(lookup *self)
762 {
763 Py_CLEAR(self->_cache);
764 Py_CLEAR(self->_mcache);
765 Py_CLEAR(self->_scache);
766 return 0;
767 }
768
769 static void
770 lookup_dealloc(lookup *self)
771 {
772 PyObject_GC_UnTrack((PyObject *)self);
773 lookup_clear(self);
774 Py_TYPE(self)->tp_free((PyObject*)self);
775 }
776
777 /*
778 def changed(self, ignored=None):
779 self._cache.clear()
780 self._mcache.clear()
781 self._scache.clear()
782 */
783 static PyObject *
784 lookup_changed(lookup *self, PyObject *ignored)
785 {
786 lookup_clear(self);
787 Py_INCREF(Py_None);
788 return Py_None;
789 }
790
791 #define ASSURE_DICT(N) if (N == NULL) { N = PyDict_New(); \
792 if (N == NULL) return NULL; \
793 }
794
795 /*
796 def _getcache(self, provided, name):
797 cache = self._cache.get(provided)
798 if cache is None:
799 cache = {}
800 self._cache[provided] = cache
801 if name:
802 c = cache.get(name)
803 if c is None:
804 c = {}
805 cache[name] = c
806 cache = c
807 return cache
808 */
809 static PyObject *
810 _subcache(PyObject *cache, PyObject *key)
811 {
812 PyObject *subcache;
813
814 subcache = PyDict_GetItem(cache, key);
815 if (subcache == NULL)
816 {
817 int status;
818
819 subcache = PyDict_New();
820 if (subcache == NULL)
821 return NULL;
822 status = PyDict_SetItem(cache, key, subcache);
823 Py_DECREF(subcache);
824 if (status < 0)
825 return NULL;
826 }
827
828 return subcache;
829 }
830 static PyObject *
831 _getcache(lookup *self, PyObject *provided, PyObject *name)
832 {
833 PyObject *cache;
834
835 ASSURE_DICT(self->_cache);
836 cache = _subcache(self->_cache, provided);
837 if (cache == NULL)
838 return NULL;
839
840 if (name != NULL && PyObject_IsTrue(name))
841 cache = _subcache(cache, name);
842
843 return cache;
844 }
845
846
847 /*
848 def lookup(self, required, provided, name=u'', default=None):
849 cache = self._getcache(provided, name)
850 if len(required) == 1:
851 result = cache.get(required[0], _not_in_mapping)
852 else:
853 result = cache.get(tuple(required), _not_in_mapping)
854
855 if result is _not_in_mapping:
856 result = self._uncached_lookup(required, provided, name)
857 if len(required) == 1:
858 cache[required[0]] = result
859 else:
860 cache[tuple(required)] = result
861
862 if result is None:
863 return default
864
865 return result
866 */
867 static PyObject *
868 tuplefy(PyObject *v)
869 {
870 if (! PyTuple_Check(v))
871 {
872 v = PyObject_CallFunctionObjArgs(OBJECT(&PyTuple_Type), v, NULL);
873 if (v == NULL)
874 return NULL;
875 }
876 else
877 Py_INCREF(v);
878
879 return v;
880 }
881 static PyObject *
882 _lookup(lookup *self,
883 PyObject *required, PyObject *provided, PyObject *name,
884 PyObject *default_)
885 {
886 PyObject *result, *key, *cache;
887
888 #ifdef PY3K
889 if ( name && !PyUnicode_Check(name) )
890 #else
891 if ( name && !PyString_Check(name) && !PyUnicode_Check(name) )
892 #endif
893 {
894 PyErr_SetString(PyExc_ValueError,
895 "name is not a string or unicode");
896 return NULL;
897 }
898 cache = _getcache(self, provided, name);
899 if (cache == NULL)
900 return NULL;
901
902 required = tuplefy(required);
903 if (required == NULL)
904 return NULL;
905
906 if (PyTuple_GET_SIZE(required) == 1)
907 key = PyTuple_GET_ITEM(required, 0);
908 else
909 key = required;
910
911 result = PyDict_GetItem(cache, key);
912 if (result == NULL)
913 {
914 int status;
915
916 result = PyObject_CallMethodObjArgs(OBJECT(self), str_uncached_lookup,
917 required, provided, name, NULL);
918 if (result == NULL)
919 {
920 Py_DECREF(required);
921 return NULL;
922 }
923 status = PyDict_SetItem(cache, key, result);
924 Py_DECREF(required);
925 if (status < 0)
926 {
927 Py_DECREF(result);
928 return NULL;
929 }
930 }
931 else
932 {
933 Py_INCREF(result);
934 Py_DECREF(required);
935 }
936
937 if (result == Py_None && default_ != NULL)
938 {
939 Py_DECREF(Py_None);
940 Py_INCREF(default_);
941 return default_;
942 }
943
944 return result;
945 }
946 static PyObject *
947 lookup_lookup(lookup *self, PyObject *args, PyObject *kwds)
948 {
949 static char *kwlist[] = {"required", "provided", "name", "default", NULL};
950 PyObject *required, *provided, *name=NULL, *default_=NULL;
951
952 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
953 &required, &provided, &name, &default_))
954 return NULL;
955
956 return _lookup(self, required, provided, name, default_);
957 }
958
959
960 /*
961 def lookup1(self, required, provided, name=u'', default=None):
962 cache = self._getcache(provided, name)
963 result = cache.get(required, _not_in_mapping)
964 if result is _not_in_mapping:
965 return self.lookup((required, ), provided, name, default)
966
967 if result is None:
968 return default
969
970 return result
971 */
972 static PyObject *
973 _lookup1(lookup *self,
974 PyObject *required, PyObject *provided, PyObject *name,
975 PyObject *default_)
976 {
977 PyObject *result, *cache;
978
979 #ifdef PY3K
980 if ( name && !PyUnicode_Check(name) )
981 #else
982 if ( name && !PyString_Check(name) && !PyUnicode_Check(name) )
983 #endif
984 {
985 PyErr_SetString(PyExc_ValueError,
986 "name is not a string or unicode");
987 return NULL;
988 }
989
990 cache = _getcache(self, provided, name);
991 if (cache == NULL)
992 return NULL;
993
994 result = PyDict_GetItem(cache, required);
995 if (result == NULL)
996 {
997 PyObject *tup;
998
999 tup = PyTuple_New(1);
1000 if (tup == NULL)
1001 return NULL;
1002 Py_INCREF(required);
1003 PyTuple_SET_ITEM(tup, 0, required);
1004 result = _lookup(self, tup, provided, name, default_);
1005 Py_DECREF(tup);
1006 }
1007 else
1008 {
1009 if (result == Py_None && default_ != NULL)
1010 {
1011 result = default_;
1012 }
1013 Py_INCREF(result);
1014 }
1015
1016 return result;
1017 }
1018 static PyObject *
1019 lookup_lookup1(lookup *self, PyObject *args, PyObject *kwds)
1020 {
1021 static char *kwlist[] = {"required", "provided", "name", "default", NULL};
1022 PyObject *required, *provided, *name=NULL, *default_=NULL;
1023
1024 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1025 &required, &provided, &name, &default_))
1026 return NULL;
1027
1028 return _lookup1(self, required, provided, name, default_);
1029 }
1030
1031 /*
1032 def adapter_hook(self, provided, object, name=u'', default=None):
1033 required = providedBy(object)
1034 cache = self._getcache(provided, name)
1035 factory = cache.get(required, _not_in_mapping)
1036 if factory is _not_in_mapping:
1037 factory = self.lookup((required, ), provided, name)
1038
1039 if factory is not None:
1040 result = factory(object)
1041 if result is not None:
1042 return result
1043
1044 return default
1045 */
1046 static PyObject *
1047 _adapter_hook(lookup *self,
1048 PyObject *provided, PyObject *object, PyObject *name,
1049 PyObject *default_)
1050 {
1051 PyObject *required, *factory, *result;
1052
1053 #ifdef PY3K
1054 if ( name && !PyUnicode_Check(name) )
1055 #else
1056 if ( name && !PyString_Check(name) && !PyUnicode_Check(name) )
1057 #endif
1058 {
1059 PyErr_SetString(PyExc_ValueError,
1060 "name is not a string or unicode");
1061 return NULL;
1062 }
1063
1064 required = providedBy(NULL, object);
1065 if (required == NULL)
1066 return NULL;
1067
1068 factory = _lookup1(self, required, provided, name, Py_None);
1069 Py_DECREF(required);
1070 if (factory == NULL)
1071 return NULL;
1072
1073 if (factory != Py_None)
1074 {
1075 result = PyObject_CallFunctionObjArgs(factory, object, NULL);
1076 Py_DECREF(factory);
1077 if (result == NULL || result != Py_None)
1078 return result;
1079 }
1080 else
1081 result = factory; /* None */
1082
1083 if (default_ == NULL || default_ == result) /* No default specified, */
1084 return result; /* Return None. result is owned None */
1085
1086 Py_DECREF(result);
1087 Py_INCREF(default_);
1088
1089 return default_;
1090 }
1091 static PyObject *
1092 lookup_adapter_hook(lookup *self, PyObject *args, PyObject *kwds)
1093 {
1094 static char *kwlist[] = {"provided", "object", "name", "default", NULL};
1095 PyObject *object, *provided, *name=NULL, *default_=NULL;
1096
1097 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1098 &provided, &object, &name, &default_))
1099 return NULL;
1100
1101 return _adapter_hook(self, provided, object, name, default_);
1102 }
1103
1104 static PyObject *
1105 lookup_queryAdapter(lookup *self, PyObject *args, PyObject *kwds)
1106 {
1107 static char *kwlist[] = {"object", "provided", "name", "default", NULL};
1108 PyObject *object, *provided, *name=NULL, *default_=NULL;
1109
1110 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1111 &object, &provided, &name, &default_))
1112 return NULL;
1113
1114 return _adapter_hook(self, provided, object, name, default_);
1115 }
1116
1117 /*
1118 def lookupAll(self, required, provided):
1119 cache = self._mcache.get(provided)
1120 if cache is None:
1121 cache = {}
1122 self._mcache[provided] = cache
1123
1124 required = tuple(required)
1125 result = cache.get(required, _not_in_mapping)
1126 if result is _not_in_mapping:
1127 result = self._uncached_lookupAll(required, provided)
1128 cache[required] = result
1129
1130 return result
1131 */
1132 static PyObject *
1133 _lookupAll(lookup *self, PyObject *required, PyObject *provided)
1134 {
1135 PyObject *cache, *result;
1136
1137 ASSURE_DICT(self->_mcache);
1138 cache = _subcache(self->_mcache, provided);
1139 if (cache == NULL)
1140 return NULL;
1141
1142 required = tuplefy(required);
1143 if (required == NULL)
1144 return NULL;
1145
1146 result = PyDict_GetItem(cache, required);
1147 if (result == NULL)
1148 {
1149 int status;
1150
1151 result = PyObject_CallMethodObjArgs(OBJECT(self), str_uncached_lookupAll,
1152 required, provided, NULL);
1153 if (result == NULL)
1154 {
1155 Py_DECREF(required);
1156 return NULL;
1157 }
1158 status = PyDict_SetItem(cache, required, result);
1159 Py_DECREF(required);
1160 if (status < 0)
1161 {
1162 Py_DECREF(result);
1163 return NULL;
1164 }
1165 }
1166 else
1167 {
1168 Py_INCREF(result);
1169 Py_DECREF(required);
1170 }
1171
1172 return result;
1173 }
1174 static PyObject *
1175 lookup_lookupAll(lookup *self, PyObject *args, PyObject *kwds)
1176 {
1177 static char *kwlist[] = {"required", "provided", NULL};
1178 PyObject *required, *provided;
1179
1180 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
1181 &required, &provided))
1182 return NULL;
1183
1184 return _lookupAll(self, required, provided);
1185 }
1186
1187 /*
1188 def subscriptions(self, required, provided):
1189 cache = self._scache.get(provided)
1190 if cache is None:
1191 cache = {}
1192 self._scache[provided] = cache
1193
1194 required = tuple(required)
1195 result = cache.get(required, _not_in_mapping)
1196 if result is _not_in_mapping:
1197 result = self._uncached_subscriptions(required, provided)
1198 cache[required] = result
1199
1200 return result
1201 */
1202 static PyObject *
1203 _subscriptions(lookup *self, PyObject *required, PyObject *provided)
1204 {
1205 PyObject *cache, *result;
1206
1207 ASSURE_DICT(self->_scache);
1208 cache = _subcache(self->_scache, provided);
1209 if (cache == NULL)
1210 return NULL;
1211
1212 required = tuplefy(required);
1213 if (required == NULL)
1214 return NULL;
1215
1216 result = PyDict_GetItem(cache, required);
1217 if (result == NULL)
1218 {
1219 int status;
1220
1221 result = PyObject_CallMethodObjArgs(
1222 OBJECT(self), str_uncached_subscriptions,
1223 required, provided, NULL);
1224 if (result == NULL)
1225 {
1226 Py_DECREF(required);
1227 return NULL;
1228 }
1229 status = PyDict_SetItem(cache, required, result);
1230 Py_DECREF(required);
1231 if (status < 0)
1232 {
1233 Py_DECREF(result);
1234 return NULL;
1235 }
1236 }
1237 else
1238 {
1239 Py_INCREF(result);
1240 Py_DECREF(required);
1241 }
1242
1243 return result;
1244 }
1245 static PyObject *
1246 lookup_subscriptions(lookup *self, PyObject *args, PyObject *kwds)
1247 {
1248 static char *kwlist[] = {"required", "provided", NULL};
1249 PyObject *required, *provided;
1250
1251 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
1252 &required, &provided))
1253 return NULL;
1254
1255 return _subscriptions(self, required, provided);
1256 }
1257
1258 static struct PyMethodDef lookup_methods[] = {
1259 {"changed", (PyCFunction)lookup_changed, METH_O, ""},
1260 {"lookup", (PyCFunction)lookup_lookup, METH_KEYWORDS | METH_VARARGS, ""},
1261 {"lookup1", (PyCFunction)lookup_lookup1, METH_KEYWORDS | METH_VARARGS, ""},
1262 {"queryAdapter", (PyCFunction)lookup_queryAdapter, METH_KEYWORDS | METH_VARARGS, ""},
1263 {"adapter_hook", (PyCFunction)lookup_adapter_hook, METH_KEYWORDS | METH_VARARGS, ""},
1264 {"lookupAll", (PyCFunction)lookup_lookupAll, METH_KEYWORDS | METH_VARARGS, ""},
1265 {"subscriptions", (PyCFunction)lookup_subscriptions, METH_KEYWORDS | METH_VARARGS, ""},
1266 {NULL, NULL} /* sentinel */
1267 };
1268
1269 static PyTypeObject LookupBase = {
1270 PyVarObject_HEAD_INIT(NULL, 0)
1271 /* tp_name */ "_zope_interface_coptimizations."
1272 "LookupBase",
1273 /* tp_basicsize */ sizeof(lookup),
1274 /* tp_itemsize */ 0,
1275 /* tp_dealloc */ (destructor)&lookup_dealloc,
1276 /* tp_print */ (printfunc)0,
1277 /* tp_getattr */ (getattrfunc)0,
1278 /* tp_setattr */ (setattrfunc)0,
1279 /* tp_compare */ 0,
1280 /* tp_repr */ (reprfunc)0,
1281 /* tp_as_number */ 0,
1282 /* tp_as_sequence */ 0,
1283 /* tp_as_mapping */ 0,
1284 /* tp_hash */ (hashfunc)0,
1285 /* tp_call */ (ternaryfunc)0,
1286 /* tp_str */ (reprfunc)0,
1287 /* tp_getattro */ (getattrofunc)0,
1288 /* tp_setattro */ (setattrofunc)0,
1289 /* tp_as_buffer */ 0,
1290 /* tp_flags */ Py_TPFLAGS_DEFAULT
1291 | Py_TPFLAGS_BASETYPE
1292 | Py_TPFLAGS_HAVE_GC,
1293 /* tp_doc */ "",
1294 /* tp_traverse */ (traverseproc)lookup_traverse,
1295 /* tp_clear */ (inquiry)lookup_clear,
1296 /* tp_richcompare */ (richcmpfunc)0,
1297 /* tp_weaklistoffset */ (long)0,
1298 /* tp_iter */ (getiterfunc)0,
1299 /* tp_iternext */ (iternextfunc)0,
1300 /* tp_methods */ lookup_methods,
1301 };
1302
1303 static int
1304 verifying_traverse(verify *self, visitproc visit, void *arg)
1305 {
1306 int vret;
1307
1308 vret = lookup_traverse((lookup *)self, visit, arg);
1309 if (vret != 0)
1310 return vret;
1311
1312 if (self->_verify_ro) {
1313 vret = visit(self->_verify_ro, arg);
1314 if (vret != 0)
1315 return vret;
1316 }
1317 if (self->_verify_generations) {
1318 vret = visit(self->_verify_generations, arg);
1319 if (vret != 0)
1320 return vret;
1321 }
1322
1323 return 0;
1324 }
1325
1326 static int
1327 verifying_clear(verify *self)
1328 {
1329 lookup_clear((lookup *)self);
1330 Py_CLEAR(self->_verify_generations);
1331 Py_CLEAR(self->_verify_ro);
1332 return 0;
1333 }
1334
1335
1336 static void
1337 verifying_dealloc(verify *self)
1338 {
1339 PyObject_GC_UnTrack((PyObject *)self);
1340 verifying_clear(self);
1341 Py_TYPE(self)->tp_free((PyObject*)self);
1342 }
1343
1344 /*
1345 def changed(self, originally_changed):
1346 super(VerifyingBasePy, self).changed(originally_changed)
1347 self._verify_ro = self._registry.ro[1:]
1348 self._verify_generations = [r._generation for r in self._verify_ro]
1349 */
1350 static PyObject *
1351 _generations_tuple(PyObject *ro)
1352 {
1353 int i, l;
1354 PyObject *generations;
1355
1356 l = PyTuple_GET_SIZE(ro);
1357 generations = PyTuple_New(l);
1358 for (i=0; i < l; i++)
1359 {
1360 PyObject *generation;
1361
1362 generation = PyObject_GetAttr(PyTuple_GET_ITEM(ro, i), str_generation);
1363 if (generation == NULL)
1364 {
1365 Py_DECREF(generations);
1366 return NULL;
1367 }
1368 PyTuple_SET_ITEM(generations, i, generation);
1369 }
1370
1371 return generations;
1372 }
1373 static PyObject *
1374 verifying_changed(verify *self, PyObject *ignored)
1375 {
1376 PyObject *t, *ro;
1377
1378 verifying_clear(self);
1379
1380 t = PyObject_GetAttr(OBJECT(self), str_registry);
1381 if (t == NULL)
1382 return NULL;
1383 ro = PyObject_GetAttr(t, strro);
1384 Py_DECREF(t);
1385 if (ro == NULL)
1386 return NULL;
1387
1388 t = PyObject_CallFunctionObjArgs(OBJECT(&PyTuple_Type), ro, NULL);
1389 Py_DECREF(ro);
1390 if (t == NULL)
1391 return NULL;
1392
1393 ro = PyTuple_GetSlice(t, 1, PyTuple_GET_SIZE(t));
1394 Py_DECREF(t);
1395 if (ro == NULL)
1396 return NULL;
1397
1398 self->_verify_generations = _generations_tuple(ro);
1399 if (self->_verify_generations == NULL)
1400 {
1401 Py_DECREF(ro);
1402 return NULL;
1403 }
1404
1405 self->_verify_ro = ro;
1406
1407 Py_INCREF(Py_None);
1408 return Py_None;
1409 }
1410
1411 /*
1412 def _verify(self):
1413 if ([r._generation for r in self._verify_ro]
1414 != self._verify_generations):
1415 self.changed(None)
1416 */
1417 static int
1418 _verify(verify *self)
1419 {
1420 PyObject *changed_result;
1421
1422 if (self->_verify_ro != NULL && self->_verify_generations != NULL)
1423 {
1424 PyObject *generations;
1425 int changed;
1426
1427 generations = _generations_tuple(self->_verify_ro);
1428 if (generations == NULL)
1429 return -1;
1430
1431 changed = PyObject_RichCompareBool(self->_verify_generations,
1432 generations, Py_NE);
1433 Py_DECREF(generations);
1434 if (changed == -1)
1435 return -1;
1436
1437 if (changed == 0)
1438 return 0;
1439 }
1440
1441 changed_result = PyObject_CallMethodObjArgs(OBJECT(self), strchanged,
1442 Py_None, NULL);
1443 if (changed_result == NULL)
1444 return -1;
1445
1446 Py_DECREF(changed_result);
1447 return 0;
1448 }
1449
1450 static PyObject *
1451 verifying_lookup(verify *self, PyObject *args, PyObject *kwds)
1452 {
1453 static char *kwlist[] = {"required", "provided", "name", "default", NULL};
1454 PyObject *required, *provided, *name=NULL, *default_=NULL;
1455
1456 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1457 &required, &provided, &name, &default_))
1458 return NULL;
1459
1460 if (_verify(self) < 0)
1461 return NULL;
1462
1463 return _lookup((lookup *)self, required, provided, name, default_);
1464 }
1465
1466 static PyObject *
1467 verifying_lookup1(verify *self, PyObject *args, PyObject *kwds)
1468 {
1469 static char *kwlist[] = {"required", "provided", "name", "default", NULL};
1470 PyObject *required, *provided, *name=NULL, *default_=NULL;
1471
1472 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1473 &required, &provided, &name, &default_))
1474 return NULL;
1475
1476 if (_verify(self) < 0)
1477 return NULL;
1478
1479 return _lookup1((lookup *)self, required, provided, name, default_);
1480 }
1481
1482 static PyObject *
1483 verifying_adapter_hook(verify *self, PyObject *args, PyObject *kwds)
1484 {
1485 static char *kwlist[] = {"provided", "object", "name", "default", NULL};
1486 PyObject *object, *provided, *name=NULL, *default_=NULL;
1487
1488 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1489 &provided, &object, &name, &default_))
1490 return NULL;
1491
1492 if (_verify(self) < 0)
1493 return NULL;
1494
1495 return _adapter_hook((lookup *)self, provided, object, name, default_);
1496 }
1497
1498 static PyObject *
1499 verifying_queryAdapter(verify *self, PyObject *args, PyObject *kwds)
1500 {
1501 static char *kwlist[] = {"object", "provided", "name", "default", NULL};
1502 PyObject *object, *provided, *name=NULL, *default_=NULL;
1503
1504 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1505 &object, &provided, &name, &default_))
1506 return NULL;
1507
1508 if (_verify(self) < 0)
1509 return NULL;
1510
1511 return _adapter_hook((lookup *)self, provided, object, name, default_);
1512 }
1513
1514 static PyObject *
1515 verifying_lookupAll(verify *self, PyObject *args, PyObject *kwds)
1516 {
1517 static char *kwlist[] = {"required", "provided", NULL};
1518 PyObject *required, *provided;
1519
1520 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
1521 &required, &provided))
1522 return NULL;
1523
1524 if (_verify(self) < 0)
1525 return NULL;
1526
1527 return _lookupAll((lookup *)self, required, provided);
1528 }
1529
1530 static PyObject *
1531 verifying_subscriptions(verify *self, PyObject *args, PyObject *kwds)
1532 {
1533 static char *kwlist[] = {"required", "provided", NULL};
1534 PyObject *required, *provided;
1535
1536 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
1537 &required, &provided))
1538 return NULL;
1539
1540 if (_verify(self) < 0)
1541 return NULL;
1542
1543 return _subscriptions((lookup *)self, required, provided);
1544 }
1545
1546 static struct PyMethodDef verifying_methods[] = {
1547 {"changed", (PyCFunction)verifying_changed, METH_O, ""},
1548 {"lookup", (PyCFunction)verifying_lookup, METH_KEYWORDS | METH_VARARGS, ""},
1549 {"lookup1", (PyCFunction)verifying_lookup1, METH_KEYWORDS | METH_VARARGS, ""},
1550 {"queryAdapter", (PyCFunction)verifying_queryAdapter, METH_KEYWORDS | METH_VARARGS, ""},
1551 {"adapter_hook", (PyCFunction)verifying_adapter_hook, METH_KEYWORDS | METH_VARARGS, ""},
1552 {"lookupAll", (PyCFunction)verifying_lookupAll, METH_KEYWORDS | METH_VARARGS, ""},
1553 {"subscriptions", (PyCFunction)verifying_subscriptions, METH_KEYWORDS | METH_VARARGS, ""},
1554 {NULL, NULL} /* sentinel */
1555 };
1556
1557 static PyTypeObject VerifyingBase = {
1558 PyVarObject_HEAD_INIT(NULL, 0)
1559 /* tp_name */ "_zope_interface_coptimizations."
1560 "VerifyingBase",
1561 /* tp_basicsize */ sizeof(verify),
1562 /* tp_itemsize */ 0,
1563 /* tp_dealloc */ (destructor)&verifying_dealloc,
1564 /* tp_print */ (printfunc)0,
1565 /* tp_getattr */ (getattrfunc)0,
1566 /* tp_setattr */ (setattrfunc)0,
1567 /* tp_compare */ 0,
1568 /* tp_repr */ (reprfunc)0,
1569 /* tp_as_number */ 0,
1570 /* tp_as_sequence */ 0,
1571 /* tp_as_mapping */ 0,
1572 /* tp_hash */ (hashfunc)0,
1573 /* tp_call */ (ternaryfunc)0,
1574 /* tp_str */ (reprfunc)0,
1575 /* tp_getattro */ (getattrofunc)0,
1576 /* tp_setattro */ (setattrofunc)0,
1577 /* tp_as_buffer */ 0,
1578 /* tp_flags */ Py_TPFLAGS_DEFAULT
1579 | Py_TPFLAGS_BASETYPE
1580 | Py_TPFLAGS_HAVE_GC,
1581 /* tp_doc */ "",
1582 /* tp_traverse */ (traverseproc)verifying_traverse,
1583 /* tp_clear */ (inquiry)verifying_clear,
1584 /* tp_richcompare */ (richcmpfunc)0,
1585 /* tp_weaklistoffset */ (long)0,
1586 /* tp_iter */ (getiterfunc)0,
1587 /* tp_iternext */ (iternextfunc)0,
1588 /* tp_methods */ verifying_methods,
1589 /* tp_members */ 0,
1590 /* tp_getset */ 0,
1591 /* tp_base */ &LookupBase,
1592 };
1593
1594 /* ========================== End: Lookup Bases ======================= */
1595 /* ==================================================================== */
1596
1597
1598
1599 static struct PyMethodDef m_methods[] = {
1600 {"implementedBy", (PyCFunction)implementedBy, METH_O,
1601 "Interfaces implemented by a class or factory.\n"
1602 "Raises TypeError if argument is neither a class nor a callable."},
1603 {"getObjectSpecification", (PyCFunction)getObjectSpecification, METH_O,
1604 "Get an object's interfaces (internal api)"},
1605 {"providedBy", (PyCFunction)providedBy, METH_O,
1606 "Get an object's interfaces"},
1607
1608 {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
1609 };
1610
1611 #if PY_MAJOR_VERSION >= 3
1612 static char module_doc[] = "C optimizations for zope.interface\n\n";
1613
1614 static struct PyModuleDef _zic_module = {
1615 PyModuleDef_HEAD_INIT,
1616 "_zope_interface_coptimizations",
1617 module_doc,
1618 -1,
1619 m_methods,
1620 NULL,
1621 NULL,
1622 NULL,
1623 NULL
1624 };
1625 #endif
1626
1627 static PyObject *
1628 init(void)
1629 {
1630 PyObject *m;
1631
1632 #if PY_MAJOR_VERSION < 3
1633 #define DEFINE_STRING(S) \
1634 if(! (str ## S = PyString_FromString(# S))) return NULL
1635 #else
1636 #define DEFINE_STRING(S) \
1637 if(! (str ## S = PyUnicode_FromString(# S))) return NULL
1638 #endif
1639
1640 DEFINE_STRING(__dict__);
1641 DEFINE_STRING(__implemented__);
1642 DEFINE_STRING(__provides__);
1643 DEFINE_STRING(__class__);
1644 DEFINE_STRING(__providedBy__);
1645 DEFINE_STRING(extends);
1646 DEFINE_STRING(_implied);
1647 DEFINE_STRING(_implements);
1648 DEFINE_STRING(_cls);
1649 DEFINE_STRING(__conform__);
1650 DEFINE_STRING(_call_conform);
1651 DEFINE_STRING(_uncached_lookup);
1652 DEFINE_STRING(_uncached_lookupAll);
1653 DEFINE_STRING(_uncached_subscriptions);
1654 DEFINE_STRING(_registry);
1655 DEFINE_STRING(_generation);
1656 DEFINE_STRING(ro);
1657 DEFINE_STRING(changed);
1658 #undef DEFINE_STRING
1659 adapter_hooks = PyList_New(0);
1660 if (adapter_hooks == NULL)
1661 return NULL;
1662
1663 /* Initialize types: */
1664 SpecType.tp_new = PyBaseObject_Type.tp_new;
1665 if (PyType_Ready(&SpecType) < 0)
1666 return NULL;
1667 OSDType.tp_new = PyBaseObject_Type.tp_new;
1668 if (PyType_Ready(&OSDType) < 0)
1669 return NULL;
1670 CPBType.tp_new = PyBaseObject_Type.tp_new;
1671 if (PyType_Ready(&CPBType) < 0)
1672 return NULL;
1673
1674 InterfaceBase.tp_new = PyBaseObject_Type.tp_new;
1675 if (PyType_Ready(&InterfaceBase) < 0)
1676 return NULL;
1677
1678 LookupBase.tp_new = PyBaseObject_Type.tp_new;
1679 if (PyType_Ready(&LookupBase) < 0)
1680 return NULL;
1681
1682 VerifyingBase.tp_new = PyBaseObject_Type.tp_new;
1683 if (PyType_Ready(&VerifyingBase) < 0)
1684 return NULL;
1685
1686 #if PY_MAJOR_VERSION < 3
1687 /* Create the module and add the functions */
1688 m = Py_InitModule3("_zope_interface_coptimizations", m_methods,
1689 "C optimizations for zope.interface\n\n");
1690 #else
1691 m = PyModule_Create(&_zic_module);
1692 #endif
1693 if (m == NULL)
1694 return NULL;
1695
1696 /* Add types: */
1697 if (PyModule_AddObject(m, "SpecificationBase", OBJECT(&SpecType)) < 0)
1698 return NULL;
1699 if (PyModule_AddObject(m, "ObjectSpecificationDescriptor",
1700 (PyObject *)&OSDType) < 0)
1701 return NULL;
1702 if (PyModule_AddObject(m, "ClassProvidesBase", OBJECT(&CPBType)) < 0)
1703 return NULL;
1704 if (PyModule_AddObject(m, "InterfaceBase", OBJECT(&InterfaceBase)) < 0)
1705 return NULL;
1706 if (PyModule_AddObject(m, "LookupBase", OBJECT(&LookupBase)) < 0)
1707 return NULL;
1708 if (PyModule_AddObject(m, "VerifyingBase", OBJECT(&VerifyingBase)) < 0)
1709 return NULL;
1710 if (PyModule_AddObject(m, "adapter_hooks", adapter_hooks) < 0)
1711 return NULL;
1712 return m;
1713 }
1714
1715 PyMODINIT_FUNC
1716 #if PY_MAJOR_VERSION < 3
1717 init_zope_interface_coptimizations(void)
1718 {
1719 init();
1720 }
1721 #else
1722 PyInit__zope_interface_coptimizations(void)
1723 {
1724 return init();
1725 }
1726 #endif
This diff has been collapsed as it changes many lines, (712 lines changed) Show them Hide them
@@ -0,0 +1,712 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2004 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Adapter management
15 """
16 import weakref
17
18 from zope.interface import implementer
19 from zope.interface import providedBy
20 from zope.interface import Interface
21 from zope.interface import ro
22 from zope.interface.interfaces import IAdapterRegistry
23
24 from zope.interface._compat import _normalize_name
25 from zope.interface._compat import STRING_TYPES
26
27 _BLANK = u''
28
29 class BaseAdapterRegistry(object):
30
31 # List of methods copied from lookup sub-objects:
32 _delegated = ('lookup', 'queryMultiAdapter', 'lookup1', 'queryAdapter',
33 'adapter_hook', 'lookupAll', 'names',
34 'subscriptions', 'subscribers')
35
36 # All registries maintain a generation that can be used by verifying
37 # registries
38 _generation = 0
39
40 def __init__(self, bases=()):
41
42 # The comments here could be improved. Possibly this bit needs
43 # explaining in a separate document, as the comments here can
44 # be quite confusing. /regebro
45
46 # {order -> {required -> {provided -> {name -> value}}}}
47 # Here "order" is actually an index in a list, "required" and
48 # "provided" are interfaces, and "required" is really a nested
49 # key. So, for example:
50 # for order == 0 (that is, self._adapters[0]), we have:
51 # {provided -> {name -> value}}
52 # but for order == 2 (that is, self._adapters[2]), we have:
53 # {r1 -> {r2 -> {provided -> {name -> value}}}}
54 #
55 self._adapters = []
56
57 # {order -> {required -> {provided -> {name -> [value]}}}}
58 # where the remarks about adapters above apply
59 self._subscribers = []
60
61 # Set, with a reference count, keeping track of the interfaces
62 # for which we have provided components:
63 self._provided = {}
64
65 # Create ``_v_lookup`` object to perform lookup. We make this a
66 # separate object to to make it easier to implement just the
67 # lookup functionality in C. This object keeps track of cache
68 # invalidation data in two kinds of registries.
69
70 # Invalidating registries have caches that are invalidated
71 # when they or their base registies change. An invalidating
72 # registry can only have invalidating registries as bases.
73 # See LookupBaseFallback below for the pertinent logic.
74
75 # Verifying registies can't rely on getting invalidation messages,
76 # so have to check the generations of base registries to determine
77 # if their cache data are current. See VerifyingBasePy below
78 # for the pertinent object.
79 self._createLookup()
80
81 # Setting the bases causes the registries described above
82 # to be initialized (self._setBases -> self.changed ->
83 # self._v_lookup.changed).
84
85 self.__bases__ = bases
86
87 def _setBases(self, bases):
88 self.__dict__['__bases__'] = bases
89 self.ro = ro.ro(self)
90 self.changed(self)
91
92 __bases__ = property(lambda self: self.__dict__['__bases__'],
93 lambda self, bases: self._setBases(bases),
94 )
95
96 def _createLookup(self):
97 self._v_lookup = self.LookupClass(self)
98 for name in self._delegated:
99 self.__dict__[name] = getattr(self._v_lookup, name)
100
101 def changed(self, originally_changed):
102 self._generation += 1
103 self._v_lookup.changed(originally_changed)
104
105 def register(self, required, provided, name, value):
106 if not isinstance(name, STRING_TYPES):
107 raise ValueError('name is not a string')
108 if value is None:
109 self.unregister(required, provided, name, value)
110 return
111
112 required = tuple(map(_convert_None_to_Interface, required))
113 name = _normalize_name(name)
114 order = len(required)
115 byorder = self._adapters
116 while len(byorder) <= order:
117 byorder.append({})
118 components = byorder[order]
119 key = required + (provided,)
120
121 for k in key:
122 d = components.get(k)
123 if d is None:
124 d = {}
125 components[k] = d
126 components = d
127
128 if components.get(name) is value:
129 return
130
131 components[name] = value
132
133 n = self._provided.get(provided, 0) + 1
134 self._provided[provided] = n
135 if n == 1:
136 self._v_lookup.add_extendor(provided)
137
138 self.changed(self)
139
140 def registered(self, required, provided, name=_BLANK):
141 required = tuple(map(_convert_None_to_Interface, required))
142 name = _normalize_name(name)
143 order = len(required)
144 byorder = self._adapters
145 if len(byorder) <= order:
146 return None
147
148 components = byorder[order]
149 key = required + (provided,)
150
151 for k in key:
152 d = components.get(k)
153 if d is None:
154 return None
155 components = d
156
157 return components.get(name)
158
159 def unregister(self, required, provided, name, value=None):
160 required = tuple(map(_convert_None_to_Interface, required))
161 order = len(required)
162 byorder = self._adapters
163 if order >= len(byorder):
164 return False
165 components = byorder[order]
166 key = required + (provided,)
167
168 # Keep track of how we got to `components`:
169 lookups = []
170 for k in key:
171 d = components.get(k)
172 if d is None:
173 return
174 lookups.append((components, k))
175 components = d
176
177 old = components.get(name)
178 if old is None:
179 return
180 if (value is not None) and (old is not value):
181 return
182
183 del components[name]
184 if not components:
185 # Clean out empty containers, since we don't want our keys
186 # to reference global objects (interfaces) unnecessarily.
187 # This is often a problem when an interface is slated for
188 # removal; a hold-over entry in the registry can make it
189 # difficult to remove such interfaces.
190 for comp, k in reversed(lookups):
191 d = comp[k]
192 if d:
193 break
194 else:
195 del comp[k]
196 while byorder and not byorder[-1]:
197 del byorder[-1]
198 n = self._provided[provided] - 1
199 if n == 0:
200 del self._provided[provided]
201 self._v_lookup.remove_extendor(provided)
202 else:
203 self._provided[provided] = n
204
205 self.changed(self)
206
207 def subscribe(self, required, provided, value):
208 required = tuple(map(_convert_None_to_Interface, required))
209 name = _BLANK
210 order = len(required)
211 byorder = self._subscribers
212 while len(byorder) <= order:
213 byorder.append({})
214 components = byorder[order]
215 key = required + (provided,)
216
217 for k in key:
218 d = components.get(k)
219 if d is None:
220 d = {}
221 components[k] = d
222 components = d
223
224 components[name] = components.get(name, ()) + (value, )
225
226 if provided is not None:
227 n = self._provided.get(provided, 0) + 1
228 self._provided[provided] = n
229 if n == 1:
230 self._v_lookup.add_extendor(provided)
231
232 self.changed(self)
233
234 def unsubscribe(self, required, provided, value=None):
235 required = tuple(map(_convert_None_to_Interface, required))
236 order = len(required)
237 byorder = self._subscribers
238 if order >= len(byorder):
239 return
240 components = byorder[order]
241 key = required + (provided,)
242
243 # Keep track of how we got to `components`:
244 lookups = []
245 for k in key:
246 d = components.get(k)
247 if d is None:
248 return
249 lookups.append((components, k))
250 components = d
251
252 old = components.get(_BLANK)
253 if not old:
254 # this is belt-and-suspenders against the failure of cleanup below
255 return # pragma: no cover
256
257 if value is None:
258 new = ()
259 else:
260 new = tuple([v for v in old if v is not value])
261
262 if new == old:
263 return
264
265 if new:
266 components[_BLANK] = new
267 else:
268 # Instead of setting components[_BLANK] = new, we clean out
269 # empty containers, since we don't want our keys to
270 # reference global objects (interfaces) unnecessarily. This
271 # is often a problem when an interface is slated for
272 # removal; a hold-over entry in the registry can make it
273 # difficult to remove such interfaces.
274 del components[_BLANK]
275 for comp, k in reversed(lookups):
276 d = comp[k]
277 if d:
278 break
279 else:
280 del comp[k]
281 while byorder and not byorder[-1]:
282 del byorder[-1]
283
284 if provided is not None:
285 n = self._provided[provided] + len(new) - len(old)
286 if n == 0:
287 del self._provided[provided]
288 self._v_lookup.remove_extendor(provided)
289
290 self.changed(self)
291
292 # XXX hack to fake out twisted's use of a private api. We need to get them
293 # to use the new registed method.
294 def get(self, _): # pragma: no cover
295 class XXXTwistedFakeOut:
296 selfImplied = {}
297 return XXXTwistedFakeOut
298
299
300 _not_in_mapping = object()
301 class LookupBaseFallback(object):
302
303 def __init__(self):
304 self._cache = {}
305 self._mcache = {}
306 self._scache = {}
307
308 def changed(self, ignored=None):
309 self._cache.clear()
310 self._mcache.clear()
311 self._scache.clear()
312
313 def _getcache(self, provided, name):
314 cache = self._cache.get(provided)
315 if cache is None:
316 cache = {}
317 self._cache[provided] = cache
318 if name:
319 c = cache.get(name)
320 if c is None:
321 c = {}
322 cache[name] = c
323 cache = c
324 return cache
325
326 def lookup(self, required, provided, name=_BLANK, default=None):
327 if not isinstance(name, STRING_TYPES):
328 raise ValueError('name is not a string')
329 cache = self._getcache(provided, name)
330 required = tuple(required)
331 if len(required) == 1:
332 result = cache.get(required[0], _not_in_mapping)
333 else:
334 result = cache.get(tuple(required), _not_in_mapping)
335
336 if result is _not_in_mapping:
337 result = self._uncached_lookup(required, provided, name)
338 if len(required) == 1:
339 cache[required[0]] = result
340 else:
341 cache[tuple(required)] = result
342
343 if result is None:
344 return default
345
346 return result
347
348 def lookup1(self, required, provided, name=_BLANK, default=None):
349 if not isinstance(name, STRING_TYPES):
350 raise ValueError('name is not a string')
351 cache = self._getcache(provided, name)
352 result = cache.get(required, _not_in_mapping)
353 if result is _not_in_mapping:
354 return self.lookup((required, ), provided, name, default)
355
356 if result is None:
357 return default
358
359 return result
360
361 def queryAdapter(self, object, provided, name=_BLANK, default=None):
362 return self.adapter_hook(provided, object, name, default)
363
364 def adapter_hook(self, provided, object, name=_BLANK, default=None):
365 if not isinstance(name, STRING_TYPES):
366 raise ValueError('name is not a string')
367 required = providedBy(object)
368 cache = self._getcache(provided, name)
369 factory = cache.get(required, _not_in_mapping)
370 if factory is _not_in_mapping:
371 factory = self.lookup((required, ), provided, name)
372
373 if factory is not None:
374 result = factory(object)
375 if result is not None:
376 return result
377
378 return default
379
380 def lookupAll(self, required, provided):
381 cache = self._mcache.get(provided)
382 if cache is None:
383 cache = {}
384 self._mcache[provided] = cache
385
386 required = tuple(required)
387 result = cache.get(required, _not_in_mapping)
388 if result is _not_in_mapping:
389 result = self._uncached_lookupAll(required, provided)
390 cache[required] = result
391
392 return result
393
394
395 def subscriptions(self, required, provided):
396 cache = self._scache.get(provided)
397 if cache is None:
398 cache = {}
399 self._scache[provided] = cache
400
401 required = tuple(required)
402 result = cache.get(required, _not_in_mapping)
403 if result is _not_in_mapping:
404 result = self._uncached_subscriptions(required, provided)
405 cache[required] = result
406
407 return result
408
409 LookupBasePy = LookupBaseFallback # BBB
410
411 try:
412 from zope.interface._zope_interface_coptimizations import LookupBase
413 except ImportError:
414 LookupBase = LookupBaseFallback
415
416
417 class VerifyingBaseFallback(LookupBaseFallback):
418 # Mixin for lookups against registries which "chain" upwards, and
419 # whose lookups invalidate their own caches whenever a parent registry
420 # bumps its own '_generation' counter. E.g., used by
421 # zope.component.persistentregistry
422
423 def changed(self, originally_changed):
424 LookupBaseFallback.changed(self, originally_changed)
425 self._verify_ro = self._registry.ro[1:]
426 self._verify_generations = [r._generation for r in self._verify_ro]
427
428 def _verify(self):
429 if ([r._generation for r in self._verify_ro]
430 != self._verify_generations):
431 self.changed(None)
432
433 def _getcache(self, provided, name):
434 self._verify()
435 return LookupBaseFallback._getcache(self, provided, name)
436
437 def lookupAll(self, required, provided):
438 self._verify()
439 return LookupBaseFallback.lookupAll(self, required, provided)
440
441 def subscriptions(self, required, provided):
442 self._verify()
443 return LookupBaseFallback.subscriptions(self, required, provided)
444
445 VerifyingBasePy = VerifyingBaseFallback #BBB
446
447 try:
448 from zope.interface._zope_interface_coptimizations import VerifyingBase
449 except ImportError:
450 VerifyingBase = VerifyingBaseFallback
451
452
453 class AdapterLookupBase(object):
454
455 def __init__(self, registry):
456 self._registry = registry
457 self._required = {}
458 self.init_extendors()
459 super(AdapterLookupBase, self).__init__()
460
461 def changed(self, ignored=None):
462 super(AdapterLookupBase, self).changed(None)
463 for r in self._required.keys():
464 r = r()
465 if r is not None:
466 r.unsubscribe(self)
467 self._required.clear()
468
469
470 # Extendors
471 # ---------
472
473 # When given an target interface for an adapter lookup, we need to consider
474 # adapters for interfaces that extend the target interface. This is
475 # what the extendors dictionary is about. It tells us all of the
476 # interfaces that extend an interface for which there are adapters
477 # registered.
478
479 # We could separate this by order and name, thus reducing the
480 # number of provided interfaces to search at run time. The tradeoff,
481 # however, is that we have to store more information. For example,
482 # if the same interface is provided for multiple names and if the
483 # interface extends many interfaces, we'll have to keep track of
484 # a fair bit of information for each name. It's better to
485 # be space efficient here and be time efficient in the cache
486 # implementation.
487
488 # TODO: add invalidation when a provided interface changes, in case
489 # the interface's __iro__ has changed. This is unlikely enough that
490 # we'll take our chances for now.
491
492 def init_extendors(self):
493 self._extendors = {}
494 for p in self._registry._provided:
495 self.add_extendor(p)
496
497 def add_extendor(self, provided):
498 _extendors = self._extendors
499 for i in provided.__iro__:
500 extendors = _extendors.get(i, ())
501 _extendors[i] = (
502 [e for e in extendors if provided.isOrExtends(e)]
503 +
504 [provided]
505 +
506 [e for e in extendors if not provided.isOrExtends(e)]
507 )
508
509 def remove_extendor(self, provided):
510 _extendors = self._extendors
511 for i in provided.__iro__:
512 _extendors[i] = [e for e in _extendors.get(i, ())
513 if e != provided]
514
515
516 def _subscribe(self, *required):
517 _refs = self._required
518 for r in required:
519 ref = r.weakref()
520 if ref not in _refs:
521 r.subscribe(self)
522 _refs[ref] = 1
523
524 def _uncached_lookup(self, required, provided, name=_BLANK):
525 required = tuple(required)
526 result = None
527 order = len(required)
528 for registry in self._registry.ro:
529 byorder = registry._adapters
530 if order >= len(byorder):
531 continue
532
533 extendors = registry._v_lookup._extendors.get(provided)
534 if not extendors:
535 continue
536
537 components = byorder[order]
538 result = _lookup(components, required, extendors, name, 0,
539 order)
540 if result is not None:
541 break
542
543 self._subscribe(*required)
544
545 return result
546
547 def queryMultiAdapter(self, objects, provided, name=_BLANK, default=None):
548 factory = self.lookup(map(providedBy, objects), provided, name)
549 if factory is None:
550 return default
551
552 result = factory(*objects)
553 if result is None:
554 return default
555
556 return result
557
558 def _uncached_lookupAll(self, required, provided):
559 required = tuple(required)
560 order = len(required)
561 result = {}
562 for registry in reversed(self._registry.ro):
563 byorder = registry._adapters
564 if order >= len(byorder):
565 continue
566 extendors = registry._v_lookup._extendors.get(provided)
567 if not extendors:
568 continue
569 components = byorder[order]
570 _lookupAll(components, required, extendors, result, 0, order)
571
572 self._subscribe(*required)
573
574 return tuple(result.items())
575
576 def names(self, required, provided):
577 return [c[0] for c in self.lookupAll(required, provided)]
578
579 def _uncached_subscriptions(self, required, provided):
580 required = tuple(required)
581 order = len(required)
582 result = []
583 for registry in reversed(self._registry.ro):
584 byorder = registry._subscribers
585 if order >= len(byorder):
586 continue
587
588 if provided is None:
589 extendors = (provided, )
590 else:
591 extendors = registry._v_lookup._extendors.get(provided)
592 if extendors is None:
593 continue
594
595 _subscriptions(byorder[order], required, extendors, _BLANK,
596 result, 0, order)
597
598 self._subscribe(*required)
599
600 return result
601
602 def subscribers(self, objects, provided):
603 subscriptions = self.subscriptions(map(providedBy, objects), provided)
604 if provided is None:
605 result = ()
606 for subscription in subscriptions:
607 subscription(*objects)
608 else:
609 result = []
610 for subscription in subscriptions:
611 subscriber = subscription(*objects)
612 if subscriber is not None:
613 result.append(subscriber)
614 return result
615
616 class AdapterLookup(AdapterLookupBase, LookupBase):
617 pass
618
619 @implementer(IAdapterRegistry)
620 class AdapterRegistry(BaseAdapterRegistry):
621
622 LookupClass = AdapterLookup
623
624 def __init__(self, bases=()):
625 # AdapterRegisties are invalidating registries, so
626 # we need to keep track of out invalidating subregistries.
627 self._v_subregistries = weakref.WeakKeyDictionary()
628
629 super(AdapterRegistry, self).__init__(bases)
630
631 def _addSubregistry(self, r):
632 self._v_subregistries[r] = 1
633
634 def _removeSubregistry(self, r):
635 if r in self._v_subregistries:
636 del self._v_subregistries[r]
637
638 def _setBases(self, bases):
639 old = self.__dict__.get('__bases__', ())
640 for r in old:
641 if r not in bases:
642 r._removeSubregistry(self)
643 for r in bases:
644 if r not in old:
645 r._addSubregistry(self)
646
647 super(AdapterRegistry, self)._setBases(bases)
648
649 def changed(self, originally_changed):
650 super(AdapterRegistry, self).changed(originally_changed)
651
652 for sub in self._v_subregistries.keys():
653 sub.changed(originally_changed)
654
655
656 class VerifyingAdapterLookup(AdapterLookupBase, VerifyingBase):
657 pass
658
659 @implementer(IAdapterRegistry)
660 class VerifyingAdapterRegistry(BaseAdapterRegistry):
661
662 LookupClass = VerifyingAdapterLookup
663
664 def _convert_None_to_Interface(x):
665 if x is None:
666 return Interface
667 else:
668 return x
669
670 def _lookup(components, specs, provided, name, i, l):
671 if i < l:
672 for spec in specs[i].__sro__:
673 comps = components.get(spec)
674 if comps:
675 r = _lookup(comps, specs, provided, name, i+1, l)
676 if r is not None:
677 return r
678 else:
679 for iface in provided:
680 comps = components.get(iface)
681 if comps:
682 r = comps.get(name)
683 if r is not None:
684 return r
685
686 return None
687
688 def _lookupAll(components, specs, provided, result, i, l):
689 if i < l:
690 for spec in reversed(specs[i].__sro__):
691 comps = components.get(spec)
692 if comps:
693 _lookupAll(comps, specs, provided, result, i+1, l)
694 else:
695 for iface in reversed(provided):
696 comps = components.get(iface)
697 if comps:
698 result.update(comps)
699
700 def _subscriptions(components, specs, provided, name, result, i, l):
701 if i < l:
702 for spec in reversed(specs[i].__sro__):
703 comps = components.get(spec)
704 if comps:
705 _subscriptions(comps, specs, provided, name, result, i+1, l)
706 else:
707 for iface in reversed(provided):
708 comps = components.get(iface)
709 if comps:
710 comps = comps.get(name)
711 if comps:
712 result.extend(comps)
@@ -0,0 +1,205 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2003 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Class advice.
15
16 This module was adapted from 'protocols.advice', part of the Python
17 Enterprise Application Kit (PEAK). Please notify the PEAK authors
18 (pje@telecommunity.com and tsarna@sarna.org) if bugs are found or
19 Zope-specific changes are required, so that the PEAK version of this module
20 can be kept in sync.
21
22 PEAK is a Python application framework that interoperates with (but does
23 not require) Zope 3 and Twisted. It provides tools for manipulating UML
24 models, object-relational persistence, aspect-oriented programming, and more.
25 Visit the PEAK home page at http://peak.telecommunity.com for more information.
26 """
27
28 from types import FunctionType
29 try:
30 from types import ClassType
31 except ImportError:
32 __python3 = True
33 else:
34 __python3 = False
35
36 import sys
37
38 def getFrameInfo(frame):
39 """Return (kind,module,locals,globals) for a frame
40
41 'kind' is one of "exec", "module", "class", "function call", or "unknown".
42 """
43
44 f_locals = frame.f_locals
45 f_globals = frame.f_globals
46
47 sameNamespace = f_locals is f_globals
48 hasModule = '__module__' in f_locals
49 hasName = '__name__' in f_globals
50
51 sameName = hasModule and hasName
52 sameName = sameName and f_globals['__name__']==f_locals['__module__']
53
54 module = hasName and sys.modules.get(f_globals['__name__']) or None
55
56 namespaceIsModule = module and module.__dict__ is f_globals
57
58 if not namespaceIsModule:
59 # some kind of funky exec
60 kind = "exec"
61 elif sameNamespace and not hasModule:
62 kind = "module"
63 elif sameName and not sameNamespace:
64 kind = "class"
65 elif not sameNamespace:
66 kind = "function call"
67 else: # pragma: no cover
68 # How can you have f_locals is f_globals, and have '__module__' set?
69 # This is probably module-level code, but with a '__module__' variable.
70 kind = "unknown"
71 return kind, module, f_locals, f_globals
72
73
74 def addClassAdvisor(callback, depth=2):
75 """Set up 'callback' to be passed the containing class upon creation
76
77 This function is designed to be called by an "advising" function executed
78 in a class suite. The "advising" function supplies a callback that it
79 wishes to have executed when the containing class is created. The
80 callback will be given one argument: the newly created containing class.
81 The return value of the callback will be used in place of the class, so
82 the callback should return the input if it does not wish to replace the
83 class.
84
85 The optional 'depth' argument to this function determines the number of
86 frames between this function and the targeted class suite. 'depth'
87 defaults to 2, since this skips this function's frame and one calling
88 function frame. If you use this function from a function called directly
89 in the class suite, the default will be correct, otherwise you will need
90 to determine the correct depth yourself.
91
92 This function works by installing a special class factory function in
93 place of the '__metaclass__' of the containing class. Therefore, only
94 callbacks *after* the last '__metaclass__' assignment in the containing
95 class will be executed. Be sure that classes using "advising" functions
96 declare any '__metaclass__' *first*, to ensure all callbacks are run."""
97 # This entire approach is invalid under Py3K. Don't even try to fix
98 # the coverage for this block there. :(
99 if __python3: # pragma: no cover
100 raise TypeError('Class advice impossible in Python3')
101
102 frame = sys._getframe(depth)
103 kind, module, caller_locals, caller_globals = getFrameInfo(frame)
104
105 # This causes a problem when zope interfaces are used from doctest.
106 # In these cases, kind == "exec".
107 #
108 #if kind != "class":
109 # raise SyntaxError(
110 # "Advice must be in the body of a class statement"
111 # )
112
113 previousMetaclass = caller_locals.get('__metaclass__')
114 if __python3: # pragma: no cover
115 defaultMetaclass = caller_globals.get('__metaclass__', type)
116 else:
117 defaultMetaclass = caller_globals.get('__metaclass__', ClassType)
118
119
120 def advise(name, bases, cdict):
121
122 if '__metaclass__' in cdict:
123 del cdict['__metaclass__']
124
125 if previousMetaclass is None:
126 if bases:
127 # find best metaclass or use global __metaclass__ if no bases
128 meta = determineMetaclass(bases)
129 else:
130 meta = defaultMetaclass
131
132 elif isClassAdvisor(previousMetaclass):
133 # special case: we can't compute the "true" metaclass here,
134 # so we need to invoke the previous metaclass and let it
135 # figure it out for us (and apply its own advice in the process)
136 meta = previousMetaclass
137
138 else:
139 meta = determineMetaclass(bases, previousMetaclass)
140
141 newClass = meta(name,bases,cdict)
142
143 # this lets the callback replace the class completely, if it wants to
144 return callback(newClass)
145
146 # introspection data only, not used by inner function
147 advise.previousMetaclass = previousMetaclass
148 advise.callback = callback
149
150 # install the advisor
151 caller_locals['__metaclass__'] = advise
152
153
154 def isClassAdvisor(ob):
155 """True if 'ob' is a class advisor function"""
156 return isinstance(ob,FunctionType) and hasattr(ob,'previousMetaclass')
157
158
159 def determineMetaclass(bases, explicit_mc=None):
160 """Determine metaclass from 1+ bases and optional explicit __metaclass__"""
161
162 meta = [getattr(b,'__class__',type(b)) for b in bases]
163
164 if explicit_mc is not None:
165 # The explicit metaclass needs to be verified for compatibility
166 # as well, and allowed to resolve the incompatible bases, if any
167 meta.append(explicit_mc)
168
169 if len(meta)==1:
170 # easy case
171 return meta[0]
172
173 candidates = minimalBases(meta) # minimal set of metaclasses
174
175 if not candidates: # pragma: no cover
176 # they're all "classic" classes
177 assert(not __python3) # This should not happen under Python 3
178 return ClassType
179
180 elif len(candidates)>1:
181 # We could auto-combine, but for now we won't...
182 raise TypeError("Incompatible metatypes",bases)
183
184 # Just one, return it
185 return candidates[0]
186
187
188 def minimalBases(classes):
189 """Reduce a list of base classes to its ordered minimum equivalent"""
190
191 if not __python3: # pragma: no cover
192 classes = [c for c in classes if c is not ClassType]
193 candidates = []
194
195 for m in classes:
196 for n in classes:
197 if issubclass(n,m) and m is not n:
198 break
199 else:
200 # m has no subclasses in 'classes'
201 if m in candidates:
202 candidates.remove(m) # ensure that we're later in the list
203 candidates.append(m)
204
205 return candidates
@@ -0,0 +1,2 b''
1 #
2 # This file is necessary to make this directory a package.
This diff has been collapsed as it changes many lines, (575 lines changed) Show them Hide them
@@ -0,0 +1,575 b''
1 ##############################################################################
2 # Copyright (c) 2002 Zope Foundation and Contributors.
3 # All Rights Reserved.
4 #
5 # This software is subject to the provisions of the Zope Public License,
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # FOR A PARTICULAR PURPOSE.
11 ##############################################################################
12 """Datetime interfaces.
13
14 This module is called idatetime because if it were called datetime the import
15 of the real datetime would fail.
16 """
17
18 from zope.interface import Interface, Attribute
19 from zope.interface import classImplements
20
21 from datetime import timedelta, date, datetime, time, tzinfo
22
23
24 class ITimeDeltaClass(Interface):
25 """This is the timedelta class interface."""
26
27 min = Attribute("The most negative timedelta object")
28
29 max = Attribute("The most positive timedelta object")
30
31 resolution = Attribute(
32 "The smallest difference between non-equal timedelta objects")
33
34
35 class ITimeDelta(ITimeDeltaClass):
36 """Represent the difference between two datetime objects.
37
38 Supported operators:
39
40 - add, subtract timedelta
41 - unary plus, minus, abs
42 - compare to timedelta
43 - multiply, divide by int/long
44
45 In addition, datetime supports subtraction of two datetime objects
46 returning a timedelta, and addition or subtraction of a datetime
47 and a timedelta giving a datetime.
48
49 Representation: (days, seconds, microseconds).
50 """
51
52 days = Attribute("Days between -999999999 and 999999999 inclusive")
53
54 seconds = Attribute("Seconds between 0 and 86399 inclusive")
55
56 microseconds = Attribute("Microseconds between 0 and 999999 inclusive")
57
58
59 class IDateClass(Interface):
60 """This is the date class interface."""
61
62 min = Attribute("The earliest representable date")
63
64 max = Attribute("The latest representable date")
65
66 resolution = Attribute(
67 "The smallest difference between non-equal date objects")
68
69 def today():
70 """Return the current local time.
71
72 This is equivalent to date.fromtimestamp(time.time())"""
73
74 def fromtimestamp(timestamp):
75 """Return the local date from a POSIX timestamp (like time.time())
76
77 This may raise ValueError, if the timestamp is out of the range of
78 values supported by the platform C localtime() function. It's common
79 for this to be restricted to years from 1970 through 2038. Note that
80 on non-POSIX systems that include leap seconds in their notion of a
81 timestamp, leap seconds are ignored by fromtimestamp().
82 """
83
84 def fromordinal(ordinal):
85 """Return the date corresponding to the proleptic Gregorian ordinal.
86
87 January 1 of year 1 has ordinal 1. ValueError is raised unless
88 1 <= ordinal <= date.max.toordinal().
89 For any date d, date.fromordinal(d.toordinal()) == d.
90 """
91
92
93 class IDate(IDateClass):
94 """Represents a date (year, month and day) in an idealized calendar.
95
96 Operators:
97
98 __repr__, __str__
99 __cmp__, __hash__
100 __add__, __radd__, __sub__ (add/radd only with timedelta arg)
101 """
102
103 year = Attribute("Between MINYEAR and MAXYEAR inclusive.")
104
105 month = Attribute("Between 1 and 12 inclusive")
106
107 day = Attribute(
108 "Between 1 and the number of days in the given month of the given year.")
109
110 def replace(year, month, day):
111 """Return a date with the same value.
112
113 Except for those members given new values by whichever keyword
114 arguments are specified. For example, if d == date(2002, 12, 31), then
115 d.replace(day=26) == date(2000, 12, 26).
116 """
117
118 def timetuple():
119 """Return a 9-element tuple of the form returned by time.localtime().
120
121 The hours, minutes and seconds are 0, and the DST flag is -1.
122 d.timetuple() is equivalent to
123 (d.year, d.month, d.day, 0, 0, 0, d.weekday(), d.toordinal() -
124 date(d.year, 1, 1).toordinal() + 1, -1)
125 """
126
127 def toordinal():
128 """Return the proleptic Gregorian ordinal of the date
129
130 January 1 of year 1 has ordinal 1. For any date object d,
131 date.fromordinal(d.toordinal()) == d.
132 """
133
134 def weekday():
135 """Return the day of the week as an integer.
136
137 Monday is 0 and Sunday is 6. For example,
138 date(2002, 12, 4).weekday() == 2, a Wednesday.
139
140 See also isoweekday().
141 """
142
143 def isoweekday():
144 """Return the day of the week as an integer.
145
146 Monday is 1 and Sunday is 7. For example,
147 date(2002, 12, 4).isoweekday() == 3, a Wednesday.
148
149 See also weekday(), isocalendar().
150 """
151
152 def isocalendar():
153 """Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
154
155 The ISO calendar is a widely used variant of the Gregorian calendar.
156 See http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm for a good
157 explanation.
158
159 The ISO year consists of 52 or 53 full weeks, and where a week starts
160 on a Monday and ends on a Sunday. The first week of an ISO year is the
161 first (Gregorian) calendar week of a year containing a Thursday. This
162 is called week number 1, and the ISO year of that Thursday is the same
163 as its Gregorian year.
164
165 For example, 2004 begins on a Thursday, so the first week of ISO year
166 2004 begins on Monday, 29 Dec 2003 and ends on Sunday, 4 Jan 2004, so
167 that date(2003, 12, 29).isocalendar() == (2004, 1, 1) and
168 date(2004, 1, 4).isocalendar() == (2004, 1, 7).
169 """
170
171 def isoformat():
172 """Return a string representing the date in ISO 8601 format.
173
174 This is 'YYYY-MM-DD'.
175 For example, date(2002, 12, 4).isoformat() == '2002-12-04'.
176 """
177
178 def __str__():
179 """For a date d, str(d) is equivalent to d.isoformat()."""
180
181 def ctime():
182 """Return a string representing the date.
183
184 For example date(2002, 12, 4).ctime() == 'Wed Dec 4 00:00:00 2002'.
185 d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple()))
186 on platforms where the native C ctime() function
187 (which time.ctime() invokes, but which date.ctime() does not invoke)
188 conforms to the C standard.
189 """
190
191 def strftime(format):
192 """Return a string representing the date.
193
194 Controlled by an explicit format string. Format codes referring to
195 hours, minutes or seconds will see 0 values.
196 """
197
198
199 class IDateTimeClass(Interface):
200 """This is the datetime class interface."""
201
202 min = Attribute("The earliest representable datetime")
203
204 max = Attribute("The latest representable datetime")
205
206 resolution = Attribute(
207 "The smallest possible difference between non-equal datetime objects")
208
209 def today():
210 """Return the current local datetime, with tzinfo None.
211
212 This is equivalent to datetime.fromtimestamp(time.time()).
213 See also now(), fromtimestamp().
214 """
215
216 def now(tz=None):
217 """Return the current local date and time.
218
219 If optional argument tz is None or not specified, this is like today(),
220 but, if possible, supplies more precision than can be gotten from going
221 through a time.time() timestamp (for example, this may be possible on
222 platforms supplying the C gettimeofday() function).
223
224 Else tz must be an instance of a class tzinfo subclass, and the current
225 date and time are converted to tz's time zone. In this case the result
226 is equivalent to tz.fromutc(datetime.utcnow().replace(tzinfo=tz)).
227
228 See also today(), utcnow().
229 """
230
231 def utcnow():
232 """Return the current UTC date and time, with tzinfo None.
233
234 This is like now(), but returns the current UTC date and time, as a
235 naive datetime object.
236
237 See also now().
238 """
239
240 def fromtimestamp(timestamp, tz=None):
241 """Return the local date and time corresponding to the POSIX timestamp.
242
243 Same as is returned by time.time(). If optional argument tz is None or
244 not specified, the timestamp is converted to the platform's local date
245 and time, and the returned datetime object is naive.
246
247 Else tz must be an instance of a class tzinfo subclass, and the
248 timestamp is converted to tz's time zone. In this case the result is
249 equivalent to
250 tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz)).
251
252 fromtimestamp() may raise ValueError, if the timestamp is out of the
253 range of values supported by the platform C localtime() or gmtime()
254 functions. It's common for this to be restricted to years in 1970
255 through 2038. Note that on non-POSIX systems that include leap seconds
256 in their notion of a timestamp, leap seconds are ignored by
257 fromtimestamp(), and then it's possible to have two timestamps
258 differing by a second that yield identical datetime objects.
259
260 See also utcfromtimestamp().
261 """
262
263 def utcfromtimestamp(timestamp):
264 """Return the UTC datetime from the POSIX timestamp with tzinfo None.
265
266 This may raise ValueError, if the timestamp is out of the range of
267 values supported by the platform C gmtime() function. It's common for
268 this to be restricted to years in 1970 through 2038.
269
270 See also fromtimestamp().
271 """
272
273 def fromordinal(ordinal):
274 """Return the datetime from the proleptic Gregorian ordinal.
275
276 January 1 of year 1 has ordinal 1. ValueError is raised unless
277 1 <= ordinal <= datetime.max.toordinal().
278 The hour, minute, second and microsecond of the result are all 0, and
279 tzinfo is None.
280 """
281
282 def combine(date, time):
283 """Return a new datetime object.
284
285 Its date members are equal to the given date object's, and whose time
286 and tzinfo members are equal to the given time object's. For any
287 datetime object d, d == datetime.combine(d.date(), d.timetz()).
288 If date is a datetime object, its time and tzinfo members are ignored.
289 """
290
291
292 class IDateTime(IDate, IDateTimeClass):
293 """Object contains all the information from a date object and a time object.
294 """
295
296 year = Attribute("Year between MINYEAR and MAXYEAR inclusive")
297
298 month = Attribute("Month between 1 and 12 inclusive")
299
300 day = Attribute(
301 "Day between 1 and the number of days in the given month of the year")
302
303 hour = Attribute("Hour in range(24)")
304
305 minute = Attribute("Minute in range(60)")
306
307 second = Attribute("Second in range(60)")
308
309 microsecond = Attribute("Microsecond in range(1000000)")
310
311 tzinfo = Attribute(
312 """The object passed as the tzinfo argument to the datetime constructor
313 or None if none was passed""")
314
315 def date():
316 """Return date object with same year, month and day."""
317
318 def time():
319 """Return time object with same hour, minute, second, microsecond.
320
321 tzinfo is None. See also method timetz().
322 """
323
324 def timetz():
325 """Return time object with same hour, minute, second, microsecond,
326 and tzinfo.
327
328 See also method time().
329 """
330
331 def replace(year, month, day, hour, minute, second, microsecond, tzinfo):
332 """Return a datetime with the same members, except for those members
333 given new values by whichever keyword arguments are specified.
334
335 Note that tzinfo=None can be specified to create a naive datetime from
336 an aware datetime with no conversion of date and time members.
337 """
338
339 def astimezone(tz):
340 """Return a datetime object with new tzinfo member tz, adjusting the
341 date and time members so the result is the same UTC time as self, but
342 in tz's local time.
343
344 tz must be an instance of a tzinfo subclass, and its utcoffset() and
345 dst() methods must not return None. self must be aware (self.tzinfo
346 must not be None, and self.utcoffset() must not return None).
347
348 If self.tzinfo is tz, self.astimezone(tz) is equal to self: no
349 adjustment of date or time members is performed. Else the result is
350 local time in time zone tz, representing the same UTC time as self:
351 after astz = dt.astimezone(tz), astz - astz.utcoffset()
352 will usually have the same date and time members as dt - dt.utcoffset().
353 The discussion of class tzinfo explains the cases at Daylight Saving
354 Time transition boundaries where this cannot be achieved (an issue only
355 if tz models both standard and daylight time).
356
357 If you merely want to attach a time zone object tz to a datetime dt
358 without adjustment of date and time members, use dt.replace(tzinfo=tz).
359 If you merely want to remove the time zone object from an aware
360 datetime dt without conversion of date and time members, use
361 dt.replace(tzinfo=None).
362
363 Note that the default tzinfo.fromutc() method can be overridden in a
364 tzinfo subclass to effect the result returned by astimezone().
365 """
366
367 def utcoffset():
368 """Return the timezone offset in minutes east of UTC (negative west of
369 UTC)."""
370
371 def dst():
372 """Return 0 if DST is not in effect, or the DST offset (in minutes
373 eastward) if DST is in effect.
374 """
375
376 def tzname():
377 """Return the timezone name."""
378
379 def timetuple():
380 """Return a 9-element tuple of the form returned by time.localtime()."""
381
382 def utctimetuple():
383 """Return UTC time tuple compatilble with time.gmtimr()."""
384
385 def toordinal():
386 """Return the proleptic Gregorian ordinal of the date.
387
388 The same as self.date().toordinal().
389 """
390
391 def weekday():
392 """Return the day of the week as an integer.
393
394 Monday is 0 and Sunday is 6. The same as self.date().weekday().
395 See also isoweekday().
396 """
397
398 def isoweekday():
399 """Return the day of the week as an integer.
400
401 Monday is 1 and Sunday is 7. The same as self.date().isoweekday.
402 See also weekday(), isocalendar().
403 """
404
405 def isocalendar():
406 """Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
407
408 The same as self.date().isocalendar().
409 """
410
411 def isoformat(sep='T'):
412 """Return a string representing the date and time in ISO 8601 format.
413
414 YYYY-MM-DDTHH:MM:SS.mmmmmm or YYYY-MM-DDTHH:MM:SS if microsecond is 0
415
416 If utcoffset() does not return None, a 6-character string is appended,
417 giving the UTC offset in (signed) hours and minutes:
418
419 YYYY-MM-DDTHH:MM:SS.mmmmmm+HH:MM or YYYY-MM-DDTHH:MM:SS+HH:MM
420 if microsecond is 0.
421
422 The optional argument sep (default 'T') is a one-character separator,
423 placed between the date and time portions of the result.
424 """
425
426 def __str__():
427 """For a datetime instance d, str(d) is equivalent to d.isoformat(' ').
428 """
429
430 def ctime():
431 """Return a string representing the date and time.
432
433 datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'.
434 d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple())) on
435 platforms where the native C ctime() function (which time.ctime()
436 invokes, but which datetime.ctime() does not invoke) conforms to the
437 C standard.
438 """
439
440 def strftime(format):
441 """Return a string representing the date and time.
442
443 This is controlled by an explicit format string.
444 """
445
446
447 class ITimeClass(Interface):
448 """This is the time class interface."""
449
450 min = Attribute("The earliest representable time")
451
452 max = Attribute("The latest representable time")
453
454 resolution = Attribute(
455 "The smallest possible difference between non-equal time objects")
456
457
458 class ITime(ITimeClass):
459 """Represent time with time zone.
460
461 Operators:
462
463 __repr__, __str__
464 __cmp__, __hash__
465 """
466
467 hour = Attribute("Hour in range(24)")
468
469 minute = Attribute("Minute in range(60)")
470
471 second = Attribute("Second in range(60)")
472
473 microsecond = Attribute("Microsecond in range(1000000)")
474
475 tzinfo = Attribute(
476 """The object passed as the tzinfo argument to the time constructor
477 or None if none was passed.""")
478
479 def replace(hour, minute, second, microsecond, tzinfo):
480 """Return a time with the same value.
481
482 Except for those members given new values by whichever keyword
483 arguments are specified. Note that tzinfo=None can be specified
484 to create a naive time from an aware time, without conversion of the
485 time members.
486 """
487
488 def isoformat():
489 """Return a string representing the time in ISO 8601 format.
490
491 That is HH:MM:SS.mmmmmm or, if self.microsecond is 0, HH:MM:SS
492 If utcoffset() does not return None, a 6-character string is appended,
493 giving the UTC offset in (signed) hours and minutes:
494 HH:MM:SS.mmmmmm+HH:MM or, if self.microsecond is 0, HH:MM:SS+HH:MM
495 """
496
497 def __str__():
498 """For a time t, str(t) is equivalent to t.isoformat()."""
499
500 def strftime(format):
501 """Return a string representing the time.
502
503 This is controlled by an explicit format string.
504 """
505
506 def utcoffset():
507 """Return the timezone offset in minutes east of UTC (negative west of
508 UTC).
509
510 If tzinfo is None, returns None, else returns
511 self.tzinfo.utcoffset(None), and raises an exception if the latter
512 doesn't return None or a timedelta object representing a whole number
513 of minutes with magnitude less than one day.
514 """
515
516 def dst():
517 """Return 0 if DST is not in effect, or the DST offset (in minutes
518 eastward) if DST is in effect.
519
520 If tzinfo is None, returns None, else returns self.tzinfo.dst(None),
521 and raises an exception if the latter doesn't return None, or a
522 timedelta object representing a whole number of minutes with
523 magnitude less than one day.
524 """
525
526 def tzname():
527 """Return the timezone name.
528
529 If tzinfo is None, returns None, else returns self.tzinfo.tzname(None),
530 or raises an exception if the latter doesn't return None or a string
531 object.
532 """
533
534
535 class ITZInfo(Interface):
536 """Time zone info class.
537 """
538
539 def utcoffset(dt):
540 """Return offset of local time from UTC, in minutes east of UTC.
541
542 If local time is west of UTC, this should be negative.
543 Note that this is intended to be the total offset from UTC;
544 for example, if a tzinfo object represents both time zone and DST
545 adjustments, utcoffset() should return their sum. If the UTC offset
546 isn't known, return None. Else the value returned must be a timedelta
547 object specifying a whole number of minutes in the range -1439 to 1439
548 inclusive (1440 = 24*60; the magnitude of the offset must be less
549 than one day).
550 """
551
552 def dst(dt):
553 """Return the daylight saving time (DST) adjustment, in minutes east
554 of UTC, or None if DST information isn't known.
555 """
556
557 def tzname(dt):
558 """Return the time zone name corresponding to the datetime object as
559 a string.
560 """
561
562 def fromutc(dt):
563 """Return an equivalent datetime in self's local time."""
564
565
566 classImplements(timedelta, ITimeDelta)
567 classImplements(date, IDate)
568 classImplements(datetime, IDateTime)
569 classImplements(time, ITime)
570 classImplements(tzinfo, ITZInfo)
571
572 ## directlyProvides(timedelta, ITimeDeltaClass)
573 ## directlyProvides(date, IDateClass)
574 ## directlyProvides(datetime, IDateTimeClass)
575 ## directlyProvides(time, ITimeClass)
@@ -0,0 +1,102 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2003 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Interfaces for standard python exceptions
15 """
16 from zope.interface import Interface
17 from zope.interface import classImplements
18
19 class IException(Interface): pass
20 class IStandardError(IException): pass
21 class IWarning(IException): pass
22 class ISyntaxError(IStandardError): pass
23 class ILookupError(IStandardError): pass
24 class IValueError(IStandardError): pass
25 class IRuntimeError(IStandardError): pass
26 class IArithmeticError(IStandardError): pass
27 class IAssertionError(IStandardError): pass
28 class IAttributeError(IStandardError): pass
29 class IDeprecationWarning(IWarning): pass
30 class IEOFError(IStandardError): pass
31 class IEnvironmentError(IStandardError): pass
32 class IFloatingPointError(IArithmeticError): pass
33 class IIOError(IEnvironmentError): pass
34 class IImportError(IStandardError): pass
35 class IIndentationError(ISyntaxError): pass
36 class IIndexError(ILookupError): pass
37 class IKeyError(ILookupError): pass
38 class IKeyboardInterrupt(IStandardError): pass
39 class IMemoryError(IStandardError): pass
40 class INameError(IStandardError): pass
41 class INotImplementedError(IRuntimeError): pass
42 class IOSError(IEnvironmentError): pass
43 class IOverflowError(IArithmeticError): pass
44 class IOverflowWarning(IWarning): pass
45 class IReferenceError(IStandardError): pass
46 class IRuntimeWarning(IWarning): pass
47 class IStopIteration(IException): pass
48 class ISyntaxWarning(IWarning): pass
49 class ISystemError(IStandardError): pass
50 class ISystemExit(IException): pass
51 class ITabError(IIndentationError): pass
52 class ITypeError(IStandardError): pass
53 class IUnboundLocalError(INameError): pass
54 class IUnicodeError(IValueError): pass
55 class IUserWarning(IWarning): pass
56 class IZeroDivisionError(IArithmeticError): pass
57
58 classImplements(ArithmeticError, IArithmeticError)
59 classImplements(AssertionError, IAssertionError)
60 classImplements(AttributeError, IAttributeError)
61 classImplements(DeprecationWarning, IDeprecationWarning)
62 classImplements(EnvironmentError, IEnvironmentError)
63 classImplements(EOFError, IEOFError)
64 classImplements(Exception, IException)
65 classImplements(FloatingPointError, IFloatingPointError)
66 classImplements(ImportError, IImportError)
67 classImplements(IndentationError, IIndentationError)
68 classImplements(IndexError, IIndexError)
69 classImplements(IOError, IIOError)
70 classImplements(KeyboardInterrupt, IKeyboardInterrupt)
71 classImplements(KeyError, IKeyError)
72 classImplements(LookupError, ILookupError)
73 classImplements(MemoryError, IMemoryError)
74 classImplements(NameError, INameError)
75 classImplements(NotImplementedError, INotImplementedError)
76 classImplements(OSError, IOSError)
77 classImplements(OverflowError, IOverflowError)
78 try:
79 classImplements(OverflowWarning, IOverflowWarning)
80 except NameError: #pragma NO COVER
81 pass # OverflowWarning was removed in Python 2.5
82 classImplements(ReferenceError, IReferenceError)
83 classImplements(RuntimeError, IRuntimeError)
84 classImplements(RuntimeWarning, IRuntimeWarning)
85 try:
86 classImplements(StandardError, IStandardError)
87 except NameError: #pragma NO COVER
88 pass # StandardError does not exist in Python 3
89 classImplements(StopIteration, IStopIteration)
90 classImplements(SyntaxError, ISyntaxError)
91 classImplements(SyntaxWarning, ISyntaxWarning)
92 classImplements(SystemError, ISystemError)
93 classImplements(SystemExit, ISystemExit)
94 classImplements(TabError, ITabError)
95 classImplements(TypeError, ITypeError)
96 classImplements(UnboundLocalError, IUnboundLocalError)
97 classImplements(UnicodeError, IUnicodeError)
98 classImplements(UserWarning, IUserWarning)
99 classImplements(ValueError, IValueError)
100 classImplements(Warning, IWarning)
101 classImplements(ZeroDivisionError, IZeroDivisionError)
102
@@ -0,0 +1,125 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Mapping Interfaces
15 """
16 from zope.interface import Interface
17
18 class IItemMapping(Interface):
19 """Simplest readable mapping object
20 """
21
22 def __getitem__(key):
23 """Get a value for a key
24
25 A KeyError is raised if there is no value for the key.
26 """
27
28
29 class IReadMapping(IItemMapping):
30 """Basic mapping interface
31 """
32
33 def get(key, default=None):
34 """Get a value for a key
35
36 The default is returned if there is no value for the key.
37 """
38
39 def __contains__(key):
40 """Tell if a key exists in the mapping."""
41
42
43 class IWriteMapping(Interface):
44 """Mapping methods for changing data"""
45
46 def __delitem__(key):
47 """Delete a value from the mapping using the key."""
48
49 def __setitem__(key, value):
50 """Set a new item in the mapping."""
51
52
53 class IEnumerableMapping(IReadMapping):
54 """Mapping objects whose items can be enumerated.
55 """
56
57 def keys():
58 """Return the keys of the mapping object.
59 """
60
61 def __iter__():
62 """Return an iterator for the keys of the mapping object.
63 """
64
65 def values():
66 """Return the values of the mapping object.
67 """
68
69 def items():
70 """Return the items of the mapping object.
71 """
72
73 def __len__():
74 """Return the number of items.
75 """
76
77 class IMapping(IWriteMapping, IEnumerableMapping):
78 ''' Simple mapping interface '''
79
80 class IIterableMapping(IEnumerableMapping):
81
82 def iterkeys():
83 "iterate over keys; equivalent to __iter__"
84
85 def itervalues():
86 "iterate over values"
87
88 def iteritems():
89 "iterate over items"
90
91 class IClonableMapping(Interface):
92
93 def copy():
94 "return copy of dict"
95
96 class IExtendedReadMapping(IIterableMapping):
97
98 def has_key(key):
99 """Tell if a key exists in the mapping; equivalent to __contains__"""
100
101 class IExtendedWriteMapping(IWriteMapping):
102
103 def clear():
104 "delete all items"
105
106 def update(d):
107 " Update D from E: for k in E.keys(): D[k] = E[k]"
108
109 def setdefault(key, default=None):
110 "D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D"
111
112 def pop(k, *args):
113 """remove specified key and return the corresponding value
114 *args may contain a single default value, or may not be supplied.
115 If key is not found, default is returned if given, otherwise
116 KeyError is raised"""
117
118 def popitem():
119 """remove and return some (key, value) pair as a
120 2-tuple; but raise KeyError if mapping is empty"""
121
122 class IFullMapping(
123 IExtendedReadMapping, IExtendedWriteMapping, IClonableMapping, IMapping):
124 ''' Full mapping interface ''' # IMapping included so tests for IMapping
125 # succeed with IFullMapping
@@ -0,0 +1,160 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Sequence Interfaces
15 """
16 __docformat__ = 'restructuredtext'
17 from zope.interface import Interface
18
19 class IMinimalSequence(Interface):
20 """Most basic sequence interface.
21
22 All sequences are iterable. This requires at least one of the
23 following:
24
25 - a `__getitem__()` method that takes a single argument; interger
26 values starting at 0 must be supported, and `IndexError` should
27 be raised for the first index for which there is no value, or
28
29 - an `__iter__()` method that returns an iterator as defined in
30 the Python documentation (http://docs.python.org/lib/typeiter.html).
31
32 """
33
34 def __getitem__(index):
35 """`x.__getitem__(index)` <==> `x[index]`
36
37 Declaring this interface does not specify whether `__getitem__`
38 supports slice objects."""
39
40 class IFiniteSequence(IMinimalSequence):
41
42 def __len__():
43 """`x.__len__()` <==> `len(x)`"""
44
45 class IReadSequence(IFiniteSequence):
46 """read interface shared by tuple and list"""
47
48 def __contains__(item):
49 """`x.__contains__(item)` <==> `item in x`"""
50
51 def __lt__(other):
52 """`x.__lt__(other)` <==> `x < other`"""
53
54 def __le__(other):
55 """`x.__le__(other)` <==> `x <= other`"""
56
57 def __eq__(other):
58 """`x.__eq__(other)` <==> `x == other`"""
59
60 def __ne__(other):
61 """`x.__ne__(other)` <==> `x != other`"""
62
63 def __gt__(other):
64 """`x.__gt__(other)` <==> `x > other`"""
65
66 def __ge__(other):
67 """`x.__ge__(other)` <==> `x >= other`"""
68
69 def __add__(other):
70 """`x.__add__(other)` <==> `x + other`"""
71
72 def __mul__(n):
73 """`x.__mul__(n)` <==> `x * n`"""
74
75 def __rmul__(n):
76 """`x.__rmul__(n)` <==> `n * x`"""
77
78 def __getslice__(i, j):
79 """`x.__getslice__(i, j)` <==> `x[i:j]`
80
81 Use of negative indices is not supported.
82
83 Deprecated since Python 2.0 but still a part of `UserList`.
84 """
85
86 class IExtendedReadSequence(IReadSequence):
87 """Full read interface for lists"""
88
89 def count(item):
90 """Return number of occurrences of value"""
91
92 def index(item, *args):
93 """Return first index of value
94
95 `L.index(value, [start, [stop]])` -> integer"""
96
97 class IUniqueMemberWriteSequence(Interface):
98 """The write contract for a sequence that may enforce unique members"""
99
100 def __setitem__(index, item):
101 """`x.__setitem__(index, item)` <==> `x[index] = item`
102
103 Declaring this interface does not specify whether `__setitem__`
104 supports slice objects.
105 """
106
107 def __delitem__(index):
108 """`x.__delitem__(index)` <==> `del x[index]`
109
110 Declaring this interface does not specify whether `__delitem__`
111 supports slice objects.
112 """
113
114 def __setslice__(i, j, other):
115 """`x.__setslice__(i, j, other)` <==> `x[i:j]=other`
116
117 Use of negative indices is not supported.
118
119 Deprecated since Python 2.0 but still a part of `UserList`.
120 """
121
122 def __delslice__(i, j):
123 """`x.__delslice__(i, j)` <==> `del x[i:j]`
124
125 Use of negative indices is not supported.
126
127 Deprecated since Python 2.0 but still a part of `UserList`.
128 """
129 def __iadd__(y):
130 """`x.__iadd__(y)` <==> `x += y`"""
131
132 def append(item):
133 """Append item to end"""
134
135 def insert(index, item):
136 """Insert item before index"""
137
138 def pop(index=-1):
139 """Remove and return item at index (default last)"""
140
141 def remove(item):
142 """Remove first occurrence of value"""
143
144 def reverse():
145 """Reverse *IN PLACE*"""
146
147 def sort(cmpfunc=None):
148 """Stable sort *IN PLACE*; `cmpfunc(x, y)` -> -1, 0, 1"""
149
150 def extend(iterable):
151 """Extend list by appending elements from the iterable"""
152
153 class IWriteSequence(IUniqueMemberWriteSequence):
154 """Full write contract for sequences"""
155
156 def __imul__(n):
157 """`x.__imul__(n)` <==> `x *= n`"""
158
159 class ISequence(IReadSequence, IWriteSequence):
160 """Full sequence contract"""
This diff has been collapsed as it changes many lines, (929 lines changed) Show them Hide them
@@ -0,0 +1,929 b''
1 ##############################################################################
2 # Copyright (c) 2003 Zope Foundation and Contributors.
3 # All Rights Reserved.
4 #
5 # This software is subject to the provisions of the Zope Public License,
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # FOR A PARTICULAR PURPOSE.
11 ##############################################################################
12 """Implementation of interface declarations
13
14 There are three flavors of declarations:
15
16 - Declarations are used to simply name declared interfaces.
17
18 - ImplementsDeclarations are used to express the interfaces that a
19 class implements (that instances of the class provides).
20
21 Implements specifications support inheriting interfaces.
22
23 - ProvidesDeclarations are used to express interfaces directly
24 provided by objects.
25
26 """
27 __docformat__ = 'restructuredtext'
28
29 import sys
30 from types import FunctionType
31 from types import MethodType
32 from types import ModuleType
33 import weakref
34
35 from zope.interface.advice import addClassAdvisor
36 from zope.interface.interface import InterfaceClass
37 from zope.interface.interface import SpecificationBase
38 from zope.interface.interface import Specification
39 from zope.interface._compat import CLASS_TYPES as DescriptorAwareMetaClasses
40 from zope.interface._compat import PYTHON3
41
42 # Registry of class-implementation specifications
43 BuiltinImplementationSpecifications = {}
44
45 _ADVICE_ERROR = ('Class advice impossible in Python3. '
46 'Use the @%s class decorator instead.')
47
48 _ADVICE_WARNING = ('The %s API is deprecated, and will not work in Python3 '
49 'Use the @%s class decorator instead.')
50
51 class named(object):
52
53 def __init__(self, name):
54 self.name = name
55
56 def __call__(self, ob):
57 ob.__component_name__ = self.name
58 return ob
59
60 class Declaration(Specification):
61 """Interface declarations"""
62
63 def __init__(self, *interfaces):
64 Specification.__init__(self, _normalizeargs(interfaces))
65
66 def changed(self, originally_changed):
67 Specification.changed(self, originally_changed)
68 try:
69 del self._v_attrs
70 except AttributeError:
71 pass
72
73 def __contains__(self, interface):
74 """Test whether an interface is in the specification
75 """
76
77 return self.extends(interface) and interface in self.interfaces()
78
79 def __iter__(self):
80 """Return an iterator for the interfaces in the specification
81 """
82 return self.interfaces()
83
84 def flattened(self):
85 """Return an iterator of all included and extended interfaces
86 """
87 return iter(self.__iro__)
88
89 def __sub__(self, other):
90 """Remove interfaces from a specification
91 """
92 return Declaration(
93 *[i for i in self.interfaces()
94 if not [j for j in other.interfaces()
95 if i.extends(j, 0)]
96 ]
97 )
98
99 def __add__(self, other):
100 """Add two specifications or a specification and an interface
101 """
102 seen = {}
103 result = []
104 for i in self.interfaces():
105 seen[i] = 1
106 result.append(i)
107 for i in other.interfaces():
108 if i not in seen:
109 seen[i] = 1
110 result.append(i)
111
112 return Declaration(*result)
113
114 __radd__ = __add__
115
116
117 ##############################################################################
118 #
119 # Implementation specifications
120 #
121 # These specify interfaces implemented by instances of classes
122
123 class Implements(Declaration):
124
125 # class whose specification should be used as additional base
126 inherit = None
127
128 # interfaces actually declared for a class
129 declared = ()
130
131 __name__ = '?'
132
133 @classmethod
134 def named(cls, name, *interfaces):
135 # Implementation method: Produce an Implements interface with
136 # a fully fleshed out __name__ before calling the constructor, which
137 # sets bases to the given interfaces and which may pass this object to
138 # other objects (e.g., to adjust dependents). If they're sorting or comparing
139 # by name, this needs to be set.
140 inst = cls.__new__(cls)
141 inst.__name__ = name
142 inst.__init__(*interfaces)
143 return inst
144
145 def __repr__(self):
146 return '<implementedBy %s>' % (self.__name__)
147
148 def __reduce__(self):
149 return implementedBy, (self.inherit, )
150
151 def __cmp(self, other):
152 # Yes, I did mean to name this __cmp, rather than __cmp__.
153 # It is a private method used by __lt__ and __gt__.
154 # This is based on, and compatible with, InterfaceClass.
155 # (The two must be mutually comparable to be able to work in e.g., BTrees.)
156 # Instances of this class generally don't have a __module__ other than
157 # `zope.interface.declarations`, whereas they *do* have a __name__ that is the
158 # fully qualified name of the object they are representing.
159
160 # Note, though, that equality and hashing are still identity based. This
161 # accounts for things like nested objects that have the same name (typically
162 # only in tests) and is consistent with pickling. As far as comparisons to InterfaceClass
163 # goes, we'll never have equal name and module to those, so we're still consistent there.
164 # Instances of this class are essentially intended to be unique and are
165 # heavily cached (note how our __reduce__ handles this) so having identity
166 # based hash and eq should also work.
167 if other is None:
168 return -1
169
170 n1 = (self.__name__, self.__module__)
171 n2 = (getattr(other, '__name__', ''), getattr(other, '__module__', ''))
172
173 # This spelling works under Python3, which doesn't have cmp().
174 return (n1 > n2) - (n1 < n2)
175
176 def __hash__(self):
177 return Declaration.__hash__(self)
178
179 # We want equality to be based on identity. However, we can't actually
180 # implement __eq__/__ne__ to do this because sometimes we get wrapped in a proxy.
181 # We need to let the proxy types implement these methods so they can handle unwrapping
182 # and then rely on: (1) the interpreter automatically changing `implements == proxy` into
183 # `proxy == implements` (which will call proxy.__eq__ to do the unwrapping) and then
184 # (2) the default equality semantics being identity based.
185
186 def __lt__(self, other):
187 c = self.__cmp(other)
188 return c < 0
189
190 def __le__(self, other):
191 c = self.__cmp(other)
192 return c <= 0
193
194 def __gt__(self, other):
195 c = self.__cmp(other)
196 return c > 0
197
198 def __ge__(self, other):
199 c = self.__cmp(other)
200 return c >= 0
201
202 def _implements_name(ob):
203 # Return the __name__ attribute to be used by its __implemented__
204 # property.
205 # This must be stable for the "same" object across processes
206 # because it is used for sorting. It needn't be unique, though, in cases
207 # like nested classes named Foo created by different functions, because
208 # equality and hashing is still based on identity.
209 # It might be nice to use __qualname__ on Python 3, but that would produce
210 # different values between Py2 and Py3.
211 return (getattr(ob, '__module__', '?') or '?') + \
212 '.' + (getattr(ob, '__name__', '?') or '?')
213
214 def implementedByFallback(cls):
215 """Return the interfaces implemented for a class' instances
216
217 The value returned is an IDeclaration.
218 """
219 try:
220 spec = cls.__dict__.get('__implemented__')
221 except AttributeError:
222
223 # we can't get the class dict. This is probably due to a
224 # security proxy. If this is the case, then probably no
225 # descriptor was installed for the class.
226
227 # We don't want to depend directly on zope.security in
228 # zope.interface, but we'll try to make reasonable
229 # accommodations in an indirect way.
230
231 # We'll check to see if there's an implements:
232
233 spec = getattr(cls, '__implemented__', None)
234 if spec is None:
235 # There's no spec stred in the class. Maybe its a builtin:
236 spec = BuiltinImplementationSpecifications.get(cls)
237 if spec is not None:
238 return spec
239 return _empty
240
241 if spec.__class__ == Implements:
242 # we defaulted to _empty or there was a spec. Good enough.
243 # Return it.
244 return spec
245
246 # TODO: need old style __implements__ compatibility?
247 # Hm, there's an __implemented__, but it's not a spec. Must be
248 # an old-style declaration. Just compute a spec for it
249 return Declaration(*_normalizeargs((spec, )))
250
251 if isinstance(spec, Implements):
252 return spec
253
254 if spec is None:
255 spec = BuiltinImplementationSpecifications.get(cls)
256 if spec is not None:
257 return spec
258
259 # TODO: need old style __implements__ compatibility?
260 spec_name = _implements_name(cls)
261 if spec is not None:
262 # old-style __implemented__ = foo declaration
263 spec = (spec, ) # tuplefy, as it might be just an int
264 spec = Implements.named(spec_name, *_normalizeargs(spec))
265 spec.inherit = None # old-style implies no inherit
266 del cls.__implemented__ # get rid of the old-style declaration
267 else:
268 try:
269 bases = cls.__bases__
270 except AttributeError:
271 if not callable(cls):
272 raise TypeError("ImplementedBy called for non-factory", cls)
273 bases = ()
274
275 spec = Implements.named(spec_name, *[implementedBy(c) for c in bases])
276 spec.inherit = cls
277
278 try:
279 cls.__implemented__ = spec
280 if not hasattr(cls, '__providedBy__'):
281 cls.__providedBy__ = objectSpecificationDescriptor
282
283 if (isinstance(cls, DescriptorAwareMetaClasses)
284 and
285 '__provides__' not in cls.__dict__):
286 # Make sure we get a __provides__ descriptor
287 cls.__provides__ = ClassProvides(
288 cls,
289 getattr(cls, '__class__', type(cls)),
290 )
291
292 except TypeError:
293 if not isinstance(cls, type):
294 raise TypeError("ImplementedBy called for non-type", cls)
295 BuiltinImplementationSpecifications[cls] = spec
296
297 return spec
298
299 implementedBy = implementedByFallback
300
301 def classImplementsOnly(cls, *interfaces):
302 """Declare the only interfaces implemented by instances of a class
303
304 The arguments after the class are one or more interfaces or interface
305 specifications (``IDeclaration`` objects).
306
307 The interfaces given (including the interfaces in the specifications)
308 replace any previous declarations.
309 """
310 spec = implementedBy(cls)
311 spec.declared = ()
312 spec.inherit = None
313 classImplements(cls, *interfaces)
314
315 def classImplements(cls, *interfaces):
316 """Declare additional interfaces implemented for instances of a class
317
318 The arguments after the class are one or more interfaces or
319 interface specifications (``IDeclaration`` objects).
320
321 The interfaces given (including the interfaces in the specifications)
322 are added to any interfaces previously declared.
323 """
324 spec = implementedBy(cls)
325 spec.declared += tuple(_normalizeargs(interfaces))
326
327 # compute the bases
328 bases = []
329 seen = {}
330 for b in spec.declared:
331 if b not in seen:
332 seen[b] = 1
333 bases.append(b)
334
335 if spec.inherit is not None:
336
337 for c in spec.inherit.__bases__:
338 b = implementedBy(c)
339 if b not in seen:
340 seen[b] = 1
341 bases.append(b)
342
343 spec.__bases__ = tuple(bases)
344
345 def _implements_advice(cls):
346 interfaces, classImplements = cls.__dict__['__implements_advice_data__']
347 del cls.__implements_advice_data__
348 classImplements(cls, *interfaces)
349 return cls
350
351
352 class implementer:
353 """Declare the interfaces implemented by instances of a class.
354
355 This function is called as a class decorator.
356
357 The arguments are one or more interfaces or interface
358 specifications (IDeclaration objects).
359
360 The interfaces given (including the interfaces in the
361 specifications) are added to any interfaces previously
362 declared.
363
364 Previous declarations include declarations for base classes
365 unless implementsOnly was used.
366
367 This function is provided for convenience. It provides a more
368 convenient way to call classImplements. For example::
369
370 @implementer(I1)
371 class C(object):
372 pass
373
374 is equivalent to calling::
375
376 classImplements(C, I1)
377
378 after the class has been created.
379 """
380
381 def __init__(self, *interfaces):
382 self.interfaces = interfaces
383
384 def __call__(self, ob):
385 if isinstance(ob, DescriptorAwareMetaClasses):
386 classImplements(ob, *self.interfaces)
387 return ob
388
389 spec_name = _implements_name(ob)
390 spec = Implements.named(spec_name, *self.interfaces)
391 try:
392 ob.__implemented__ = spec
393 except AttributeError:
394 raise TypeError("Can't declare implements", ob)
395 return ob
396
397 class implementer_only:
398 """Declare the only interfaces implemented by instances of a class
399
400 This function is called as a class decorator.
401
402 The arguments are one or more interfaces or interface
403 specifications (IDeclaration objects).
404
405 Previous declarations including declarations for base classes
406 are overridden.
407
408 This function is provided for convenience. It provides a more
409 convenient way to call classImplementsOnly. For example::
410
411 @implementer_only(I1)
412 class C(object): pass
413
414 is equivalent to calling::
415
416 classImplementsOnly(I1)
417
418 after the class has been created.
419 """
420
421 def __init__(self, *interfaces):
422 self.interfaces = interfaces
423
424 def __call__(self, ob):
425 if isinstance(ob, (FunctionType, MethodType)):
426 # XXX Does this decorator make sense for anything but classes?
427 # I don't think so. There can be no inheritance of interfaces
428 # on a method pr function....
429 raise ValueError('The implementer_only decorator is not '
430 'supported for methods or functions.')
431 else:
432 # Assume it's a class:
433 classImplementsOnly(ob, *self.interfaces)
434 return ob
435
436 def _implements(name, interfaces, classImplements):
437 # This entire approach is invalid under Py3K. Don't even try to fix
438 # the coverage for this block there. :(
439 frame = sys._getframe(2)
440 locals = frame.f_locals
441
442 # Try to make sure we were called from a class def. In 2.2.0 we can't
443 # check for __module__ since it doesn't seem to be added to the locals
444 # until later on.
445 if locals is frame.f_globals or '__module__' not in locals:
446 raise TypeError(name+" can be used only from a class definition.")
447
448 if '__implements_advice_data__' in locals:
449 raise TypeError(name+" can be used only once in a class definition.")
450
451 locals['__implements_advice_data__'] = interfaces, classImplements
452 addClassAdvisor(_implements_advice, depth=3)
453
454 def implements(*interfaces):
455 """Declare interfaces implemented by instances of a class
456
457 This function is called in a class definition.
458
459 The arguments are one or more interfaces or interface
460 specifications (IDeclaration objects).
461
462 The interfaces given (including the interfaces in the
463 specifications) are added to any interfaces previously
464 declared.
465
466 Previous declarations include declarations for base classes
467 unless implementsOnly was used.
468
469 This function is provided for convenience. It provides a more
470 convenient way to call classImplements. For example::
471
472 implements(I1)
473
474 is equivalent to calling::
475
476 classImplements(C, I1)
477
478 after the class has been created.
479 """
480 # This entire approach is invalid under Py3K. Don't even try to fix
481 # the coverage for this block there. :(
482 if PYTHON3:
483 raise TypeError(_ADVICE_ERROR % 'implementer')
484 _implements("implements", interfaces, classImplements)
485
486 def implementsOnly(*interfaces):
487 """Declare the only interfaces implemented by instances of a class
488
489 This function is called in a class definition.
490
491 The arguments are one or more interfaces or interface
492 specifications (IDeclaration objects).
493
494 Previous declarations including declarations for base classes
495 are overridden.
496
497 This function is provided for convenience. It provides a more
498 convenient way to call classImplementsOnly. For example::
499
500 implementsOnly(I1)
501
502 is equivalent to calling::
503
504 classImplementsOnly(I1)
505
506 after the class has been created.
507 """
508 # This entire approach is invalid under Py3K. Don't even try to fix
509 # the coverage for this block there. :(
510 if PYTHON3:
511 raise TypeError(_ADVICE_ERROR % 'implementer_only')
512 _implements("implementsOnly", interfaces, classImplementsOnly)
513
514 ##############################################################################
515 #
516 # Instance declarations
517
518 class Provides(Declaration): # Really named ProvidesClass
519 """Implement __provides__, the instance-specific specification
520
521 When an object is pickled, we pickle the interfaces that it implements.
522 """
523
524 def __init__(self, cls, *interfaces):
525 self.__args = (cls, ) + interfaces
526 self._cls = cls
527 Declaration.__init__(self, *(interfaces + (implementedBy(cls), )))
528
529 def __reduce__(self):
530 return Provides, self.__args
531
532 __module__ = 'zope.interface'
533
534 def __get__(self, inst, cls):
535 """Make sure that a class __provides__ doesn't leak to an instance
536 """
537 if inst is None and cls is self._cls:
538 # We were accessed through a class, so we are the class'
539 # provides spec. Just return this object, but only if we are
540 # being called on the same class that we were defined for:
541 return self
542
543 raise AttributeError('__provides__')
544
545 ProvidesClass = Provides
546
547 # Registry of instance declarations
548 # This is a memory optimization to allow objects to share specifications.
549 InstanceDeclarations = weakref.WeakValueDictionary()
550
551 def Provides(*interfaces):
552 """Cache instance declarations
553
554 Instance declarations are shared among instances that have the same
555 declaration. The declarations are cached in a weak value dictionary.
556 """
557 spec = InstanceDeclarations.get(interfaces)
558 if spec is None:
559 spec = ProvidesClass(*interfaces)
560 InstanceDeclarations[interfaces] = spec
561
562 return spec
563
564 Provides.__safe_for_unpickling__ = True
565
566
567 def directlyProvides(object, *interfaces):
568 """Declare interfaces declared directly for an object
569
570 The arguments after the object are one or more interfaces or interface
571 specifications (``IDeclaration`` objects).
572
573 The interfaces given (including the interfaces in the specifications)
574 replace interfaces previously declared for the object.
575 """
576 cls = getattr(object, '__class__', None)
577 if cls is not None and getattr(cls, '__class__', None) is cls:
578 # It's a meta class (well, at least it it could be an extension class)
579 # Note that we can't get here from Py3k tests: there is no normal
580 # class which isn't descriptor aware.
581 if not isinstance(object,
582 DescriptorAwareMetaClasses):
583 raise TypeError("Attempt to make an interface declaration on a "
584 "non-descriptor-aware class")
585
586 interfaces = _normalizeargs(interfaces)
587 if cls is None:
588 cls = type(object)
589
590 issub = False
591 for damc in DescriptorAwareMetaClasses:
592 if issubclass(cls, damc):
593 issub = True
594 break
595 if issub:
596 # we have a class or type. We'll use a special descriptor
597 # that provides some extra caching
598 object.__provides__ = ClassProvides(object, cls, *interfaces)
599 else:
600 object.__provides__ = Provides(cls, *interfaces)
601
602
603 def alsoProvides(object, *interfaces):
604 """Declare interfaces declared directly for an object
605
606 The arguments after the object are one or more interfaces or interface
607 specifications (``IDeclaration`` objects).
608
609 The interfaces given (including the interfaces in the specifications) are
610 added to the interfaces previously declared for the object.
611 """
612 directlyProvides(object, directlyProvidedBy(object), *interfaces)
613
614 def noLongerProvides(object, interface):
615 """ Removes a directly provided interface from an object.
616 """
617 directlyProvides(object, directlyProvidedBy(object) - interface)
618 if interface.providedBy(object):
619 raise ValueError("Can only remove directly provided interfaces.")
620
621 class ClassProvidesBaseFallback(object):
622
623 def __get__(self, inst, cls):
624 if cls is self._cls:
625 # We only work if called on the class we were defined for
626
627 if inst is None:
628 # We were accessed through a class, so we are the class'
629 # provides spec. Just return this object as is:
630 return self
631
632 return self._implements
633
634 raise AttributeError('__provides__')
635
636 ClassProvidesBasePy = ClassProvidesBaseFallback # BBB
637 ClassProvidesBase = ClassProvidesBaseFallback
638
639 # Try to get C base:
640 try:
641 import zope.interface._zope_interface_coptimizations
642 except ImportError:
643 pass
644 else:
645 from zope.interface._zope_interface_coptimizations import ClassProvidesBase
646
647
648 class ClassProvides(Declaration, ClassProvidesBase):
649 """Special descriptor for class __provides__
650
651 The descriptor caches the implementedBy info, so that
652 we can get declarations for objects without instance-specific
653 interfaces a bit quicker.
654 """
655 def __init__(self, cls, metacls, *interfaces):
656 self._cls = cls
657 self._implements = implementedBy(cls)
658 self.__args = (cls, metacls, ) + interfaces
659 Declaration.__init__(self, *(interfaces + (implementedBy(metacls), )))
660
661 def __reduce__(self):
662 return self.__class__, self.__args
663
664 # Copy base-class method for speed
665 __get__ = ClassProvidesBase.__get__
666
667 def directlyProvidedBy(object):
668 """Return the interfaces directly provided by the given object
669
670 The value returned is an ``IDeclaration``.
671 """
672 provides = getattr(object, "__provides__", None)
673 if (provides is None # no spec
674 or
675 # We might have gotten the implements spec, as an
676 # optimization. If so, it's like having only one base, that we
677 # lop off to exclude class-supplied declarations:
678 isinstance(provides, Implements)
679 ):
680 return _empty
681
682 # Strip off the class part of the spec:
683 return Declaration(provides.__bases__[:-1])
684
685 def classProvides(*interfaces):
686 """Declare interfaces provided directly by a class
687
688 This function is called in a class definition.
689
690 The arguments are one or more interfaces or interface specifications
691 (``IDeclaration`` objects).
692
693 The given interfaces (including the interfaces in the specifications)
694 are used to create the class's direct-object interface specification.
695 An error will be raised if the module class has an direct interface
696 specification. In other words, it is an error to call this function more
697 than once in a class definition.
698
699 Note that the given interfaces have nothing to do with the interfaces
700 implemented by instances of the class.
701
702 This function is provided for convenience. It provides a more convenient
703 way to call directlyProvides for a class. For example::
704
705 classProvides(I1)
706
707 is equivalent to calling::
708
709 directlyProvides(theclass, I1)
710
711 after the class has been created.
712 """
713 # This entire approach is invalid under Py3K. Don't even try to fix
714 # the coverage for this block there. :(
715
716 if PYTHON3:
717 raise TypeError(_ADVICE_ERROR % 'provider')
718
719 frame = sys._getframe(1)
720 locals = frame.f_locals
721
722 # Try to make sure we were called from a class def
723 if (locals is frame.f_globals) or ('__module__' not in locals):
724 raise TypeError("classProvides can be used only from a "
725 "class definition.")
726
727 if '__provides__' in locals:
728 raise TypeError(
729 "classProvides can only be used once in a class definition.")
730
731 locals["__provides__"] = _normalizeargs(interfaces)
732
733 addClassAdvisor(_classProvides_advice, depth=2)
734
735 def _classProvides_advice(cls):
736 # This entire approach is invalid under Py3K. Don't even try to fix
737 # the coverage for this block there. :(
738 interfaces = cls.__dict__['__provides__']
739 del cls.__provides__
740 directlyProvides(cls, *interfaces)
741 return cls
742
743 class provider:
744 """Class decorator version of classProvides"""
745
746 def __init__(self, *interfaces):
747 self.interfaces = interfaces
748
749 def __call__(self, ob):
750 directlyProvides(ob, *self.interfaces)
751 return ob
752
753 def moduleProvides(*interfaces):
754 """Declare interfaces provided by a module
755
756 This function is used in a module definition.
757
758 The arguments are one or more interfaces or interface specifications
759 (``IDeclaration`` objects).
760
761 The given interfaces (including the interfaces in the specifications) are
762 used to create the module's direct-object interface specification. An
763 error will be raised if the module already has an interface specification.
764 In other words, it is an error to call this function more than once in a
765 module definition.
766
767 This function is provided for convenience. It provides a more convenient
768 way to call directlyProvides. For example::
769
770 moduleImplements(I1)
771
772 is equivalent to::
773
774 directlyProvides(sys.modules[__name__], I1)
775 """
776 frame = sys._getframe(1)
777 locals = frame.f_locals
778
779 # Try to make sure we were called from a class def
780 if (locals is not frame.f_globals) or ('__name__' not in locals):
781 raise TypeError(
782 "moduleProvides can only be used from a module definition.")
783
784 if '__provides__' in locals:
785 raise TypeError(
786 "moduleProvides can only be used once in a module definition.")
787
788 locals["__provides__"] = Provides(ModuleType,
789 *_normalizeargs(interfaces))
790
791 ##############################################################################
792 #
793 # Declaration querying support
794
795 # XXX: is this a fossil? Nobody calls it, no unit tests exercise it, no
796 # doctests import it, and the package __init__ doesn't import it.
797 def ObjectSpecification(direct, cls):
798 """Provide object specifications
799
800 These combine information for the object and for it's classes.
801 """
802 return Provides(cls, direct) # pragma: no cover fossil
803
804 def getObjectSpecificationFallback(ob):
805
806 provides = getattr(ob, '__provides__', None)
807 if provides is not None:
808 if isinstance(provides, SpecificationBase):
809 return provides
810
811 try:
812 cls = ob.__class__
813 except AttributeError:
814 # We can't get the class, so just consider provides
815 return _empty
816
817 return implementedBy(cls)
818
819 getObjectSpecification = getObjectSpecificationFallback
820
821 def providedByFallback(ob):
822
823 # Here we have either a special object, an old-style declaration
824 # or a descriptor
825
826 # Try to get __providedBy__
827 try:
828 r = ob.__providedBy__
829 except AttributeError:
830 # Not set yet. Fall back to lower-level thing that computes it
831 return getObjectSpecification(ob)
832
833 try:
834 # We might have gotten a descriptor from an instance of a
835 # class (like an ExtensionClass) that doesn't support
836 # descriptors. We'll make sure we got one by trying to get
837 # the only attribute, which all specs have.
838 r.extends
839
840 except AttributeError:
841
842 # The object's class doesn't understand descriptors.
843 # Sigh. We need to get an object descriptor, but we have to be
844 # careful. We want to use the instance's __provides__, if
845 # there is one, but only if it didn't come from the class.
846
847 try:
848 r = ob.__provides__
849 except AttributeError:
850 # No __provides__, so just fall back to implementedBy
851 return implementedBy(ob.__class__)
852
853 # We need to make sure we got the __provides__ from the
854 # instance. We'll do this by making sure we don't get the same
855 # thing from the class:
856
857 try:
858 cp = ob.__class__.__provides__
859 except AttributeError:
860 # The ob doesn't have a class or the class has no
861 # provides, assume we're done:
862 return r
863
864 if r is cp:
865 # Oops, we got the provides from the class. This means
866 # the object doesn't have it's own. We should use implementedBy
867 return implementedBy(ob.__class__)
868
869 return r
870 providedBy = providedByFallback
871
872 class ObjectSpecificationDescriptorFallback(object):
873 """Implement the `__providedBy__` attribute
874
875 The `__providedBy__` attribute computes the interfaces peovided by
876 an object.
877 """
878
879 def __get__(self, inst, cls):
880 """Get an object specification for an object
881 """
882 if inst is None:
883 return getObjectSpecification(cls)
884
885 provides = getattr(inst, '__provides__', None)
886 if provides is not None:
887 return provides
888
889 return implementedBy(cls)
890
891 ObjectSpecificationDescriptor = ObjectSpecificationDescriptorFallback
892
893 ##############################################################################
894
895 def _normalizeargs(sequence, output = None):
896 """Normalize declaration arguments
897
898 Normalization arguments might contain Declarions, tuples, or single
899 interfaces.
900
901 Anything but individial interfaces or implements specs will be expanded.
902 """
903 if output is None:
904 output = []
905
906 cls = sequence.__class__
907 if InterfaceClass in cls.__mro__ or Implements in cls.__mro__:
908 output.append(sequence)
909 else:
910 for v in sequence:
911 _normalizeargs(v, output)
912
913 return output
914
915 _empty = Declaration()
916
917 try:
918 import zope.interface._zope_interface_coptimizations
919 except ImportError:
920 pass
921 else:
922 from zope.interface._zope_interface_coptimizations import implementedBy
923 from zope.interface._zope_interface_coptimizations import providedBy
924 from zope.interface._zope_interface_coptimizations import (
925 getObjectSpecification)
926 from zope.interface._zope_interface_coptimizations import (
927 ObjectSpecificationDescriptor)
928
929 objectSpecificationDescriptor = ObjectSpecificationDescriptor()
@@ -0,0 +1,120 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """ Pretty-Print an Interface object as structured text (Yum)
15
16 This module provides a function, asStructuredText, for rendering an
17 interface as structured text.
18 """
19 import zope.interface
20
21
22 def asStructuredText(I, munge=0, rst=False):
23 """ Output structured text format. Note, this will whack any existing
24 'structured' format of the text.
25
26 If `rst=True`, then the output will quote all code as inline literals in
27 accordance with 'reStructuredText' markup principles.
28 """
29
30 if rst:
31 inline_literal = lambda s: "``%s``" % (s,)
32 else:
33 inline_literal = lambda s: s
34
35 r = [inline_literal(I.getName())]
36 outp = r.append
37 level = 1
38
39 if I.getDoc():
40 outp(_justify_and_indent(_trim_doc_string(I.getDoc()), level))
41
42 bases = [base
43 for base in I.__bases__
44 if base is not zope.interface.Interface
45 ]
46 if bases:
47 outp(_justify_and_indent("This interface extends:", level, munge))
48 level += 1
49 for b in bases:
50 item = "o %s" % inline_literal(b.getName())
51 outp(_justify_and_indent(_trim_doc_string(item), level, munge))
52 level -= 1
53
54 namesAndDescriptions = sorted(I.namesAndDescriptions())
55
56 outp(_justify_and_indent("Attributes:", level, munge))
57 level += 1
58 for name, desc in namesAndDescriptions:
59 if not hasattr(desc, 'getSignatureString'): # ugh...
60 item = "%s -- %s" % (inline_literal(desc.getName()),
61 desc.getDoc() or 'no documentation')
62 outp(_justify_and_indent(_trim_doc_string(item), level, munge))
63 level -= 1
64
65 outp(_justify_and_indent("Methods:", level, munge))
66 level += 1
67 for name, desc in namesAndDescriptions:
68 if hasattr(desc, 'getSignatureString'): # ugh...
69 _call = "%s%s" % (desc.getName(), desc.getSignatureString())
70 item = "%s -- %s" % (inline_literal(_call),
71 desc.getDoc() or 'no documentation')
72 outp(_justify_and_indent(_trim_doc_string(item), level, munge))
73
74 return "\n\n".join(r) + "\n\n"
75
76
77 def asReStructuredText(I, munge=0):
78 """ Output reStructuredText format. Note, this will whack any existing
79 'structured' format of the text."""
80 return asStructuredText(I, munge=munge, rst=True)
81
82
83 def _trim_doc_string(text):
84 """ Trims a doc string to make it format
85 correctly with structured text. """
86
87 lines = text.replace('\r\n', '\n').split('\n')
88 nlines = [lines.pop(0)]
89 if lines:
90 min_indent = min([len(line) - len(line.lstrip())
91 for line in lines])
92 for line in lines:
93 nlines.append(line[min_indent:])
94
95 return '\n'.join(nlines)
96
97
98 def _justify_and_indent(text, level, munge=0, width=72):
99 """ indent and justify text, rejustify (munge) if specified """
100
101 indent = " " * level
102
103 if munge:
104 lines = []
105 line = indent
106 text = text.split()
107
108 for word in text:
109 line = ' '.join([line, word])
110 if len(line) > width:
111 lines.append(line)
112 line = indent
113 else:
114 lines.append(line)
115
116 return '\n'.join(lines)
117
118 else:
119 return indent + \
120 text.strip().replace("\r\n", "\n") .replace("\n", "\n" + indent)
@@ -0,0 +1,67 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Interface-specific exceptions
15 """
16
17 class Invalid(Exception):
18 """A specification is violated
19 """
20
21 class DoesNotImplement(Invalid):
22 """ This object does not implement """
23 def __init__(self, interface):
24 self.interface = interface
25
26 def __str__(self):
27 return """An object does not implement interface %(interface)s
28
29 """ % self.__dict__
30
31 class BrokenImplementation(Invalid):
32 """An attribute is not completely implemented.
33 """
34
35 def __init__(self, interface, name):
36 self.interface=interface
37 self.name=name
38
39 def __str__(self):
40 return """An object has failed to implement interface %(interface)s
41
42 The %(name)s attribute was not provided.
43 """ % self.__dict__
44
45 class BrokenMethodImplementation(Invalid):
46 """An method is not completely implemented.
47 """
48
49 def __init__(self, method, mess):
50 self.method=method
51 self.mess=mess
52
53 def __str__(self):
54 return """The implementation of %(method)s violates its contract
55 because %(mess)s.
56 """ % self.__dict__
57
58 class InvalidInterface(Exception):
59 """The interface has invalid contents
60 """
61
62 class BadImplements(TypeError):
63 """An implementation assertion is invalid
64
65 because it doesn't contain an interface or a sequence of valid
66 implementation assertions.
67 """
This diff has been collapsed as it changes many lines, (686 lines changed) Show them Hide them
@@ -0,0 +1,686 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Interface object implementation
15 """
16 from __future__ import generators
17
18 import sys
19 from types import MethodType
20 from types import FunctionType
21 import warnings
22 import weakref
23
24 from zope.interface.exceptions import Invalid
25 from zope.interface.ro import ro
26
27
28 CO_VARARGS = 4
29 CO_VARKEYWORDS = 8
30 TAGGED_DATA = '__interface_tagged_values__'
31
32 _decorator_non_return = object()
33
34 def invariant(call):
35 f_locals = sys._getframe(1).f_locals
36 tags = f_locals.setdefault(TAGGED_DATA, {})
37 invariants = tags.setdefault('invariants', [])
38 invariants.append(call)
39 return _decorator_non_return
40
41
42 def taggedValue(key, value):
43 """Attaches a tagged value to an interface at definition time."""
44 f_locals = sys._getframe(1).f_locals
45 tagged_values = f_locals.setdefault(TAGGED_DATA, {})
46 tagged_values[key] = value
47 return _decorator_non_return
48
49
50 class Element(object):
51
52 # We can't say this yet because we don't have enough
53 # infrastructure in place.
54 #
55 #implements(IElement)
56
57 def __init__(self, __name__, __doc__=''):
58 """Create an 'attribute' description
59 """
60 if not __doc__ and __name__.find(' ') >= 0:
61 __doc__ = __name__
62 __name__ = None
63
64 self.__name__=__name__
65 self.__doc__=__doc__
66 self.__tagged_values = {}
67
68 def getName(self):
69 """ Returns the name of the object. """
70 return self.__name__
71
72 def getDoc(self):
73 """ Returns the documentation for the object. """
74 return self.__doc__
75
76 def getTaggedValue(self, tag):
77 """ Returns the value associated with 'tag'. """
78 return self.__tagged_values[tag]
79
80 def queryTaggedValue(self, tag, default=None):
81 """ Returns the value associated with 'tag'. """
82 return self.__tagged_values.get(tag, default)
83
84 def getTaggedValueTags(self):
85 """ Returns a list of all tags. """
86 return self.__tagged_values.keys()
87
88 def setTaggedValue(self, tag, value):
89 """ Associates 'value' with 'key'. """
90 self.__tagged_values[tag] = value
91
92 class SpecificationBasePy(object):
93
94 def providedBy(self, ob):
95 """Is the interface implemented by an object
96 """
97 spec = providedBy(ob)
98 return self in spec._implied
99
100 def implementedBy(self, cls):
101 """Test whether the specification is implemented by a class or factory.
102
103 Raise TypeError if argument is neither a class nor a callable.
104 """
105 spec = implementedBy(cls)
106 return self in spec._implied
107
108 def isOrExtends(self, interface):
109 """Is the interface the same as or extend the given interface
110 """
111 return interface in self._implied
112
113 __call__ = isOrExtends
114
115 SpecificationBase = SpecificationBasePy
116 try:
117 from zope.interface._zope_interface_coptimizations import SpecificationBase
118 except ImportError:
119 pass
120
121 _marker = object()
122 class InterfaceBasePy(object):
123 """Base class that wants to be replaced with a C base :)
124 """
125
126 def __call__(self, obj, alternate=_marker):
127 """Adapt an object to the interface
128 """
129 conform = getattr(obj, '__conform__', None)
130 if conform is not None:
131 adapter = self._call_conform(conform)
132 if adapter is not None:
133 return adapter
134
135 adapter = self.__adapt__(obj)
136
137 if adapter is not None:
138 return adapter
139 elif alternate is not _marker:
140 return alternate
141 else:
142 raise TypeError("Could not adapt", obj, self)
143
144 def __adapt__(self, obj):
145 """Adapt an object to the reciever
146 """
147 if self.providedBy(obj):
148 return obj
149
150 for hook in adapter_hooks:
151 adapter = hook(self, obj)
152 if adapter is not None:
153 return adapter
154
155
156 InterfaceBase = InterfaceBasePy
157 try:
158 from zope.interface._zope_interface_coptimizations import InterfaceBase
159 except ImportError:
160 pass
161
162
163 adapter_hooks = []
164 try:
165 from zope.interface._zope_interface_coptimizations import adapter_hooks
166 except ImportError:
167 pass
168
169
170 class Specification(SpecificationBase):
171 """Specifications
172
173 An interface specification is used to track interface declarations
174 and component registrations.
175
176 This class is a base class for both interfaces themselves and for
177 interface specifications (declarations).
178
179 Specifications are mutable. If you reassign their bases, their
180 relations with other specifications are adjusted accordingly.
181 """
182
183 # Copy some base class methods for speed
184 isOrExtends = SpecificationBase.isOrExtends
185 providedBy = SpecificationBase.providedBy
186
187 def __init__(self, bases=()):
188 self._implied = {}
189 self.dependents = weakref.WeakKeyDictionary()
190 self.__bases__ = tuple(bases)
191
192 def subscribe(self, dependent):
193 self.dependents[dependent] = self.dependents.get(dependent, 0) + 1
194
195 def unsubscribe(self, dependent):
196 n = self.dependents.get(dependent, 0) - 1
197 if not n:
198 del self.dependents[dependent]
199 elif n > 0:
200 self.dependents[dependent] = n
201 else:
202 raise KeyError(dependent)
203
204 def __setBases(self, bases):
205 # Register ourselves as a dependent of our old bases
206 for b in self.__bases__:
207 b.unsubscribe(self)
208
209 # Register ourselves as a dependent of our bases
210 self.__dict__['__bases__'] = bases
211 for b in bases:
212 b.subscribe(self)
213
214 self.changed(self)
215
216 __bases__ = property(
217
218 lambda self: self.__dict__.get('__bases__', ()),
219 __setBases,
220 )
221
222 def changed(self, originally_changed):
223 """We, or something we depend on, have changed
224 """
225 try:
226 del self._v_attrs
227 except AttributeError:
228 pass
229
230 implied = self._implied
231 implied.clear()
232
233 ancestors = ro(self)
234
235 try:
236 if Interface not in ancestors:
237 ancestors.append(Interface)
238 except NameError:
239 pass # defining Interface itself
240
241 self.__sro__ = tuple(ancestors)
242 self.__iro__ = tuple([ancestor for ancestor in ancestors
243 if isinstance(ancestor, InterfaceClass)
244 ])
245
246 for ancestor in ancestors:
247 # We directly imply our ancestors:
248 implied[ancestor] = ()
249
250 # Now, advise our dependents of change:
251 for dependent in tuple(self.dependents.keys()):
252 dependent.changed(originally_changed)
253
254
255 def interfaces(self):
256 """Return an iterator for the interfaces in the specification.
257 """
258 seen = {}
259 for base in self.__bases__:
260 for interface in base.interfaces():
261 if interface not in seen:
262 seen[interface] = 1
263 yield interface
264
265
266 def extends(self, interface, strict=True):
267 """Does the specification extend the given interface?
268
269 Test whether an interface in the specification extends the
270 given interface
271 """
272 return ((interface in self._implied)
273 and
274 ((not strict) or (self != interface))
275 )
276
277 def weakref(self, callback=None):
278 return weakref.ref(self, callback)
279
280 def get(self, name, default=None):
281 """Query for an attribute description
282 """
283 try:
284 attrs = self._v_attrs
285 except AttributeError:
286 attrs = self._v_attrs = {}
287 attr = attrs.get(name)
288 if attr is None:
289 for iface in self.__iro__:
290 attr = iface.direct(name)
291 if attr is not None:
292 attrs[name] = attr
293 break
294
295 if attr is None:
296 return default
297 else:
298 return attr
299
300 class InterfaceClass(Element, InterfaceBase, Specification):
301 """Prototype (scarecrow) Interfaces Implementation."""
302
303 # We can't say this yet because we don't have enough
304 # infrastructure in place.
305 #
306 #implements(IInterface)
307
308 def __init__(self, name, bases=(), attrs=None, __doc__=None,
309 __module__=None):
310
311 if attrs is None:
312 attrs = {}
313
314 if __module__ is None:
315 __module__ = attrs.get('__module__')
316 if isinstance(__module__, str):
317 del attrs['__module__']
318 else:
319 try:
320 # Figure out what module defined the interface.
321 # This is how cPython figures out the module of
322 # a class, but of course it does it in C. :-/
323 __module__ = sys._getframe(1).f_globals['__name__']
324 except (AttributeError, KeyError): # pragma: no cover
325 pass
326
327 self.__module__ = __module__
328
329 d = attrs.get('__doc__')
330 if d is not None:
331 if not isinstance(d, Attribute):
332 if __doc__ is None:
333 __doc__ = d
334 del attrs['__doc__']
335
336 if __doc__ is None:
337 __doc__ = ''
338
339 Element.__init__(self, name, __doc__)
340
341 tagged_data = attrs.pop(TAGGED_DATA, None)
342 if tagged_data is not None:
343 for key, val in tagged_data.items():
344 self.setTaggedValue(key, val)
345
346 for base in bases:
347 if not isinstance(base, InterfaceClass):
348 raise TypeError('Expected base interfaces')
349
350 Specification.__init__(self, bases)
351
352 # Make sure that all recorded attributes (and methods) are of type
353 # `Attribute` and `Method`
354 for name, attr in list(attrs.items()):
355 if name in ('__locals__', '__qualname__', '__annotations__'):
356 # __locals__: Python 3 sometimes adds this.
357 # __qualname__: PEP 3155 (Python 3.3+)
358 # __annotations__: PEP 3107 (Python 3.0+)
359 del attrs[name]
360 continue
361 if isinstance(attr, Attribute):
362 attr.interface = self
363 if not attr.__name__:
364 attr.__name__ = name
365 elif isinstance(attr, FunctionType):
366 attrs[name] = fromFunction(attr, self, name=name)
367 elif attr is _decorator_non_return:
368 del attrs[name]
369 else:
370 raise InvalidInterface("Concrete attribute, " + name)
371
372 self.__attrs = attrs
373
374 self.__identifier__ = "%s.%s" % (self.__module__, self.__name__)
375
376 def interfaces(self):
377 """Return an iterator for the interfaces in the specification.
378 """
379 yield self
380
381 def getBases(self):
382 return self.__bases__
383
384 def isEqualOrExtendedBy(self, other):
385 """Same interface or extends?"""
386 return self == other or other.extends(self)
387
388 def names(self, all=False):
389 """Return the attribute names defined by the interface."""
390 if not all:
391 return self.__attrs.keys()
392
393 r = self.__attrs.copy()
394
395 for base in self.__bases__:
396 r.update(dict.fromkeys(base.names(all)))
397
398 return r.keys()
399
400 def __iter__(self):
401 return iter(self.names(all=True))
402
403 def namesAndDescriptions(self, all=False):
404 """Return attribute names and descriptions defined by interface."""
405 if not all:
406 return self.__attrs.items()
407
408 r = {}
409 for base in self.__bases__[::-1]:
410 r.update(dict(base.namesAndDescriptions(all)))
411
412 r.update(self.__attrs)
413
414 return r.items()
415
416 def getDescriptionFor(self, name):
417 """Return the attribute description for the given name."""
418 r = self.get(name)
419 if r is not None:
420 return r
421
422 raise KeyError(name)
423
424 __getitem__ = getDescriptionFor
425
426 def __contains__(self, name):
427 return self.get(name) is not None
428
429 def direct(self, name):
430 return self.__attrs.get(name)
431
432 def queryDescriptionFor(self, name, default=None):
433 return self.get(name, default)
434
435 def validateInvariants(self, obj, errors=None):
436 """validate object to defined invariants."""
437 for call in self.queryTaggedValue('invariants', []):
438 try:
439 call(obj)
440 except Invalid as e:
441 if errors is None:
442 raise
443 else:
444 errors.append(e)
445 for base in self.__bases__:
446 try:
447 base.validateInvariants(obj, errors)
448 except Invalid:
449 if errors is None:
450 raise
451 if errors:
452 raise Invalid(errors)
453
454 def __repr__(self): # pragma: no cover
455 try:
456 return self._v_repr
457 except AttributeError:
458 name = self.__name__
459 m = self.__module__
460 if m:
461 name = '%s.%s' % (m, name)
462 r = "<%s %s>" % (self.__class__.__name__, name)
463 self._v_repr = r
464 return r
465
466 def _call_conform(self, conform):
467 try:
468 return conform(self)
469 except TypeError: # pragma: no cover
470 # We got a TypeError. It might be an error raised by
471 # the __conform__ implementation, or *we* may have
472 # made the TypeError by calling an unbound method
473 # (object is a class). In the later case, we behave
474 # as though there is no __conform__ method. We can
475 # detect this case by checking whether there is more
476 # than one traceback object in the traceback chain:
477 if sys.exc_info()[2].tb_next is not None:
478 # There is more than one entry in the chain, so
479 # reraise the error:
480 raise
481 # This clever trick is from Phillip Eby
482
483 return None # pragma: no cover
484
485 def __reduce__(self):
486 return self.__name__
487
488 def __cmp(self, other):
489 # Yes, I did mean to name this __cmp, rather than __cmp__.
490 # It is a private method used by __lt__ and __gt__.
491 # I don't want to override __eq__ because I want the default
492 # __eq__, which is really fast.
493 """Make interfaces sortable
494
495 TODO: It would ne nice if:
496
497 More specific interfaces should sort before less specific ones.
498 Otherwise, sort on name and module.
499
500 But this is too complicated, and we're going to punt on it
501 for now.
502
503 For now, sort on interface and module name.
504
505 None is treated as a pseudo interface that implies the loosest
506 contact possible, no contract. For that reason, all interfaces
507 sort before None.
508
509 """
510 if other is None:
511 return -1
512
513 n1 = (getattr(self, '__name__', ''), getattr(self, '__module__', ''))
514 n2 = (getattr(other, '__name__', ''), getattr(other, '__module__', ''))
515
516 # This spelling works under Python3, which doesn't have cmp().
517 return (n1 > n2) - (n1 < n2)
518
519 def __hash__(self):
520 d = self.__dict__
521 if '__module__' not in d or '__name__' not in d: # pragma: no cover
522 warnings.warn('Hashing uninitialized InterfaceClass instance')
523 return 1
524 return hash((self.__name__, self.__module__))
525
526 def __eq__(self, other):
527 c = self.__cmp(other)
528 return c == 0
529
530 def __ne__(self, other):
531 c = self.__cmp(other)
532 return c != 0
533
534 def __lt__(self, other):
535 c = self.__cmp(other)
536 return c < 0
537
538 def __le__(self, other):
539 c = self.__cmp(other)
540 return c <= 0
541
542 def __gt__(self, other):
543 c = self.__cmp(other)
544 return c > 0
545
546 def __ge__(self, other):
547 c = self.__cmp(other)
548 return c >= 0
549
550
551 Interface = InterfaceClass("Interface", __module__ = 'zope.interface')
552
553 class Attribute(Element):
554 """Attribute descriptions
555 """
556
557 # We can't say this yet because we don't have enough
558 # infrastructure in place.
559 #
560 # implements(IAttribute)
561
562 interface = None
563
564
565 class Method(Attribute):
566 """Method interfaces
567
568 The idea here is that you have objects that describe methods.
569 This provides an opportunity for rich meta-data.
570 """
571
572 # We can't say this yet because we don't have enough
573 # infrastructure in place.
574 #
575 # implements(IMethod)
576
577 positional = required = ()
578 _optional = varargs = kwargs = None
579 def _get_optional(self):
580 if self._optional is None:
581 return {}
582 return self._optional
583 def _set_optional(self, opt):
584 self._optional = opt
585 def _del_optional(self):
586 self._optional = None
587 optional = property(_get_optional, _set_optional, _del_optional)
588
589 def __call__(self, *args, **kw):
590 raise BrokenImplementation(self.interface, self.__name__)
591
592 def getSignatureInfo(self):
593 return {'positional': self.positional,
594 'required': self.required,
595 'optional': self.optional,
596 'varargs': self.varargs,
597 'kwargs': self.kwargs,
598 }
599
600 def getSignatureString(self):
601 sig = []
602 for v in self.positional:
603 sig.append(v)
604 if v in self.optional.keys():
605 sig[-1] += "=" + repr(self.optional[v])
606 if self.varargs:
607 sig.append("*" + self.varargs)
608 if self.kwargs:
609 sig.append("**" + self.kwargs)
610
611 return "(%s)" % ", ".join(sig)
612
613 def fromFunction(func, interface=None, imlevel=0, name=None):
614 name = name or func.__name__
615 method = Method(name, func.__doc__)
616 defaults = getattr(func, '__defaults__', None) or ()
617 code = func.__code__
618 # Number of positional arguments
619 na = code.co_argcount-imlevel
620 names = code.co_varnames[imlevel:]
621 opt = {}
622 # Number of required arguments
623 nr = na-len(defaults)
624 if nr < 0:
625 defaults=defaults[-nr:]
626 nr = 0
627
628 # Determine the optional arguments.
629 opt.update(dict(zip(names[nr:], defaults)))
630
631 method.positional = names[:na]
632 method.required = names[:nr]
633 method.optional = opt
634
635 argno = na
636
637 # Determine the function's variable argument's name (i.e. *args)
638 if code.co_flags & CO_VARARGS:
639 method.varargs = names[argno]
640 argno = argno + 1
641 else:
642 method.varargs = None
643
644 # Determine the function's keyword argument's name (i.e. **kw)
645 if code.co_flags & CO_VARKEYWORDS:
646 method.kwargs = names[argno]
647 else:
648 method.kwargs = None
649
650 method.interface = interface
651
652 for key, value in func.__dict__.items():
653 method.setTaggedValue(key, value)
654
655 return method
656
657
658 def fromMethod(meth, interface=None, name=None):
659 if isinstance(meth, MethodType):
660 func = meth.__func__
661 else:
662 func = meth
663 return fromFunction(func, interface, imlevel=1, name=name)
664
665
666 # Now we can create the interesting interfaces and wire them up:
667 def _wire():
668 from zope.interface.declarations import classImplements
669
670 from zope.interface.interfaces import IAttribute
671 classImplements(Attribute, IAttribute)
672
673 from zope.interface.interfaces import IMethod
674 classImplements(Method, IMethod)
675
676 from zope.interface.interfaces import IInterface
677 classImplements(InterfaceClass, IInterface)
678
679 from zope.interface.interfaces import ISpecification
680 classImplements(Specification, ISpecification)
681
682 # We import this here to deal with module dependencies.
683 from zope.interface.declarations import implementedBy
684 from zope.interface.declarations import providedBy
685 from zope.interface.exceptions import InvalidInterface
686 from zope.interface.exceptions import BrokenImplementation
This diff has been collapsed as it changes many lines, (1294 lines changed) Show them Hide them
@@ -0,0 +1,1294 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Interface Package Interfaces
15 """
16 __docformat__ = 'restructuredtext'
17
18 from zope.interface.interface import Attribute
19 from zope.interface.interface import Interface
20 from zope.interface.declarations import implementer
21
22
23 _BLANK = u''
24
25 class IElement(Interface):
26 """Objects that have basic documentation and tagged values.
27 """
28
29 __name__ = Attribute('__name__', 'The object name')
30 __doc__ = Attribute('__doc__', 'The object doc string')
31
32 def getTaggedValue(tag):
33 """Returns the value associated with `tag`.
34
35 Raise a `KeyError` of the tag isn't set.
36 """
37
38 def queryTaggedValue(tag, default=None):
39 """Returns the value associated with `tag`.
40
41 Return the default value of the tag isn't set.
42 """
43
44 def getTaggedValueTags():
45 """Returns a list of all tags."""
46
47 def setTaggedValue(tag, value):
48 """Associates `value` with `key`."""
49
50
51 class IAttribute(IElement):
52 """Attribute descriptors"""
53
54 interface = Attribute('interface',
55 'Stores the interface instance in which the '
56 'attribute is located.')
57
58
59 class IMethod(IAttribute):
60 """Method attributes"""
61
62 def getSignatureInfo():
63 """Returns the signature information.
64
65 This method returns a dictionary with the following keys:
66
67 o `positional` - All positional arguments.
68
69 o `required` - A list of all required arguments.
70
71 o `optional` - A list of all optional arguments.
72
73 o `varargs` - The name of the varargs argument.
74
75 o `kwargs` - The name of the kwargs argument.
76 """
77
78 def getSignatureString():
79 """Return a signature string suitable for inclusion in documentation.
80
81 This method returns the function signature string. For example, if you
82 have `func(a, b, c=1, d='f')`, then the signature string is `(a, b,
83 c=1, d='f')`.
84 """
85
86 class ISpecification(Interface):
87 """Object Behavioral specifications"""
88
89 def providedBy(object):
90 """Test whether the interface is implemented by the object
91
92 Return true of the object asserts that it implements the
93 interface, including asserting that it implements an extended
94 interface.
95 """
96
97 def implementedBy(class_):
98 """Test whether the interface is implemented by instances of the class
99
100 Return true of the class asserts that its instances implement the
101 interface, including asserting that they implement an extended
102 interface.
103 """
104
105 def isOrExtends(other):
106 """Test whether the specification is or extends another
107 """
108
109 def extends(other, strict=True):
110 """Test whether a specification extends another
111
112 The specification extends other if it has other as a base
113 interface or if one of it's bases extends other.
114
115 If strict is false, then the specification extends itself.
116 """
117
118 def weakref(callback=None):
119 """Return a weakref to the specification
120
121 This method is, regrettably, needed to allow weakrefs to be
122 computed to security-proxied specifications. While the
123 zope.interface package does not require zope.security or
124 zope.proxy, it has to be able to coexist with it.
125
126 """
127
128 __bases__ = Attribute("""Base specifications
129
130 A tuple if specifications from which this specification is
131 directly derived.
132
133 """)
134
135 __sro__ = Attribute("""Specification-resolution order
136
137 A tuple of the specification and all of it's ancestor
138 specifications from most specific to least specific.
139
140 (This is similar to the method-resolution order for new-style classes.)
141 """)
142
143 __iro__ = Attribute("""Interface-resolution order
144
145 A tuple of the of the specification's ancestor interfaces from
146 most specific to least specific. The specification itself is
147 included if it is an interface.
148
149 (This is similar to the method-resolution order for new-style classes.)
150 """)
151
152 def get(name, default=None):
153 """Look up the description for a name
154
155 If the named attribute is not defined, the default is
156 returned.
157 """
158
159
160 class IInterface(ISpecification, IElement):
161 """Interface objects
162
163 Interface objects describe the behavior of an object by containing
164 useful information about the object. This information includes:
165
166 o Prose documentation about the object. In Python terms, this
167 is called the "doc string" of the interface. In this element,
168 you describe how the object works in prose language and any
169 other useful information about the object.
170
171 o Descriptions of attributes. Attribute descriptions include
172 the name of the attribute and prose documentation describing
173 the attributes usage.
174
175 o Descriptions of methods. Method descriptions can include:
176
177 - Prose "doc string" documentation about the method and its
178 usage.
179
180 - A description of the methods arguments; how many arguments
181 are expected, optional arguments and their default values,
182 the position or arguments in the signature, whether the
183 method accepts arbitrary arguments and whether the method
184 accepts arbitrary keyword arguments.
185
186 o Optional tagged data. Interface objects (and their attributes and
187 methods) can have optional, application specific tagged data
188 associated with them. Examples uses for this are examples,
189 security assertions, pre/post conditions, and other possible
190 information you may want to associate with an Interface or its
191 attributes.
192
193 Not all of this information is mandatory. For example, you may
194 only want the methods of your interface to have prose
195 documentation and not describe the arguments of the method in
196 exact detail. Interface objects are flexible and let you give or
197 take any of these components.
198
199 Interfaces are created with the Python class statement using
200 either Interface.Interface or another interface, as in::
201
202 from zope.interface import Interface
203
204 class IMyInterface(Interface):
205 '''Interface documentation'''
206
207 def meth(arg1, arg2):
208 '''Documentation for meth'''
209
210 # Note that there is no self argument
211
212 class IMySubInterface(IMyInterface):
213 '''Interface documentation'''
214
215 def meth2():
216 '''Documentation for meth2'''
217
218 You use interfaces in two ways:
219
220 o You assert that your object implement the interfaces.
221
222 There are several ways that you can assert that an object
223 implements an interface:
224
225 1. Call zope.interface.implements in your class definition.
226
227 2. Call zope.interfaces.directlyProvides on your object.
228
229 3. Call 'zope.interface.classImplements' to assert that instances
230 of a class implement an interface.
231
232 For example::
233
234 from zope.interface import classImplements
235
236 classImplements(some_class, some_interface)
237
238 This approach is useful when it is not an option to modify
239 the class source. Note that this doesn't affect what the
240 class itself implements, but only what its instances
241 implement.
242
243 o You query interface meta-data. See the IInterface methods and
244 attributes for details.
245
246 """
247
248 def names(all=False):
249 """Get the interface attribute names
250
251 Return a sequence of the names of the attributes, including
252 methods, included in the interface definition.
253
254 Normally, only directly defined attributes are included. If
255 a true positional or keyword argument is given, then
256 attributes defined by base classes will be included.
257 """
258
259 def namesAndDescriptions(all=False):
260 """Get the interface attribute names and descriptions
261
262 Return a sequence of the names and descriptions of the
263 attributes, including methods, as name-value pairs, included
264 in the interface definition.
265
266 Normally, only directly defined attributes are included. If
267 a true positional or keyword argument is given, then
268 attributes defined by base classes will be included.
269 """
270
271 def __getitem__(name):
272 """Get the description for a name
273
274 If the named attribute is not defined, a KeyError is raised.
275 """
276
277 def direct(name):
278 """Get the description for the name if it was defined by the interface
279
280 If the interface doesn't define the name, returns None.
281 """
282
283 def validateInvariants(obj, errors=None):
284 """Validate invariants
285
286 Validate object to defined invariants. If errors is None,
287 raises first Invalid error; if errors is a list, appends all errors
288 to list, then raises Invalid with the errors as the first element
289 of the "args" tuple."""
290
291 def __contains__(name):
292 """Test whether the name is defined by the interface"""
293
294 def __iter__():
295 """Return an iterator over the names defined by the interface
296
297 The names iterated include all of the names defined by the
298 interface directly and indirectly by base interfaces.
299 """
300
301 __module__ = Attribute("""The name of the module defining the interface""")
302
303 class IDeclaration(ISpecification):
304 """Interface declaration
305
306 Declarations are used to express the interfaces implemented by
307 classes or provided by objects.
308 """
309
310 def __contains__(interface):
311 """Test whether an interface is in the specification
312
313 Return true if the given interface is one of the interfaces in
314 the specification and false otherwise.
315 """
316
317 def __iter__():
318 """Return an iterator for the interfaces in the specification
319 """
320
321 def flattened():
322 """Return an iterator of all included and extended interfaces
323
324 An iterator is returned for all interfaces either included in
325 or extended by interfaces included in the specifications
326 without duplicates. The interfaces are in "interface
327 resolution order". The interface resolution order is such that
328 base interfaces are listed after interfaces that extend them
329 and, otherwise, interfaces are included in the order that they
330 were defined in the specification.
331 """
332
333 def __sub__(interfaces):
334 """Create an interface specification with some interfaces excluded
335
336 The argument can be an interface or an interface
337 specifications. The interface or interfaces given in a
338 specification are subtracted from the interface specification.
339
340 Removing an interface that is not in the specification does
341 not raise an error. Doing so has no effect.
342
343 Removing an interface also removes sub-interfaces of the interface.
344
345 """
346
347 def __add__(interfaces):
348 """Create an interface specification with some interfaces added
349
350 The argument can be an interface or an interface
351 specifications. The interface or interfaces given in a
352 specification are added to the interface specification.
353
354 Adding an interface that is already in the specification does
355 not raise an error. Doing so has no effect.
356 """
357
358 def __nonzero__():
359 """Return a true value of the interface specification is non-empty
360 """
361
362 class IInterfaceDeclaration(Interface):
363 """Declare and check the interfaces of objects
364
365 The functions defined in this interface are used to declare the
366 interfaces that objects provide and to query the interfaces that have
367 been declared.
368
369 Interfaces can be declared for objects in two ways:
370
371 - Interfaces are declared for instances of the object's class
372
373 - Interfaces are declared for the object directly.
374
375 The interfaces declared for an object are, therefore, the union of
376 interfaces declared for the object directly and the interfaces
377 declared for instances of the object's class.
378
379 Note that we say that a class implements the interfaces provided
380 by it's instances. An instance can also provide interfaces
381 directly. The interfaces provided by an object are the union of
382 the interfaces provided directly and the interfaces implemented by
383 the class.
384 """
385
386 def providedBy(ob):
387 """Return the interfaces provided by an object
388
389 This is the union of the interfaces directly provided by an
390 object and interfaces implemented by it's class.
391
392 The value returned is an IDeclaration.
393 """
394
395 def implementedBy(class_):
396 """Return the interfaces implemented for a class' instances
397
398 The value returned is an IDeclaration.
399 """
400
401 def classImplements(class_, *interfaces):
402 """Declare additional interfaces implemented for instances of a class
403
404 The arguments after the class are one or more interfaces or
405 interface specifications (IDeclaration objects).
406
407 The interfaces given (including the interfaces in the
408 specifications) are added to any interfaces previously
409 declared.
410
411 Consider the following example::
412
413 class C(A, B):
414 ...
415
416 classImplements(C, I1, I2)
417
418
419 Instances of ``C`` provide ``I1``, ``I2``, and whatever interfaces
420 instances of ``A`` and ``B`` provide.
421 """
422
423 def implementer(*interfaces):
424 """Create a decorator for declaring interfaces implemented by a facory
425
426 A callable is returned that makes an implements declaration on
427 objects passed to it.
428 """
429
430 def classImplementsOnly(class_, *interfaces):
431 """Declare the only interfaces implemented by instances of a class
432
433 The arguments after the class are one or more interfaces or
434 interface specifications (IDeclaration objects).
435
436 The interfaces given (including the interfaces in the
437 specifications) replace any previous declarations.
438
439 Consider the following example::
440
441 class C(A, B):
442 ...
443
444 classImplements(C, IA, IB. IC)
445 classImplementsOnly(C. I1, I2)
446
447 Instances of ``C`` provide only ``I1``, ``I2``, and regardless of
448 whatever interfaces instances of ``A`` and ``B`` implement.
449 """
450
451 def implementer_only(*interfaces):
452 """Create a decorator for declaring the only interfaces implemented
453
454 A callable is returned that makes an implements declaration on
455 objects passed to it.
456 """
457
458 def directlyProvidedBy(object):
459 """Return the interfaces directly provided by the given object
460
461 The value returned is an IDeclaration.
462 """
463
464 def directlyProvides(object, *interfaces):
465 """Declare interfaces declared directly for an object
466
467 The arguments after the object are one or more interfaces or
468 interface specifications (IDeclaration objects).
469
470 The interfaces given (including the interfaces in the
471 specifications) replace interfaces previously
472 declared for the object.
473
474 Consider the following example::
475
476 class C(A, B):
477 ...
478
479 ob = C()
480 directlyProvides(ob, I1, I2)
481
482 The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces
483 instances have been declared for instances of ``C``.
484
485 To remove directly provided interfaces, use ``directlyProvidedBy`` and
486 subtract the unwanted interfaces. For example::
487
488 directlyProvides(ob, directlyProvidedBy(ob)-I2)
489
490 removes I2 from the interfaces directly provided by
491 ``ob``. The object, ``ob`` no longer directly provides ``I2``,
492 although it might still provide ``I2`` if it's class
493 implements ``I2``.
494
495 To add directly provided interfaces, use ``directlyProvidedBy`` and
496 include additional interfaces. For example::
497
498 directlyProvides(ob, directlyProvidedBy(ob), I2)
499
500 adds I2 to the interfaces directly provided by ob.
501 """
502
503 def alsoProvides(object, *interfaces):
504 """Declare additional interfaces directly for an object::
505
506 alsoProvides(ob, I1)
507
508 is equivalent to::
509
510 directlyProvides(ob, directlyProvidedBy(ob), I1)
511 """
512
513 def noLongerProvides(object, interface):
514 """Remove an interface from the list of an object's directly
515 provided interfaces::
516
517 noLongerProvides(ob, I1)
518
519 is equivalent to::
520
521 directlyProvides(ob, directlyProvidedBy(ob)-I1)
522
523 with the exception that if ``I1`` is an interface that is
524 provided by ``ob`` through the class's implementation,
525 ValueError is raised.
526 """
527
528 def implements(*interfaces):
529 """Declare interfaces implemented by instances of a class
530
531 This function is called in a class definition (Python 2.x only).
532
533 The arguments are one or more interfaces or interface
534 specifications (IDeclaration objects).
535
536 The interfaces given (including the interfaces in the
537 specifications) are added to any interfaces previously
538 declared.
539
540 Previous declarations include declarations for base classes
541 unless implementsOnly was used.
542
543 This function is provided for convenience. It provides a more
544 convenient way to call classImplements. For example::
545
546 implements(I1)
547
548 is equivalent to calling::
549
550 classImplements(C, I1)
551
552 after the class has been created.
553
554 Consider the following example (Python 2.x only)::
555
556 class C(A, B):
557 implements(I1, I2)
558
559
560 Instances of ``C`` implement ``I1``, ``I2``, and whatever interfaces
561 instances of ``A`` and ``B`` implement.
562 """
563
564 def implementsOnly(*interfaces):
565 """Declare the only interfaces implemented by instances of a class
566
567 This function is called in a class definition (Python 2.x only).
568
569 The arguments are one or more interfaces or interface
570 specifications (IDeclaration objects).
571
572 Previous declarations including declarations for base classes
573 are overridden.
574
575 This function is provided for convenience. It provides a more
576 convenient way to call classImplementsOnly. For example::
577
578 implementsOnly(I1)
579
580 is equivalent to calling::
581
582 classImplementsOnly(I1)
583
584 after the class has been created.
585
586 Consider the following example (Python 2.x only)::
587
588 class C(A, B):
589 implementsOnly(I1, I2)
590
591
592 Instances of ``C`` implement ``I1``, ``I2``, regardless of what
593 instances of ``A`` and ``B`` implement.
594 """
595
596 def classProvides(*interfaces):
597 """Declare interfaces provided directly by a class
598
599 This function is called in a class definition.
600
601 The arguments are one or more interfaces or interface
602 specifications (IDeclaration objects).
603
604 The given interfaces (including the interfaces in the
605 specifications) are used to create the class's direct-object
606 interface specification. An error will be raised if the module
607 class has an direct interface specification. In other words, it is
608 an error to call this function more than once in a class
609 definition.
610
611 Note that the given interfaces have nothing to do with the
612 interfaces implemented by instances of the class.
613
614 This function is provided for convenience. It provides a more
615 convenient way to call directlyProvides for a class. For example::
616
617 classProvides(I1)
618
619 is equivalent to calling::
620
621 directlyProvides(theclass, I1)
622
623 after the class has been created.
624 """
625 def provider(*interfaces):
626 """A class decorator version of classProvides"""
627
628 def moduleProvides(*interfaces):
629 """Declare interfaces provided by a module
630
631 This function is used in a module definition.
632
633 The arguments are one or more interfaces or interface
634 specifications (IDeclaration objects).
635
636 The given interfaces (including the interfaces in the
637 specifications) are used to create the module's direct-object
638 interface specification. An error will be raised if the module
639 already has an interface specification. In other words, it is
640 an error to call this function more than once in a module
641 definition.
642
643 This function is provided for convenience. It provides a more
644 convenient way to call directlyProvides for a module. For example::
645
646 moduleImplements(I1)
647
648 is equivalent to::
649
650 directlyProvides(sys.modules[__name__], I1)
651 """
652
653 def Declaration(*interfaces):
654 """Create an interface specification
655
656 The arguments are one or more interfaces or interface
657 specifications (IDeclaration objects).
658
659 A new interface specification (IDeclaration) with
660 the given interfaces is returned.
661 """
662
663 class IAdapterRegistry(Interface):
664 """Provide an interface-based registry for adapters
665
666 This registry registers objects that are in some sense "from" a
667 sequence of specification to an interface and a name.
668
669 No specific semantics are assumed for the registered objects,
670 however, the most common application will be to register factories
671 that adapt objects providing required specifications to a provided
672 interface.
673 """
674
675 def register(required, provided, name, value):
676 """Register a value
677
678 A value is registered for a *sequence* of required specifications, a
679 provided interface, and a name, which must be text.
680 """
681
682 def registered(required, provided, name=_BLANK):
683 """Return the component registered for the given interfaces and name
684
685 name must be text.
686
687 Unlike the lookup method, this methods won't retrieve
688 components registered for more specific required interfaces or
689 less specific provided interfaces.
690
691 If no component was registered exactly for the given
692 interfaces and name, then None is returned.
693
694 """
695
696 def lookup(required, provided, name='', default=None):
697 """Lookup a value
698
699 A value is looked up based on a *sequence* of required
700 specifications, a provided interface, and a name, which must be
701 text.
702 """
703
704 def queryMultiAdapter(objects, provided, name=_BLANK, default=None):
705 """Adapt a sequence of objects to a named, provided, interface
706 """
707
708 def lookup1(required, provided, name=_BLANK, default=None):
709 """Lookup a value using a single required interface
710
711 A value is looked up based on a single required
712 specifications, a provided interface, and a name, which must be
713 text.
714 """
715
716 def queryAdapter(object, provided, name=_BLANK, default=None):
717 """Adapt an object using a registered adapter factory.
718 """
719
720 def adapter_hook(provided, object, name=_BLANK, default=None):
721 """Adapt an object using a registered adapter factory.
722
723 name must be text.
724 """
725
726 def lookupAll(required, provided):
727 """Find all adapters from the required to the provided interfaces
728
729 An iterable object is returned that provides name-value two-tuples.
730 """
731
732 def names(required, provided):
733 """Return the names for which there are registered objects
734 """
735
736 def subscribe(required, provided, subscriber, name=_BLANK):
737 """Register a subscriber
738
739 A subscriber is registered for a *sequence* of required
740 specifications, a provided interface, and a name.
741
742 Multiple subscribers may be registered for the same (or
743 equivalent) interfaces.
744 """
745
746 def subscriptions(required, provided, name=_BLANK):
747 """Get a sequence of subscribers
748
749 Subscribers for a *sequence* of required interfaces, and a provided
750 interface are returned.
751 """
752
753 def subscribers(objects, provided, name=_BLANK):
754 """Get a sequence of subscription adapters
755 """
756
757 # begin formerly in zope.component
758
759 class ComponentLookupError(LookupError):
760 """A component could not be found."""
761
762 class Invalid(Exception):
763 """A component doesn't satisfy a promise."""
764
765 class IObjectEvent(Interface):
766 """An event related to an object.
767
768 The object that generated this event is not necessarily the object
769 refered to by location.
770 """
771
772 object = Attribute("The subject of the event.")
773
774
775 @implementer(IObjectEvent)
776 class ObjectEvent(object):
777
778 def __init__(self, object):
779 self.object = object
780
781 class IComponentLookup(Interface):
782 """Component Manager for a Site
783
784 This object manages the components registered at a particular site. The
785 definition of a site is intentionally vague.
786 """
787
788 adapters = Attribute(
789 "Adapter Registry to manage all registered adapters.")
790
791 utilities = Attribute(
792 "Adapter Registry to manage all registered utilities.")
793
794 def queryAdapter(object, interface, name=_BLANK, default=None):
795 """Look for a named adapter to an interface for an object
796
797 If a matching adapter cannot be found, returns the default.
798 """
799
800 def getAdapter(object, interface, name=_BLANK):
801 """Look for a named adapter to an interface for an object
802
803 If a matching adapter cannot be found, a ComponentLookupError
804 is raised.
805 """
806
807 def queryMultiAdapter(objects, interface, name=_BLANK, default=None):
808 """Look for a multi-adapter to an interface for multiple objects
809
810 If a matching adapter cannot be found, returns the default.
811 """
812
813 def getMultiAdapter(objects, interface, name=_BLANK):
814 """Look for a multi-adapter to an interface for multiple objects
815
816 If a matching adapter cannot be found, a ComponentLookupError
817 is raised.
818 """
819
820 def getAdapters(objects, provided):
821 """Look for all matching adapters to a provided interface for objects
822
823 Return an iterable of name-adapter pairs for adapters that
824 provide the given interface.
825 """
826
827 def subscribers(objects, provided):
828 """Get subscribers
829
830 Subscribers are returned that provide the provided interface
831 and that depend on and are comuted from the sequence of
832 required objects.
833 """
834
835 def handle(*objects):
836 """Call handlers for the given objects
837
838 Handlers registered for the given objects are called.
839 """
840
841 def queryUtility(interface, name='', default=None):
842 """Look up a utility that provides an interface.
843
844 If one is not found, returns default.
845 """
846
847 def getUtilitiesFor(interface):
848 """Look up the registered utilities that provide an interface.
849
850 Returns an iterable of name-utility pairs.
851 """
852
853 def getAllUtilitiesRegisteredFor(interface):
854 """Return all registered utilities for an interface
855
856 This includes overridden utilities.
857
858 An iterable of utility instances is returned. No names are
859 returned.
860 """
861
862 class IRegistration(Interface):
863 """A registration-information object
864 """
865
866 registry = Attribute("The registry having the registration")
867
868 name = Attribute("The registration name")
869
870 info = Attribute("""Information about the registration
871
872 This is information deemed useful to people browsing the
873 configuration of a system. It could, for example, include
874 commentary or information about the source of the configuration.
875 """)
876
877 class IUtilityRegistration(IRegistration):
878 """Information about the registration of a utility
879 """
880
881 factory = Attribute("The factory used to create the utility. Optional.")
882 component = Attribute("The object registered")
883 provided = Attribute("The interface provided by the component")
884
885 class _IBaseAdapterRegistration(IRegistration):
886 """Information about the registration of an adapter
887 """
888
889 factory = Attribute("The factory used to create adapters")
890
891 required = Attribute("""The adapted interfaces
892
893 This is a sequence of interfaces adapters by the registered
894 factory. The factory will be caled with a sequence of objects, as
895 positional arguments, that provide these interfaces.
896 """)
897
898 provided = Attribute("""The interface provided by the adapters.
899
900 This interface is implemented by the factory
901 """)
902
903 class IAdapterRegistration(_IBaseAdapterRegistration):
904 """Information about the registration of an adapter
905 """
906
907 class ISubscriptionAdapterRegistration(_IBaseAdapterRegistration):
908 """Information about the registration of a subscription adapter
909 """
910
911 class IHandlerRegistration(IRegistration):
912
913 handler = Attribute("An object called used to handle an event")
914
915 required = Attribute("""The handled interfaces
916
917 This is a sequence of interfaces handled by the registered
918 handler. The handler will be caled with a sequence of objects, as
919 positional arguments, that provide these interfaces.
920 """)
921
922 class IRegistrationEvent(IObjectEvent):
923 """An event that involves a registration"""
924
925
926 @implementer(IRegistrationEvent)
927 class RegistrationEvent(ObjectEvent):
928 """There has been a change in a registration
929 """
930 def __repr__(self):
931 return "%s event:\n%r" % (self.__class__.__name__, self.object)
932
933 class IRegistered(IRegistrationEvent):
934 """A component or factory was registered
935 """
936
937 @implementer(IRegistered)
938 class Registered(RegistrationEvent):
939 pass
940
941 class IUnregistered(IRegistrationEvent):
942 """A component or factory was unregistered
943 """
944
945 @implementer(IUnregistered)
946 class Unregistered(RegistrationEvent):
947 """A component or factory was unregistered
948 """
949 pass
950
951 class IComponentRegistry(Interface):
952 """Register components
953 """
954
955 def registerUtility(component=None, provided=None, name=_BLANK,
956 info=_BLANK, factory=None):
957 """Register a utility
958
959 factory
960 Factory for the component to be registerd.
961
962 component
963 The registered component
964
965 provided
966 This is the interface provided by the utility. If the
967 component provides a single interface, then this
968 argument is optional and the component-implemented
969 interface will be used.
970
971 name
972 The utility name.
973
974 info
975 An object that can be converted to a string to provide
976 information about the registration.
977
978 Only one of component and factory can be used.
979 A Registered event is generated with an IUtilityRegistration.
980 """
981
982 def unregisterUtility(component=None, provided=None, name=_BLANK,
983 factory=None):
984 """Unregister a utility
985
986 A boolean is returned indicating whether the registry was
987 changed. If the given component is None and there is no
988 component registered, or if the given component is not
989 None and is not registered, then the function returns
990 False, otherwise it returns True.
991
992 factory
993 Factory for the component to be unregisterd.
994
995 component
996 The registered component The given component can be
997 None, in which case any component registered to provide
998 the given provided interface with the given name is
999 unregistered.
1000
1001 provided
1002 This is the interface provided by the utility. If the
1003 component is not None and provides a single interface,
1004 then this argument is optional and the
1005 component-implemented interface will be used.
1006
1007 name
1008 The utility name.
1009
1010 Only one of component and factory can be used.
1011 An UnRegistered event is generated with an IUtilityRegistration.
1012 """
1013
1014 def registeredUtilities():
1015 """Return an iterable of IUtilityRegistration instances.
1016
1017 These registrations describe the current utility registrations
1018 in the object.
1019 """
1020
1021 def registerAdapter(factory, required=None, provided=None, name=_BLANK,
1022 info=_BLANK):
1023 """Register an adapter factory
1024
1025 Parameters:
1026
1027 factory
1028 The object used to compute the adapter
1029
1030 required
1031 This is a sequence of specifications for objects to be
1032 adapted. If omitted, then the value of the factory's
1033 __component_adapts__ attribute will be used. The
1034 __component_adapts__ attribute is usually attribute is
1035 normally set in class definitions using adapts
1036 function, or for callables using the adapter
1037 decorator. If the factory doesn't have a
1038 __component_adapts__ adapts attribute, then this
1039 argument is required.
1040
1041 provided
1042 This is the interface provided by the adapter and
1043 implemented by the factory. If the factory
1044 implements a single interface, then this argument is
1045 optional and the factory-implemented interface will be
1046 used.
1047
1048 name
1049 The adapter name.
1050
1051 info
1052 An object that can be converted to a string to provide
1053 information about the registration.
1054
1055 A Registered event is generated with an IAdapterRegistration.
1056 """
1057
1058 def unregisterAdapter(factory=None, required=None,
1059 provided=None, name=_BLANK):
1060 """Unregister an adapter factory
1061
1062 A boolean is returned indicating whether the registry was
1063 changed. If the given component is None and there is no
1064 component registered, or if the given component is not
1065 None and is not registered, then the function returns
1066 False, otherwise it returns True.
1067
1068 Parameters:
1069
1070 factory
1071 This is the object used to compute the adapter. The
1072 factory can be None, in which case any factory
1073 registered to implement the given provided interface
1074 for the given required specifications with the given
1075 name is unregistered.
1076
1077 required
1078 This is a sequence of specifications for objects to be
1079 adapted. If the factory is not None and the required
1080 arguments is omitted, then the value of the factory's
1081 __component_adapts__ attribute will be used. The
1082 __component_adapts__ attribute attribute is normally
1083 set in class definitions using adapts function, or for
1084 callables using the adapter decorator. If the factory
1085 is None or doesn't have a __component_adapts__ adapts
1086 attribute, then this argument is required.
1087
1088 provided
1089 This is the interface provided by the adapter and
1090 implemented by the factory. If the factory is not
1091 None and implements a single interface, then this
1092 argument is optional and the factory-implemented
1093 interface will be used.
1094
1095 name
1096 The adapter name.
1097
1098 An Unregistered event is generated with an IAdapterRegistration.
1099 """
1100
1101 def registeredAdapters():
1102 """Return an iterable of IAdapterRegistration instances.
1103
1104 These registrations describe the current adapter registrations
1105 in the object.
1106 """
1107
1108 def registerSubscriptionAdapter(factory, required=None, provides=None,
1109 name=_BLANK, info=''):
1110 """Register a subscriber factory
1111
1112 Parameters:
1113
1114 factory
1115 The object used to compute the adapter
1116
1117 required
1118 This is a sequence of specifications for objects to be
1119 adapted. If omitted, then the value of the factory's
1120 __component_adapts__ attribute will be used. The
1121 __component_adapts__ attribute is usually attribute is
1122 normally set in class definitions using adapts
1123 function, or for callables using the adapter
1124 decorator. If the factory doesn't have a
1125 __component_adapts__ adapts attribute, then this
1126 argument is required.
1127
1128 provided
1129 This is the interface provided by the adapter and
1130 implemented by the factory. If the factory implements
1131 a single interface, then this argument is optional and
1132 the factory-implemented interface will be used.
1133
1134 name
1135 The adapter name.
1136
1137 Currently, only the empty string is accepted. Other
1138 strings will be accepted in the future when support for
1139 named subscribers is added.
1140
1141 info
1142 An object that can be converted to a string to provide
1143 information about the registration.
1144
1145 A Registered event is generated with an
1146 ISubscriptionAdapterRegistration.
1147 """
1148
1149 def unregisterSubscriptionAdapter(factory=None, required=None,
1150 provides=None, name=_BLANK):
1151 """Unregister a subscriber factory.
1152
1153 A boolean is returned indicating whether the registry was
1154 changed. If the given component is None and there is no
1155 component registered, or if the given component is not
1156 None and is not registered, then the function returns
1157 False, otherwise it returns True.
1158
1159 Parameters:
1160
1161 factory
1162 This is the object used to compute the adapter. The
1163 factory can be None, in which case any factories
1164 registered to implement the given provided interface
1165 for the given required specifications with the given
1166 name are unregistered.
1167
1168 required
1169 This is a sequence of specifications for objects to be
1170 adapted. If the factory is not None and the required
1171 arguments is omitted, then the value of the factory's
1172 __component_adapts__ attribute will be used. The
1173 __component_adapts__ attribute attribute is normally
1174 set in class definitions using adapts function, or for
1175 callables using the adapter decorator. If the factory
1176 is None or doesn't have a __component_adapts__ adapts
1177 attribute, then this argument is required.
1178
1179 provided
1180 This is the interface provided by the adapter and
1181 implemented by the factory. If the factory is not
1182 None implements a single interface, then this argument
1183 is optional and the factory-implemented interface will
1184 be used.
1185
1186 name
1187 The adapter name.
1188
1189 Currently, only the empty string is accepted. Other
1190 strings will be accepted in the future when support for
1191 named subscribers is added.
1192
1193 An Unregistered event is generated with an
1194 ISubscriptionAdapterRegistration.
1195 """
1196
1197 def registeredSubscriptionAdapters():
1198 """Return an iterable of ISubscriptionAdapterRegistration instances.
1199
1200 These registrations describe the current subscription adapter
1201 registrations in the object.
1202 """
1203
1204 def registerHandler(handler, required=None, name=_BLANK, info=''):
1205 """Register a handler.
1206
1207 A handler is a subscriber that doesn't compute an adapter
1208 but performs some function when called.
1209
1210 Parameters:
1211
1212 handler
1213 The object used to handle some event represented by
1214 the objects passed to it.
1215
1216 required
1217 This is a sequence of specifications for objects to be
1218 adapted. If omitted, then the value of the factory's
1219 __component_adapts__ attribute will be used. The
1220 __component_adapts__ attribute is usually attribute is
1221 normally set in class definitions using adapts
1222 function, or for callables using the adapter
1223 decorator. If the factory doesn't have a
1224 __component_adapts__ adapts attribute, then this
1225 argument is required.
1226
1227 name
1228 The handler name.
1229
1230 Currently, only the empty string is accepted. Other
1231 strings will be accepted in the future when support for
1232 named handlers is added.
1233
1234 info
1235 An object that can be converted to a string to provide
1236 information about the registration.
1237
1238
1239 A Registered event is generated with an IHandlerRegistration.
1240 """
1241
1242 def unregisterHandler(handler=None, required=None, name=_BLANK):
1243 """Unregister a handler.
1244
1245 A handler is a subscriber that doesn't compute an adapter
1246 but performs some function when called.
1247
1248 A boolean is returned indicating whether the registry was
1249 changed.
1250
1251 Parameters:
1252
1253 handler
1254 This is the object used to handle some event
1255 represented by the objects passed to it. The handler
1256 can be None, in which case any handlers registered for
1257 the given required specifications with the given are
1258 unregistered.
1259
1260 required
1261 This is a sequence of specifications for objects to be
1262 adapted. If omitted, then the value of the factory's
1263 __component_adapts__ attribute will be used. The
1264 __component_adapts__ attribute is usually attribute is
1265 normally set in class definitions using adapts
1266 function, or for callables using the adapter
1267 decorator. If the factory doesn't have a
1268 __component_adapts__ adapts attribute, then this
1269 argument is required.
1270
1271 name
1272 The handler name.
1273
1274 Currently, only the empty string is accepted. Other
1275 strings will be accepted in the future when support for
1276 named handlers is added.
1277
1278 An Unregistered event is generated with an IHandlerRegistration.
1279 """
1280
1281 def registeredHandlers():
1282 """Return an iterable of IHandlerRegistration instances.
1283
1284 These registrations describe the current handler registrations
1285 in the object.
1286 """
1287
1288
1289 class IComponents(IComponentLookup, IComponentRegistry):
1290 """Component registration and access
1291 """
1292
1293
1294 # end formerly in zope.component
This diff has been collapsed as it changes many lines, (654 lines changed) Show them Hide them
@@ -0,0 +1,654 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2006 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Basic components support
15 """
16 from collections import defaultdict
17
18 try:
19 from zope.event import notify
20 except ImportError: # pragma: no cover
21 def notify(*arg, **kw): pass
22
23 from zope.interface.interfaces import ISpecification
24 from zope.interface.interfaces import ComponentLookupError
25 from zope.interface.interfaces import IAdapterRegistration
26 from zope.interface.interfaces import IComponents
27 from zope.interface.interfaces import IHandlerRegistration
28 from zope.interface.interfaces import ISubscriptionAdapterRegistration
29 from zope.interface.interfaces import IUtilityRegistration
30 from zope.interface.interfaces import Registered
31 from zope.interface.interfaces import Unregistered
32
33 from zope.interface.interface import Interface
34 from zope.interface.declarations import implementedBy
35 from zope.interface.declarations import implementer
36 from zope.interface.declarations import implementer_only
37 from zope.interface.declarations import providedBy
38 from zope.interface.adapter import AdapterRegistry
39 from zope.interface._compat import CLASS_TYPES
40 from zope.interface._compat import STRING_TYPES
41
42
43 class _UnhashableComponentCounter(object):
44 # defaultdict(int)-like object for unhashable components
45
46 def __init__(self, otherdict):
47 # [(component, count)]
48 self._data = [item for item in otherdict.items()]
49
50 def __getitem__(self, key):
51 for component, count in self._data:
52 if component == key:
53 return count
54 return 0
55
56 def __setitem__(self, component, count):
57 for i, data in enumerate(self._data):
58 if data[0] == component:
59 self._data[i] = component, count
60 return
61 self._data.append((component, count))
62
63 def __delitem__(self, component):
64 for i, data in enumerate(self._data):
65 if data[0] == component:
66 del self._data[i]
67 return
68 raise KeyError(component) # pragma: no cover
69
70 def _defaultdict_int():
71 return defaultdict(int)
72
73 class _UtilityRegistrations(object):
74
75 def __init__(self, utilities, utility_registrations):
76 # {provided -> {component: count}}
77 self._cache = defaultdict(_defaultdict_int)
78 self._utilities = utilities
79 self._utility_registrations = utility_registrations
80
81 self.__populate_cache()
82
83 def __populate_cache(self):
84 for ((p, _), data) in iter(self._utility_registrations.items()):
85 component = data[0]
86 self.__cache_utility(p, component)
87
88 def __cache_utility(self, provided, component):
89 try:
90 self._cache[provided][component] += 1
91 except TypeError:
92 # The component is not hashable, and we have a dict. Switch to a strategy
93 # that doesn't use hashing.
94 prov = self._cache[provided] = _UnhashableComponentCounter(self._cache[provided])
95 prov[component] += 1
96
97 def __uncache_utility(self, provided, component):
98 provided = self._cache[provided]
99 # It seems like this line could raise a TypeError if component isn't
100 # hashable and we haven't yet switched to _UnhashableComponentCounter. However,
101 # we can't actually get in that situation. In order to get here, we would
102 # have had to cache the utility already which would have switched
103 # the datastructure if needed.
104 count = provided[component]
105 count -= 1
106 if count == 0:
107 del provided[component]
108 else:
109 provided[component] = count
110 return count > 0
111
112 def _is_utility_subscribed(self, provided, component):
113 try:
114 return self._cache[provided][component] > 0
115 except TypeError:
116 # Not hashable and we're still using a dict
117 return False
118
119 def registerUtility(self, provided, name, component, info, factory):
120 subscribed = self._is_utility_subscribed(provided, component)
121
122 self._utility_registrations[(provided, name)] = component, info, factory
123 self._utilities.register((), provided, name, component)
124
125 if not subscribed:
126 self._utilities.subscribe((), provided, component)
127
128 self.__cache_utility(provided, component)
129
130 def unregisterUtility(self, provided, name, component):
131 del self._utility_registrations[(provided, name)]
132 self._utilities.unregister((), provided, name)
133
134 subscribed = self.__uncache_utility(provided, component)
135
136 if not subscribed:
137 self._utilities.unsubscribe((), provided, component)
138
139
140 @implementer(IComponents)
141 class Components(object):
142
143 _v_utility_registrations_cache = None
144
145 def __init__(self, name='', bases=()):
146 # __init__ is used for test cleanup as well as initialization.
147 # XXX add a separate API for test cleanup.
148 assert isinstance(name, STRING_TYPES)
149 self.__name__ = name
150 self._init_registries()
151 self._init_registrations()
152 self.__bases__ = tuple(bases)
153 self._v_utility_registrations_cache = None
154
155 def __repr__(self):
156 return "<%s %s>" % (self.__class__.__name__, self.__name__)
157
158 def __reduce__(self):
159 # Mimic what a persistent.Persistent object does and elide
160 # _v_ attributes so that they don't get saved in ZODB.
161 # This allows us to store things that cannot be pickled in such
162 # attributes.
163 reduction = super(Components, self).__reduce__()
164 # (callable, args, state, listiter, dictiter)
165 # We assume the state is always a dict; the last three items
166 # are technically optional and can be missing or None.
167 filtered_state = {k: v for k, v in reduction[2].items()
168 if not k.startswith('_v_')}
169 reduction = list(reduction)
170 reduction[2] = filtered_state
171 return tuple(reduction)
172
173 def _init_registries(self):
174 # Subclasses have never been required to call this method
175 # if they override it, merely to fill in these two attributes.
176 self.adapters = AdapterRegistry()
177 self.utilities = AdapterRegistry()
178
179 def _init_registrations(self):
180 self._utility_registrations = {}
181 self._adapter_registrations = {}
182 self._subscription_registrations = []
183 self._handler_registrations = []
184
185 @property
186 def _utility_registrations_cache(self):
187 # We use a _v_ attribute internally so that data aren't saved in ZODB,
188 # because this object cannot be pickled.
189 cache = self._v_utility_registrations_cache
190 if (cache is None
191 or cache._utilities is not self.utilities
192 or cache._utility_registrations is not self._utility_registrations):
193 cache = self._v_utility_registrations_cache = _UtilityRegistrations(
194 self.utilities,
195 self._utility_registrations)
196 return cache
197
198 def _getBases(self):
199 # Subclasses might override
200 return self.__dict__.get('__bases__', ())
201
202 def _setBases(self, bases):
203 # Subclasses might override
204 self.adapters.__bases__ = tuple([
205 base.adapters for base in bases])
206 self.utilities.__bases__ = tuple([
207 base.utilities for base in bases])
208 self.__dict__['__bases__'] = tuple(bases)
209
210 __bases__ = property(
211 lambda self: self._getBases(),
212 lambda self, bases: self._setBases(bases),
213 )
214
215 def registerUtility(self, component=None, provided=None, name=u'',
216 info=u'', event=True, factory=None):
217 if factory:
218 if component:
219 raise TypeError("Can't specify factory and component.")
220 component = factory()
221
222 if provided is None:
223 provided = _getUtilityProvided(component)
224
225 if name == u'':
226 name = _getName(component)
227
228 reg = self._utility_registrations.get((provided, name))
229 if reg is not None:
230 if reg[:2] == (component, info):
231 # already registered
232 return
233 self.unregisterUtility(reg[0], provided, name)
234
235 self._utility_registrations_cache.registerUtility(
236 provided, name, component, info, factory)
237
238 if event:
239 notify(Registered(
240 UtilityRegistration(self, provided, name, component, info,
241 factory)
242 ))
243
244 def unregisterUtility(self, component=None, provided=None, name=u'',
245 factory=None):
246 if factory:
247 if component:
248 raise TypeError("Can't specify factory and component.")
249 component = factory()
250
251 if provided is None:
252 if component is None:
253 raise TypeError("Must specify one of component, factory and "
254 "provided")
255 provided = _getUtilityProvided(component)
256
257 old = self._utility_registrations.get((provided, name))
258 if (old is None) or ((component is not None) and
259 (component != old[0])):
260 return False
261
262 if component is None:
263 component = old[0]
264
265 # Note that component is now the old thing registered
266 self._utility_registrations_cache.unregisterUtility(
267 provided, name, component)
268
269 notify(Unregistered(
270 UtilityRegistration(self, provided, name, component, *old[1:])
271 ))
272
273 return True
274
275 def registeredUtilities(self):
276 for ((provided, name), data
277 ) in iter(self._utility_registrations.items()):
278 yield UtilityRegistration(self, provided, name, *data)
279
280 def queryUtility(self, provided, name=u'', default=None):
281 return self.utilities.lookup((), provided, name, default)
282
283 def getUtility(self, provided, name=u''):
284 utility = self.utilities.lookup((), provided, name)
285 if utility is None:
286 raise ComponentLookupError(provided, name)
287 return utility
288
289 def getUtilitiesFor(self, interface):
290 for name, utility in self.utilities.lookupAll((), interface):
291 yield name, utility
292
293 def getAllUtilitiesRegisteredFor(self, interface):
294 return self.utilities.subscriptions((), interface)
295
296 def registerAdapter(self, factory, required=None, provided=None,
297 name=u'', info=u'', event=True):
298 if provided is None:
299 provided = _getAdapterProvided(factory)
300 required = _getAdapterRequired(factory, required)
301 if name == u'':
302 name = _getName(factory)
303 self._adapter_registrations[(required, provided, name)
304 ] = factory, info
305 self.adapters.register(required, provided, name, factory)
306
307 if event:
308 notify(Registered(
309 AdapterRegistration(self, required, provided, name,
310 factory, info)
311 ))
312
313
314 def unregisterAdapter(self, factory=None,
315 required=None, provided=None, name=u'',
316 ):
317 if provided is None:
318 if factory is None:
319 raise TypeError("Must specify one of factory and provided")
320 provided = _getAdapterProvided(factory)
321
322 if (required is None) and (factory is None):
323 raise TypeError("Must specify one of factory and required")
324
325 required = _getAdapterRequired(factory, required)
326 old = self._adapter_registrations.get((required, provided, name))
327 if (old is None) or ((factory is not None) and
328 (factory != old[0])):
329 return False
330
331 del self._adapter_registrations[(required, provided, name)]
332 self.adapters.unregister(required, provided, name)
333
334 notify(Unregistered(
335 AdapterRegistration(self, required, provided, name,
336 *old)
337 ))
338
339 return True
340
341 def registeredAdapters(self):
342 for ((required, provided, name), (component, info)
343 ) in iter(self._adapter_registrations.items()):
344 yield AdapterRegistration(self, required, provided, name,
345 component, info)
346
347 def queryAdapter(self, object, interface, name=u'', default=None):
348 return self.adapters.queryAdapter(object, interface, name, default)
349
350 def getAdapter(self, object, interface, name=u''):
351 adapter = self.adapters.queryAdapter(object, interface, name)
352 if adapter is None:
353 raise ComponentLookupError(object, interface, name)
354 return adapter
355
356 def queryMultiAdapter(self, objects, interface, name=u'',
357 default=None):
358 return self.adapters.queryMultiAdapter(
359 objects, interface, name, default)
360
361 def getMultiAdapter(self, objects, interface, name=u''):
362 adapter = self.adapters.queryMultiAdapter(objects, interface, name)
363 if adapter is None:
364 raise ComponentLookupError(objects, interface, name)
365 return adapter
366
367 def getAdapters(self, objects, provided):
368 for name, factory in self.adapters.lookupAll(
369 list(map(providedBy, objects)),
370 provided):
371 adapter = factory(*objects)
372 if adapter is not None:
373 yield name, adapter
374
375 def registerSubscriptionAdapter(self,
376 factory, required=None, provided=None,
377 name=u'', info=u'',
378 event=True):
379 if name:
380 raise TypeError("Named subscribers are not yet supported")
381 if provided is None:
382 provided = _getAdapterProvided(factory)
383 required = _getAdapterRequired(factory, required)
384 self._subscription_registrations.append(
385 (required, provided, name, factory, info)
386 )
387 self.adapters.subscribe(required, provided, factory)
388
389 if event:
390 notify(Registered(
391 SubscriptionRegistration(self, required, provided, name,
392 factory, info)
393 ))
394
395 def registeredSubscriptionAdapters(self):
396 for data in self._subscription_registrations:
397 yield SubscriptionRegistration(self, *data)
398
399 def unregisterSubscriptionAdapter(self, factory=None,
400 required=None, provided=None, name=u'',
401 ):
402 if name:
403 raise TypeError("Named subscribers are not yet supported")
404 if provided is None:
405 if factory is None:
406 raise TypeError("Must specify one of factory and provided")
407 provided = _getAdapterProvided(factory)
408
409 if (required is None) and (factory is None):
410 raise TypeError("Must specify one of factory and required")
411
412 required = _getAdapterRequired(factory, required)
413
414 if factory is None:
415 new = [(r, p, n, f, i)
416 for (r, p, n, f, i)
417 in self._subscription_registrations
418 if not (r == required and p == provided)
419 ]
420 else:
421 new = [(r, p, n, f, i)
422 for (r, p, n, f, i)
423 in self._subscription_registrations
424 if not (r == required and p == provided and f == factory)
425 ]
426
427 if len(new) == len(self._subscription_registrations):
428 return False
429
430
431 self._subscription_registrations[:] = new
432 self.adapters.unsubscribe(required, provided, factory)
433
434 notify(Unregistered(
435 SubscriptionRegistration(self, required, provided, name,
436 factory, '')
437 ))
438
439 return True
440
441 def subscribers(self, objects, provided):
442 return self.adapters.subscribers(objects, provided)
443
444 def registerHandler(self,
445 factory, required=None,
446 name=u'', info=u'',
447 event=True):
448 if name:
449 raise TypeError("Named handlers are not yet supported")
450 required = _getAdapterRequired(factory, required)
451 self._handler_registrations.append(
452 (required, name, factory, info)
453 )
454 self.adapters.subscribe(required, None, factory)
455
456 if event:
457 notify(Registered(
458 HandlerRegistration(self, required, name, factory, info)
459 ))
460
461 def registeredHandlers(self):
462 for data in self._handler_registrations:
463 yield HandlerRegistration(self, *data)
464
465 def unregisterHandler(self, factory=None, required=None, name=u''):
466 if name:
467 raise TypeError("Named subscribers are not yet supported")
468
469 if (required is None) and (factory is None):
470 raise TypeError("Must specify one of factory and required")
471
472 required = _getAdapterRequired(factory, required)
473
474 if factory is None:
475 new = [(r, n, f, i)
476 for (r, n, f, i)
477 in self._handler_registrations
478 if r != required
479 ]
480 else:
481 new = [(r, n, f, i)
482 for (r, n, f, i)
483 in self._handler_registrations
484 if not (r == required and f == factory)
485 ]
486
487 if len(new) == len(self._handler_registrations):
488 return False
489
490 self._handler_registrations[:] = new
491 self.adapters.unsubscribe(required, None, factory)
492
493 notify(Unregistered(
494 HandlerRegistration(self, required, name, factory, '')
495 ))
496
497 return True
498
499 def handle(self, *objects):
500 self.adapters.subscribers(objects, None)
501
502
503 def _getName(component):
504 try:
505 return component.__component_name__
506 except AttributeError:
507 return u''
508
509 def _getUtilityProvided(component):
510 provided = list(providedBy(component))
511 if len(provided) == 1:
512 return provided[0]
513 raise TypeError(
514 "The utility doesn't provide a single interface "
515 "and no provided interface was specified.")
516
517 def _getAdapterProvided(factory):
518 provided = list(implementedBy(factory))
519 if len(provided) == 1:
520 return provided[0]
521 raise TypeError(
522 "The adapter factory doesn't implement a single interface "
523 "and no provided interface was specified.")
524
525 def _getAdapterRequired(factory, required):
526 if required is None:
527 try:
528 required = factory.__component_adapts__
529 except AttributeError:
530 raise TypeError(
531 "The adapter factory doesn't have a __component_adapts__ "
532 "attribute and no required specifications were specified"
533 )
534 elif ISpecification.providedBy(required):
535 raise TypeError("the required argument should be a list of "
536 "interfaces, not a single interface")
537
538 result = []
539 for r in required:
540 if r is None:
541 r = Interface
542 elif not ISpecification.providedBy(r):
543 if isinstance(r, CLASS_TYPES):
544 r = implementedBy(r)
545 else:
546 raise TypeError("Required specification must be a "
547 "specification or class."
548 )
549 result.append(r)
550 return tuple(result)
551
552
553 @implementer(IUtilityRegistration)
554 class UtilityRegistration(object):
555
556 def __init__(self, registry, provided, name, component, doc, factory=None):
557 (self.registry, self.provided, self.name, self.component, self.info,
558 self.factory
559 ) = registry, provided, name, component, doc, factory
560
561 def __repr__(self):
562 return '%s(%r, %s, %r, %s, %r, %r)' % (
563 self.__class__.__name__,
564 self.registry,
565 getattr(self.provided, '__name__', None), self.name,
566 getattr(self.component, '__name__', repr(self.component)),
567 self.factory, self.info,
568 )
569
570 def __hash__(self):
571 return id(self)
572
573 def __eq__(self, other):
574 return repr(self) == repr(other)
575
576 def __ne__(self, other):
577 return repr(self) != repr(other)
578
579 def __lt__(self, other):
580 return repr(self) < repr(other)
581
582 def __le__(self, other):
583 return repr(self) <= repr(other)
584
585 def __gt__(self, other):
586 return repr(self) > repr(other)
587
588 def __ge__(self, other):
589 return repr(self) >= repr(other)
590
591 @implementer(IAdapterRegistration)
592 class AdapterRegistration(object):
593
594 def __init__(self, registry, required, provided, name, component, doc):
595 (self.registry, self.required, self.provided, self.name,
596 self.factory, self.info
597 ) = registry, required, provided, name, component, doc
598
599 def __repr__(self):
600 return '%s(%r, %s, %s, %r, %s, %r)' % (
601 self.__class__.__name__,
602 self.registry,
603 '[' + ", ".join([r.__name__ for r in self.required]) + ']',
604 getattr(self.provided, '__name__', None), self.name,
605 getattr(self.factory, '__name__', repr(self.factory)), self.info,
606 )
607
608 def __hash__(self):
609 return id(self)
610
611 def __eq__(self, other):
612 return repr(self) == repr(other)
613
614 def __ne__(self, other):
615 return repr(self) != repr(other)
616
617 def __lt__(self, other):
618 return repr(self) < repr(other)
619
620 def __le__(self, other):
621 return repr(self) <= repr(other)
622
623 def __gt__(self, other):
624 return repr(self) > repr(other)
625
626 def __ge__(self, other):
627 return repr(self) >= repr(other)
628
629 @implementer_only(ISubscriptionAdapterRegistration)
630 class SubscriptionRegistration(AdapterRegistration):
631 pass
632
633
634 @implementer_only(IHandlerRegistration)
635 class HandlerRegistration(AdapterRegistration):
636
637 def __init__(self, registry, required, name, handler, doc):
638 (self.registry, self.required, self.name, self.handler, self.info
639 ) = registry, required, name, handler, doc
640
641 @property
642 def factory(self):
643 return self.handler
644
645 provided = None
646
647 def __repr__(self):
648 return '%s(%r, %s, %r, %s, %r)' % (
649 self.__class__.__name__,
650 self.registry,
651 '[' + ", ".join([r.__name__ for r in self.required]) + ']',
652 self.name,
653 getattr(self.factory, '__name__', repr(self.factory)), self.info,
654 )
@@ -0,0 +1,64 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2003 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Compute a resolution order for an object and its bases
15 """
16 __docformat__ = 'restructuredtext'
17
18 def _mergeOrderings(orderings):
19 """Merge multiple orderings so that within-ordering order is preserved
20
21 Orderings are constrained in such a way that if an object appears
22 in two or more orderings, then the suffix that begins with the
23 object must be in both orderings.
24
25 For example:
26
27 >>> _mergeOrderings([
28 ... ['x', 'y', 'z'],
29 ... ['q', 'z'],
30 ... [1, 3, 5],
31 ... ['z']
32 ... ])
33 ['x', 'y', 'q', 1, 3, 5, 'z']
34
35 """
36
37 seen = {}
38 result = []
39 for ordering in reversed(orderings):
40 for o in reversed(ordering):
41 if o not in seen:
42 seen[o] = 1
43 result.insert(0, o)
44
45 return result
46
47 def _flatten(ob):
48 result = [ob]
49 i = 0
50 for ob in iter(result):
51 i += 1
52 # The recursive calls can be avoided by inserting the base classes
53 # into the dynamically growing list directly after the currently
54 # considered object; the iterator makes sure this will keep working
55 # in the future, since it cannot rely on the length of the list
56 # by definition.
57 result[i:i] = ob.__bases__
58 return result
59
60
61 def ro(object):
62 """Compute a "resolution order" for an object
63 """
64 return _mergeOrderings([_flatten(object)])
@@ -0,0 +1,120 b''
1 ##############################################################################
2 #
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
5 #
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
12 #
13 ##############################################################################
14 """Verify interface implementations
15 """
16 from zope.interface.exceptions import BrokenImplementation, DoesNotImplement
17 from zope.interface.exceptions import BrokenMethodImplementation
18 from types import FunctionType, MethodType
19 from zope.interface.interface import fromMethod, fromFunction, Method
20 import sys
21
22 # This will be monkey-patched when running under Zope 2, so leave this
23 # here:
24 MethodTypes = (MethodType, )
25
26
27 def _verify(iface, candidate, tentative=0, vtype=None):
28 """Verify that 'candidate' might correctly implements 'iface'.
29
30 This involves:
31
32 o Making sure the candidate defines all the necessary methods
33
34 o Making sure the methods have the correct signature
35
36 o Making sure the candidate asserts that it implements the interface
37
38 Note that this isn't the same as verifying that the class does
39 implement the interface.
40
41 If optional tentative is true, suppress the "is implemented by" test.
42 """
43
44 if vtype == 'c':
45 tester = iface.implementedBy
46 else:
47 tester = iface.providedBy
48
49 if not tentative and not tester(candidate):
50 raise DoesNotImplement(iface)
51
52 # Here the `desc` is either an `Attribute` or `Method` instance
53 for name, desc in iface.namesAndDescriptions(1):
54 try:
55 attr = getattr(candidate, name)
56 except AttributeError:
57 if (not isinstance(desc, Method)) and vtype == 'c':
58 # We can't verify non-methods on classes, since the
59 # class may provide attrs in it's __init__.
60 continue
61
62 raise BrokenImplementation(iface, name)
63
64 if not isinstance(desc, Method):
65 # If it's not a method, there's nothing else we can test
66 continue
67
68 if isinstance(attr, FunctionType):
69 if sys.version_info[0] >= 3 and isinstance(candidate, type):
70 # This is an "unbound method" in Python 3.
71 meth = fromFunction(attr, iface, name=name,
72 imlevel=1)
73 else:
74 # Nope, just a normal function
75 meth = fromFunction(attr, iface, name=name)
76 elif (isinstance(attr, MethodTypes)
77 and type(attr.__func__) is FunctionType):
78 meth = fromMethod(attr, iface, name)
79 elif isinstance(attr, property) and vtype == 'c':
80 # We without an instance we cannot be sure it's not a
81 # callable.
82 continue
83 else:
84 if not callable(attr):
85 raise BrokenMethodImplementation(name, "Not a method")
86 # sigh, it's callable, but we don't know how to introspect it, so
87 # we have to give it a pass.
88 continue
89
90 # Make sure that the required and implemented method signatures are
91 # the same.
92 desc = desc.getSignatureInfo()
93 meth = meth.getSignatureInfo()
94
95 mess = _incompat(desc, meth)
96 if mess:
97 raise BrokenMethodImplementation(name, mess)
98
99 return True
100
101 def verifyClass(iface, candidate, tentative=0):
102 return _verify(iface, candidate, tentative, vtype='c')
103
104 def verifyObject(iface, candidate, tentative=0):
105 return _verify(iface, candidate, tentative, vtype='o')
106
107 def _incompat(required, implemented):
108 #if (required['positional'] !=
109 # implemented['positional'][:len(required['positional'])]
110 # and implemented['kwargs'] is None):
111 # return 'imlementation has different argument names'
112 if len(implemented['required']) > len(required['required']):
113 return 'implementation requires too many arguments'
114 if ((len(implemented['positional']) < len(required['positional']))
115 and not implemented['varargs']):
116 return "implementation doesn't allow enough arguments"
117 if required['kwargs'] and not implemented['kwargs']:
118 return "implementation doesn't support keyword arguments"
119 if required['varargs'] and not implemented['varargs']:
120 return "implementation doesn't support variable arguments"
General Comments 0
You need to be logged in to leave comments. Login now