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