##// 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 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """Interfaces
14 """Interfaces
15
15
16 This package implements the Python "scarecrow" proposal.
16 This package implements the Python "scarecrow" proposal.
17
17
18 The package exports two objects, `Interface` and `Attribute` directly. It also
18 The package exports two objects, `Interface` and `Attribute` directly. It also
19 exports several helper methods. Interface is used to create an interface with
19 exports several helper methods. Interface is used to create an interface with
20 a class statement, as in:
20 a class statement, as in:
21
21
22 class IMyInterface(Interface):
22 class IMyInterface(Interface):
23 '''Interface documentation
23 '''Interface documentation
24 '''
24 '''
25
25
26 def meth(arg1, arg2):
26 def meth(arg1, arg2):
27 '''Documentation for meth
27 '''Documentation for meth
28 '''
28 '''
29
29
30 # Note that there is no self argument
30 # Note that there is no self argument
31
31
32 To find out what you can do with interfaces, see the interface
32 To find out what you can do with interfaces, see the interface
33 interface, `IInterface` in the `interfaces` module.
33 interface, `IInterface` in the `interfaces` module.
34
34
35 The package has several public modules:
35 The package has several public modules:
36
36
37 o `declarations` provides utilities to declare interfaces on objects. It
37 o `declarations` provides utilities to declare interfaces on objects. It
38 also provides a wide range of helpful utilities that aid in managing
38 also provides a wide range of helpful utilities that aid in managing
39 declared interfaces. Most of its public names are however imported here.
39 declared interfaces. Most of its public names are however imported here.
40
40
41 o `document` has a utility for documenting an interface as structured text.
41 o `document` has a utility for documenting an interface as structured text.
42
42
43 o `exceptions` has the interface-defined exceptions
43 o `exceptions` has the interface-defined exceptions
44
44
45 o `interfaces` contains a list of all public interfaces for this package.
45 o `interfaces` contains a list of all public interfaces for this package.
46
46
47 o `verify` has utilities for verifying implementations of interfaces.
47 o `verify` has utilities for verifying implementations of interfaces.
48
48
49 See the module doc strings for more information.
49 See the module doc strings for more information.
50 """
50 """
51
52 from __future__ import absolute_import
53
51 __docformat__ = 'restructuredtext'
54 __docformat__ = 'restructuredtext'
52
55
53 from zope.interface.interface import Interface
56 from .interface import Interface
54 from zope.interface.interface import _wire
57 from .interface import _wire
55
58
56 # Need to actually get the interface elements to implement the right interfaces
59 # Need to actually get the interface elements to implement the right interfaces
57 _wire()
60 _wire()
58 del _wire
61 del _wire
59
62
60 from zope.interface.declarations import Declaration
63 from .declarations import Declaration
61 from zope.interface.declarations import alsoProvides
64 from .declarations import alsoProvides
62 from zope.interface.declarations import classImplements
65 from .declarations import classImplements
63 from zope.interface.declarations import classImplementsOnly
66 from .declarations import classImplementsOnly
64 from zope.interface.declarations import classProvides
67 from .declarations import classProvides
65 from zope.interface.declarations import directlyProvidedBy
68 from .declarations import directlyProvidedBy
66 from zope.interface.declarations import directlyProvides
69 from .declarations import directlyProvides
67 from zope.interface.declarations import implementedBy
70 from .declarations import implementedBy
68 from zope.interface.declarations import implementer
71 from .declarations import implementer
69 from zope.interface.declarations import implementer_only
72 from .declarations import implementer_only
70 from zope.interface.declarations import implements
73 from .declarations import implements
71 from zope.interface.declarations import implementsOnly
74 from .declarations import implementsOnly
72 from zope.interface.declarations import moduleProvides
75 from .declarations import moduleProvides
73 from zope.interface.declarations import named
76 from .declarations import named
74 from zope.interface.declarations import noLongerProvides
77 from .declarations import noLongerProvides
75 from zope.interface.declarations import providedBy
78 from .declarations import providedBy
76 from zope.interface.declarations import provider
79 from .declarations import provider
77 from zope.interface.exceptions import Invalid
80 from .exceptions import Invalid
78 from zope.interface.interface import Attribute
81 from .interface import Attribute
79 from zope.interface.interface import invariant
82 from .interface import invariant
80 from zope.interface.interface import taggedValue
83 from .interface import taggedValue
81
84
82 # The following are to make spec pickles cleaner
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 moduleProvides(IInterfaceDeclaration)
91 moduleProvides(IInterfaceDeclaration)
89
92
90 __all__ = ('Interface', 'Attribute') + tuple(IInterfaceDeclaration)
93 __all__ = ('Interface', 'Attribute') + tuple(IInterfaceDeclaration)
@@ -1,58 +1,60 b''
1 ##############################################################################
1 ##############################################################################
2 #
2 #
3 # Copyright (c) 2006 Zope Foundation and Contributors.
3 # Copyright (c) 2006 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """Basic components support
14 """Basic components support
15 """
15 """
16 from __future__ import absolute_import
17
16 import sys
18 import sys
17 import types
19 import types
18
20
19 if sys.version_info[0] < 3:
21 if sys.version_info[0] < 3:
20
22
21 def _normalize_name(name):
23 def _normalize_name(name):
22 if isinstance(name, basestring):
24 if isinstance(name, basestring):
23 return unicode(name)
25 return unicode(name)
24 raise TypeError("name must be a regular or unicode string")
26 raise TypeError("name must be a regular or unicode string")
25
27
26 CLASS_TYPES = (type, types.ClassType)
28 CLASS_TYPES = (type, types.ClassType)
27 STRING_TYPES = (basestring,)
29 STRING_TYPES = (basestring,)
28
30
29 _BUILTINS = '__builtin__'
31 _BUILTINS = '__builtin__'
30
32
31 PYTHON3 = False
33 PYTHON3 = False
32 PYTHON2 = True
34 PYTHON2 = True
33
35
34 else:
36 else:
35
37
36 def _normalize_name(name):
38 def _normalize_name(name):
37 if isinstance(name, bytes):
39 if isinstance(name, bytes):
38 name = str(name, 'ascii')
40 name = str(name, 'ascii')
39 if isinstance(name, str):
41 if isinstance(name, str):
40 return name
42 return name
41 raise TypeError("name must be a string or ASCII-only bytes")
43 raise TypeError("name must be a string or ASCII-only bytes")
42
44
43 CLASS_TYPES = (type,)
45 CLASS_TYPES = (type,)
44 STRING_TYPES = (str,)
46 STRING_TYPES = (str,)
45
47
46 _BUILTINS = 'builtins'
48 _BUILTINS = 'builtins'
47
49
48 PYTHON3 = True
50 PYTHON3 = True
49 PYTHON2 = False
51 PYTHON2 = False
50
52
51 def _skip_under_py3k(test_method):
53 def _skip_under_py3k(test_method):
52 import unittest
54 import unittest
53 return unittest.skipIf(sys.version_info[0] >= 3, "Only on Python 2")(test_method)
55 return unittest.skipIf(sys.version_info[0] >= 3, "Only on Python 2")(test_method)
54
56
55
57
56 def _skip_under_py2(test_method):
58 def _skip_under_py2(test_method):
57 import unittest
59 import unittest
58 return unittest.skipIf(sys.version_info[0] < 3, "Only on Python 3")(test_method)
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 # Copyright (c) 2002 Zope Foundation and Contributors.
3 # Copyright (c) 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """Adapter-style interface registry
14 """Adapter-style interface registry
15
15
16 See Adapter class.
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 def _flatten(implements, include_None=0):
23 def _flatten(implements, include_None=0):
21
24
22 try:
25 try:
23 r = implements.flattened()
26 r = implements.flattened()
24 except AttributeError:
27 except AttributeError:
25 if implements is None:
28 if implements is None:
26 r=()
29 r=()
27 else:
30 else:
28 r = Declaration(implements).flattened()
31 r = Declaration(implements).flattened()
29
32
30 if not include_None:
33 if not include_None:
31 return r
34 return r
32
35
33 r = list(r)
36 r = list(r)
34 r.append(None)
37 r.append(None)
35 return r
38 return r
@@ -1,1726 +1,1727 b''
1 /*###########################################################################
1 /*###########################################################################
2 #
2 #
3 # Copyright (c) 2003 Zope Foundation and Contributors.
3 # Copyright (c) 2003 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ############################################################################*/
13 ############################################################################*/
14
14
15 #include "Python.h"
15 #include "Python.h"
16 #include "structmember.h"
16 #include "structmember.h"
17
17
18 #define TYPE(O) ((PyTypeObject*)(O))
18 #define TYPE(O) ((PyTypeObject*)(O))
19 #define OBJECT(O) ((PyObject*)(O))
19 #define OBJECT(O) ((PyObject*)(O))
20 #define CLASSIC(O) ((PyClassObject*)(O))
20 #define CLASSIC(O) ((PyClassObject*)(O))
21 #ifndef PyVarObject_HEAD_INIT
21 #ifndef PyVarObject_HEAD_INIT
22 #define PyVarObject_HEAD_INIT(a, b) PyObject_HEAD_INIT(a) b,
22 #define PyVarObject_HEAD_INIT(a, b) PyObject_HEAD_INIT(a) b,
23 #endif
23 #endif
24 #ifndef Py_TYPE
24 #ifndef Py_TYPE
25 #define Py_TYPE(o) ((o)->ob_type)
25 #define Py_TYPE(o) ((o)->ob_type)
26 #endif
26 #endif
27
27
28 #if PY_MAJOR_VERSION >= 3
28 #if PY_MAJOR_VERSION >= 3
29 #define PY3K
29 #define PY3K
30 #endif
30 #endif
31
31
32 static PyObject *str__dict__, *str__implemented__, *strextends;
32 static PyObject *str__dict__, *str__implemented__, *strextends;
33 static PyObject *BuiltinImplementationSpecifications, *str__provides__;
33 static PyObject *BuiltinImplementationSpecifications, *str__provides__;
34 static PyObject *str__class__, *str__providedBy__;
34 static PyObject *str__class__, *str__providedBy__;
35 static PyObject *empty, *fallback, *str_implied, *str_cls, *str_implements;
35 static PyObject *empty, *fallback, *str_implied, *str_cls, *str_implements;
36 static PyObject *str__conform__, *str_call_conform, *adapter_hooks;
36 static PyObject *str__conform__, *str_call_conform, *adapter_hooks;
37 static PyObject *str_uncached_lookup, *str_uncached_lookupAll;
37 static PyObject *str_uncached_lookup, *str_uncached_lookupAll;
38 static PyObject *str_uncached_subscriptions;
38 static PyObject *str_uncached_subscriptions;
39 static PyObject *str_registry, *strro, *str_generation, *strchanged;
39 static PyObject *str_registry, *strro, *str_generation, *strchanged;
40
40
41 static PyTypeObject *Implements;
41 static PyTypeObject *Implements;
42
42
43 static int imported_declarations = 0;
43 static int imported_declarations = 0;
44
44
45 static int
45 static int
46 import_declarations(void)
46 import_declarations(void)
47 {
47 {
48 PyObject *declarations, *i;
48 PyObject *declarations, *i;
49
49
50 declarations = PyImport_ImportModule("zope.interface.declarations");
50 declarations = PyImport_ImportModule(
51 "mercurial.thirdparty.zope.interface.declarations");
51 if (declarations == NULL)
52 if (declarations == NULL)
52 return -1;
53 return -1;
53
54
54 BuiltinImplementationSpecifications = PyObject_GetAttrString(
55 BuiltinImplementationSpecifications = PyObject_GetAttrString(
55 declarations, "BuiltinImplementationSpecifications");
56 declarations, "BuiltinImplementationSpecifications");
56 if (BuiltinImplementationSpecifications == NULL)
57 if (BuiltinImplementationSpecifications == NULL)
57 return -1;
58 return -1;
58
59
59 empty = PyObject_GetAttrString(declarations, "_empty");
60 empty = PyObject_GetAttrString(declarations, "_empty");
60 if (empty == NULL)
61 if (empty == NULL)
61 return -1;
62 return -1;
62
63
63 fallback = PyObject_GetAttrString(declarations, "implementedByFallback");
64 fallback = PyObject_GetAttrString(declarations, "implementedByFallback");
64 if (fallback == NULL)
65 if (fallback == NULL)
65 return -1;
66 return -1;
66
67
67
68
68
69
69 i = PyObject_GetAttrString(declarations, "Implements");
70 i = PyObject_GetAttrString(declarations, "Implements");
70 if (i == NULL)
71 if (i == NULL)
71 return -1;
72 return -1;
72
73
73 if (! PyType_Check(i))
74 if (! PyType_Check(i))
74 {
75 {
75 PyErr_SetString(PyExc_TypeError,
76 PyErr_SetString(PyExc_TypeError,
76 "zope.interface.declarations.Implements is not a type");
77 "zope.interface.declarations.Implements is not a type");
77 return -1;
78 return -1;
78 }
79 }
79
80
80 Implements = (PyTypeObject *)i;
81 Implements = (PyTypeObject *)i;
81
82
82 Py_DECREF(declarations);
83 Py_DECREF(declarations);
83
84
84 imported_declarations = 1;
85 imported_declarations = 1;
85 return 0;
86 return 0;
86 }
87 }
87
88
88 static PyTypeObject SpecType; /* Forward */
89 static PyTypeObject SpecType; /* Forward */
89
90
90 static PyObject *
91 static PyObject *
91 implementedByFallback(PyObject *cls)
92 implementedByFallback(PyObject *cls)
92 {
93 {
93 if (imported_declarations == 0 && import_declarations() < 0)
94 if (imported_declarations == 0 && import_declarations() < 0)
94 return NULL;
95 return NULL;
95
96
96 return PyObject_CallFunctionObjArgs(fallback, cls, NULL);
97 return PyObject_CallFunctionObjArgs(fallback, cls, NULL);
97 }
98 }
98
99
99 static PyObject *
100 static PyObject *
100 implementedBy(PyObject *ignored, PyObject *cls)
101 implementedBy(PyObject *ignored, PyObject *cls)
101 {
102 {
102 /* Fast retrieval of implements spec, if possible, to optimize
103 /* Fast retrieval of implements spec, if possible, to optimize
103 common case. Use fallback code if we get stuck.
104 common case. Use fallback code if we get stuck.
104 */
105 */
105
106
106 PyObject *dict = NULL, *spec;
107 PyObject *dict = NULL, *spec;
107
108
108 if (PyType_Check(cls))
109 if (PyType_Check(cls))
109 {
110 {
110 dict = TYPE(cls)->tp_dict;
111 dict = TYPE(cls)->tp_dict;
111 Py_XINCREF(dict);
112 Py_XINCREF(dict);
112 }
113 }
113
114
114 if (dict == NULL)
115 if (dict == NULL)
115 dict = PyObject_GetAttr(cls, str__dict__);
116 dict = PyObject_GetAttr(cls, str__dict__);
116
117
117 if (dict == NULL)
118 if (dict == NULL)
118 {
119 {
119 /* Probably a security proxied class, use more expensive fallback code */
120 /* Probably a security proxied class, use more expensive fallback code */
120 PyErr_Clear();
121 PyErr_Clear();
121 return implementedByFallback(cls);
122 return implementedByFallback(cls);
122 }
123 }
123
124
124 spec = PyObject_GetItem(dict, str__implemented__);
125 spec = PyObject_GetItem(dict, str__implemented__);
125 Py_DECREF(dict);
126 Py_DECREF(dict);
126 if (spec)
127 if (spec)
127 {
128 {
128 if (imported_declarations == 0 && import_declarations() < 0)
129 if (imported_declarations == 0 && import_declarations() < 0)
129 return NULL;
130 return NULL;
130
131
131 if (PyObject_TypeCheck(spec, Implements))
132 if (PyObject_TypeCheck(spec, Implements))
132 return spec;
133 return spec;
133
134
134 /* Old-style declaration, use more expensive fallback code */
135 /* Old-style declaration, use more expensive fallback code */
135 Py_DECREF(spec);
136 Py_DECREF(spec);
136 return implementedByFallback(cls);
137 return implementedByFallback(cls);
137 }
138 }
138
139
139 PyErr_Clear();
140 PyErr_Clear();
140
141
141 /* Maybe we have a builtin */
142 /* Maybe we have a builtin */
142 if (imported_declarations == 0 && import_declarations() < 0)
143 if (imported_declarations == 0 && import_declarations() < 0)
143 return NULL;
144 return NULL;
144
145
145 spec = PyDict_GetItem(BuiltinImplementationSpecifications, cls);
146 spec = PyDict_GetItem(BuiltinImplementationSpecifications, cls);
146 if (spec != NULL)
147 if (spec != NULL)
147 {
148 {
148 Py_INCREF(spec);
149 Py_INCREF(spec);
149 return spec;
150 return spec;
150 }
151 }
151
152
152 /* We're stuck, use fallback */
153 /* We're stuck, use fallback */
153 return implementedByFallback(cls);
154 return implementedByFallback(cls);
154 }
155 }
155
156
156 static PyObject *
157 static PyObject *
157 getObjectSpecification(PyObject *ignored, PyObject *ob)
158 getObjectSpecification(PyObject *ignored, PyObject *ob)
158 {
159 {
159 PyObject *cls, *result;
160 PyObject *cls, *result;
160
161
161 result = PyObject_GetAttr(ob, str__provides__);
162 result = PyObject_GetAttr(ob, str__provides__);
162 if (result != NULL && PyObject_TypeCheck(result, &SpecType))
163 if (result != NULL && PyObject_TypeCheck(result, &SpecType))
163 return result;
164 return result;
164
165
165 PyErr_Clear();
166 PyErr_Clear();
166
167
167 /* We do a getattr here so as not to be defeated by proxies */
168 /* We do a getattr here so as not to be defeated by proxies */
168 cls = PyObject_GetAttr(ob, str__class__);
169 cls = PyObject_GetAttr(ob, str__class__);
169 if (cls == NULL)
170 if (cls == NULL)
170 {
171 {
171 PyErr_Clear();
172 PyErr_Clear();
172 if (imported_declarations == 0 && import_declarations() < 0)
173 if (imported_declarations == 0 && import_declarations() < 0)
173 return NULL;
174 return NULL;
174 Py_INCREF(empty);
175 Py_INCREF(empty);
175 return empty;
176 return empty;
176 }
177 }
177
178
178 result = implementedBy(NULL, cls);
179 result = implementedBy(NULL, cls);
179 Py_DECREF(cls);
180 Py_DECREF(cls);
180
181
181 return result;
182 return result;
182 }
183 }
183
184
184 static PyObject *
185 static PyObject *
185 providedBy(PyObject *ignored, PyObject *ob)
186 providedBy(PyObject *ignored, PyObject *ob)
186 {
187 {
187 PyObject *result, *cls, *cp;
188 PyObject *result, *cls, *cp;
188
189
189 result = PyObject_GetAttr(ob, str__providedBy__);
190 result = PyObject_GetAttr(ob, str__providedBy__);
190 if (result == NULL)
191 if (result == NULL)
191 {
192 {
192 PyErr_Clear();
193 PyErr_Clear();
193 return getObjectSpecification(NULL, ob);
194 return getObjectSpecification(NULL, ob);
194 }
195 }
195
196
196
197
197 /* We want to make sure we have a spec. We can't do a type check
198 /* We want to make sure we have a spec. We can't do a type check
198 because we may have a proxy, so we'll just try to get the
199 because we may have a proxy, so we'll just try to get the
199 only attribute.
200 only attribute.
200 */
201 */
201 if (PyObject_TypeCheck(result, &SpecType)
202 if (PyObject_TypeCheck(result, &SpecType)
202 ||
203 ||
203 PyObject_HasAttr(result, strextends)
204 PyObject_HasAttr(result, strextends)
204 )
205 )
205 return result;
206 return result;
206
207
207 /*
208 /*
208 The object's class doesn't understand descriptors.
209 The object's class doesn't understand descriptors.
209 Sigh. We need to get an object descriptor, but we have to be
210 Sigh. We need to get an object descriptor, but we have to be
210 careful. We want to use the instance's __provides__,l if
211 careful. We want to use the instance's __provides__,l if
211 there is one, but only if it didn't come from the class.
212 there is one, but only if it didn't come from the class.
212 */
213 */
213 Py_DECREF(result);
214 Py_DECREF(result);
214
215
215 cls = PyObject_GetAttr(ob, str__class__);
216 cls = PyObject_GetAttr(ob, str__class__);
216 if (cls == NULL)
217 if (cls == NULL)
217 return NULL;
218 return NULL;
218
219
219 result = PyObject_GetAttr(ob, str__provides__);
220 result = PyObject_GetAttr(ob, str__provides__);
220 if (result == NULL)
221 if (result == NULL)
221 {
222 {
222 /* No __provides__, so just fall back to implementedBy */
223 /* No __provides__, so just fall back to implementedBy */
223 PyErr_Clear();
224 PyErr_Clear();
224 result = implementedBy(NULL, cls);
225 result = implementedBy(NULL, cls);
225 Py_DECREF(cls);
226 Py_DECREF(cls);
226 return result;
227 return result;
227 }
228 }
228
229
229 cp = PyObject_GetAttr(cls, str__provides__);
230 cp = PyObject_GetAttr(cls, str__provides__);
230 if (cp == NULL)
231 if (cp == NULL)
231 {
232 {
232 /* The the class has no provides, assume we're done: */
233 /* The the class has no provides, assume we're done: */
233 PyErr_Clear();
234 PyErr_Clear();
234 Py_DECREF(cls);
235 Py_DECREF(cls);
235 return result;
236 return result;
236 }
237 }
237
238
238 if (cp == result)
239 if (cp == result)
239 {
240 {
240 /*
241 /*
241 Oops, we got the provides from the class. This means
242 Oops, we got the provides from the class. This means
242 the object doesn't have it's own. We should use implementedBy
243 the object doesn't have it's own. We should use implementedBy
243 */
244 */
244 Py_DECREF(result);
245 Py_DECREF(result);
245 result = implementedBy(NULL, cls);
246 result = implementedBy(NULL, cls);
246 }
247 }
247
248
248 Py_DECREF(cls);
249 Py_DECREF(cls);
249 Py_DECREF(cp);
250 Py_DECREF(cp);
250
251
251 return result;
252 return result;
252 }
253 }
253
254
254 /*
255 /*
255 Get an attribute from an inst dict. Return a borrowed reference.
256 Get an attribute from an inst dict. Return a borrowed reference.
256
257
257 This has a number of advantages:
258 This has a number of advantages:
258
259
259 - It avoids layers of Python api
260 - It avoids layers of Python api
260
261
261 - It doesn't waste time looking for descriptors
262 - It doesn't waste time looking for descriptors
262
263
263 - It fails wo raising an exception, although that shouldn't really
264 - It fails wo raising an exception, although that shouldn't really
264 matter.
265 matter.
265
266
266 */
267 */
267 static PyObject *
268 static PyObject *
268 inst_attr(PyObject *self, PyObject *name)
269 inst_attr(PyObject *self, PyObject *name)
269 {
270 {
270 PyObject **dictp, *v;
271 PyObject **dictp, *v;
271
272
272 dictp = _PyObject_GetDictPtr(self);
273 dictp = _PyObject_GetDictPtr(self);
273 if (dictp && *dictp && (v = PyDict_GetItem(*dictp, name)))
274 if (dictp && *dictp && (v = PyDict_GetItem(*dictp, name)))
274 return v;
275 return v;
275 PyErr_SetObject(PyExc_AttributeError, name);
276 PyErr_SetObject(PyExc_AttributeError, name);
276 return NULL;
277 return NULL;
277 }
278 }
278
279
279
280
280 static PyObject *
281 static PyObject *
281 Spec_extends(PyObject *self, PyObject *other)
282 Spec_extends(PyObject *self, PyObject *other)
282 {
283 {
283 PyObject *implied;
284 PyObject *implied;
284
285
285 implied = inst_attr(self, str_implied);
286 implied = inst_attr(self, str_implied);
286 if (implied == NULL)
287 if (implied == NULL)
287 return NULL;
288 return NULL;
288
289
289 #ifdef Py_True
290 #ifdef Py_True
290 if (PyDict_GetItem(implied, other) != NULL)
291 if (PyDict_GetItem(implied, other) != NULL)
291 {
292 {
292 Py_INCREF(Py_True);
293 Py_INCREF(Py_True);
293 return Py_True;
294 return Py_True;
294 }
295 }
295 Py_INCREF(Py_False);
296 Py_INCREF(Py_False);
296 return Py_False;
297 return Py_False;
297 #else
298 #else
298 return PyInt_FromLong(PyDict_GetItem(implied, other) != NULL);
299 return PyInt_FromLong(PyDict_GetItem(implied, other) != NULL);
299 #endif
300 #endif
300 }
301 }
301
302
302 static char Spec_extends__doc__[] =
303 static char Spec_extends__doc__[] =
303 "Test whether a specification is or extends another"
304 "Test whether a specification is or extends another"
304 ;
305 ;
305
306
306 static char Spec_providedBy__doc__[] =
307 static char Spec_providedBy__doc__[] =
307 "Test whether an interface is implemented by the specification"
308 "Test whether an interface is implemented by the specification"
308 ;
309 ;
309
310
310 static PyObject *
311 static PyObject *
311 Spec_call(PyObject *self, PyObject *args, PyObject *kw)
312 Spec_call(PyObject *self, PyObject *args, PyObject *kw)
312 {
313 {
313 PyObject *spec;
314 PyObject *spec;
314
315
315 if (! PyArg_ParseTuple(args, "O", &spec))
316 if (! PyArg_ParseTuple(args, "O", &spec))
316 return NULL;
317 return NULL;
317 return Spec_extends(self, spec);
318 return Spec_extends(self, spec);
318 }
319 }
319
320
320 static PyObject *
321 static PyObject *
321 Spec_providedBy(PyObject *self, PyObject *ob)
322 Spec_providedBy(PyObject *self, PyObject *ob)
322 {
323 {
323 PyObject *decl, *item;
324 PyObject *decl, *item;
324
325
325 decl = providedBy(NULL, ob);
326 decl = providedBy(NULL, ob);
326 if (decl == NULL)
327 if (decl == NULL)
327 return NULL;
328 return NULL;
328
329
329 if (PyObject_TypeCheck(decl, &SpecType))
330 if (PyObject_TypeCheck(decl, &SpecType))
330 item = Spec_extends(decl, self);
331 item = Spec_extends(decl, self);
331 else
332 else
332 /* decl is probably a security proxy. We have to go the long way
333 /* decl is probably a security proxy. We have to go the long way
333 around.
334 around.
334 */
335 */
335 item = PyObject_CallFunctionObjArgs(decl, self, NULL);
336 item = PyObject_CallFunctionObjArgs(decl, self, NULL);
336
337
337 Py_DECREF(decl);
338 Py_DECREF(decl);
338 return item;
339 return item;
339 }
340 }
340
341
341
342
342 static char Spec_implementedBy__doc__[] =
343 static char Spec_implementedBy__doc__[] =
343 "Test whether the specification is implemented by a class or factory.\n"
344 "Test whether the specification is implemented by a class or factory.\n"
344 "Raise TypeError if argument is neither a class nor a callable."
345 "Raise TypeError if argument is neither a class nor a callable."
345 ;
346 ;
346
347
347 static PyObject *
348 static PyObject *
348 Spec_implementedBy(PyObject *self, PyObject *cls)
349 Spec_implementedBy(PyObject *self, PyObject *cls)
349 {
350 {
350 PyObject *decl, *item;
351 PyObject *decl, *item;
351
352
352 decl = implementedBy(NULL, cls);
353 decl = implementedBy(NULL, cls);
353 if (decl == NULL)
354 if (decl == NULL)
354 return NULL;
355 return NULL;
355
356
356 if (PyObject_TypeCheck(decl, &SpecType))
357 if (PyObject_TypeCheck(decl, &SpecType))
357 item = Spec_extends(decl, self);
358 item = Spec_extends(decl, self);
358 else
359 else
359 item = PyObject_CallFunctionObjArgs(decl, self, NULL);
360 item = PyObject_CallFunctionObjArgs(decl, self, NULL);
360
361
361 Py_DECREF(decl);
362 Py_DECREF(decl);
362 return item;
363 return item;
363 }
364 }
364
365
365 static struct PyMethodDef Spec_methods[] = {
366 static struct PyMethodDef Spec_methods[] = {
366 {"providedBy",
367 {"providedBy",
367 (PyCFunction)Spec_providedBy, METH_O,
368 (PyCFunction)Spec_providedBy, METH_O,
368 Spec_providedBy__doc__},
369 Spec_providedBy__doc__},
369 {"implementedBy",
370 {"implementedBy",
370 (PyCFunction)Spec_implementedBy, METH_O,
371 (PyCFunction)Spec_implementedBy, METH_O,
371 Spec_implementedBy__doc__},
372 Spec_implementedBy__doc__},
372 {"isOrExtends", (PyCFunction)Spec_extends, METH_O,
373 {"isOrExtends", (PyCFunction)Spec_extends, METH_O,
373 Spec_extends__doc__},
374 Spec_extends__doc__},
374
375
375 {NULL, NULL} /* sentinel */
376 {NULL, NULL} /* sentinel */
376 };
377 };
377
378
378 static PyTypeObject SpecType = {
379 static PyTypeObject SpecType = {
379 PyVarObject_HEAD_INIT(NULL, 0)
380 PyVarObject_HEAD_INIT(NULL, 0)
380 /* tp_name */ "_interface_coptimizations."
381 /* tp_name */ "_interface_coptimizations."
381 "SpecificationBase",
382 "SpecificationBase",
382 /* tp_basicsize */ 0,
383 /* tp_basicsize */ 0,
383 /* tp_itemsize */ 0,
384 /* tp_itemsize */ 0,
384 /* tp_dealloc */ (destructor)0,
385 /* tp_dealloc */ (destructor)0,
385 /* tp_print */ (printfunc)0,
386 /* tp_print */ (printfunc)0,
386 /* tp_getattr */ (getattrfunc)0,
387 /* tp_getattr */ (getattrfunc)0,
387 /* tp_setattr */ (setattrfunc)0,
388 /* tp_setattr */ (setattrfunc)0,
388 /* tp_compare */ 0,
389 /* tp_compare */ 0,
389 /* tp_repr */ (reprfunc)0,
390 /* tp_repr */ (reprfunc)0,
390 /* tp_as_number */ 0,
391 /* tp_as_number */ 0,
391 /* tp_as_sequence */ 0,
392 /* tp_as_sequence */ 0,
392 /* tp_as_mapping */ 0,
393 /* tp_as_mapping */ 0,
393 /* tp_hash */ (hashfunc)0,
394 /* tp_hash */ (hashfunc)0,
394 /* tp_call */ (ternaryfunc)Spec_call,
395 /* tp_call */ (ternaryfunc)Spec_call,
395 /* tp_str */ (reprfunc)0,
396 /* tp_str */ (reprfunc)0,
396 /* tp_getattro */ (getattrofunc)0,
397 /* tp_getattro */ (getattrofunc)0,
397 /* tp_setattro */ (setattrofunc)0,
398 /* tp_setattro */ (setattrofunc)0,
398 /* tp_as_buffer */ 0,
399 /* tp_as_buffer */ 0,
399 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
400 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
400 "Base type for Specification objects",
401 "Base type for Specification objects",
401 /* tp_traverse */ (traverseproc)0,
402 /* tp_traverse */ (traverseproc)0,
402 /* tp_clear */ (inquiry)0,
403 /* tp_clear */ (inquiry)0,
403 /* tp_richcompare */ (richcmpfunc)0,
404 /* tp_richcompare */ (richcmpfunc)0,
404 /* tp_weaklistoffset */ (long)0,
405 /* tp_weaklistoffset */ (long)0,
405 /* tp_iter */ (getiterfunc)0,
406 /* tp_iter */ (getiterfunc)0,
406 /* tp_iternext */ (iternextfunc)0,
407 /* tp_iternext */ (iternextfunc)0,
407 /* tp_methods */ Spec_methods,
408 /* tp_methods */ Spec_methods,
408 };
409 };
409
410
410 static PyObject *
411 static PyObject *
411 OSD_descr_get(PyObject *self, PyObject *inst, PyObject *cls)
412 OSD_descr_get(PyObject *self, PyObject *inst, PyObject *cls)
412 {
413 {
413 PyObject *provides;
414 PyObject *provides;
414
415
415 if (inst == NULL)
416 if (inst == NULL)
416 return getObjectSpecification(NULL, cls);
417 return getObjectSpecification(NULL, cls);
417
418
418 provides = PyObject_GetAttr(inst, str__provides__);
419 provides = PyObject_GetAttr(inst, str__provides__);
419 if (provides != NULL)
420 if (provides != NULL)
420 return provides;
421 return provides;
421 PyErr_Clear();
422 PyErr_Clear();
422 return implementedBy(NULL, cls);
423 return implementedBy(NULL, cls);
423 }
424 }
424
425
425 static PyTypeObject OSDType = {
426 static PyTypeObject OSDType = {
426 PyVarObject_HEAD_INIT(NULL, 0)
427 PyVarObject_HEAD_INIT(NULL, 0)
427 /* tp_name */ "_interface_coptimizations."
428 /* tp_name */ "_interface_coptimizations."
428 "ObjectSpecificationDescriptor",
429 "ObjectSpecificationDescriptor",
429 /* tp_basicsize */ 0,
430 /* tp_basicsize */ 0,
430 /* tp_itemsize */ 0,
431 /* tp_itemsize */ 0,
431 /* tp_dealloc */ (destructor)0,
432 /* tp_dealloc */ (destructor)0,
432 /* tp_print */ (printfunc)0,
433 /* tp_print */ (printfunc)0,
433 /* tp_getattr */ (getattrfunc)0,
434 /* tp_getattr */ (getattrfunc)0,
434 /* tp_setattr */ (setattrfunc)0,
435 /* tp_setattr */ (setattrfunc)0,
435 /* tp_compare */ 0,
436 /* tp_compare */ 0,
436 /* tp_repr */ (reprfunc)0,
437 /* tp_repr */ (reprfunc)0,
437 /* tp_as_number */ 0,
438 /* tp_as_number */ 0,
438 /* tp_as_sequence */ 0,
439 /* tp_as_sequence */ 0,
439 /* tp_as_mapping */ 0,
440 /* tp_as_mapping */ 0,
440 /* tp_hash */ (hashfunc)0,
441 /* tp_hash */ (hashfunc)0,
441 /* tp_call */ (ternaryfunc)0,
442 /* tp_call */ (ternaryfunc)0,
442 /* tp_str */ (reprfunc)0,
443 /* tp_str */ (reprfunc)0,
443 /* tp_getattro */ (getattrofunc)0,
444 /* tp_getattro */ (getattrofunc)0,
444 /* tp_setattro */ (setattrofunc)0,
445 /* tp_setattro */ (setattrofunc)0,
445 /* tp_as_buffer */ 0,
446 /* tp_as_buffer */ 0,
446 /* tp_flags */ Py_TPFLAGS_DEFAULT
447 /* tp_flags */ Py_TPFLAGS_DEFAULT
447 | Py_TPFLAGS_BASETYPE ,
448 | Py_TPFLAGS_BASETYPE ,
448 "Object Specification Descriptor",
449 "Object Specification Descriptor",
449 /* tp_traverse */ (traverseproc)0,
450 /* tp_traverse */ (traverseproc)0,
450 /* tp_clear */ (inquiry)0,
451 /* tp_clear */ (inquiry)0,
451 /* tp_richcompare */ (richcmpfunc)0,
452 /* tp_richcompare */ (richcmpfunc)0,
452 /* tp_weaklistoffset */ (long)0,
453 /* tp_weaklistoffset */ (long)0,
453 /* tp_iter */ (getiterfunc)0,
454 /* tp_iter */ (getiterfunc)0,
454 /* tp_iternext */ (iternextfunc)0,
455 /* tp_iternext */ (iternextfunc)0,
455 /* tp_methods */ 0,
456 /* tp_methods */ 0,
456 /* tp_members */ 0,
457 /* tp_members */ 0,
457 /* tp_getset */ 0,
458 /* tp_getset */ 0,
458 /* tp_base */ 0,
459 /* tp_base */ 0,
459 /* tp_dict */ 0, /* internal use */
460 /* tp_dict */ 0, /* internal use */
460 /* tp_descr_get */ (descrgetfunc)OSD_descr_get,
461 /* tp_descr_get */ (descrgetfunc)OSD_descr_get,
461 };
462 };
462
463
463 static PyObject *
464 static PyObject *
464 CPB_descr_get(PyObject *self, PyObject *inst, PyObject *cls)
465 CPB_descr_get(PyObject *self, PyObject *inst, PyObject *cls)
465 {
466 {
466 PyObject *mycls, *implements;
467 PyObject *mycls, *implements;
467
468
468 mycls = inst_attr(self, str_cls);
469 mycls = inst_attr(self, str_cls);
469 if (mycls == NULL)
470 if (mycls == NULL)
470 return NULL;
471 return NULL;
471
472
472 if (cls == mycls)
473 if (cls == mycls)
473 {
474 {
474 if (inst == NULL)
475 if (inst == NULL)
475 {
476 {
476 Py_INCREF(self);
477 Py_INCREF(self);
477 return OBJECT(self);
478 return OBJECT(self);
478 }
479 }
479
480
480 implements = inst_attr(self, str_implements);
481 implements = inst_attr(self, str_implements);
481 Py_XINCREF(implements);
482 Py_XINCREF(implements);
482 return implements;
483 return implements;
483 }
484 }
484
485
485 PyErr_SetObject(PyExc_AttributeError, str__provides__);
486 PyErr_SetObject(PyExc_AttributeError, str__provides__);
486 return NULL;
487 return NULL;
487 }
488 }
488
489
489 static PyTypeObject CPBType = {
490 static PyTypeObject CPBType = {
490 PyVarObject_HEAD_INIT(NULL, 0)
491 PyVarObject_HEAD_INIT(NULL, 0)
491 /* tp_name */ "_interface_coptimizations."
492 /* tp_name */ "_interface_coptimizations."
492 "ClassProvidesBase",
493 "ClassProvidesBase",
493 /* tp_basicsize */ 0,
494 /* tp_basicsize */ 0,
494 /* tp_itemsize */ 0,
495 /* tp_itemsize */ 0,
495 /* tp_dealloc */ (destructor)0,
496 /* tp_dealloc */ (destructor)0,
496 /* tp_print */ (printfunc)0,
497 /* tp_print */ (printfunc)0,
497 /* tp_getattr */ (getattrfunc)0,
498 /* tp_getattr */ (getattrfunc)0,
498 /* tp_setattr */ (setattrfunc)0,
499 /* tp_setattr */ (setattrfunc)0,
499 /* tp_compare */ 0,
500 /* tp_compare */ 0,
500 /* tp_repr */ (reprfunc)0,
501 /* tp_repr */ (reprfunc)0,
501 /* tp_as_number */ 0,
502 /* tp_as_number */ 0,
502 /* tp_as_sequence */ 0,
503 /* tp_as_sequence */ 0,
503 /* tp_as_mapping */ 0,
504 /* tp_as_mapping */ 0,
504 /* tp_hash */ (hashfunc)0,
505 /* tp_hash */ (hashfunc)0,
505 /* tp_call */ (ternaryfunc)0,
506 /* tp_call */ (ternaryfunc)0,
506 /* tp_str */ (reprfunc)0,
507 /* tp_str */ (reprfunc)0,
507 /* tp_getattro */ (getattrofunc)0,
508 /* tp_getattro */ (getattrofunc)0,
508 /* tp_setattro */ (setattrofunc)0,
509 /* tp_setattro */ (setattrofunc)0,
509 /* tp_as_buffer */ 0,
510 /* tp_as_buffer */ 0,
510 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
511 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
511 "C Base class for ClassProvides",
512 "C Base class for ClassProvides",
512 /* tp_traverse */ (traverseproc)0,
513 /* tp_traverse */ (traverseproc)0,
513 /* tp_clear */ (inquiry)0,
514 /* tp_clear */ (inquiry)0,
514 /* tp_richcompare */ (richcmpfunc)0,
515 /* tp_richcompare */ (richcmpfunc)0,
515 /* tp_weaklistoffset */ (long)0,
516 /* tp_weaklistoffset */ (long)0,
516 /* tp_iter */ (getiterfunc)0,
517 /* tp_iter */ (getiterfunc)0,
517 /* tp_iternext */ (iternextfunc)0,
518 /* tp_iternext */ (iternextfunc)0,
518 /* tp_methods */ 0,
519 /* tp_methods */ 0,
519 /* tp_members */ 0,
520 /* tp_members */ 0,
520 /* tp_getset */ 0,
521 /* tp_getset */ 0,
521 /* tp_base */ &SpecType,
522 /* tp_base */ &SpecType,
522 /* tp_dict */ 0, /* internal use */
523 /* tp_dict */ 0, /* internal use */
523 /* tp_descr_get */ (descrgetfunc)CPB_descr_get,
524 /* tp_descr_get */ (descrgetfunc)CPB_descr_get,
524 };
525 };
525
526
526 /* ==================================================================== */
527 /* ==================================================================== */
527 /* ========== Begin: __call__ and __adapt__ =========================== */
528 /* ========== Begin: __call__ and __adapt__ =========================== */
528
529
529 /*
530 /*
530 def __adapt__(self, obj):
531 def __adapt__(self, obj):
531 """Adapt an object to the reciever
532 """Adapt an object to the reciever
532 """
533 """
533 if self.providedBy(obj):
534 if self.providedBy(obj):
534 return obj
535 return obj
535
536
536 for hook in adapter_hooks:
537 for hook in adapter_hooks:
537 adapter = hook(self, obj)
538 adapter = hook(self, obj)
538 if adapter is not None:
539 if adapter is not None:
539 return adapter
540 return adapter
540
541
541
542
542 */
543 */
543 static PyObject *
544 static PyObject *
544 __adapt__(PyObject *self, PyObject *obj)
545 __adapt__(PyObject *self, PyObject *obj)
545 {
546 {
546 PyObject *decl, *args, *adapter;
547 PyObject *decl, *args, *adapter;
547 int implements, i, l;
548 int implements, i, l;
548
549
549 decl = providedBy(NULL, obj);
550 decl = providedBy(NULL, obj);
550 if (decl == NULL)
551 if (decl == NULL)
551 return NULL;
552 return NULL;
552
553
553 if (PyObject_TypeCheck(decl, &SpecType))
554 if (PyObject_TypeCheck(decl, &SpecType))
554 {
555 {
555 PyObject *implied;
556 PyObject *implied;
556
557
557 implied = inst_attr(decl, str_implied);
558 implied = inst_attr(decl, str_implied);
558 if (implied == NULL)
559 if (implied == NULL)
559 {
560 {
560 Py_DECREF(decl);
561 Py_DECREF(decl);
561 return NULL;
562 return NULL;
562 }
563 }
563
564
564 implements = PyDict_GetItem(implied, self) != NULL;
565 implements = PyDict_GetItem(implied, self) != NULL;
565 Py_DECREF(decl);
566 Py_DECREF(decl);
566 }
567 }
567 else
568 else
568 {
569 {
569 /* decl is probably a security proxy. We have to go the long way
570 /* decl is probably a security proxy. We have to go the long way
570 around.
571 around.
571 */
572 */
572 PyObject *r;
573 PyObject *r;
573 r = PyObject_CallFunctionObjArgs(decl, self, NULL);
574 r = PyObject_CallFunctionObjArgs(decl, self, NULL);
574 Py_DECREF(decl);
575 Py_DECREF(decl);
575 if (r == NULL)
576 if (r == NULL)
576 return NULL;
577 return NULL;
577 implements = PyObject_IsTrue(r);
578 implements = PyObject_IsTrue(r);
578 Py_DECREF(r);
579 Py_DECREF(r);
579 }
580 }
580
581
581 if (implements)
582 if (implements)
582 {
583 {
583 Py_INCREF(obj);
584 Py_INCREF(obj);
584 return obj;
585 return obj;
585 }
586 }
586
587
587 l = PyList_GET_SIZE(adapter_hooks);
588 l = PyList_GET_SIZE(adapter_hooks);
588 args = PyTuple_New(2);
589 args = PyTuple_New(2);
589 if (args == NULL)
590 if (args == NULL)
590 return NULL;
591 return NULL;
591 Py_INCREF(self);
592 Py_INCREF(self);
592 PyTuple_SET_ITEM(args, 0, self);
593 PyTuple_SET_ITEM(args, 0, self);
593 Py_INCREF(obj);
594 Py_INCREF(obj);
594 PyTuple_SET_ITEM(args, 1, obj);
595 PyTuple_SET_ITEM(args, 1, obj);
595 for (i = 0; i < l; i++)
596 for (i = 0; i < l; i++)
596 {
597 {
597 adapter = PyObject_CallObject(PyList_GET_ITEM(adapter_hooks, i), args);
598 adapter = PyObject_CallObject(PyList_GET_ITEM(adapter_hooks, i), args);
598 if (adapter == NULL || adapter != Py_None)
599 if (adapter == NULL || adapter != Py_None)
599 {
600 {
600 Py_DECREF(args);
601 Py_DECREF(args);
601 return adapter;
602 return adapter;
602 }
603 }
603 Py_DECREF(adapter);
604 Py_DECREF(adapter);
604 }
605 }
605
606
606 Py_DECREF(args);
607 Py_DECREF(args);
607
608
608 Py_INCREF(Py_None);
609 Py_INCREF(Py_None);
609 return Py_None;
610 return Py_None;
610 }
611 }
611
612
612 static struct PyMethodDef ib_methods[] = {
613 static struct PyMethodDef ib_methods[] = {
613 {"__adapt__", (PyCFunction)__adapt__, METH_O,
614 {"__adapt__", (PyCFunction)__adapt__, METH_O,
614 "Adapt an object to the reciever"},
615 "Adapt an object to the reciever"},
615 {NULL, NULL} /* sentinel */
616 {NULL, NULL} /* sentinel */
616 };
617 };
617
618
618 /*
619 /*
619 def __call__(self, obj, alternate=_marker):
620 def __call__(self, obj, alternate=_marker):
620 conform = getattr(obj, '__conform__', None)
621 conform = getattr(obj, '__conform__', None)
621 if conform is not None:
622 if conform is not None:
622 adapter = self._call_conform(conform)
623 adapter = self._call_conform(conform)
623 if adapter is not None:
624 if adapter is not None:
624 return adapter
625 return adapter
625
626
626 adapter = self.__adapt__(obj)
627 adapter = self.__adapt__(obj)
627
628
628 if adapter is not None:
629 if adapter is not None:
629 return adapter
630 return adapter
630 elif alternate is not _marker:
631 elif alternate is not _marker:
631 return alternate
632 return alternate
632 else:
633 else:
633 raise TypeError("Could not adapt", obj, self)
634 raise TypeError("Could not adapt", obj, self)
634 */
635 */
635 static PyObject *
636 static PyObject *
636 ib_call(PyObject *self, PyObject *args, PyObject *kwargs)
637 ib_call(PyObject *self, PyObject *args, PyObject *kwargs)
637 {
638 {
638 PyObject *conform, *obj, *alternate=NULL, *adapter;
639 PyObject *conform, *obj, *alternate=NULL, *adapter;
639
640
640 static char *kwlist[] = {"obj", "alternate", NULL};
641 static char *kwlist[] = {"obj", "alternate", NULL};
641
642
642 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist,
643 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist,
643 &obj, &alternate))
644 &obj, &alternate))
644 return NULL;
645 return NULL;
645
646
646 conform = PyObject_GetAttr(obj, str__conform__);
647 conform = PyObject_GetAttr(obj, str__conform__);
647 if (conform != NULL)
648 if (conform != NULL)
648 {
649 {
649 adapter = PyObject_CallMethodObjArgs(self, str_call_conform,
650 adapter = PyObject_CallMethodObjArgs(self, str_call_conform,
650 conform, NULL);
651 conform, NULL);
651 Py_DECREF(conform);
652 Py_DECREF(conform);
652 if (adapter == NULL || adapter != Py_None)
653 if (adapter == NULL || adapter != Py_None)
653 return adapter;
654 return adapter;
654 Py_DECREF(adapter);
655 Py_DECREF(adapter);
655 }
656 }
656 else
657 else
657 PyErr_Clear();
658 PyErr_Clear();
658
659
659 adapter = __adapt__(self, obj);
660 adapter = __adapt__(self, obj);
660 if (adapter == NULL || adapter != Py_None)
661 if (adapter == NULL || adapter != Py_None)
661 return adapter;
662 return adapter;
662 Py_DECREF(adapter);
663 Py_DECREF(adapter);
663
664
664 if (alternate != NULL)
665 if (alternate != NULL)
665 {
666 {
666 Py_INCREF(alternate);
667 Py_INCREF(alternate);
667 return alternate;
668 return alternate;
668 }
669 }
669
670
670 adapter = Py_BuildValue("sOO", "Could not adapt", obj, self);
671 adapter = Py_BuildValue("sOO", "Could not adapt", obj, self);
671 if (adapter != NULL)
672 if (adapter != NULL)
672 {
673 {
673 PyErr_SetObject(PyExc_TypeError, adapter);
674 PyErr_SetObject(PyExc_TypeError, adapter);
674 Py_DECREF(adapter);
675 Py_DECREF(adapter);
675 }
676 }
676 return NULL;
677 return NULL;
677 }
678 }
678
679
679 static PyTypeObject InterfaceBase = {
680 static PyTypeObject InterfaceBase = {
680 PyVarObject_HEAD_INIT(NULL, 0)
681 PyVarObject_HEAD_INIT(NULL, 0)
681 /* tp_name */ "_zope_interface_coptimizations."
682 /* tp_name */ "_zope_interface_coptimizations."
682 "InterfaceBase",
683 "InterfaceBase",
683 /* tp_basicsize */ 0,
684 /* tp_basicsize */ 0,
684 /* tp_itemsize */ 0,
685 /* tp_itemsize */ 0,
685 /* tp_dealloc */ (destructor)0,
686 /* tp_dealloc */ (destructor)0,
686 /* tp_print */ (printfunc)0,
687 /* tp_print */ (printfunc)0,
687 /* tp_getattr */ (getattrfunc)0,
688 /* tp_getattr */ (getattrfunc)0,
688 /* tp_setattr */ (setattrfunc)0,
689 /* tp_setattr */ (setattrfunc)0,
689 /* tp_compare */ 0,
690 /* tp_compare */ 0,
690 /* tp_repr */ (reprfunc)0,
691 /* tp_repr */ (reprfunc)0,
691 /* tp_as_number */ 0,
692 /* tp_as_number */ 0,
692 /* tp_as_sequence */ 0,
693 /* tp_as_sequence */ 0,
693 /* tp_as_mapping */ 0,
694 /* tp_as_mapping */ 0,
694 /* tp_hash */ (hashfunc)0,
695 /* tp_hash */ (hashfunc)0,
695 /* tp_call */ (ternaryfunc)ib_call,
696 /* tp_call */ (ternaryfunc)ib_call,
696 /* tp_str */ (reprfunc)0,
697 /* tp_str */ (reprfunc)0,
697 /* tp_getattro */ (getattrofunc)0,
698 /* tp_getattro */ (getattrofunc)0,
698 /* tp_setattro */ (setattrofunc)0,
699 /* tp_setattro */ (setattrofunc)0,
699 /* tp_as_buffer */ 0,
700 /* tp_as_buffer */ 0,
700 /* tp_flags */ Py_TPFLAGS_DEFAULT
701 /* tp_flags */ Py_TPFLAGS_DEFAULT
701 | Py_TPFLAGS_BASETYPE ,
702 | Py_TPFLAGS_BASETYPE ,
702 /* tp_doc */ "Interface base type providing __call__ and __adapt__",
703 /* tp_doc */ "Interface base type providing __call__ and __adapt__",
703 /* tp_traverse */ (traverseproc)0,
704 /* tp_traverse */ (traverseproc)0,
704 /* tp_clear */ (inquiry)0,
705 /* tp_clear */ (inquiry)0,
705 /* tp_richcompare */ (richcmpfunc)0,
706 /* tp_richcompare */ (richcmpfunc)0,
706 /* tp_weaklistoffset */ (long)0,
707 /* tp_weaklistoffset */ (long)0,
707 /* tp_iter */ (getiterfunc)0,
708 /* tp_iter */ (getiterfunc)0,
708 /* tp_iternext */ (iternextfunc)0,
709 /* tp_iternext */ (iternextfunc)0,
709 /* tp_methods */ ib_methods,
710 /* tp_methods */ ib_methods,
710 };
711 };
711
712
712 /* =================== End: __call__ and __adapt__ ==================== */
713 /* =================== End: __call__ and __adapt__ ==================== */
713 /* ==================================================================== */
714 /* ==================================================================== */
714
715
715 /* ==================================================================== */
716 /* ==================================================================== */
716 /* ========================== Begin: Lookup Bases ===================== */
717 /* ========================== Begin: Lookup Bases ===================== */
717
718
718 typedef struct {
719 typedef struct {
719 PyObject_HEAD
720 PyObject_HEAD
720 PyObject *_cache;
721 PyObject *_cache;
721 PyObject *_mcache;
722 PyObject *_mcache;
722 PyObject *_scache;
723 PyObject *_scache;
723 } lookup;
724 } lookup;
724
725
725 typedef struct {
726 typedef struct {
726 PyObject_HEAD
727 PyObject_HEAD
727 PyObject *_cache;
728 PyObject *_cache;
728 PyObject *_mcache;
729 PyObject *_mcache;
729 PyObject *_scache;
730 PyObject *_scache;
730 PyObject *_verify_ro;
731 PyObject *_verify_ro;
731 PyObject *_verify_generations;
732 PyObject *_verify_generations;
732 } verify;
733 } verify;
733
734
734 static int
735 static int
735 lookup_traverse(lookup *self, visitproc visit, void *arg)
736 lookup_traverse(lookup *self, visitproc visit, void *arg)
736 {
737 {
737 int vret;
738 int vret;
738
739
739 if (self->_cache) {
740 if (self->_cache) {
740 vret = visit(self->_cache, arg);
741 vret = visit(self->_cache, arg);
741 if (vret != 0)
742 if (vret != 0)
742 return vret;
743 return vret;
743 }
744 }
744
745
745 if (self->_mcache) {
746 if (self->_mcache) {
746 vret = visit(self->_mcache, arg);
747 vret = visit(self->_mcache, arg);
747 if (vret != 0)
748 if (vret != 0)
748 return vret;
749 return vret;
749 }
750 }
750
751
751 if (self->_scache) {
752 if (self->_scache) {
752 vret = visit(self->_scache, arg);
753 vret = visit(self->_scache, arg);
753 if (vret != 0)
754 if (vret != 0)
754 return vret;
755 return vret;
755 }
756 }
756
757
757 return 0;
758 return 0;
758 }
759 }
759
760
760 static int
761 static int
761 lookup_clear(lookup *self)
762 lookup_clear(lookup *self)
762 {
763 {
763 Py_CLEAR(self->_cache);
764 Py_CLEAR(self->_cache);
764 Py_CLEAR(self->_mcache);
765 Py_CLEAR(self->_mcache);
765 Py_CLEAR(self->_scache);
766 Py_CLEAR(self->_scache);
766 return 0;
767 return 0;
767 }
768 }
768
769
769 static void
770 static void
770 lookup_dealloc(lookup *self)
771 lookup_dealloc(lookup *self)
771 {
772 {
772 PyObject_GC_UnTrack((PyObject *)self);
773 PyObject_GC_UnTrack((PyObject *)self);
773 lookup_clear(self);
774 lookup_clear(self);
774 Py_TYPE(self)->tp_free((PyObject*)self);
775 Py_TYPE(self)->tp_free((PyObject*)self);
775 }
776 }
776
777
777 /*
778 /*
778 def changed(self, ignored=None):
779 def changed(self, ignored=None):
779 self._cache.clear()
780 self._cache.clear()
780 self._mcache.clear()
781 self._mcache.clear()
781 self._scache.clear()
782 self._scache.clear()
782 */
783 */
783 static PyObject *
784 static PyObject *
784 lookup_changed(lookup *self, PyObject *ignored)
785 lookup_changed(lookup *self, PyObject *ignored)
785 {
786 {
786 lookup_clear(self);
787 lookup_clear(self);
787 Py_INCREF(Py_None);
788 Py_INCREF(Py_None);
788 return Py_None;
789 return Py_None;
789 }
790 }
790
791
791 #define ASSURE_DICT(N) if (N == NULL) { N = PyDict_New(); \
792 #define ASSURE_DICT(N) if (N == NULL) { N = PyDict_New(); \
792 if (N == NULL) return NULL; \
793 if (N == NULL) return NULL; \
793 }
794 }
794
795
795 /*
796 /*
796 def _getcache(self, provided, name):
797 def _getcache(self, provided, name):
797 cache = self._cache.get(provided)
798 cache = self._cache.get(provided)
798 if cache is None:
799 if cache is None:
799 cache = {}
800 cache = {}
800 self._cache[provided] = cache
801 self._cache[provided] = cache
801 if name:
802 if name:
802 c = cache.get(name)
803 c = cache.get(name)
803 if c is None:
804 if c is None:
804 c = {}
805 c = {}
805 cache[name] = c
806 cache[name] = c
806 cache = c
807 cache = c
807 return cache
808 return cache
808 */
809 */
809 static PyObject *
810 static PyObject *
810 _subcache(PyObject *cache, PyObject *key)
811 _subcache(PyObject *cache, PyObject *key)
811 {
812 {
812 PyObject *subcache;
813 PyObject *subcache;
813
814
814 subcache = PyDict_GetItem(cache, key);
815 subcache = PyDict_GetItem(cache, key);
815 if (subcache == NULL)
816 if (subcache == NULL)
816 {
817 {
817 int status;
818 int status;
818
819
819 subcache = PyDict_New();
820 subcache = PyDict_New();
820 if (subcache == NULL)
821 if (subcache == NULL)
821 return NULL;
822 return NULL;
822 status = PyDict_SetItem(cache, key, subcache);
823 status = PyDict_SetItem(cache, key, subcache);
823 Py_DECREF(subcache);
824 Py_DECREF(subcache);
824 if (status < 0)
825 if (status < 0)
825 return NULL;
826 return NULL;
826 }
827 }
827
828
828 return subcache;
829 return subcache;
829 }
830 }
830 static PyObject *
831 static PyObject *
831 _getcache(lookup *self, PyObject *provided, PyObject *name)
832 _getcache(lookup *self, PyObject *provided, PyObject *name)
832 {
833 {
833 PyObject *cache;
834 PyObject *cache;
834
835
835 ASSURE_DICT(self->_cache);
836 ASSURE_DICT(self->_cache);
836 cache = _subcache(self->_cache, provided);
837 cache = _subcache(self->_cache, provided);
837 if (cache == NULL)
838 if (cache == NULL)
838 return NULL;
839 return NULL;
839
840
840 if (name != NULL && PyObject_IsTrue(name))
841 if (name != NULL && PyObject_IsTrue(name))
841 cache = _subcache(cache, name);
842 cache = _subcache(cache, name);
842
843
843 return cache;
844 return cache;
844 }
845 }
845
846
846
847
847 /*
848 /*
848 def lookup(self, required, provided, name=u'', default=None):
849 def lookup(self, required, provided, name=u'', default=None):
849 cache = self._getcache(provided, name)
850 cache = self._getcache(provided, name)
850 if len(required) == 1:
851 if len(required) == 1:
851 result = cache.get(required[0], _not_in_mapping)
852 result = cache.get(required[0], _not_in_mapping)
852 else:
853 else:
853 result = cache.get(tuple(required), _not_in_mapping)
854 result = cache.get(tuple(required), _not_in_mapping)
854
855
855 if result is _not_in_mapping:
856 if result is _not_in_mapping:
856 result = self._uncached_lookup(required, provided, name)
857 result = self._uncached_lookup(required, provided, name)
857 if len(required) == 1:
858 if len(required) == 1:
858 cache[required[0]] = result
859 cache[required[0]] = result
859 else:
860 else:
860 cache[tuple(required)] = result
861 cache[tuple(required)] = result
861
862
862 if result is None:
863 if result is None:
863 return default
864 return default
864
865
865 return result
866 return result
866 */
867 */
867 static PyObject *
868 static PyObject *
868 tuplefy(PyObject *v)
869 tuplefy(PyObject *v)
869 {
870 {
870 if (! PyTuple_Check(v))
871 if (! PyTuple_Check(v))
871 {
872 {
872 v = PyObject_CallFunctionObjArgs(OBJECT(&PyTuple_Type), v, NULL);
873 v = PyObject_CallFunctionObjArgs(OBJECT(&PyTuple_Type), v, NULL);
873 if (v == NULL)
874 if (v == NULL)
874 return NULL;
875 return NULL;
875 }
876 }
876 else
877 else
877 Py_INCREF(v);
878 Py_INCREF(v);
878
879
879 return v;
880 return v;
880 }
881 }
881 static PyObject *
882 static PyObject *
882 _lookup(lookup *self,
883 _lookup(lookup *self,
883 PyObject *required, PyObject *provided, PyObject *name,
884 PyObject *required, PyObject *provided, PyObject *name,
884 PyObject *default_)
885 PyObject *default_)
885 {
886 {
886 PyObject *result, *key, *cache;
887 PyObject *result, *key, *cache;
887
888
888 #ifdef PY3K
889 #ifdef PY3K
889 if ( name && !PyUnicode_Check(name) )
890 if ( name && !PyUnicode_Check(name) )
890 #else
891 #else
891 if ( name && !PyString_Check(name) && !PyUnicode_Check(name) )
892 if ( name && !PyString_Check(name) && !PyUnicode_Check(name) )
892 #endif
893 #endif
893 {
894 {
894 PyErr_SetString(PyExc_ValueError,
895 PyErr_SetString(PyExc_ValueError,
895 "name is not a string or unicode");
896 "name is not a string or unicode");
896 return NULL;
897 return NULL;
897 }
898 }
898 cache = _getcache(self, provided, name);
899 cache = _getcache(self, provided, name);
899 if (cache == NULL)
900 if (cache == NULL)
900 return NULL;
901 return NULL;
901
902
902 required = tuplefy(required);
903 required = tuplefy(required);
903 if (required == NULL)
904 if (required == NULL)
904 return NULL;
905 return NULL;
905
906
906 if (PyTuple_GET_SIZE(required) == 1)
907 if (PyTuple_GET_SIZE(required) == 1)
907 key = PyTuple_GET_ITEM(required, 0);
908 key = PyTuple_GET_ITEM(required, 0);
908 else
909 else
909 key = required;
910 key = required;
910
911
911 result = PyDict_GetItem(cache, key);
912 result = PyDict_GetItem(cache, key);
912 if (result == NULL)
913 if (result == NULL)
913 {
914 {
914 int status;
915 int status;
915
916
916 result = PyObject_CallMethodObjArgs(OBJECT(self), str_uncached_lookup,
917 result = PyObject_CallMethodObjArgs(OBJECT(self), str_uncached_lookup,
917 required, provided, name, NULL);
918 required, provided, name, NULL);
918 if (result == NULL)
919 if (result == NULL)
919 {
920 {
920 Py_DECREF(required);
921 Py_DECREF(required);
921 return NULL;
922 return NULL;
922 }
923 }
923 status = PyDict_SetItem(cache, key, result);
924 status = PyDict_SetItem(cache, key, result);
924 Py_DECREF(required);
925 Py_DECREF(required);
925 if (status < 0)
926 if (status < 0)
926 {
927 {
927 Py_DECREF(result);
928 Py_DECREF(result);
928 return NULL;
929 return NULL;
929 }
930 }
930 }
931 }
931 else
932 else
932 {
933 {
933 Py_INCREF(result);
934 Py_INCREF(result);
934 Py_DECREF(required);
935 Py_DECREF(required);
935 }
936 }
936
937
937 if (result == Py_None && default_ != NULL)
938 if (result == Py_None && default_ != NULL)
938 {
939 {
939 Py_DECREF(Py_None);
940 Py_DECREF(Py_None);
940 Py_INCREF(default_);
941 Py_INCREF(default_);
941 return default_;
942 return default_;
942 }
943 }
943
944
944 return result;
945 return result;
945 }
946 }
946 static PyObject *
947 static PyObject *
947 lookup_lookup(lookup *self, PyObject *args, PyObject *kwds)
948 lookup_lookup(lookup *self, PyObject *args, PyObject *kwds)
948 {
949 {
949 static char *kwlist[] = {"required", "provided", "name", "default", NULL};
950 static char *kwlist[] = {"required", "provided", "name", "default", NULL};
950 PyObject *required, *provided, *name=NULL, *default_=NULL;
951 PyObject *required, *provided, *name=NULL, *default_=NULL;
951
952
952 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
953 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
953 &required, &provided, &name, &default_))
954 &required, &provided, &name, &default_))
954 return NULL;
955 return NULL;
955
956
956 return _lookup(self, required, provided, name, default_);
957 return _lookup(self, required, provided, name, default_);
957 }
958 }
958
959
959
960
960 /*
961 /*
961 def lookup1(self, required, provided, name=u'', default=None):
962 def lookup1(self, required, provided, name=u'', default=None):
962 cache = self._getcache(provided, name)
963 cache = self._getcache(provided, name)
963 result = cache.get(required, _not_in_mapping)
964 result = cache.get(required, _not_in_mapping)
964 if result is _not_in_mapping:
965 if result is _not_in_mapping:
965 return self.lookup((required, ), provided, name, default)
966 return self.lookup((required, ), provided, name, default)
966
967
967 if result is None:
968 if result is None:
968 return default
969 return default
969
970
970 return result
971 return result
971 */
972 */
972 static PyObject *
973 static PyObject *
973 _lookup1(lookup *self,
974 _lookup1(lookup *self,
974 PyObject *required, PyObject *provided, PyObject *name,
975 PyObject *required, PyObject *provided, PyObject *name,
975 PyObject *default_)
976 PyObject *default_)
976 {
977 {
977 PyObject *result, *cache;
978 PyObject *result, *cache;
978
979
979 #ifdef PY3K
980 #ifdef PY3K
980 if ( name && !PyUnicode_Check(name) )
981 if ( name && !PyUnicode_Check(name) )
981 #else
982 #else
982 if ( name && !PyString_Check(name) && !PyUnicode_Check(name) )
983 if ( name && !PyString_Check(name) && !PyUnicode_Check(name) )
983 #endif
984 #endif
984 {
985 {
985 PyErr_SetString(PyExc_ValueError,
986 PyErr_SetString(PyExc_ValueError,
986 "name is not a string or unicode");
987 "name is not a string or unicode");
987 return NULL;
988 return NULL;
988 }
989 }
989
990
990 cache = _getcache(self, provided, name);
991 cache = _getcache(self, provided, name);
991 if (cache == NULL)
992 if (cache == NULL)
992 return NULL;
993 return NULL;
993
994
994 result = PyDict_GetItem(cache, required);
995 result = PyDict_GetItem(cache, required);
995 if (result == NULL)
996 if (result == NULL)
996 {
997 {
997 PyObject *tup;
998 PyObject *tup;
998
999
999 tup = PyTuple_New(1);
1000 tup = PyTuple_New(1);
1000 if (tup == NULL)
1001 if (tup == NULL)
1001 return NULL;
1002 return NULL;
1002 Py_INCREF(required);
1003 Py_INCREF(required);
1003 PyTuple_SET_ITEM(tup, 0, required);
1004 PyTuple_SET_ITEM(tup, 0, required);
1004 result = _lookup(self, tup, provided, name, default_);
1005 result = _lookup(self, tup, provided, name, default_);
1005 Py_DECREF(tup);
1006 Py_DECREF(tup);
1006 }
1007 }
1007 else
1008 else
1008 {
1009 {
1009 if (result == Py_None && default_ != NULL)
1010 if (result == Py_None && default_ != NULL)
1010 {
1011 {
1011 result = default_;
1012 result = default_;
1012 }
1013 }
1013 Py_INCREF(result);
1014 Py_INCREF(result);
1014 }
1015 }
1015
1016
1016 return result;
1017 return result;
1017 }
1018 }
1018 static PyObject *
1019 static PyObject *
1019 lookup_lookup1(lookup *self, PyObject *args, PyObject *kwds)
1020 lookup_lookup1(lookup *self, PyObject *args, PyObject *kwds)
1020 {
1021 {
1021 static char *kwlist[] = {"required", "provided", "name", "default", NULL};
1022 static char *kwlist[] = {"required", "provided", "name", "default", NULL};
1022 PyObject *required, *provided, *name=NULL, *default_=NULL;
1023 PyObject *required, *provided, *name=NULL, *default_=NULL;
1023
1024
1024 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1025 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1025 &required, &provided, &name, &default_))
1026 &required, &provided, &name, &default_))
1026 return NULL;
1027 return NULL;
1027
1028
1028 return _lookup1(self, required, provided, name, default_);
1029 return _lookup1(self, required, provided, name, default_);
1029 }
1030 }
1030
1031
1031 /*
1032 /*
1032 def adapter_hook(self, provided, object, name=u'', default=None):
1033 def adapter_hook(self, provided, object, name=u'', default=None):
1033 required = providedBy(object)
1034 required = providedBy(object)
1034 cache = self._getcache(provided, name)
1035 cache = self._getcache(provided, name)
1035 factory = cache.get(required, _not_in_mapping)
1036 factory = cache.get(required, _not_in_mapping)
1036 if factory is _not_in_mapping:
1037 if factory is _not_in_mapping:
1037 factory = self.lookup((required, ), provided, name)
1038 factory = self.lookup((required, ), provided, name)
1038
1039
1039 if factory is not None:
1040 if factory is not None:
1040 result = factory(object)
1041 result = factory(object)
1041 if result is not None:
1042 if result is not None:
1042 return result
1043 return result
1043
1044
1044 return default
1045 return default
1045 */
1046 */
1046 static PyObject *
1047 static PyObject *
1047 _adapter_hook(lookup *self,
1048 _adapter_hook(lookup *self,
1048 PyObject *provided, PyObject *object, PyObject *name,
1049 PyObject *provided, PyObject *object, PyObject *name,
1049 PyObject *default_)
1050 PyObject *default_)
1050 {
1051 {
1051 PyObject *required, *factory, *result;
1052 PyObject *required, *factory, *result;
1052
1053
1053 #ifdef PY3K
1054 #ifdef PY3K
1054 if ( name && !PyUnicode_Check(name) )
1055 if ( name && !PyUnicode_Check(name) )
1055 #else
1056 #else
1056 if ( name && !PyString_Check(name) && !PyUnicode_Check(name) )
1057 if ( name && !PyString_Check(name) && !PyUnicode_Check(name) )
1057 #endif
1058 #endif
1058 {
1059 {
1059 PyErr_SetString(PyExc_ValueError,
1060 PyErr_SetString(PyExc_ValueError,
1060 "name is not a string or unicode");
1061 "name is not a string or unicode");
1061 return NULL;
1062 return NULL;
1062 }
1063 }
1063
1064
1064 required = providedBy(NULL, object);
1065 required = providedBy(NULL, object);
1065 if (required == NULL)
1066 if (required == NULL)
1066 return NULL;
1067 return NULL;
1067
1068
1068 factory = _lookup1(self, required, provided, name, Py_None);
1069 factory = _lookup1(self, required, provided, name, Py_None);
1069 Py_DECREF(required);
1070 Py_DECREF(required);
1070 if (factory == NULL)
1071 if (factory == NULL)
1071 return NULL;
1072 return NULL;
1072
1073
1073 if (factory != Py_None)
1074 if (factory != Py_None)
1074 {
1075 {
1075 result = PyObject_CallFunctionObjArgs(factory, object, NULL);
1076 result = PyObject_CallFunctionObjArgs(factory, object, NULL);
1076 Py_DECREF(factory);
1077 Py_DECREF(factory);
1077 if (result == NULL || result != Py_None)
1078 if (result == NULL || result != Py_None)
1078 return result;
1079 return result;
1079 }
1080 }
1080 else
1081 else
1081 result = factory; /* None */
1082 result = factory; /* None */
1082
1083
1083 if (default_ == NULL || default_ == result) /* No default specified, */
1084 if (default_ == NULL || default_ == result) /* No default specified, */
1084 return result; /* Return None. result is owned None */
1085 return result; /* Return None. result is owned None */
1085
1086
1086 Py_DECREF(result);
1087 Py_DECREF(result);
1087 Py_INCREF(default_);
1088 Py_INCREF(default_);
1088
1089
1089 return default_;
1090 return default_;
1090 }
1091 }
1091 static PyObject *
1092 static PyObject *
1092 lookup_adapter_hook(lookup *self, PyObject *args, PyObject *kwds)
1093 lookup_adapter_hook(lookup *self, PyObject *args, PyObject *kwds)
1093 {
1094 {
1094 static char *kwlist[] = {"provided", "object", "name", "default", NULL};
1095 static char *kwlist[] = {"provided", "object", "name", "default", NULL};
1095 PyObject *object, *provided, *name=NULL, *default_=NULL;
1096 PyObject *object, *provided, *name=NULL, *default_=NULL;
1096
1097
1097 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1098 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1098 &provided, &object, &name, &default_))
1099 &provided, &object, &name, &default_))
1099 return NULL;
1100 return NULL;
1100
1101
1101 return _adapter_hook(self, provided, object, name, default_);
1102 return _adapter_hook(self, provided, object, name, default_);
1102 }
1103 }
1103
1104
1104 static PyObject *
1105 static PyObject *
1105 lookup_queryAdapter(lookup *self, PyObject *args, PyObject *kwds)
1106 lookup_queryAdapter(lookup *self, PyObject *args, PyObject *kwds)
1106 {
1107 {
1107 static char *kwlist[] = {"object", "provided", "name", "default", NULL};
1108 static char *kwlist[] = {"object", "provided", "name", "default", NULL};
1108 PyObject *object, *provided, *name=NULL, *default_=NULL;
1109 PyObject *object, *provided, *name=NULL, *default_=NULL;
1109
1110
1110 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1111 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1111 &object, &provided, &name, &default_))
1112 &object, &provided, &name, &default_))
1112 return NULL;
1113 return NULL;
1113
1114
1114 return _adapter_hook(self, provided, object, name, default_);
1115 return _adapter_hook(self, provided, object, name, default_);
1115 }
1116 }
1116
1117
1117 /*
1118 /*
1118 def lookupAll(self, required, provided):
1119 def lookupAll(self, required, provided):
1119 cache = self._mcache.get(provided)
1120 cache = self._mcache.get(provided)
1120 if cache is None:
1121 if cache is None:
1121 cache = {}
1122 cache = {}
1122 self._mcache[provided] = cache
1123 self._mcache[provided] = cache
1123
1124
1124 required = tuple(required)
1125 required = tuple(required)
1125 result = cache.get(required, _not_in_mapping)
1126 result = cache.get(required, _not_in_mapping)
1126 if result is _not_in_mapping:
1127 if result is _not_in_mapping:
1127 result = self._uncached_lookupAll(required, provided)
1128 result = self._uncached_lookupAll(required, provided)
1128 cache[required] = result
1129 cache[required] = result
1129
1130
1130 return result
1131 return result
1131 */
1132 */
1132 static PyObject *
1133 static PyObject *
1133 _lookupAll(lookup *self, PyObject *required, PyObject *provided)
1134 _lookupAll(lookup *self, PyObject *required, PyObject *provided)
1134 {
1135 {
1135 PyObject *cache, *result;
1136 PyObject *cache, *result;
1136
1137
1137 ASSURE_DICT(self->_mcache);
1138 ASSURE_DICT(self->_mcache);
1138 cache = _subcache(self->_mcache, provided);
1139 cache = _subcache(self->_mcache, provided);
1139 if (cache == NULL)
1140 if (cache == NULL)
1140 return NULL;
1141 return NULL;
1141
1142
1142 required = tuplefy(required);
1143 required = tuplefy(required);
1143 if (required == NULL)
1144 if (required == NULL)
1144 return NULL;
1145 return NULL;
1145
1146
1146 result = PyDict_GetItem(cache, required);
1147 result = PyDict_GetItem(cache, required);
1147 if (result == NULL)
1148 if (result == NULL)
1148 {
1149 {
1149 int status;
1150 int status;
1150
1151
1151 result = PyObject_CallMethodObjArgs(OBJECT(self), str_uncached_lookupAll,
1152 result = PyObject_CallMethodObjArgs(OBJECT(self), str_uncached_lookupAll,
1152 required, provided, NULL);
1153 required, provided, NULL);
1153 if (result == NULL)
1154 if (result == NULL)
1154 {
1155 {
1155 Py_DECREF(required);
1156 Py_DECREF(required);
1156 return NULL;
1157 return NULL;
1157 }
1158 }
1158 status = PyDict_SetItem(cache, required, result);
1159 status = PyDict_SetItem(cache, required, result);
1159 Py_DECREF(required);
1160 Py_DECREF(required);
1160 if (status < 0)
1161 if (status < 0)
1161 {
1162 {
1162 Py_DECREF(result);
1163 Py_DECREF(result);
1163 return NULL;
1164 return NULL;
1164 }
1165 }
1165 }
1166 }
1166 else
1167 else
1167 {
1168 {
1168 Py_INCREF(result);
1169 Py_INCREF(result);
1169 Py_DECREF(required);
1170 Py_DECREF(required);
1170 }
1171 }
1171
1172
1172 return result;
1173 return result;
1173 }
1174 }
1174 static PyObject *
1175 static PyObject *
1175 lookup_lookupAll(lookup *self, PyObject *args, PyObject *kwds)
1176 lookup_lookupAll(lookup *self, PyObject *args, PyObject *kwds)
1176 {
1177 {
1177 static char *kwlist[] = {"required", "provided", NULL};
1178 static char *kwlist[] = {"required", "provided", NULL};
1178 PyObject *required, *provided;
1179 PyObject *required, *provided;
1179
1180
1180 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
1181 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
1181 &required, &provided))
1182 &required, &provided))
1182 return NULL;
1183 return NULL;
1183
1184
1184 return _lookupAll(self, required, provided);
1185 return _lookupAll(self, required, provided);
1185 }
1186 }
1186
1187
1187 /*
1188 /*
1188 def subscriptions(self, required, provided):
1189 def subscriptions(self, required, provided):
1189 cache = self._scache.get(provided)
1190 cache = self._scache.get(provided)
1190 if cache is None:
1191 if cache is None:
1191 cache = {}
1192 cache = {}
1192 self._scache[provided] = cache
1193 self._scache[provided] = cache
1193
1194
1194 required = tuple(required)
1195 required = tuple(required)
1195 result = cache.get(required, _not_in_mapping)
1196 result = cache.get(required, _not_in_mapping)
1196 if result is _not_in_mapping:
1197 if result is _not_in_mapping:
1197 result = self._uncached_subscriptions(required, provided)
1198 result = self._uncached_subscriptions(required, provided)
1198 cache[required] = result
1199 cache[required] = result
1199
1200
1200 return result
1201 return result
1201 */
1202 */
1202 static PyObject *
1203 static PyObject *
1203 _subscriptions(lookup *self, PyObject *required, PyObject *provided)
1204 _subscriptions(lookup *self, PyObject *required, PyObject *provided)
1204 {
1205 {
1205 PyObject *cache, *result;
1206 PyObject *cache, *result;
1206
1207
1207 ASSURE_DICT(self->_scache);
1208 ASSURE_DICT(self->_scache);
1208 cache = _subcache(self->_scache, provided);
1209 cache = _subcache(self->_scache, provided);
1209 if (cache == NULL)
1210 if (cache == NULL)
1210 return NULL;
1211 return NULL;
1211
1212
1212 required = tuplefy(required);
1213 required = tuplefy(required);
1213 if (required == NULL)
1214 if (required == NULL)
1214 return NULL;
1215 return NULL;
1215
1216
1216 result = PyDict_GetItem(cache, required);
1217 result = PyDict_GetItem(cache, required);
1217 if (result == NULL)
1218 if (result == NULL)
1218 {
1219 {
1219 int status;
1220 int status;
1220
1221
1221 result = PyObject_CallMethodObjArgs(
1222 result = PyObject_CallMethodObjArgs(
1222 OBJECT(self), str_uncached_subscriptions,
1223 OBJECT(self), str_uncached_subscriptions,
1223 required, provided, NULL);
1224 required, provided, NULL);
1224 if (result == NULL)
1225 if (result == NULL)
1225 {
1226 {
1226 Py_DECREF(required);
1227 Py_DECREF(required);
1227 return NULL;
1228 return NULL;
1228 }
1229 }
1229 status = PyDict_SetItem(cache, required, result);
1230 status = PyDict_SetItem(cache, required, result);
1230 Py_DECREF(required);
1231 Py_DECREF(required);
1231 if (status < 0)
1232 if (status < 0)
1232 {
1233 {
1233 Py_DECREF(result);
1234 Py_DECREF(result);
1234 return NULL;
1235 return NULL;
1235 }
1236 }
1236 }
1237 }
1237 else
1238 else
1238 {
1239 {
1239 Py_INCREF(result);
1240 Py_INCREF(result);
1240 Py_DECREF(required);
1241 Py_DECREF(required);
1241 }
1242 }
1242
1243
1243 return result;
1244 return result;
1244 }
1245 }
1245 static PyObject *
1246 static PyObject *
1246 lookup_subscriptions(lookup *self, PyObject *args, PyObject *kwds)
1247 lookup_subscriptions(lookup *self, PyObject *args, PyObject *kwds)
1247 {
1248 {
1248 static char *kwlist[] = {"required", "provided", NULL};
1249 static char *kwlist[] = {"required", "provided", NULL};
1249 PyObject *required, *provided;
1250 PyObject *required, *provided;
1250
1251
1251 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
1252 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
1252 &required, &provided))
1253 &required, &provided))
1253 return NULL;
1254 return NULL;
1254
1255
1255 return _subscriptions(self, required, provided);
1256 return _subscriptions(self, required, provided);
1256 }
1257 }
1257
1258
1258 static struct PyMethodDef lookup_methods[] = {
1259 static struct PyMethodDef lookup_methods[] = {
1259 {"changed", (PyCFunction)lookup_changed, METH_O, ""},
1260 {"changed", (PyCFunction)lookup_changed, METH_O, ""},
1260 {"lookup", (PyCFunction)lookup_lookup, METH_KEYWORDS | METH_VARARGS, ""},
1261 {"lookup", (PyCFunction)lookup_lookup, METH_KEYWORDS | METH_VARARGS, ""},
1261 {"lookup1", (PyCFunction)lookup_lookup1, METH_KEYWORDS | METH_VARARGS, ""},
1262 {"lookup1", (PyCFunction)lookup_lookup1, METH_KEYWORDS | METH_VARARGS, ""},
1262 {"queryAdapter", (PyCFunction)lookup_queryAdapter, METH_KEYWORDS | METH_VARARGS, ""},
1263 {"queryAdapter", (PyCFunction)lookup_queryAdapter, METH_KEYWORDS | METH_VARARGS, ""},
1263 {"adapter_hook", (PyCFunction)lookup_adapter_hook, METH_KEYWORDS | METH_VARARGS, ""},
1264 {"adapter_hook", (PyCFunction)lookup_adapter_hook, METH_KEYWORDS | METH_VARARGS, ""},
1264 {"lookupAll", (PyCFunction)lookup_lookupAll, METH_KEYWORDS | METH_VARARGS, ""},
1265 {"lookupAll", (PyCFunction)lookup_lookupAll, METH_KEYWORDS | METH_VARARGS, ""},
1265 {"subscriptions", (PyCFunction)lookup_subscriptions, METH_KEYWORDS | METH_VARARGS, ""},
1266 {"subscriptions", (PyCFunction)lookup_subscriptions, METH_KEYWORDS | METH_VARARGS, ""},
1266 {NULL, NULL} /* sentinel */
1267 {NULL, NULL} /* sentinel */
1267 };
1268 };
1268
1269
1269 static PyTypeObject LookupBase = {
1270 static PyTypeObject LookupBase = {
1270 PyVarObject_HEAD_INIT(NULL, 0)
1271 PyVarObject_HEAD_INIT(NULL, 0)
1271 /* tp_name */ "_zope_interface_coptimizations."
1272 /* tp_name */ "_zope_interface_coptimizations."
1272 "LookupBase",
1273 "LookupBase",
1273 /* tp_basicsize */ sizeof(lookup),
1274 /* tp_basicsize */ sizeof(lookup),
1274 /* tp_itemsize */ 0,
1275 /* tp_itemsize */ 0,
1275 /* tp_dealloc */ (destructor)&lookup_dealloc,
1276 /* tp_dealloc */ (destructor)&lookup_dealloc,
1276 /* tp_print */ (printfunc)0,
1277 /* tp_print */ (printfunc)0,
1277 /* tp_getattr */ (getattrfunc)0,
1278 /* tp_getattr */ (getattrfunc)0,
1278 /* tp_setattr */ (setattrfunc)0,
1279 /* tp_setattr */ (setattrfunc)0,
1279 /* tp_compare */ 0,
1280 /* tp_compare */ 0,
1280 /* tp_repr */ (reprfunc)0,
1281 /* tp_repr */ (reprfunc)0,
1281 /* tp_as_number */ 0,
1282 /* tp_as_number */ 0,
1282 /* tp_as_sequence */ 0,
1283 /* tp_as_sequence */ 0,
1283 /* tp_as_mapping */ 0,
1284 /* tp_as_mapping */ 0,
1284 /* tp_hash */ (hashfunc)0,
1285 /* tp_hash */ (hashfunc)0,
1285 /* tp_call */ (ternaryfunc)0,
1286 /* tp_call */ (ternaryfunc)0,
1286 /* tp_str */ (reprfunc)0,
1287 /* tp_str */ (reprfunc)0,
1287 /* tp_getattro */ (getattrofunc)0,
1288 /* tp_getattro */ (getattrofunc)0,
1288 /* tp_setattro */ (setattrofunc)0,
1289 /* tp_setattro */ (setattrofunc)0,
1289 /* tp_as_buffer */ 0,
1290 /* tp_as_buffer */ 0,
1290 /* tp_flags */ Py_TPFLAGS_DEFAULT
1291 /* tp_flags */ Py_TPFLAGS_DEFAULT
1291 | Py_TPFLAGS_BASETYPE
1292 | Py_TPFLAGS_BASETYPE
1292 | Py_TPFLAGS_HAVE_GC,
1293 | Py_TPFLAGS_HAVE_GC,
1293 /* tp_doc */ "",
1294 /* tp_doc */ "",
1294 /* tp_traverse */ (traverseproc)lookup_traverse,
1295 /* tp_traverse */ (traverseproc)lookup_traverse,
1295 /* tp_clear */ (inquiry)lookup_clear,
1296 /* tp_clear */ (inquiry)lookup_clear,
1296 /* tp_richcompare */ (richcmpfunc)0,
1297 /* tp_richcompare */ (richcmpfunc)0,
1297 /* tp_weaklistoffset */ (long)0,
1298 /* tp_weaklistoffset */ (long)0,
1298 /* tp_iter */ (getiterfunc)0,
1299 /* tp_iter */ (getiterfunc)0,
1299 /* tp_iternext */ (iternextfunc)0,
1300 /* tp_iternext */ (iternextfunc)0,
1300 /* tp_methods */ lookup_methods,
1301 /* tp_methods */ lookup_methods,
1301 };
1302 };
1302
1303
1303 static int
1304 static int
1304 verifying_traverse(verify *self, visitproc visit, void *arg)
1305 verifying_traverse(verify *self, visitproc visit, void *arg)
1305 {
1306 {
1306 int vret;
1307 int vret;
1307
1308
1308 vret = lookup_traverse((lookup *)self, visit, arg);
1309 vret = lookup_traverse((lookup *)self, visit, arg);
1309 if (vret != 0)
1310 if (vret != 0)
1310 return vret;
1311 return vret;
1311
1312
1312 if (self->_verify_ro) {
1313 if (self->_verify_ro) {
1313 vret = visit(self->_verify_ro, arg);
1314 vret = visit(self->_verify_ro, arg);
1314 if (vret != 0)
1315 if (vret != 0)
1315 return vret;
1316 return vret;
1316 }
1317 }
1317 if (self->_verify_generations) {
1318 if (self->_verify_generations) {
1318 vret = visit(self->_verify_generations, arg);
1319 vret = visit(self->_verify_generations, arg);
1319 if (vret != 0)
1320 if (vret != 0)
1320 return vret;
1321 return vret;
1321 }
1322 }
1322
1323
1323 return 0;
1324 return 0;
1324 }
1325 }
1325
1326
1326 static int
1327 static int
1327 verifying_clear(verify *self)
1328 verifying_clear(verify *self)
1328 {
1329 {
1329 lookup_clear((lookup *)self);
1330 lookup_clear((lookup *)self);
1330 Py_CLEAR(self->_verify_generations);
1331 Py_CLEAR(self->_verify_generations);
1331 Py_CLEAR(self->_verify_ro);
1332 Py_CLEAR(self->_verify_ro);
1332 return 0;
1333 return 0;
1333 }
1334 }
1334
1335
1335
1336
1336 static void
1337 static void
1337 verifying_dealloc(verify *self)
1338 verifying_dealloc(verify *self)
1338 {
1339 {
1339 PyObject_GC_UnTrack((PyObject *)self);
1340 PyObject_GC_UnTrack((PyObject *)self);
1340 verifying_clear(self);
1341 verifying_clear(self);
1341 Py_TYPE(self)->tp_free((PyObject*)self);
1342 Py_TYPE(self)->tp_free((PyObject*)self);
1342 }
1343 }
1343
1344
1344 /*
1345 /*
1345 def changed(self, originally_changed):
1346 def changed(self, originally_changed):
1346 super(VerifyingBasePy, self).changed(originally_changed)
1347 super(VerifyingBasePy, self).changed(originally_changed)
1347 self._verify_ro = self._registry.ro[1:]
1348 self._verify_ro = self._registry.ro[1:]
1348 self._verify_generations = [r._generation for r in self._verify_ro]
1349 self._verify_generations = [r._generation for r in self._verify_ro]
1349 */
1350 */
1350 static PyObject *
1351 static PyObject *
1351 _generations_tuple(PyObject *ro)
1352 _generations_tuple(PyObject *ro)
1352 {
1353 {
1353 int i, l;
1354 int i, l;
1354 PyObject *generations;
1355 PyObject *generations;
1355
1356
1356 l = PyTuple_GET_SIZE(ro);
1357 l = PyTuple_GET_SIZE(ro);
1357 generations = PyTuple_New(l);
1358 generations = PyTuple_New(l);
1358 for (i=0; i < l; i++)
1359 for (i=0; i < l; i++)
1359 {
1360 {
1360 PyObject *generation;
1361 PyObject *generation;
1361
1362
1362 generation = PyObject_GetAttr(PyTuple_GET_ITEM(ro, i), str_generation);
1363 generation = PyObject_GetAttr(PyTuple_GET_ITEM(ro, i), str_generation);
1363 if (generation == NULL)
1364 if (generation == NULL)
1364 {
1365 {
1365 Py_DECREF(generations);
1366 Py_DECREF(generations);
1366 return NULL;
1367 return NULL;
1367 }
1368 }
1368 PyTuple_SET_ITEM(generations, i, generation);
1369 PyTuple_SET_ITEM(generations, i, generation);
1369 }
1370 }
1370
1371
1371 return generations;
1372 return generations;
1372 }
1373 }
1373 static PyObject *
1374 static PyObject *
1374 verifying_changed(verify *self, PyObject *ignored)
1375 verifying_changed(verify *self, PyObject *ignored)
1375 {
1376 {
1376 PyObject *t, *ro;
1377 PyObject *t, *ro;
1377
1378
1378 verifying_clear(self);
1379 verifying_clear(self);
1379
1380
1380 t = PyObject_GetAttr(OBJECT(self), str_registry);
1381 t = PyObject_GetAttr(OBJECT(self), str_registry);
1381 if (t == NULL)
1382 if (t == NULL)
1382 return NULL;
1383 return NULL;
1383 ro = PyObject_GetAttr(t, strro);
1384 ro = PyObject_GetAttr(t, strro);
1384 Py_DECREF(t);
1385 Py_DECREF(t);
1385 if (ro == NULL)
1386 if (ro == NULL)
1386 return NULL;
1387 return NULL;
1387
1388
1388 t = PyObject_CallFunctionObjArgs(OBJECT(&PyTuple_Type), ro, NULL);
1389 t = PyObject_CallFunctionObjArgs(OBJECT(&PyTuple_Type), ro, NULL);
1389 Py_DECREF(ro);
1390 Py_DECREF(ro);
1390 if (t == NULL)
1391 if (t == NULL)
1391 return NULL;
1392 return NULL;
1392
1393
1393 ro = PyTuple_GetSlice(t, 1, PyTuple_GET_SIZE(t));
1394 ro = PyTuple_GetSlice(t, 1, PyTuple_GET_SIZE(t));
1394 Py_DECREF(t);
1395 Py_DECREF(t);
1395 if (ro == NULL)
1396 if (ro == NULL)
1396 return NULL;
1397 return NULL;
1397
1398
1398 self->_verify_generations = _generations_tuple(ro);
1399 self->_verify_generations = _generations_tuple(ro);
1399 if (self->_verify_generations == NULL)
1400 if (self->_verify_generations == NULL)
1400 {
1401 {
1401 Py_DECREF(ro);
1402 Py_DECREF(ro);
1402 return NULL;
1403 return NULL;
1403 }
1404 }
1404
1405
1405 self->_verify_ro = ro;
1406 self->_verify_ro = ro;
1406
1407
1407 Py_INCREF(Py_None);
1408 Py_INCREF(Py_None);
1408 return Py_None;
1409 return Py_None;
1409 }
1410 }
1410
1411
1411 /*
1412 /*
1412 def _verify(self):
1413 def _verify(self):
1413 if ([r._generation for r in self._verify_ro]
1414 if ([r._generation for r in self._verify_ro]
1414 != self._verify_generations):
1415 != self._verify_generations):
1415 self.changed(None)
1416 self.changed(None)
1416 */
1417 */
1417 static int
1418 static int
1418 _verify(verify *self)
1419 _verify(verify *self)
1419 {
1420 {
1420 PyObject *changed_result;
1421 PyObject *changed_result;
1421
1422
1422 if (self->_verify_ro != NULL && self->_verify_generations != NULL)
1423 if (self->_verify_ro != NULL && self->_verify_generations != NULL)
1423 {
1424 {
1424 PyObject *generations;
1425 PyObject *generations;
1425 int changed;
1426 int changed;
1426
1427
1427 generations = _generations_tuple(self->_verify_ro);
1428 generations = _generations_tuple(self->_verify_ro);
1428 if (generations == NULL)
1429 if (generations == NULL)
1429 return -1;
1430 return -1;
1430
1431
1431 changed = PyObject_RichCompareBool(self->_verify_generations,
1432 changed = PyObject_RichCompareBool(self->_verify_generations,
1432 generations, Py_NE);
1433 generations, Py_NE);
1433 Py_DECREF(generations);
1434 Py_DECREF(generations);
1434 if (changed == -1)
1435 if (changed == -1)
1435 return -1;
1436 return -1;
1436
1437
1437 if (changed == 0)
1438 if (changed == 0)
1438 return 0;
1439 return 0;
1439 }
1440 }
1440
1441
1441 changed_result = PyObject_CallMethodObjArgs(OBJECT(self), strchanged,
1442 changed_result = PyObject_CallMethodObjArgs(OBJECT(self), strchanged,
1442 Py_None, NULL);
1443 Py_None, NULL);
1443 if (changed_result == NULL)
1444 if (changed_result == NULL)
1444 return -1;
1445 return -1;
1445
1446
1446 Py_DECREF(changed_result);
1447 Py_DECREF(changed_result);
1447 return 0;
1448 return 0;
1448 }
1449 }
1449
1450
1450 static PyObject *
1451 static PyObject *
1451 verifying_lookup(verify *self, PyObject *args, PyObject *kwds)
1452 verifying_lookup(verify *self, PyObject *args, PyObject *kwds)
1452 {
1453 {
1453 static char *kwlist[] = {"required", "provided", "name", "default", NULL};
1454 static char *kwlist[] = {"required", "provided", "name", "default", NULL};
1454 PyObject *required, *provided, *name=NULL, *default_=NULL;
1455 PyObject *required, *provided, *name=NULL, *default_=NULL;
1455
1456
1456 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1457 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1457 &required, &provided, &name, &default_))
1458 &required, &provided, &name, &default_))
1458 return NULL;
1459 return NULL;
1459
1460
1460 if (_verify(self) < 0)
1461 if (_verify(self) < 0)
1461 return NULL;
1462 return NULL;
1462
1463
1463 return _lookup((lookup *)self, required, provided, name, default_);
1464 return _lookup((lookup *)self, required, provided, name, default_);
1464 }
1465 }
1465
1466
1466 static PyObject *
1467 static PyObject *
1467 verifying_lookup1(verify *self, PyObject *args, PyObject *kwds)
1468 verifying_lookup1(verify *self, PyObject *args, PyObject *kwds)
1468 {
1469 {
1469 static char *kwlist[] = {"required", "provided", "name", "default", NULL};
1470 static char *kwlist[] = {"required", "provided", "name", "default", NULL};
1470 PyObject *required, *provided, *name=NULL, *default_=NULL;
1471 PyObject *required, *provided, *name=NULL, *default_=NULL;
1471
1472
1472 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1473 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1473 &required, &provided, &name, &default_))
1474 &required, &provided, &name, &default_))
1474 return NULL;
1475 return NULL;
1475
1476
1476 if (_verify(self) < 0)
1477 if (_verify(self) < 0)
1477 return NULL;
1478 return NULL;
1478
1479
1479 return _lookup1((lookup *)self, required, provided, name, default_);
1480 return _lookup1((lookup *)self, required, provided, name, default_);
1480 }
1481 }
1481
1482
1482 static PyObject *
1483 static PyObject *
1483 verifying_adapter_hook(verify *self, PyObject *args, PyObject *kwds)
1484 verifying_adapter_hook(verify *self, PyObject *args, PyObject *kwds)
1484 {
1485 {
1485 static char *kwlist[] = {"provided", "object", "name", "default", NULL};
1486 static char *kwlist[] = {"provided", "object", "name", "default", NULL};
1486 PyObject *object, *provided, *name=NULL, *default_=NULL;
1487 PyObject *object, *provided, *name=NULL, *default_=NULL;
1487
1488
1488 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1489 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1489 &provided, &object, &name, &default_))
1490 &provided, &object, &name, &default_))
1490 return NULL;
1491 return NULL;
1491
1492
1492 if (_verify(self) < 0)
1493 if (_verify(self) < 0)
1493 return NULL;
1494 return NULL;
1494
1495
1495 return _adapter_hook((lookup *)self, provided, object, name, default_);
1496 return _adapter_hook((lookup *)self, provided, object, name, default_);
1496 }
1497 }
1497
1498
1498 static PyObject *
1499 static PyObject *
1499 verifying_queryAdapter(verify *self, PyObject *args, PyObject *kwds)
1500 verifying_queryAdapter(verify *self, PyObject *args, PyObject *kwds)
1500 {
1501 {
1501 static char *kwlist[] = {"object", "provided", "name", "default", NULL};
1502 static char *kwlist[] = {"object", "provided", "name", "default", NULL};
1502 PyObject *object, *provided, *name=NULL, *default_=NULL;
1503 PyObject *object, *provided, *name=NULL, *default_=NULL;
1503
1504
1504 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1505 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist,
1505 &object, &provided, &name, &default_))
1506 &object, &provided, &name, &default_))
1506 return NULL;
1507 return NULL;
1507
1508
1508 if (_verify(self) < 0)
1509 if (_verify(self) < 0)
1509 return NULL;
1510 return NULL;
1510
1511
1511 return _adapter_hook((lookup *)self, provided, object, name, default_);
1512 return _adapter_hook((lookup *)self, provided, object, name, default_);
1512 }
1513 }
1513
1514
1514 static PyObject *
1515 static PyObject *
1515 verifying_lookupAll(verify *self, PyObject *args, PyObject *kwds)
1516 verifying_lookupAll(verify *self, PyObject *args, PyObject *kwds)
1516 {
1517 {
1517 static char *kwlist[] = {"required", "provided", NULL};
1518 static char *kwlist[] = {"required", "provided", NULL};
1518 PyObject *required, *provided;
1519 PyObject *required, *provided;
1519
1520
1520 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
1521 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
1521 &required, &provided))
1522 &required, &provided))
1522 return NULL;
1523 return NULL;
1523
1524
1524 if (_verify(self) < 0)
1525 if (_verify(self) < 0)
1525 return NULL;
1526 return NULL;
1526
1527
1527 return _lookupAll((lookup *)self, required, provided);
1528 return _lookupAll((lookup *)self, required, provided);
1528 }
1529 }
1529
1530
1530 static PyObject *
1531 static PyObject *
1531 verifying_subscriptions(verify *self, PyObject *args, PyObject *kwds)
1532 verifying_subscriptions(verify *self, PyObject *args, PyObject *kwds)
1532 {
1533 {
1533 static char *kwlist[] = {"required", "provided", NULL};
1534 static char *kwlist[] = {"required", "provided", NULL};
1534 PyObject *required, *provided;
1535 PyObject *required, *provided;
1535
1536
1536 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
1537 if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist,
1537 &required, &provided))
1538 &required, &provided))
1538 return NULL;
1539 return NULL;
1539
1540
1540 if (_verify(self) < 0)
1541 if (_verify(self) < 0)
1541 return NULL;
1542 return NULL;
1542
1543
1543 return _subscriptions((lookup *)self, required, provided);
1544 return _subscriptions((lookup *)self, required, provided);
1544 }
1545 }
1545
1546
1546 static struct PyMethodDef verifying_methods[] = {
1547 static struct PyMethodDef verifying_methods[] = {
1547 {"changed", (PyCFunction)verifying_changed, METH_O, ""},
1548 {"changed", (PyCFunction)verifying_changed, METH_O, ""},
1548 {"lookup", (PyCFunction)verifying_lookup, METH_KEYWORDS | METH_VARARGS, ""},
1549 {"lookup", (PyCFunction)verifying_lookup, METH_KEYWORDS | METH_VARARGS, ""},
1549 {"lookup1", (PyCFunction)verifying_lookup1, METH_KEYWORDS | METH_VARARGS, ""},
1550 {"lookup1", (PyCFunction)verifying_lookup1, METH_KEYWORDS | METH_VARARGS, ""},
1550 {"queryAdapter", (PyCFunction)verifying_queryAdapter, METH_KEYWORDS | METH_VARARGS, ""},
1551 {"queryAdapter", (PyCFunction)verifying_queryAdapter, METH_KEYWORDS | METH_VARARGS, ""},
1551 {"adapter_hook", (PyCFunction)verifying_adapter_hook, METH_KEYWORDS | METH_VARARGS, ""},
1552 {"adapter_hook", (PyCFunction)verifying_adapter_hook, METH_KEYWORDS | METH_VARARGS, ""},
1552 {"lookupAll", (PyCFunction)verifying_lookupAll, METH_KEYWORDS | METH_VARARGS, ""},
1553 {"lookupAll", (PyCFunction)verifying_lookupAll, METH_KEYWORDS | METH_VARARGS, ""},
1553 {"subscriptions", (PyCFunction)verifying_subscriptions, METH_KEYWORDS | METH_VARARGS, ""},
1554 {"subscriptions", (PyCFunction)verifying_subscriptions, METH_KEYWORDS | METH_VARARGS, ""},
1554 {NULL, NULL} /* sentinel */
1555 {NULL, NULL} /* sentinel */
1555 };
1556 };
1556
1557
1557 static PyTypeObject VerifyingBase = {
1558 static PyTypeObject VerifyingBase = {
1558 PyVarObject_HEAD_INIT(NULL, 0)
1559 PyVarObject_HEAD_INIT(NULL, 0)
1559 /* tp_name */ "_zope_interface_coptimizations."
1560 /* tp_name */ "_zope_interface_coptimizations."
1560 "VerifyingBase",
1561 "VerifyingBase",
1561 /* tp_basicsize */ sizeof(verify),
1562 /* tp_basicsize */ sizeof(verify),
1562 /* tp_itemsize */ 0,
1563 /* tp_itemsize */ 0,
1563 /* tp_dealloc */ (destructor)&verifying_dealloc,
1564 /* tp_dealloc */ (destructor)&verifying_dealloc,
1564 /* tp_print */ (printfunc)0,
1565 /* tp_print */ (printfunc)0,
1565 /* tp_getattr */ (getattrfunc)0,
1566 /* tp_getattr */ (getattrfunc)0,
1566 /* tp_setattr */ (setattrfunc)0,
1567 /* tp_setattr */ (setattrfunc)0,
1567 /* tp_compare */ 0,
1568 /* tp_compare */ 0,
1568 /* tp_repr */ (reprfunc)0,
1569 /* tp_repr */ (reprfunc)0,
1569 /* tp_as_number */ 0,
1570 /* tp_as_number */ 0,
1570 /* tp_as_sequence */ 0,
1571 /* tp_as_sequence */ 0,
1571 /* tp_as_mapping */ 0,
1572 /* tp_as_mapping */ 0,
1572 /* tp_hash */ (hashfunc)0,
1573 /* tp_hash */ (hashfunc)0,
1573 /* tp_call */ (ternaryfunc)0,
1574 /* tp_call */ (ternaryfunc)0,
1574 /* tp_str */ (reprfunc)0,
1575 /* tp_str */ (reprfunc)0,
1575 /* tp_getattro */ (getattrofunc)0,
1576 /* tp_getattro */ (getattrofunc)0,
1576 /* tp_setattro */ (setattrofunc)0,
1577 /* tp_setattro */ (setattrofunc)0,
1577 /* tp_as_buffer */ 0,
1578 /* tp_as_buffer */ 0,
1578 /* tp_flags */ Py_TPFLAGS_DEFAULT
1579 /* tp_flags */ Py_TPFLAGS_DEFAULT
1579 | Py_TPFLAGS_BASETYPE
1580 | Py_TPFLAGS_BASETYPE
1580 | Py_TPFLAGS_HAVE_GC,
1581 | Py_TPFLAGS_HAVE_GC,
1581 /* tp_doc */ "",
1582 /* tp_doc */ "",
1582 /* tp_traverse */ (traverseproc)verifying_traverse,
1583 /* tp_traverse */ (traverseproc)verifying_traverse,
1583 /* tp_clear */ (inquiry)verifying_clear,
1584 /* tp_clear */ (inquiry)verifying_clear,
1584 /* tp_richcompare */ (richcmpfunc)0,
1585 /* tp_richcompare */ (richcmpfunc)0,
1585 /* tp_weaklistoffset */ (long)0,
1586 /* tp_weaklistoffset */ (long)0,
1586 /* tp_iter */ (getiterfunc)0,
1587 /* tp_iter */ (getiterfunc)0,
1587 /* tp_iternext */ (iternextfunc)0,
1588 /* tp_iternext */ (iternextfunc)0,
1588 /* tp_methods */ verifying_methods,
1589 /* tp_methods */ verifying_methods,
1589 /* tp_members */ 0,
1590 /* tp_members */ 0,
1590 /* tp_getset */ 0,
1591 /* tp_getset */ 0,
1591 /* tp_base */ &LookupBase,
1592 /* tp_base */ &LookupBase,
1592 };
1593 };
1593
1594
1594 /* ========================== End: Lookup Bases ======================= */
1595 /* ========================== End: Lookup Bases ======================= */
1595 /* ==================================================================== */
1596 /* ==================================================================== */
1596
1597
1597
1598
1598
1599
1599 static struct PyMethodDef m_methods[] = {
1600 static struct PyMethodDef m_methods[] = {
1600 {"implementedBy", (PyCFunction)implementedBy, METH_O,
1601 {"implementedBy", (PyCFunction)implementedBy, METH_O,
1601 "Interfaces implemented by a class or factory.\n"
1602 "Interfaces implemented by a class or factory.\n"
1602 "Raises TypeError if argument is neither a class nor a callable."},
1603 "Raises TypeError if argument is neither a class nor a callable."},
1603 {"getObjectSpecification", (PyCFunction)getObjectSpecification, METH_O,
1604 {"getObjectSpecification", (PyCFunction)getObjectSpecification, METH_O,
1604 "Get an object's interfaces (internal api)"},
1605 "Get an object's interfaces (internal api)"},
1605 {"providedBy", (PyCFunction)providedBy, METH_O,
1606 {"providedBy", (PyCFunction)providedBy, METH_O,
1606 "Get an object's interfaces"},
1607 "Get an object's interfaces"},
1607
1608
1608 {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
1609 {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
1609 };
1610 };
1610
1611
1611 #if PY_MAJOR_VERSION >= 3
1612 #if PY_MAJOR_VERSION >= 3
1612 static char module_doc[] = "C optimizations for zope.interface\n\n";
1613 static char module_doc[] = "C optimizations for zope.interface\n\n";
1613
1614
1614 static struct PyModuleDef _zic_module = {
1615 static struct PyModuleDef _zic_module = {
1615 PyModuleDef_HEAD_INIT,
1616 PyModuleDef_HEAD_INIT,
1616 "_zope_interface_coptimizations",
1617 "_zope_interface_coptimizations",
1617 module_doc,
1618 module_doc,
1618 -1,
1619 -1,
1619 m_methods,
1620 m_methods,
1620 NULL,
1621 NULL,
1621 NULL,
1622 NULL,
1622 NULL,
1623 NULL,
1623 NULL
1624 NULL
1624 };
1625 };
1625 #endif
1626 #endif
1626
1627
1627 static PyObject *
1628 static PyObject *
1628 init(void)
1629 init(void)
1629 {
1630 {
1630 PyObject *m;
1631 PyObject *m;
1631
1632
1632 #if PY_MAJOR_VERSION < 3
1633 #if PY_MAJOR_VERSION < 3
1633 #define DEFINE_STRING(S) \
1634 #define DEFINE_STRING(S) \
1634 if(! (str ## S = PyString_FromString(# S))) return NULL
1635 if(! (str ## S = PyString_FromString(# S))) return NULL
1635 #else
1636 #else
1636 #define DEFINE_STRING(S) \
1637 #define DEFINE_STRING(S) \
1637 if(! (str ## S = PyUnicode_FromString(# S))) return NULL
1638 if(! (str ## S = PyUnicode_FromString(# S))) return NULL
1638 #endif
1639 #endif
1639
1640
1640 DEFINE_STRING(__dict__);
1641 DEFINE_STRING(__dict__);
1641 DEFINE_STRING(__implemented__);
1642 DEFINE_STRING(__implemented__);
1642 DEFINE_STRING(__provides__);
1643 DEFINE_STRING(__provides__);
1643 DEFINE_STRING(__class__);
1644 DEFINE_STRING(__class__);
1644 DEFINE_STRING(__providedBy__);
1645 DEFINE_STRING(__providedBy__);
1645 DEFINE_STRING(extends);
1646 DEFINE_STRING(extends);
1646 DEFINE_STRING(_implied);
1647 DEFINE_STRING(_implied);
1647 DEFINE_STRING(_implements);
1648 DEFINE_STRING(_implements);
1648 DEFINE_STRING(_cls);
1649 DEFINE_STRING(_cls);
1649 DEFINE_STRING(__conform__);
1650 DEFINE_STRING(__conform__);
1650 DEFINE_STRING(_call_conform);
1651 DEFINE_STRING(_call_conform);
1651 DEFINE_STRING(_uncached_lookup);
1652 DEFINE_STRING(_uncached_lookup);
1652 DEFINE_STRING(_uncached_lookupAll);
1653 DEFINE_STRING(_uncached_lookupAll);
1653 DEFINE_STRING(_uncached_subscriptions);
1654 DEFINE_STRING(_uncached_subscriptions);
1654 DEFINE_STRING(_registry);
1655 DEFINE_STRING(_registry);
1655 DEFINE_STRING(_generation);
1656 DEFINE_STRING(_generation);
1656 DEFINE_STRING(ro);
1657 DEFINE_STRING(ro);
1657 DEFINE_STRING(changed);
1658 DEFINE_STRING(changed);
1658 #undef DEFINE_STRING
1659 #undef DEFINE_STRING
1659 adapter_hooks = PyList_New(0);
1660 adapter_hooks = PyList_New(0);
1660 if (adapter_hooks == NULL)
1661 if (adapter_hooks == NULL)
1661 return NULL;
1662 return NULL;
1662
1663
1663 /* Initialize types: */
1664 /* Initialize types: */
1664 SpecType.tp_new = PyBaseObject_Type.tp_new;
1665 SpecType.tp_new = PyBaseObject_Type.tp_new;
1665 if (PyType_Ready(&SpecType) < 0)
1666 if (PyType_Ready(&SpecType) < 0)
1666 return NULL;
1667 return NULL;
1667 OSDType.tp_new = PyBaseObject_Type.tp_new;
1668 OSDType.tp_new = PyBaseObject_Type.tp_new;
1668 if (PyType_Ready(&OSDType) < 0)
1669 if (PyType_Ready(&OSDType) < 0)
1669 return NULL;
1670 return NULL;
1670 CPBType.tp_new = PyBaseObject_Type.tp_new;
1671 CPBType.tp_new = PyBaseObject_Type.tp_new;
1671 if (PyType_Ready(&CPBType) < 0)
1672 if (PyType_Ready(&CPBType) < 0)
1672 return NULL;
1673 return NULL;
1673
1674
1674 InterfaceBase.tp_new = PyBaseObject_Type.tp_new;
1675 InterfaceBase.tp_new = PyBaseObject_Type.tp_new;
1675 if (PyType_Ready(&InterfaceBase) < 0)
1676 if (PyType_Ready(&InterfaceBase) < 0)
1676 return NULL;
1677 return NULL;
1677
1678
1678 LookupBase.tp_new = PyBaseObject_Type.tp_new;
1679 LookupBase.tp_new = PyBaseObject_Type.tp_new;
1679 if (PyType_Ready(&LookupBase) < 0)
1680 if (PyType_Ready(&LookupBase) < 0)
1680 return NULL;
1681 return NULL;
1681
1682
1682 VerifyingBase.tp_new = PyBaseObject_Type.tp_new;
1683 VerifyingBase.tp_new = PyBaseObject_Type.tp_new;
1683 if (PyType_Ready(&VerifyingBase) < 0)
1684 if (PyType_Ready(&VerifyingBase) < 0)
1684 return NULL;
1685 return NULL;
1685
1686
1686 #if PY_MAJOR_VERSION < 3
1687 #if PY_MAJOR_VERSION < 3
1687 /* Create the module and add the functions */
1688 /* Create the module and add the functions */
1688 m = Py_InitModule3("_zope_interface_coptimizations", m_methods,
1689 m = Py_InitModule3("_zope_interface_coptimizations", m_methods,
1689 "C optimizations for zope.interface\n\n");
1690 "C optimizations for zope.interface\n\n");
1690 #else
1691 #else
1691 m = PyModule_Create(&_zic_module);
1692 m = PyModule_Create(&_zic_module);
1692 #endif
1693 #endif
1693 if (m == NULL)
1694 if (m == NULL)
1694 return NULL;
1695 return NULL;
1695
1696
1696 /* Add types: */
1697 /* Add types: */
1697 if (PyModule_AddObject(m, "SpecificationBase", OBJECT(&SpecType)) < 0)
1698 if (PyModule_AddObject(m, "SpecificationBase", OBJECT(&SpecType)) < 0)
1698 return NULL;
1699 return NULL;
1699 if (PyModule_AddObject(m, "ObjectSpecificationDescriptor",
1700 if (PyModule_AddObject(m, "ObjectSpecificationDescriptor",
1700 (PyObject *)&OSDType) < 0)
1701 (PyObject *)&OSDType) < 0)
1701 return NULL;
1702 return NULL;
1702 if (PyModule_AddObject(m, "ClassProvidesBase", OBJECT(&CPBType)) < 0)
1703 if (PyModule_AddObject(m, "ClassProvidesBase", OBJECT(&CPBType)) < 0)
1703 return NULL;
1704 return NULL;
1704 if (PyModule_AddObject(m, "InterfaceBase", OBJECT(&InterfaceBase)) < 0)
1705 if (PyModule_AddObject(m, "InterfaceBase", OBJECT(&InterfaceBase)) < 0)
1705 return NULL;
1706 return NULL;
1706 if (PyModule_AddObject(m, "LookupBase", OBJECT(&LookupBase)) < 0)
1707 if (PyModule_AddObject(m, "LookupBase", OBJECT(&LookupBase)) < 0)
1707 return NULL;
1708 return NULL;
1708 if (PyModule_AddObject(m, "VerifyingBase", OBJECT(&VerifyingBase)) < 0)
1709 if (PyModule_AddObject(m, "VerifyingBase", OBJECT(&VerifyingBase)) < 0)
1709 return NULL;
1710 return NULL;
1710 if (PyModule_AddObject(m, "adapter_hooks", adapter_hooks) < 0)
1711 if (PyModule_AddObject(m, "adapter_hooks", adapter_hooks) < 0)
1711 return NULL;
1712 return NULL;
1712 return m;
1713 return m;
1713 }
1714 }
1714
1715
1715 PyMODINIT_FUNC
1716 PyMODINIT_FUNC
1716 #if PY_MAJOR_VERSION < 3
1717 #if PY_MAJOR_VERSION < 3
1717 init_zope_interface_coptimizations(void)
1718 init_zope_interface_coptimizations(void)
1718 {
1719 {
1719 init();
1720 init();
1720 }
1721 }
1721 #else
1722 #else
1722 PyInit__zope_interface_coptimizations(void)
1723 PyInit__zope_interface_coptimizations(void)
1723 {
1724 {
1724 return init();
1725 return init();
1725 }
1726 }
1726 #endif
1727 #endif
@@ -1,712 +1,714 b''
1 ##############################################################################
1 ##############################################################################
2 #
2 #
3 # Copyright (c) 2004 Zope Foundation and Contributors.
3 # Copyright (c) 2004 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """Adapter management
14 """Adapter management
15 """
15 """
16 from __future__ import absolute_import
17
16 import weakref
18 import weakref
17
19
18 from zope.interface import implementer
20 from . import implementer
19 from zope.interface import providedBy
21 from . import providedBy
20 from zope.interface import Interface
22 from . import Interface
21 from zope.interface import ro
23 from . import ro
22 from zope.interface.interfaces import IAdapterRegistry
24 from .interfaces import IAdapterRegistry
23
25
24 from zope.interface._compat import _normalize_name
26 from ._compat import _normalize_name
25 from zope.interface._compat import STRING_TYPES
27 from ._compat import STRING_TYPES
26
28
27 _BLANK = u''
29 _BLANK = u''
28
30
29 class BaseAdapterRegistry(object):
31 class BaseAdapterRegistry(object):
30
32
31 # List of methods copied from lookup sub-objects:
33 # List of methods copied from lookup sub-objects:
32 _delegated = ('lookup', 'queryMultiAdapter', 'lookup1', 'queryAdapter',
34 _delegated = ('lookup', 'queryMultiAdapter', 'lookup1', 'queryAdapter',
33 'adapter_hook', 'lookupAll', 'names',
35 'adapter_hook', 'lookupAll', 'names',
34 'subscriptions', 'subscribers')
36 'subscriptions', 'subscribers')
35
37
36 # All registries maintain a generation that can be used by verifying
38 # All registries maintain a generation that can be used by verifying
37 # registries
39 # registries
38 _generation = 0
40 _generation = 0
39
41
40 def __init__(self, bases=()):
42 def __init__(self, bases=()):
41
43
42 # The comments here could be improved. Possibly this bit needs
44 # The comments here could be improved. Possibly this bit needs
43 # explaining in a separate document, as the comments here can
45 # explaining in a separate document, as the comments here can
44 # be quite confusing. /regebro
46 # be quite confusing. /regebro
45
47
46 # {order -> {required -> {provided -> {name -> value}}}}
48 # {order -> {required -> {provided -> {name -> value}}}}
47 # Here "order" is actually an index in a list, "required" and
49 # Here "order" is actually an index in a list, "required" and
48 # "provided" are interfaces, and "required" is really a nested
50 # "provided" are interfaces, and "required" is really a nested
49 # key. So, for example:
51 # key. So, for example:
50 # for order == 0 (that is, self._adapters[0]), we have:
52 # for order == 0 (that is, self._adapters[0]), we have:
51 # {provided -> {name -> value}}
53 # {provided -> {name -> value}}
52 # but for order == 2 (that is, self._adapters[2]), we have:
54 # but for order == 2 (that is, self._adapters[2]), we have:
53 # {r1 -> {r2 -> {provided -> {name -> value}}}}
55 # {r1 -> {r2 -> {provided -> {name -> value}}}}
54 #
56 #
55 self._adapters = []
57 self._adapters = []
56
58
57 # {order -> {required -> {provided -> {name -> [value]}}}}
59 # {order -> {required -> {provided -> {name -> [value]}}}}
58 # where the remarks about adapters above apply
60 # where the remarks about adapters above apply
59 self._subscribers = []
61 self._subscribers = []
60
62
61 # Set, with a reference count, keeping track of the interfaces
63 # Set, with a reference count, keeping track of the interfaces
62 # for which we have provided components:
64 # for which we have provided components:
63 self._provided = {}
65 self._provided = {}
64
66
65 # Create ``_v_lookup`` object to perform lookup. We make this a
67 # Create ``_v_lookup`` object to perform lookup. We make this a
66 # separate object to to make it easier to implement just the
68 # separate object to to make it easier to implement just the
67 # lookup functionality in C. This object keeps track of cache
69 # lookup functionality in C. This object keeps track of cache
68 # invalidation data in two kinds of registries.
70 # invalidation data in two kinds of registries.
69
71
70 # Invalidating registries have caches that are invalidated
72 # Invalidating registries have caches that are invalidated
71 # when they or their base registies change. An invalidating
73 # when they or their base registies change. An invalidating
72 # registry can only have invalidating registries as bases.
74 # registry can only have invalidating registries as bases.
73 # See LookupBaseFallback below for the pertinent logic.
75 # See LookupBaseFallback below for the pertinent logic.
74
76
75 # Verifying registies can't rely on getting invalidation messages,
77 # Verifying registies can't rely on getting invalidation messages,
76 # so have to check the generations of base registries to determine
78 # so have to check the generations of base registries to determine
77 # if their cache data are current. See VerifyingBasePy below
79 # if their cache data are current. See VerifyingBasePy below
78 # for the pertinent object.
80 # for the pertinent object.
79 self._createLookup()
81 self._createLookup()
80
82
81 # Setting the bases causes the registries described above
83 # Setting the bases causes the registries described above
82 # to be initialized (self._setBases -> self.changed ->
84 # to be initialized (self._setBases -> self.changed ->
83 # self._v_lookup.changed).
85 # self._v_lookup.changed).
84
86
85 self.__bases__ = bases
87 self.__bases__ = bases
86
88
87 def _setBases(self, bases):
89 def _setBases(self, bases):
88 self.__dict__['__bases__'] = bases
90 self.__dict__['__bases__'] = bases
89 self.ro = ro.ro(self)
91 self.ro = ro.ro(self)
90 self.changed(self)
92 self.changed(self)
91
93
92 __bases__ = property(lambda self: self.__dict__['__bases__'],
94 __bases__ = property(lambda self: self.__dict__['__bases__'],
93 lambda self, bases: self._setBases(bases),
95 lambda self, bases: self._setBases(bases),
94 )
96 )
95
97
96 def _createLookup(self):
98 def _createLookup(self):
97 self._v_lookup = self.LookupClass(self)
99 self._v_lookup = self.LookupClass(self)
98 for name in self._delegated:
100 for name in self._delegated:
99 self.__dict__[name] = getattr(self._v_lookup, name)
101 self.__dict__[name] = getattr(self._v_lookup, name)
100
102
101 def changed(self, originally_changed):
103 def changed(self, originally_changed):
102 self._generation += 1
104 self._generation += 1
103 self._v_lookup.changed(originally_changed)
105 self._v_lookup.changed(originally_changed)
104
106
105 def register(self, required, provided, name, value):
107 def register(self, required, provided, name, value):
106 if not isinstance(name, STRING_TYPES):
108 if not isinstance(name, STRING_TYPES):
107 raise ValueError('name is not a string')
109 raise ValueError('name is not a string')
108 if value is None:
110 if value is None:
109 self.unregister(required, provided, name, value)
111 self.unregister(required, provided, name, value)
110 return
112 return
111
113
112 required = tuple(map(_convert_None_to_Interface, required))
114 required = tuple(map(_convert_None_to_Interface, required))
113 name = _normalize_name(name)
115 name = _normalize_name(name)
114 order = len(required)
116 order = len(required)
115 byorder = self._adapters
117 byorder = self._adapters
116 while len(byorder) <= order:
118 while len(byorder) <= order:
117 byorder.append({})
119 byorder.append({})
118 components = byorder[order]
120 components = byorder[order]
119 key = required + (provided,)
121 key = required + (provided,)
120
122
121 for k in key:
123 for k in key:
122 d = components.get(k)
124 d = components.get(k)
123 if d is None:
125 if d is None:
124 d = {}
126 d = {}
125 components[k] = d
127 components[k] = d
126 components = d
128 components = d
127
129
128 if components.get(name) is value:
130 if components.get(name) is value:
129 return
131 return
130
132
131 components[name] = value
133 components[name] = value
132
134
133 n = self._provided.get(provided, 0) + 1
135 n = self._provided.get(provided, 0) + 1
134 self._provided[provided] = n
136 self._provided[provided] = n
135 if n == 1:
137 if n == 1:
136 self._v_lookup.add_extendor(provided)
138 self._v_lookup.add_extendor(provided)
137
139
138 self.changed(self)
140 self.changed(self)
139
141
140 def registered(self, required, provided, name=_BLANK):
142 def registered(self, required, provided, name=_BLANK):
141 required = tuple(map(_convert_None_to_Interface, required))
143 required = tuple(map(_convert_None_to_Interface, required))
142 name = _normalize_name(name)
144 name = _normalize_name(name)
143 order = len(required)
145 order = len(required)
144 byorder = self._adapters
146 byorder = self._adapters
145 if len(byorder) <= order:
147 if len(byorder) <= order:
146 return None
148 return None
147
149
148 components = byorder[order]
150 components = byorder[order]
149 key = required + (provided,)
151 key = required + (provided,)
150
152
151 for k in key:
153 for k in key:
152 d = components.get(k)
154 d = components.get(k)
153 if d is None:
155 if d is None:
154 return None
156 return None
155 components = d
157 components = d
156
158
157 return components.get(name)
159 return components.get(name)
158
160
159 def unregister(self, required, provided, name, value=None):
161 def unregister(self, required, provided, name, value=None):
160 required = tuple(map(_convert_None_to_Interface, required))
162 required = tuple(map(_convert_None_to_Interface, required))
161 order = len(required)
163 order = len(required)
162 byorder = self._adapters
164 byorder = self._adapters
163 if order >= len(byorder):
165 if order >= len(byorder):
164 return False
166 return False
165 components = byorder[order]
167 components = byorder[order]
166 key = required + (provided,)
168 key = required + (provided,)
167
169
168 # Keep track of how we got to `components`:
170 # Keep track of how we got to `components`:
169 lookups = []
171 lookups = []
170 for k in key:
172 for k in key:
171 d = components.get(k)
173 d = components.get(k)
172 if d is None:
174 if d is None:
173 return
175 return
174 lookups.append((components, k))
176 lookups.append((components, k))
175 components = d
177 components = d
176
178
177 old = components.get(name)
179 old = components.get(name)
178 if old is None:
180 if old is None:
179 return
181 return
180 if (value is not None) and (old is not value):
182 if (value is not None) and (old is not value):
181 return
183 return
182
184
183 del components[name]
185 del components[name]
184 if not components:
186 if not components:
185 # Clean out empty containers, since we don't want our keys
187 # Clean out empty containers, since we don't want our keys
186 # to reference global objects (interfaces) unnecessarily.
188 # to reference global objects (interfaces) unnecessarily.
187 # This is often a problem when an interface is slated for
189 # This is often a problem when an interface is slated for
188 # removal; a hold-over entry in the registry can make it
190 # removal; a hold-over entry in the registry can make it
189 # difficult to remove such interfaces.
191 # difficult to remove such interfaces.
190 for comp, k in reversed(lookups):
192 for comp, k in reversed(lookups):
191 d = comp[k]
193 d = comp[k]
192 if d:
194 if d:
193 break
195 break
194 else:
196 else:
195 del comp[k]
197 del comp[k]
196 while byorder and not byorder[-1]:
198 while byorder and not byorder[-1]:
197 del byorder[-1]
199 del byorder[-1]
198 n = self._provided[provided] - 1
200 n = self._provided[provided] - 1
199 if n == 0:
201 if n == 0:
200 del self._provided[provided]
202 del self._provided[provided]
201 self._v_lookup.remove_extendor(provided)
203 self._v_lookup.remove_extendor(provided)
202 else:
204 else:
203 self._provided[provided] = n
205 self._provided[provided] = n
204
206
205 self.changed(self)
207 self.changed(self)
206
208
207 def subscribe(self, required, provided, value):
209 def subscribe(self, required, provided, value):
208 required = tuple(map(_convert_None_to_Interface, required))
210 required = tuple(map(_convert_None_to_Interface, required))
209 name = _BLANK
211 name = _BLANK
210 order = len(required)
212 order = len(required)
211 byorder = self._subscribers
213 byorder = self._subscribers
212 while len(byorder) <= order:
214 while len(byorder) <= order:
213 byorder.append({})
215 byorder.append({})
214 components = byorder[order]
216 components = byorder[order]
215 key = required + (provided,)
217 key = required + (provided,)
216
218
217 for k in key:
219 for k in key:
218 d = components.get(k)
220 d = components.get(k)
219 if d is None:
221 if d is None:
220 d = {}
222 d = {}
221 components[k] = d
223 components[k] = d
222 components = d
224 components = d
223
225
224 components[name] = components.get(name, ()) + (value, )
226 components[name] = components.get(name, ()) + (value, )
225
227
226 if provided is not None:
228 if provided is not None:
227 n = self._provided.get(provided, 0) + 1
229 n = self._provided.get(provided, 0) + 1
228 self._provided[provided] = n
230 self._provided[provided] = n
229 if n == 1:
231 if n == 1:
230 self._v_lookup.add_extendor(provided)
232 self._v_lookup.add_extendor(provided)
231
233
232 self.changed(self)
234 self.changed(self)
233
235
234 def unsubscribe(self, required, provided, value=None):
236 def unsubscribe(self, required, provided, value=None):
235 required = tuple(map(_convert_None_to_Interface, required))
237 required = tuple(map(_convert_None_to_Interface, required))
236 order = len(required)
238 order = len(required)
237 byorder = self._subscribers
239 byorder = self._subscribers
238 if order >= len(byorder):
240 if order >= len(byorder):
239 return
241 return
240 components = byorder[order]
242 components = byorder[order]
241 key = required + (provided,)
243 key = required + (provided,)
242
244
243 # Keep track of how we got to `components`:
245 # Keep track of how we got to `components`:
244 lookups = []
246 lookups = []
245 for k in key:
247 for k in key:
246 d = components.get(k)
248 d = components.get(k)
247 if d is None:
249 if d is None:
248 return
250 return
249 lookups.append((components, k))
251 lookups.append((components, k))
250 components = d
252 components = d
251
253
252 old = components.get(_BLANK)
254 old = components.get(_BLANK)
253 if not old:
255 if not old:
254 # this is belt-and-suspenders against the failure of cleanup below
256 # this is belt-and-suspenders against the failure of cleanup below
255 return # pragma: no cover
257 return # pragma: no cover
256
258
257 if value is None:
259 if value is None:
258 new = ()
260 new = ()
259 else:
261 else:
260 new = tuple([v for v in old if v is not value])
262 new = tuple([v for v in old if v is not value])
261
263
262 if new == old:
264 if new == old:
263 return
265 return
264
266
265 if new:
267 if new:
266 components[_BLANK] = new
268 components[_BLANK] = new
267 else:
269 else:
268 # Instead of setting components[_BLANK] = new, we clean out
270 # Instead of setting components[_BLANK] = new, we clean out
269 # empty containers, since we don't want our keys to
271 # empty containers, since we don't want our keys to
270 # reference global objects (interfaces) unnecessarily. This
272 # reference global objects (interfaces) unnecessarily. This
271 # is often a problem when an interface is slated for
273 # is often a problem when an interface is slated for
272 # removal; a hold-over entry in the registry can make it
274 # removal; a hold-over entry in the registry can make it
273 # difficult to remove such interfaces.
275 # difficult to remove such interfaces.
274 del components[_BLANK]
276 del components[_BLANK]
275 for comp, k in reversed(lookups):
277 for comp, k in reversed(lookups):
276 d = comp[k]
278 d = comp[k]
277 if d:
279 if d:
278 break
280 break
279 else:
281 else:
280 del comp[k]
282 del comp[k]
281 while byorder and not byorder[-1]:
283 while byorder and not byorder[-1]:
282 del byorder[-1]
284 del byorder[-1]
283
285
284 if provided is not None:
286 if provided is not None:
285 n = self._provided[provided] + len(new) - len(old)
287 n = self._provided[provided] + len(new) - len(old)
286 if n == 0:
288 if n == 0:
287 del self._provided[provided]
289 del self._provided[provided]
288 self._v_lookup.remove_extendor(provided)
290 self._v_lookup.remove_extendor(provided)
289
291
290 self.changed(self)
292 self.changed(self)
291
293
292 # XXX hack to fake out twisted's use of a private api. We need to get them
294 # XXX hack to fake out twisted's use of a private api. We need to get them
293 # to use the new registed method.
295 # to use the new registed method.
294 def get(self, _): # pragma: no cover
296 def get(self, _): # pragma: no cover
295 class XXXTwistedFakeOut:
297 class XXXTwistedFakeOut:
296 selfImplied = {}
298 selfImplied = {}
297 return XXXTwistedFakeOut
299 return XXXTwistedFakeOut
298
300
299
301
300 _not_in_mapping = object()
302 _not_in_mapping = object()
301 class LookupBaseFallback(object):
303 class LookupBaseFallback(object):
302
304
303 def __init__(self):
305 def __init__(self):
304 self._cache = {}
306 self._cache = {}
305 self._mcache = {}
307 self._mcache = {}
306 self._scache = {}
308 self._scache = {}
307
309
308 def changed(self, ignored=None):
310 def changed(self, ignored=None):
309 self._cache.clear()
311 self._cache.clear()
310 self._mcache.clear()
312 self._mcache.clear()
311 self._scache.clear()
313 self._scache.clear()
312
314
313 def _getcache(self, provided, name):
315 def _getcache(self, provided, name):
314 cache = self._cache.get(provided)
316 cache = self._cache.get(provided)
315 if cache is None:
317 if cache is None:
316 cache = {}
318 cache = {}
317 self._cache[provided] = cache
319 self._cache[provided] = cache
318 if name:
320 if name:
319 c = cache.get(name)
321 c = cache.get(name)
320 if c is None:
322 if c is None:
321 c = {}
323 c = {}
322 cache[name] = c
324 cache[name] = c
323 cache = c
325 cache = c
324 return cache
326 return cache
325
327
326 def lookup(self, required, provided, name=_BLANK, default=None):
328 def lookup(self, required, provided, name=_BLANK, default=None):
327 if not isinstance(name, STRING_TYPES):
329 if not isinstance(name, STRING_TYPES):
328 raise ValueError('name is not a string')
330 raise ValueError('name is not a string')
329 cache = self._getcache(provided, name)
331 cache = self._getcache(provided, name)
330 required = tuple(required)
332 required = tuple(required)
331 if len(required) == 1:
333 if len(required) == 1:
332 result = cache.get(required[0], _not_in_mapping)
334 result = cache.get(required[0], _not_in_mapping)
333 else:
335 else:
334 result = cache.get(tuple(required), _not_in_mapping)
336 result = cache.get(tuple(required), _not_in_mapping)
335
337
336 if result is _not_in_mapping:
338 if result is _not_in_mapping:
337 result = self._uncached_lookup(required, provided, name)
339 result = self._uncached_lookup(required, provided, name)
338 if len(required) == 1:
340 if len(required) == 1:
339 cache[required[0]] = result
341 cache[required[0]] = result
340 else:
342 else:
341 cache[tuple(required)] = result
343 cache[tuple(required)] = result
342
344
343 if result is None:
345 if result is None:
344 return default
346 return default
345
347
346 return result
348 return result
347
349
348 def lookup1(self, required, provided, name=_BLANK, default=None):
350 def lookup1(self, required, provided, name=_BLANK, default=None):
349 if not isinstance(name, STRING_TYPES):
351 if not isinstance(name, STRING_TYPES):
350 raise ValueError('name is not a string')
352 raise ValueError('name is not a string')
351 cache = self._getcache(provided, name)
353 cache = self._getcache(provided, name)
352 result = cache.get(required, _not_in_mapping)
354 result = cache.get(required, _not_in_mapping)
353 if result is _not_in_mapping:
355 if result is _not_in_mapping:
354 return self.lookup((required, ), provided, name, default)
356 return self.lookup((required, ), provided, name, default)
355
357
356 if result is None:
358 if result is None:
357 return default
359 return default
358
360
359 return result
361 return result
360
362
361 def queryAdapter(self, object, provided, name=_BLANK, default=None):
363 def queryAdapter(self, object, provided, name=_BLANK, default=None):
362 return self.adapter_hook(provided, object, name, default)
364 return self.adapter_hook(provided, object, name, default)
363
365
364 def adapter_hook(self, provided, object, name=_BLANK, default=None):
366 def adapter_hook(self, provided, object, name=_BLANK, default=None):
365 if not isinstance(name, STRING_TYPES):
367 if not isinstance(name, STRING_TYPES):
366 raise ValueError('name is not a string')
368 raise ValueError('name is not a string')
367 required = providedBy(object)
369 required = providedBy(object)
368 cache = self._getcache(provided, name)
370 cache = self._getcache(provided, name)
369 factory = cache.get(required, _not_in_mapping)
371 factory = cache.get(required, _not_in_mapping)
370 if factory is _not_in_mapping:
372 if factory is _not_in_mapping:
371 factory = self.lookup((required, ), provided, name)
373 factory = self.lookup((required, ), provided, name)
372
374
373 if factory is not None:
375 if factory is not None:
374 result = factory(object)
376 result = factory(object)
375 if result is not None:
377 if result is not None:
376 return result
378 return result
377
379
378 return default
380 return default
379
381
380 def lookupAll(self, required, provided):
382 def lookupAll(self, required, provided):
381 cache = self._mcache.get(provided)
383 cache = self._mcache.get(provided)
382 if cache is None:
384 if cache is None:
383 cache = {}
385 cache = {}
384 self._mcache[provided] = cache
386 self._mcache[provided] = cache
385
387
386 required = tuple(required)
388 required = tuple(required)
387 result = cache.get(required, _not_in_mapping)
389 result = cache.get(required, _not_in_mapping)
388 if result is _not_in_mapping:
390 if result is _not_in_mapping:
389 result = self._uncached_lookupAll(required, provided)
391 result = self._uncached_lookupAll(required, provided)
390 cache[required] = result
392 cache[required] = result
391
393
392 return result
394 return result
393
395
394
396
395 def subscriptions(self, required, provided):
397 def subscriptions(self, required, provided):
396 cache = self._scache.get(provided)
398 cache = self._scache.get(provided)
397 if cache is None:
399 if cache is None:
398 cache = {}
400 cache = {}
399 self._scache[provided] = cache
401 self._scache[provided] = cache
400
402
401 required = tuple(required)
403 required = tuple(required)
402 result = cache.get(required, _not_in_mapping)
404 result = cache.get(required, _not_in_mapping)
403 if result is _not_in_mapping:
405 if result is _not_in_mapping:
404 result = self._uncached_subscriptions(required, provided)
406 result = self._uncached_subscriptions(required, provided)
405 cache[required] = result
407 cache[required] = result
406
408
407 return result
409 return result
408
410
409 LookupBasePy = LookupBaseFallback # BBB
411 LookupBasePy = LookupBaseFallback # BBB
410
412
411 try:
413 try:
412 from zope.interface._zope_interface_coptimizations import LookupBase
414 from ._zope_interface_coptimizations import LookupBase
413 except ImportError:
415 except ImportError:
414 LookupBase = LookupBaseFallback
416 LookupBase = LookupBaseFallback
415
417
416
418
417 class VerifyingBaseFallback(LookupBaseFallback):
419 class VerifyingBaseFallback(LookupBaseFallback):
418 # Mixin for lookups against registries which "chain" upwards, and
420 # Mixin for lookups against registries which "chain" upwards, and
419 # whose lookups invalidate their own caches whenever a parent registry
421 # whose lookups invalidate their own caches whenever a parent registry
420 # bumps its own '_generation' counter. E.g., used by
422 # bumps its own '_generation' counter. E.g., used by
421 # zope.component.persistentregistry
423 # zope.component.persistentregistry
422
424
423 def changed(self, originally_changed):
425 def changed(self, originally_changed):
424 LookupBaseFallback.changed(self, originally_changed)
426 LookupBaseFallback.changed(self, originally_changed)
425 self._verify_ro = self._registry.ro[1:]
427 self._verify_ro = self._registry.ro[1:]
426 self._verify_generations = [r._generation for r in self._verify_ro]
428 self._verify_generations = [r._generation for r in self._verify_ro]
427
429
428 def _verify(self):
430 def _verify(self):
429 if ([r._generation for r in self._verify_ro]
431 if ([r._generation for r in self._verify_ro]
430 != self._verify_generations):
432 != self._verify_generations):
431 self.changed(None)
433 self.changed(None)
432
434
433 def _getcache(self, provided, name):
435 def _getcache(self, provided, name):
434 self._verify()
436 self._verify()
435 return LookupBaseFallback._getcache(self, provided, name)
437 return LookupBaseFallback._getcache(self, provided, name)
436
438
437 def lookupAll(self, required, provided):
439 def lookupAll(self, required, provided):
438 self._verify()
440 self._verify()
439 return LookupBaseFallback.lookupAll(self, required, provided)
441 return LookupBaseFallback.lookupAll(self, required, provided)
440
442
441 def subscriptions(self, required, provided):
443 def subscriptions(self, required, provided):
442 self._verify()
444 self._verify()
443 return LookupBaseFallback.subscriptions(self, required, provided)
445 return LookupBaseFallback.subscriptions(self, required, provided)
444
446
445 VerifyingBasePy = VerifyingBaseFallback #BBB
447 VerifyingBasePy = VerifyingBaseFallback #BBB
446
448
447 try:
449 try:
448 from zope.interface._zope_interface_coptimizations import VerifyingBase
450 from ._zope_interface_coptimizations import VerifyingBase
449 except ImportError:
451 except ImportError:
450 VerifyingBase = VerifyingBaseFallback
452 VerifyingBase = VerifyingBaseFallback
451
453
452
454
453 class AdapterLookupBase(object):
455 class AdapterLookupBase(object):
454
456
455 def __init__(self, registry):
457 def __init__(self, registry):
456 self._registry = registry
458 self._registry = registry
457 self._required = {}
459 self._required = {}
458 self.init_extendors()
460 self.init_extendors()
459 super(AdapterLookupBase, self).__init__()
461 super(AdapterLookupBase, self).__init__()
460
462
461 def changed(self, ignored=None):
463 def changed(self, ignored=None):
462 super(AdapterLookupBase, self).changed(None)
464 super(AdapterLookupBase, self).changed(None)
463 for r in self._required.keys():
465 for r in self._required.keys():
464 r = r()
466 r = r()
465 if r is not None:
467 if r is not None:
466 r.unsubscribe(self)
468 r.unsubscribe(self)
467 self._required.clear()
469 self._required.clear()
468
470
469
471
470 # Extendors
472 # Extendors
471 # ---------
473 # ---------
472
474
473 # When given an target interface for an adapter lookup, we need to consider
475 # When given an target interface for an adapter lookup, we need to consider
474 # adapters for interfaces that extend the target interface. This is
476 # adapters for interfaces that extend the target interface. This is
475 # what the extendors dictionary is about. It tells us all of the
477 # what the extendors dictionary is about. It tells us all of the
476 # interfaces that extend an interface for which there are adapters
478 # interfaces that extend an interface for which there are adapters
477 # registered.
479 # registered.
478
480
479 # We could separate this by order and name, thus reducing the
481 # We could separate this by order and name, thus reducing the
480 # number of provided interfaces to search at run time. The tradeoff,
482 # number of provided interfaces to search at run time. The tradeoff,
481 # however, is that we have to store more information. For example,
483 # however, is that we have to store more information. For example,
482 # if the same interface is provided for multiple names and if the
484 # if the same interface is provided for multiple names and if the
483 # interface extends many interfaces, we'll have to keep track of
485 # interface extends many interfaces, we'll have to keep track of
484 # a fair bit of information for each name. It's better to
486 # a fair bit of information for each name. It's better to
485 # be space efficient here and be time efficient in the cache
487 # be space efficient here and be time efficient in the cache
486 # implementation.
488 # implementation.
487
489
488 # TODO: add invalidation when a provided interface changes, in case
490 # TODO: add invalidation when a provided interface changes, in case
489 # the interface's __iro__ has changed. This is unlikely enough that
491 # the interface's __iro__ has changed. This is unlikely enough that
490 # we'll take our chances for now.
492 # we'll take our chances for now.
491
493
492 def init_extendors(self):
494 def init_extendors(self):
493 self._extendors = {}
495 self._extendors = {}
494 for p in self._registry._provided:
496 for p in self._registry._provided:
495 self.add_extendor(p)
497 self.add_extendor(p)
496
498
497 def add_extendor(self, provided):
499 def add_extendor(self, provided):
498 _extendors = self._extendors
500 _extendors = self._extendors
499 for i in provided.__iro__:
501 for i in provided.__iro__:
500 extendors = _extendors.get(i, ())
502 extendors = _extendors.get(i, ())
501 _extendors[i] = (
503 _extendors[i] = (
502 [e for e in extendors if provided.isOrExtends(e)]
504 [e for e in extendors if provided.isOrExtends(e)]
503 +
505 +
504 [provided]
506 [provided]
505 +
507 +
506 [e for e in extendors if not provided.isOrExtends(e)]
508 [e for e in extendors if not provided.isOrExtends(e)]
507 )
509 )
508
510
509 def remove_extendor(self, provided):
511 def remove_extendor(self, provided):
510 _extendors = self._extendors
512 _extendors = self._extendors
511 for i in provided.__iro__:
513 for i in provided.__iro__:
512 _extendors[i] = [e for e in _extendors.get(i, ())
514 _extendors[i] = [e for e in _extendors.get(i, ())
513 if e != provided]
515 if e != provided]
514
516
515
517
516 def _subscribe(self, *required):
518 def _subscribe(self, *required):
517 _refs = self._required
519 _refs = self._required
518 for r in required:
520 for r in required:
519 ref = r.weakref()
521 ref = r.weakref()
520 if ref not in _refs:
522 if ref not in _refs:
521 r.subscribe(self)
523 r.subscribe(self)
522 _refs[ref] = 1
524 _refs[ref] = 1
523
525
524 def _uncached_lookup(self, required, provided, name=_BLANK):
526 def _uncached_lookup(self, required, provided, name=_BLANK):
525 required = tuple(required)
527 required = tuple(required)
526 result = None
528 result = None
527 order = len(required)
529 order = len(required)
528 for registry in self._registry.ro:
530 for registry in self._registry.ro:
529 byorder = registry._adapters
531 byorder = registry._adapters
530 if order >= len(byorder):
532 if order >= len(byorder):
531 continue
533 continue
532
534
533 extendors = registry._v_lookup._extendors.get(provided)
535 extendors = registry._v_lookup._extendors.get(provided)
534 if not extendors:
536 if not extendors:
535 continue
537 continue
536
538
537 components = byorder[order]
539 components = byorder[order]
538 result = _lookup(components, required, extendors, name, 0,
540 result = _lookup(components, required, extendors, name, 0,
539 order)
541 order)
540 if result is not None:
542 if result is not None:
541 break
543 break
542
544
543 self._subscribe(*required)
545 self._subscribe(*required)
544
546
545 return result
547 return result
546
548
547 def queryMultiAdapter(self, objects, provided, name=_BLANK, default=None):
549 def queryMultiAdapter(self, objects, provided, name=_BLANK, default=None):
548 factory = self.lookup(map(providedBy, objects), provided, name)
550 factory = self.lookup(map(providedBy, objects), provided, name)
549 if factory is None:
551 if factory is None:
550 return default
552 return default
551
553
552 result = factory(*objects)
554 result = factory(*objects)
553 if result is None:
555 if result is None:
554 return default
556 return default
555
557
556 return result
558 return result
557
559
558 def _uncached_lookupAll(self, required, provided):
560 def _uncached_lookupAll(self, required, provided):
559 required = tuple(required)
561 required = tuple(required)
560 order = len(required)
562 order = len(required)
561 result = {}
563 result = {}
562 for registry in reversed(self._registry.ro):
564 for registry in reversed(self._registry.ro):
563 byorder = registry._adapters
565 byorder = registry._adapters
564 if order >= len(byorder):
566 if order >= len(byorder):
565 continue
567 continue
566 extendors = registry._v_lookup._extendors.get(provided)
568 extendors = registry._v_lookup._extendors.get(provided)
567 if not extendors:
569 if not extendors:
568 continue
570 continue
569 components = byorder[order]
571 components = byorder[order]
570 _lookupAll(components, required, extendors, result, 0, order)
572 _lookupAll(components, required, extendors, result, 0, order)
571
573
572 self._subscribe(*required)
574 self._subscribe(*required)
573
575
574 return tuple(result.items())
576 return tuple(result.items())
575
577
576 def names(self, required, provided):
578 def names(self, required, provided):
577 return [c[0] for c in self.lookupAll(required, provided)]
579 return [c[0] for c in self.lookupAll(required, provided)]
578
580
579 def _uncached_subscriptions(self, required, provided):
581 def _uncached_subscriptions(self, required, provided):
580 required = tuple(required)
582 required = tuple(required)
581 order = len(required)
583 order = len(required)
582 result = []
584 result = []
583 for registry in reversed(self._registry.ro):
585 for registry in reversed(self._registry.ro):
584 byorder = registry._subscribers
586 byorder = registry._subscribers
585 if order >= len(byorder):
587 if order >= len(byorder):
586 continue
588 continue
587
589
588 if provided is None:
590 if provided is None:
589 extendors = (provided, )
591 extendors = (provided, )
590 else:
592 else:
591 extendors = registry._v_lookup._extendors.get(provided)
593 extendors = registry._v_lookup._extendors.get(provided)
592 if extendors is None:
594 if extendors is None:
593 continue
595 continue
594
596
595 _subscriptions(byorder[order], required, extendors, _BLANK,
597 _subscriptions(byorder[order], required, extendors, _BLANK,
596 result, 0, order)
598 result, 0, order)
597
599
598 self._subscribe(*required)
600 self._subscribe(*required)
599
601
600 return result
602 return result
601
603
602 def subscribers(self, objects, provided):
604 def subscribers(self, objects, provided):
603 subscriptions = self.subscriptions(map(providedBy, objects), provided)
605 subscriptions = self.subscriptions(map(providedBy, objects), provided)
604 if provided is None:
606 if provided is None:
605 result = ()
607 result = ()
606 for subscription in subscriptions:
608 for subscription in subscriptions:
607 subscription(*objects)
609 subscription(*objects)
608 else:
610 else:
609 result = []
611 result = []
610 for subscription in subscriptions:
612 for subscription in subscriptions:
611 subscriber = subscription(*objects)
613 subscriber = subscription(*objects)
612 if subscriber is not None:
614 if subscriber is not None:
613 result.append(subscriber)
615 result.append(subscriber)
614 return result
616 return result
615
617
616 class AdapterLookup(AdapterLookupBase, LookupBase):
618 class AdapterLookup(AdapterLookupBase, LookupBase):
617 pass
619 pass
618
620
619 @implementer(IAdapterRegistry)
621 @implementer(IAdapterRegistry)
620 class AdapterRegistry(BaseAdapterRegistry):
622 class AdapterRegistry(BaseAdapterRegistry):
621
623
622 LookupClass = AdapterLookup
624 LookupClass = AdapterLookup
623
625
624 def __init__(self, bases=()):
626 def __init__(self, bases=()):
625 # AdapterRegisties are invalidating registries, so
627 # AdapterRegisties are invalidating registries, so
626 # we need to keep track of out invalidating subregistries.
628 # we need to keep track of out invalidating subregistries.
627 self._v_subregistries = weakref.WeakKeyDictionary()
629 self._v_subregistries = weakref.WeakKeyDictionary()
628
630
629 super(AdapterRegistry, self).__init__(bases)
631 super(AdapterRegistry, self).__init__(bases)
630
632
631 def _addSubregistry(self, r):
633 def _addSubregistry(self, r):
632 self._v_subregistries[r] = 1
634 self._v_subregistries[r] = 1
633
635
634 def _removeSubregistry(self, r):
636 def _removeSubregistry(self, r):
635 if r in self._v_subregistries:
637 if r in self._v_subregistries:
636 del self._v_subregistries[r]
638 del self._v_subregistries[r]
637
639
638 def _setBases(self, bases):
640 def _setBases(self, bases):
639 old = self.__dict__.get('__bases__', ())
641 old = self.__dict__.get('__bases__', ())
640 for r in old:
642 for r in old:
641 if r not in bases:
643 if r not in bases:
642 r._removeSubregistry(self)
644 r._removeSubregistry(self)
643 for r in bases:
645 for r in bases:
644 if r not in old:
646 if r not in old:
645 r._addSubregistry(self)
647 r._addSubregistry(self)
646
648
647 super(AdapterRegistry, self)._setBases(bases)
649 super(AdapterRegistry, self)._setBases(bases)
648
650
649 def changed(self, originally_changed):
651 def changed(self, originally_changed):
650 super(AdapterRegistry, self).changed(originally_changed)
652 super(AdapterRegistry, self).changed(originally_changed)
651
653
652 for sub in self._v_subregistries.keys():
654 for sub in self._v_subregistries.keys():
653 sub.changed(originally_changed)
655 sub.changed(originally_changed)
654
656
655
657
656 class VerifyingAdapterLookup(AdapterLookupBase, VerifyingBase):
658 class VerifyingAdapterLookup(AdapterLookupBase, VerifyingBase):
657 pass
659 pass
658
660
659 @implementer(IAdapterRegistry)
661 @implementer(IAdapterRegistry)
660 class VerifyingAdapterRegistry(BaseAdapterRegistry):
662 class VerifyingAdapterRegistry(BaseAdapterRegistry):
661
663
662 LookupClass = VerifyingAdapterLookup
664 LookupClass = VerifyingAdapterLookup
663
665
664 def _convert_None_to_Interface(x):
666 def _convert_None_to_Interface(x):
665 if x is None:
667 if x is None:
666 return Interface
668 return Interface
667 else:
669 else:
668 return x
670 return x
669
671
670 def _lookup(components, specs, provided, name, i, l):
672 def _lookup(components, specs, provided, name, i, l):
671 if i < l:
673 if i < l:
672 for spec in specs[i].__sro__:
674 for spec in specs[i].__sro__:
673 comps = components.get(spec)
675 comps = components.get(spec)
674 if comps:
676 if comps:
675 r = _lookup(comps, specs, provided, name, i+1, l)
677 r = _lookup(comps, specs, provided, name, i+1, l)
676 if r is not None:
678 if r is not None:
677 return r
679 return r
678 else:
680 else:
679 for iface in provided:
681 for iface in provided:
680 comps = components.get(iface)
682 comps = components.get(iface)
681 if comps:
683 if comps:
682 r = comps.get(name)
684 r = comps.get(name)
683 if r is not None:
685 if r is not None:
684 return r
686 return r
685
687
686 return None
688 return None
687
689
688 def _lookupAll(components, specs, provided, result, i, l):
690 def _lookupAll(components, specs, provided, result, i, l):
689 if i < l:
691 if i < l:
690 for spec in reversed(specs[i].__sro__):
692 for spec in reversed(specs[i].__sro__):
691 comps = components.get(spec)
693 comps = components.get(spec)
692 if comps:
694 if comps:
693 _lookupAll(comps, specs, provided, result, i+1, l)
695 _lookupAll(comps, specs, provided, result, i+1, l)
694 else:
696 else:
695 for iface in reversed(provided):
697 for iface in reversed(provided):
696 comps = components.get(iface)
698 comps = components.get(iface)
697 if comps:
699 if comps:
698 result.update(comps)
700 result.update(comps)
699
701
700 def _subscriptions(components, specs, provided, name, result, i, l):
702 def _subscriptions(components, specs, provided, name, result, i, l):
701 if i < l:
703 if i < l:
702 for spec in reversed(specs[i].__sro__):
704 for spec in reversed(specs[i].__sro__):
703 comps = components.get(spec)
705 comps = components.get(spec)
704 if comps:
706 if comps:
705 _subscriptions(comps, specs, provided, name, result, i+1, l)
707 _subscriptions(comps, specs, provided, name, result, i+1, l)
706 else:
708 else:
707 for iface in reversed(provided):
709 for iface in reversed(provided):
708 comps = components.get(iface)
710 comps = components.get(iface)
709 if comps:
711 if comps:
710 comps = comps.get(name)
712 comps = comps.get(name)
711 if comps:
713 if comps:
712 result.extend(comps)
714 result.extend(comps)
@@ -1,205 +1,207 b''
1 ##############################################################################
1 ##############################################################################
2 #
2 #
3 # Copyright (c) 2003 Zope Foundation and Contributors.
3 # Copyright (c) 2003 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """Class advice.
14 """Class advice.
15
15
16 This module was adapted from 'protocols.advice', part of the Python
16 This module was adapted from 'protocols.advice', part of the Python
17 Enterprise Application Kit (PEAK). Please notify the PEAK authors
17 Enterprise Application Kit (PEAK). Please notify the PEAK authors
18 (pje@telecommunity.com and tsarna@sarna.org) if bugs are found or
18 (pje@telecommunity.com and tsarna@sarna.org) if bugs are found or
19 Zope-specific changes are required, so that the PEAK version of this module
19 Zope-specific changes are required, so that the PEAK version of this module
20 can be kept in sync.
20 can be kept in sync.
21
21
22 PEAK is a Python application framework that interoperates with (but does
22 PEAK is a Python application framework that interoperates with (but does
23 not require) Zope 3 and Twisted. It provides tools for manipulating UML
23 not require) Zope 3 and Twisted. It provides tools for manipulating UML
24 models, object-relational persistence, aspect-oriented programming, and more.
24 models, object-relational persistence, aspect-oriented programming, and more.
25 Visit the PEAK home page at http://peak.telecommunity.com for more information.
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 from types import FunctionType
30 from types import FunctionType
29 try:
31 try:
30 from types import ClassType
32 from types import ClassType
31 except ImportError:
33 except ImportError:
32 __python3 = True
34 __python3 = True
33 else:
35 else:
34 __python3 = False
36 __python3 = False
35
37
36 import sys
38 import sys
37
39
38 def getFrameInfo(frame):
40 def getFrameInfo(frame):
39 """Return (kind,module,locals,globals) for a frame
41 """Return (kind,module,locals,globals) for a frame
40
42
41 'kind' is one of "exec", "module", "class", "function call", or "unknown".
43 'kind' is one of "exec", "module", "class", "function call", or "unknown".
42 """
44 """
43
45
44 f_locals = frame.f_locals
46 f_locals = frame.f_locals
45 f_globals = frame.f_globals
47 f_globals = frame.f_globals
46
48
47 sameNamespace = f_locals is f_globals
49 sameNamespace = f_locals is f_globals
48 hasModule = '__module__' in f_locals
50 hasModule = '__module__' in f_locals
49 hasName = '__name__' in f_globals
51 hasName = '__name__' in f_globals
50
52
51 sameName = hasModule and hasName
53 sameName = hasModule and hasName
52 sameName = sameName and f_globals['__name__']==f_locals['__module__']
54 sameName = sameName and f_globals['__name__']==f_locals['__module__']
53
55
54 module = hasName and sys.modules.get(f_globals['__name__']) or None
56 module = hasName and sys.modules.get(f_globals['__name__']) or None
55
57
56 namespaceIsModule = module and module.__dict__ is f_globals
58 namespaceIsModule = module and module.__dict__ is f_globals
57
59
58 if not namespaceIsModule:
60 if not namespaceIsModule:
59 # some kind of funky exec
61 # some kind of funky exec
60 kind = "exec"
62 kind = "exec"
61 elif sameNamespace and not hasModule:
63 elif sameNamespace and not hasModule:
62 kind = "module"
64 kind = "module"
63 elif sameName and not sameNamespace:
65 elif sameName and not sameNamespace:
64 kind = "class"
66 kind = "class"
65 elif not sameNamespace:
67 elif not sameNamespace:
66 kind = "function call"
68 kind = "function call"
67 else: # pragma: no cover
69 else: # pragma: no cover
68 # How can you have f_locals is f_globals, and have '__module__' set?
70 # How can you have f_locals is f_globals, and have '__module__' set?
69 # This is probably module-level code, but with a '__module__' variable.
71 # This is probably module-level code, but with a '__module__' variable.
70 kind = "unknown"
72 kind = "unknown"
71 return kind, module, f_locals, f_globals
73 return kind, module, f_locals, f_globals
72
74
73
75
74 def addClassAdvisor(callback, depth=2):
76 def addClassAdvisor(callback, depth=2):
75 """Set up 'callback' to be passed the containing class upon creation
77 """Set up 'callback' to be passed the containing class upon creation
76
78
77 This function is designed to be called by an "advising" function executed
79 This function is designed to be called by an "advising" function executed
78 in a class suite. The "advising" function supplies a callback that it
80 in a class suite. The "advising" function supplies a callback that it
79 wishes to have executed when the containing class is created. The
81 wishes to have executed when the containing class is created. The
80 callback will be given one argument: the newly created containing class.
82 callback will be given one argument: the newly created containing class.
81 The return value of the callback will be used in place of the class, so
83 The return value of the callback will be used in place of the class, so
82 the callback should return the input if it does not wish to replace the
84 the callback should return the input if it does not wish to replace the
83 class.
85 class.
84
86
85 The optional 'depth' argument to this function determines the number of
87 The optional 'depth' argument to this function determines the number of
86 frames between this function and the targeted class suite. 'depth'
88 frames between this function and the targeted class suite. 'depth'
87 defaults to 2, since this skips this function's frame and one calling
89 defaults to 2, since this skips this function's frame and one calling
88 function frame. If you use this function from a function called directly
90 function frame. If you use this function from a function called directly
89 in the class suite, the default will be correct, otherwise you will need
91 in the class suite, the default will be correct, otherwise you will need
90 to determine the correct depth yourself.
92 to determine the correct depth yourself.
91
93
92 This function works by installing a special class factory function in
94 This function works by installing a special class factory function in
93 place of the '__metaclass__' of the containing class. Therefore, only
95 place of the '__metaclass__' of the containing class. Therefore, only
94 callbacks *after* the last '__metaclass__' assignment in the containing
96 callbacks *after* the last '__metaclass__' assignment in the containing
95 class will be executed. Be sure that classes using "advising" functions
97 class will be executed. Be sure that classes using "advising" functions
96 declare any '__metaclass__' *first*, to ensure all callbacks are run."""
98 declare any '__metaclass__' *first*, to ensure all callbacks are run."""
97 # This entire approach is invalid under Py3K. Don't even try to fix
99 # This entire approach is invalid under Py3K. Don't even try to fix
98 # the coverage for this block there. :(
100 # the coverage for this block there. :(
99 if __python3: # pragma: no cover
101 if __python3: # pragma: no cover
100 raise TypeError('Class advice impossible in Python3')
102 raise TypeError('Class advice impossible in Python3')
101
103
102 frame = sys._getframe(depth)
104 frame = sys._getframe(depth)
103 kind, module, caller_locals, caller_globals = getFrameInfo(frame)
105 kind, module, caller_locals, caller_globals = getFrameInfo(frame)
104
106
105 # This causes a problem when zope interfaces are used from doctest.
107 # This causes a problem when zope interfaces are used from doctest.
106 # In these cases, kind == "exec".
108 # In these cases, kind == "exec".
107 #
109 #
108 #if kind != "class":
110 #if kind != "class":
109 # raise SyntaxError(
111 # raise SyntaxError(
110 # "Advice must be in the body of a class statement"
112 # "Advice must be in the body of a class statement"
111 # )
113 # )
112
114
113 previousMetaclass = caller_locals.get('__metaclass__')
115 previousMetaclass = caller_locals.get('__metaclass__')
114 if __python3: # pragma: no cover
116 if __python3: # pragma: no cover
115 defaultMetaclass = caller_globals.get('__metaclass__', type)
117 defaultMetaclass = caller_globals.get('__metaclass__', type)
116 else:
118 else:
117 defaultMetaclass = caller_globals.get('__metaclass__', ClassType)
119 defaultMetaclass = caller_globals.get('__metaclass__', ClassType)
118
120
119
121
120 def advise(name, bases, cdict):
122 def advise(name, bases, cdict):
121
123
122 if '__metaclass__' in cdict:
124 if '__metaclass__' in cdict:
123 del cdict['__metaclass__']
125 del cdict['__metaclass__']
124
126
125 if previousMetaclass is None:
127 if previousMetaclass is None:
126 if bases:
128 if bases:
127 # find best metaclass or use global __metaclass__ if no bases
129 # find best metaclass or use global __metaclass__ if no bases
128 meta = determineMetaclass(bases)
130 meta = determineMetaclass(bases)
129 else:
131 else:
130 meta = defaultMetaclass
132 meta = defaultMetaclass
131
133
132 elif isClassAdvisor(previousMetaclass):
134 elif isClassAdvisor(previousMetaclass):
133 # special case: we can't compute the "true" metaclass here,
135 # special case: we can't compute the "true" metaclass here,
134 # so we need to invoke the previous metaclass and let it
136 # so we need to invoke the previous metaclass and let it
135 # figure it out for us (and apply its own advice in the process)
137 # figure it out for us (and apply its own advice in the process)
136 meta = previousMetaclass
138 meta = previousMetaclass
137
139
138 else:
140 else:
139 meta = determineMetaclass(bases, previousMetaclass)
141 meta = determineMetaclass(bases, previousMetaclass)
140
142
141 newClass = meta(name,bases,cdict)
143 newClass = meta(name,bases,cdict)
142
144
143 # this lets the callback replace the class completely, if it wants to
145 # this lets the callback replace the class completely, if it wants to
144 return callback(newClass)
146 return callback(newClass)
145
147
146 # introspection data only, not used by inner function
148 # introspection data only, not used by inner function
147 advise.previousMetaclass = previousMetaclass
149 advise.previousMetaclass = previousMetaclass
148 advise.callback = callback
150 advise.callback = callback
149
151
150 # install the advisor
152 # install the advisor
151 caller_locals['__metaclass__'] = advise
153 caller_locals['__metaclass__'] = advise
152
154
153
155
154 def isClassAdvisor(ob):
156 def isClassAdvisor(ob):
155 """True if 'ob' is a class advisor function"""
157 """True if 'ob' is a class advisor function"""
156 return isinstance(ob,FunctionType) and hasattr(ob,'previousMetaclass')
158 return isinstance(ob,FunctionType) and hasattr(ob,'previousMetaclass')
157
159
158
160
159 def determineMetaclass(bases, explicit_mc=None):
161 def determineMetaclass(bases, explicit_mc=None):
160 """Determine metaclass from 1+ bases and optional explicit __metaclass__"""
162 """Determine metaclass from 1+ bases and optional explicit __metaclass__"""
161
163
162 meta = [getattr(b,'__class__',type(b)) for b in bases]
164 meta = [getattr(b,'__class__',type(b)) for b in bases]
163
165
164 if explicit_mc is not None:
166 if explicit_mc is not None:
165 # The explicit metaclass needs to be verified for compatibility
167 # The explicit metaclass needs to be verified for compatibility
166 # as well, and allowed to resolve the incompatible bases, if any
168 # as well, and allowed to resolve the incompatible bases, if any
167 meta.append(explicit_mc)
169 meta.append(explicit_mc)
168
170
169 if len(meta)==1:
171 if len(meta)==1:
170 # easy case
172 # easy case
171 return meta[0]
173 return meta[0]
172
174
173 candidates = minimalBases(meta) # minimal set of metaclasses
175 candidates = minimalBases(meta) # minimal set of metaclasses
174
176
175 if not candidates: # pragma: no cover
177 if not candidates: # pragma: no cover
176 # they're all "classic" classes
178 # they're all "classic" classes
177 assert(not __python3) # This should not happen under Python 3
179 assert(not __python3) # This should not happen under Python 3
178 return ClassType
180 return ClassType
179
181
180 elif len(candidates)>1:
182 elif len(candidates)>1:
181 # We could auto-combine, but for now we won't...
183 # We could auto-combine, but for now we won't...
182 raise TypeError("Incompatible metatypes",bases)
184 raise TypeError("Incompatible metatypes",bases)
183
185
184 # Just one, return it
186 # Just one, return it
185 return candidates[0]
187 return candidates[0]
186
188
187
189
188 def minimalBases(classes):
190 def minimalBases(classes):
189 """Reduce a list of base classes to its ordered minimum equivalent"""
191 """Reduce a list of base classes to its ordered minimum equivalent"""
190
192
191 if not __python3: # pragma: no cover
193 if not __python3: # pragma: no cover
192 classes = [c for c in classes if c is not ClassType]
194 classes = [c for c in classes if c is not ClassType]
193 candidates = []
195 candidates = []
194
196
195 for m in classes:
197 for m in classes:
196 for n in classes:
198 for n in classes:
197 if issubclass(n,m) and m is not n:
199 if issubclass(n,m) and m is not n:
198 break
200 break
199 else:
201 else:
200 # m has no subclasses in 'classes'
202 # m has no subclasses in 'classes'
201 if m in candidates:
203 if m in candidates:
202 candidates.remove(m) # ensure that we're later in the list
204 candidates.remove(m) # ensure that we're later in the list
203 candidates.append(m)
205 candidates.append(m)
204
206
205 return candidates
207 return candidates
@@ -1,575 +1,577 b''
1 ##############################################################################
1 ##############################################################################
2 # Copyright (c) 2002 Zope Foundation and Contributors.
2 # Copyright (c) 2002 Zope Foundation and Contributors.
3 # All Rights Reserved.
3 # All Rights Reserved.
4 #
4 #
5 # This software is subject to the provisions of the Zope Public License,
5 # This software is subject to the provisions of the Zope Public License,
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # FOR A PARTICULAR PURPOSE.
10 # FOR A PARTICULAR PURPOSE.
11 ##############################################################################
11 ##############################################################################
12 """Datetime interfaces.
12 """Datetime interfaces.
13
13
14 This module is called idatetime because if it were called datetime the import
14 This module is called idatetime because if it were called datetime the import
15 of the real datetime would fail.
15 of the real datetime would fail.
16 """
16 """
17
17
18 from zope.interface import Interface, Attribute
18 from __future__ import absolute_import
19 from zope.interface import classImplements
19
20 from .. import Interface, Attribute
21 from .. import classImplements
20
22
21 from datetime import timedelta, date, datetime, time, tzinfo
23 from datetime import timedelta, date, datetime, time, tzinfo
22
24
23
25
24 class ITimeDeltaClass(Interface):
26 class ITimeDeltaClass(Interface):
25 """This is the timedelta class interface."""
27 """This is the timedelta class interface."""
26
28
27 min = Attribute("The most negative timedelta object")
29 min = Attribute("The most negative timedelta object")
28
30
29 max = Attribute("The most positive timedelta object")
31 max = Attribute("The most positive timedelta object")
30
32
31 resolution = Attribute(
33 resolution = Attribute(
32 "The smallest difference between non-equal timedelta objects")
34 "The smallest difference between non-equal timedelta objects")
33
35
34
36
35 class ITimeDelta(ITimeDeltaClass):
37 class ITimeDelta(ITimeDeltaClass):
36 """Represent the difference between two datetime objects.
38 """Represent the difference between two datetime objects.
37
39
38 Supported operators:
40 Supported operators:
39
41
40 - add, subtract timedelta
42 - add, subtract timedelta
41 - unary plus, minus, abs
43 - unary plus, minus, abs
42 - compare to timedelta
44 - compare to timedelta
43 - multiply, divide by int/long
45 - multiply, divide by int/long
44
46
45 In addition, datetime supports subtraction of two datetime objects
47 In addition, datetime supports subtraction of two datetime objects
46 returning a timedelta, and addition or subtraction of a datetime
48 returning a timedelta, and addition or subtraction of a datetime
47 and a timedelta giving a datetime.
49 and a timedelta giving a datetime.
48
50
49 Representation: (days, seconds, microseconds).
51 Representation: (days, seconds, microseconds).
50 """
52 """
51
53
52 days = Attribute("Days between -999999999 and 999999999 inclusive")
54 days = Attribute("Days between -999999999 and 999999999 inclusive")
53
55
54 seconds = Attribute("Seconds between 0 and 86399 inclusive")
56 seconds = Attribute("Seconds between 0 and 86399 inclusive")
55
57
56 microseconds = Attribute("Microseconds between 0 and 999999 inclusive")
58 microseconds = Attribute("Microseconds between 0 and 999999 inclusive")
57
59
58
60
59 class IDateClass(Interface):
61 class IDateClass(Interface):
60 """This is the date class interface."""
62 """This is the date class interface."""
61
63
62 min = Attribute("The earliest representable date")
64 min = Attribute("The earliest representable date")
63
65
64 max = Attribute("The latest representable date")
66 max = Attribute("The latest representable date")
65
67
66 resolution = Attribute(
68 resolution = Attribute(
67 "The smallest difference between non-equal date objects")
69 "The smallest difference between non-equal date objects")
68
70
69 def today():
71 def today():
70 """Return the current local time.
72 """Return the current local time.
71
73
72 This is equivalent to date.fromtimestamp(time.time())"""
74 This is equivalent to date.fromtimestamp(time.time())"""
73
75
74 def fromtimestamp(timestamp):
76 def fromtimestamp(timestamp):
75 """Return the local date from a POSIX timestamp (like time.time())
77 """Return the local date from a POSIX timestamp (like time.time())
76
78
77 This may raise ValueError, if the timestamp is out of the range of
79 This may raise ValueError, if the timestamp is out of the range of
78 values supported by the platform C localtime() function. It's common
80 values supported by the platform C localtime() function. It's common
79 for this to be restricted to years from 1970 through 2038. Note that
81 for this to be restricted to years from 1970 through 2038. Note that
80 on non-POSIX systems that include leap seconds in their notion of a
82 on non-POSIX systems that include leap seconds in their notion of a
81 timestamp, leap seconds are ignored by fromtimestamp().
83 timestamp, leap seconds are ignored by fromtimestamp().
82 """
84 """
83
85
84 def fromordinal(ordinal):
86 def fromordinal(ordinal):
85 """Return the date corresponding to the proleptic Gregorian ordinal.
87 """Return the date corresponding to the proleptic Gregorian ordinal.
86
88
87 January 1 of year 1 has ordinal 1. ValueError is raised unless
89 January 1 of year 1 has ordinal 1. ValueError is raised unless
88 1 <= ordinal <= date.max.toordinal().
90 1 <= ordinal <= date.max.toordinal().
89 For any date d, date.fromordinal(d.toordinal()) == d.
91 For any date d, date.fromordinal(d.toordinal()) == d.
90 """
92 """
91
93
92
94
93 class IDate(IDateClass):
95 class IDate(IDateClass):
94 """Represents a date (year, month and day) in an idealized calendar.
96 """Represents a date (year, month and day) in an idealized calendar.
95
97
96 Operators:
98 Operators:
97
99
98 __repr__, __str__
100 __repr__, __str__
99 __cmp__, __hash__
101 __cmp__, __hash__
100 __add__, __radd__, __sub__ (add/radd only with timedelta arg)
102 __add__, __radd__, __sub__ (add/radd only with timedelta arg)
101 """
103 """
102
104
103 year = Attribute("Between MINYEAR and MAXYEAR inclusive.")
105 year = Attribute("Between MINYEAR and MAXYEAR inclusive.")
104
106
105 month = Attribute("Between 1 and 12 inclusive")
107 month = Attribute("Between 1 and 12 inclusive")
106
108
107 day = Attribute(
109 day = Attribute(
108 "Between 1 and the number of days in the given month of the given year.")
110 "Between 1 and the number of days in the given month of the given year.")
109
111
110 def replace(year, month, day):
112 def replace(year, month, day):
111 """Return a date with the same value.
113 """Return a date with the same value.
112
114
113 Except for those members given new values by whichever keyword
115 Except for those members given new values by whichever keyword
114 arguments are specified. For example, if d == date(2002, 12, 31), then
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 def timetuple():
120 def timetuple():
119 """Return a 9-element tuple of the form returned by time.localtime().
121 """Return a 9-element tuple of the form returned by time.localtime().
120
122
121 The hours, minutes and seconds are 0, and the DST flag is -1.
123 The hours, minutes and seconds are 0, and the DST flag is -1.
122 d.timetuple() is equivalent to
124 d.timetuple() is equivalent to
123 (d.year, d.month, d.day, 0, 0, 0, d.weekday(), d.toordinal() -
125 (d.year, d.month, d.day, 0, 0, 0, d.weekday(), d.toordinal() -
124 date(d.year, 1, 1).toordinal() + 1, -1)
126 date(d.year, 1, 1).toordinal() + 1, -1)
125 """
127 """
126
128
127 def toordinal():
129 def toordinal():
128 """Return the proleptic Gregorian ordinal of the date
130 """Return the proleptic Gregorian ordinal of the date
129
131
130 January 1 of year 1 has ordinal 1. For any date object d,
132 January 1 of year 1 has ordinal 1. For any date object d,
131 date.fromordinal(d.toordinal()) == d.
133 date.fromordinal(d.toordinal()) == d.
132 """
134 """
133
135
134 def weekday():
136 def weekday():
135 """Return the day of the week as an integer.
137 """Return the day of the week as an integer.
136
138
137 Monday is 0 and Sunday is 6. For example,
139 Monday is 0 and Sunday is 6. For example,
138 date(2002, 12, 4).weekday() == 2, a Wednesday.
140 date(2002, 12, 4).weekday() == 2, a Wednesday.
139
141
140 See also isoweekday().
142 See also isoweekday().
141 """
143 """
142
144
143 def isoweekday():
145 def isoweekday():
144 """Return the day of the week as an integer.
146 """Return the day of the week as an integer.
145
147
146 Monday is 1 and Sunday is 7. For example,
148 Monday is 1 and Sunday is 7. For example,
147 date(2002, 12, 4).isoweekday() == 3, a Wednesday.
149 date(2002, 12, 4).isoweekday() == 3, a Wednesday.
148
150
149 See also weekday(), isocalendar().
151 See also weekday(), isocalendar().
150 """
152 """
151
153
152 def isocalendar():
154 def isocalendar():
153 """Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
155 """Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
154
156
155 The ISO calendar is a widely used variant of the Gregorian calendar.
157 The ISO calendar is a widely used variant of the Gregorian calendar.
156 See http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm for a good
158 See http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm for a good
157 explanation.
159 explanation.
158
160
159 The ISO year consists of 52 or 53 full weeks, and where a week starts
161 The ISO year consists of 52 or 53 full weeks, and where a week starts
160 on a Monday and ends on a Sunday. The first week of an ISO year is the
162 on a Monday and ends on a Sunday. The first week of an ISO year is the
161 first (Gregorian) calendar week of a year containing a Thursday. This
163 first (Gregorian) calendar week of a year containing a Thursday. This
162 is called week number 1, and the ISO year of that Thursday is the same
164 is called week number 1, and the ISO year of that Thursday is the same
163 as its Gregorian year.
165 as its Gregorian year.
164
166
165 For example, 2004 begins on a Thursday, so the first week of ISO year
167 For example, 2004 begins on a Thursday, so the first week of ISO year
166 2004 begins on Monday, 29 Dec 2003 and ends on Sunday, 4 Jan 2004, so
168 2004 begins on Monday, 29 Dec 2003 and ends on Sunday, 4 Jan 2004, so
167 that date(2003, 12, 29).isocalendar() == (2004, 1, 1) and
169 that date(2003, 12, 29).isocalendar() == (2004, 1, 1) and
168 date(2004, 1, 4).isocalendar() == (2004, 1, 7).
170 date(2004, 1, 4).isocalendar() == (2004, 1, 7).
169 """
171 """
170
172
171 def isoformat():
173 def isoformat():
172 """Return a string representing the date in ISO 8601 format.
174 """Return a string representing the date in ISO 8601 format.
173
175
174 This is 'YYYY-MM-DD'.
176 This is 'YYYY-MM-DD'.
175 For example, date(2002, 12, 4).isoformat() == '2002-12-04'.
177 For example, date(2002, 12, 4).isoformat() == '2002-12-04'.
176 """
178 """
177
179
178 def __str__():
180 def __str__():
179 """For a date d, str(d) is equivalent to d.isoformat()."""
181 """For a date d, str(d) is equivalent to d.isoformat()."""
180
182
181 def ctime():
183 def ctime():
182 """Return a string representing the date.
184 """Return a string representing the date.
183
185
184 For example date(2002, 12, 4).ctime() == 'Wed Dec 4 00:00:00 2002'.
186 For example date(2002, 12, 4).ctime() == 'Wed Dec 4 00:00:00 2002'.
185 d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple()))
187 d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple()))
186 on platforms where the native C ctime() function
188 on platforms where the native C ctime() function
187 (which time.ctime() invokes, but which date.ctime() does not invoke)
189 (which time.ctime() invokes, but which date.ctime() does not invoke)
188 conforms to the C standard.
190 conforms to the C standard.
189 """
191 """
190
192
191 def strftime(format):
193 def strftime(format):
192 """Return a string representing the date.
194 """Return a string representing the date.
193
195
194 Controlled by an explicit format string. Format codes referring to
196 Controlled by an explicit format string. Format codes referring to
195 hours, minutes or seconds will see 0 values.
197 hours, minutes or seconds will see 0 values.
196 """
198 """
197
199
198
200
199 class IDateTimeClass(Interface):
201 class IDateTimeClass(Interface):
200 """This is the datetime class interface."""
202 """This is the datetime class interface."""
201
203
202 min = Attribute("The earliest representable datetime")
204 min = Attribute("The earliest representable datetime")
203
205
204 max = Attribute("The latest representable datetime")
206 max = Attribute("The latest representable datetime")
205
207
206 resolution = Attribute(
208 resolution = Attribute(
207 "The smallest possible difference between non-equal datetime objects")
209 "The smallest possible difference between non-equal datetime objects")
208
210
209 def today():
211 def today():
210 """Return the current local datetime, with tzinfo None.
212 """Return the current local datetime, with tzinfo None.
211
213
212 This is equivalent to datetime.fromtimestamp(time.time()).
214 This is equivalent to datetime.fromtimestamp(time.time()).
213 See also now(), fromtimestamp().
215 See also now(), fromtimestamp().
214 """
216 """
215
217
216 def now(tz=None):
218 def now(tz=None):
217 """Return the current local date and time.
219 """Return the current local date and time.
218
220
219 If optional argument tz is None or not specified, this is like today(),
221 If optional argument tz is None or not specified, this is like today(),
220 but, if possible, supplies more precision than can be gotten from going
222 but, if possible, supplies more precision than can be gotten from going
221 through a time.time() timestamp (for example, this may be possible on
223 through a time.time() timestamp (for example, this may be possible on
222 platforms supplying the C gettimeofday() function).
224 platforms supplying the C gettimeofday() function).
223
225
224 Else tz must be an instance of a class tzinfo subclass, and the current
226 Else tz must be an instance of a class tzinfo subclass, and the current
225 date and time are converted to tz's time zone. In this case the result
227 date and time are converted to tz's time zone. In this case the result
226 is equivalent to tz.fromutc(datetime.utcnow().replace(tzinfo=tz)).
228 is equivalent to tz.fromutc(datetime.utcnow().replace(tzinfo=tz)).
227
229
228 See also today(), utcnow().
230 See also today(), utcnow().
229 """
231 """
230
232
231 def utcnow():
233 def utcnow():
232 """Return the current UTC date and time, with tzinfo None.
234 """Return the current UTC date and time, with tzinfo None.
233
235
234 This is like now(), but returns the current UTC date and time, as a
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 See also now().
239 See also now().
238 """
240 """
239
241
240 def fromtimestamp(timestamp, tz=None):
242 def fromtimestamp(timestamp, tz=None):
241 """Return the local date and time corresponding to the POSIX timestamp.
243 """Return the local date and time corresponding to the POSIX timestamp.
242
244
243 Same as is returned by time.time(). If optional argument tz is None or
245 Same as is returned by time.time(). If optional argument tz is None or
244 not specified, the timestamp is converted to the platform's local date
246 not specified, the timestamp is converted to the platform's local date
245 and time, and the returned datetime object is naive.
247 and time, and the returned datetime object is naive.
246
248
247 Else tz must be an instance of a class tzinfo subclass, and the
249 Else tz must be an instance of a class tzinfo subclass, and the
248 timestamp is converted to tz's time zone. In this case the result is
250 timestamp is converted to tz's time zone. In this case the result is
249 equivalent to
251 equivalent to
250 tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz)).
252 tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz)).
251
253
252 fromtimestamp() may raise ValueError, if the timestamp is out of the
254 fromtimestamp() may raise ValueError, if the timestamp is out of the
253 range of values supported by the platform C localtime() or gmtime()
255 range of values supported by the platform C localtime() or gmtime()
254 functions. It's common for this to be restricted to years in 1970
256 functions. It's common for this to be restricted to years in 1970
255 through 2038. Note that on non-POSIX systems that include leap seconds
257 through 2038. Note that on non-POSIX systems that include leap seconds
256 in their notion of a timestamp, leap seconds are ignored by
258 in their notion of a timestamp, leap seconds are ignored by
257 fromtimestamp(), and then it's possible to have two timestamps
259 fromtimestamp(), and then it's possible to have two timestamps
258 differing by a second that yield identical datetime objects.
260 differing by a second that yield identical datetime objects.
259
261
260 See also utcfromtimestamp().
262 See also utcfromtimestamp().
261 """
263 """
262
264
263 def utcfromtimestamp(timestamp):
265 def utcfromtimestamp(timestamp):
264 """Return the UTC datetime from the POSIX timestamp with tzinfo None.
266 """Return the UTC datetime from the POSIX timestamp with tzinfo None.
265
267
266 This may raise ValueError, if the timestamp is out of the range of
268 This may raise ValueError, if the timestamp is out of the range of
267 values supported by the platform C gmtime() function. It's common for
269 values supported by the platform C gmtime() function. It's common for
268 this to be restricted to years in 1970 through 2038.
270 this to be restricted to years in 1970 through 2038.
269
271
270 See also fromtimestamp().
272 See also fromtimestamp().
271 """
273 """
272
274
273 def fromordinal(ordinal):
275 def fromordinal(ordinal):
274 """Return the datetime from the proleptic Gregorian ordinal.
276 """Return the datetime from the proleptic Gregorian ordinal.
275
277
276 January 1 of year 1 has ordinal 1. ValueError is raised unless
278 January 1 of year 1 has ordinal 1. ValueError is raised unless
277 1 <= ordinal <= datetime.max.toordinal().
279 1 <= ordinal <= datetime.max.toordinal().
278 The hour, minute, second and microsecond of the result are all 0, and
280 The hour, minute, second and microsecond of the result are all 0, and
279 tzinfo is None.
281 tzinfo is None.
280 """
282 """
281
283
282 def combine(date, time):
284 def combine(date, time):
283 """Return a new datetime object.
285 """Return a new datetime object.
284
286
285 Its date members are equal to the given date object's, and whose time
287 Its date members are equal to the given date object's, and whose time
286 and tzinfo members are equal to the given time object's. For any
288 and tzinfo members are equal to the given time object's. For any
287 datetime object d, d == datetime.combine(d.date(), d.timetz()).
289 datetime object d, d == datetime.combine(d.date(), d.timetz()).
288 If date is a datetime object, its time and tzinfo members are ignored.
290 If date is a datetime object, its time and tzinfo members are ignored.
289 """
291 """
290
292
291
293
292 class IDateTime(IDate, IDateTimeClass):
294 class IDateTime(IDate, IDateTimeClass):
293 """Object contains all the information from a date object and a time object.
295 """Object contains all the information from a date object and a time object.
294 """
296 """
295
297
296 year = Attribute("Year between MINYEAR and MAXYEAR inclusive")
298 year = Attribute("Year between MINYEAR and MAXYEAR inclusive")
297
299
298 month = Attribute("Month between 1 and 12 inclusive")
300 month = Attribute("Month between 1 and 12 inclusive")
299
301
300 day = Attribute(
302 day = Attribute(
301 "Day between 1 and the number of days in the given month of the year")
303 "Day between 1 and the number of days in the given month of the year")
302
304
303 hour = Attribute("Hour in range(24)")
305 hour = Attribute("Hour in range(24)")
304
306
305 minute = Attribute("Minute in range(60)")
307 minute = Attribute("Minute in range(60)")
306
308
307 second = Attribute("Second in range(60)")
309 second = Attribute("Second in range(60)")
308
310
309 microsecond = Attribute("Microsecond in range(1000000)")
311 microsecond = Attribute("Microsecond in range(1000000)")
310
312
311 tzinfo = Attribute(
313 tzinfo = Attribute(
312 """The object passed as the tzinfo argument to the datetime constructor
314 """The object passed as the tzinfo argument to the datetime constructor
313 or None if none was passed""")
315 or None if none was passed""")
314
316
315 def date():
317 def date():
316 """Return date object with same year, month and day."""
318 """Return date object with same year, month and day."""
317
319
318 def time():
320 def time():
319 """Return time object with same hour, minute, second, microsecond.
321 """Return time object with same hour, minute, second, microsecond.
320
322
321 tzinfo is None. See also method timetz().
323 tzinfo is None. See also method timetz().
322 """
324 """
323
325
324 def timetz():
326 def timetz():
325 """Return time object with same hour, minute, second, microsecond,
327 """Return time object with same hour, minute, second, microsecond,
326 and tzinfo.
328 and tzinfo.
327
329
328 See also method time().
330 See also method time().
329 """
331 """
330
332
331 def replace(year, month, day, hour, minute, second, microsecond, tzinfo):
333 def replace(year, month, day, hour, minute, second, microsecond, tzinfo):
332 """Return a datetime with the same members, except for those members
334 """Return a datetime with the same members, except for those members
333 given new values by whichever keyword arguments are specified.
335 given new values by whichever keyword arguments are specified.
334
336
335 Note that tzinfo=None can be specified to create a naive datetime from
337 Note that tzinfo=None can be specified to create a naive datetime from
336 an aware datetime with no conversion of date and time members.
338 an aware datetime with no conversion of date and time members.
337 """
339 """
338
340
339 def astimezone(tz):
341 def astimezone(tz):
340 """Return a datetime object with new tzinfo member tz, adjusting the
342 """Return a datetime object with new tzinfo member tz, adjusting the
341 date and time members so the result is the same UTC time as self, but
343 date and time members so the result is the same UTC time as self, but
342 in tz's local time.
344 in tz's local time.
343
345
344 tz must be an instance of a tzinfo subclass, and its utcoffset() and
346 tz must be an instance of a tzinfo subclass, and its utcoffset() and
345 dst() methods must not return None. self must be aware (self.tzinfo
347 dst() methods must not return None. self must be aware (self.tzinfo
346 must not be None, and self.utcoffset() must not return None).
348 must not be None, and self.utcoffset() must not return None).
347
349
348 If self.tzinfo is tz, self.astimezone(tz) is equal to self: no
350 If self.tzinfo is tz, self.astimezone(tz) is equal to self: no
349 adjustment of date or time members is performed. Else the result is
351 adjustment of date or time members is performed. Else the result is
350 local time in time zone tz, representing the same UTC time as self:
352 local time in time zone tz, representing the same UTC time as self:
351 after astz = dt.astimezone(tz), astz - astz.utcoffset()
353 after astz = dt.astimezone(tz), astz - astz.utcoffset()
352 will usually have the same date and time members as dt - dt.utcoffset().
354 will usually have the same date and time members as dt - dt.utcoffset().
353 The discussion of class tzinfo explains the cases at Daylight Saving
355 The discussion of class tzinfo explains the cases at Daylight Saving
354 Time transition boundaries where this cannot be achieved (an issue only
356 Time transition boundaries where this cannot be achieved (an issue only
355 if tz models both standard and daylight time).
357 if tz models both standard and daylight time).
356
358
357 If you merely want to attach a time zone object tz to a datetime dt
359 If you merely want to attach a time zone object tz to a datetime dt
358 without adjustment of date and time members, use dt.replace(tzinfo=tz).
360 without adjustment of date and time members, use dt.replace(tzinfo=tz).
359 If you merely want to remove the time zone object from an aware
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 dt.replace(tzinfo=None).
363 dt.replace(tzinfo=None).
362
364
363 Note that the default tzinfo.fromutc() method can be overridden in a
365 Note that the default tzinfo.fromutc() method can be overridden in a
364 tzinfo subclass to effect the result returned by astimezone().
366 tzinfo subclass to effect the result returned by astimezone().
365 """
367 """
366
368
367 def utcoffset():
369 def utcoffset():
368 """Return the timezone offset in minutes east of UTC (negative west of
370 """Return the timezone offset in minutes east of UTC (negative west of
369 UTC)."""
371 UTC)."""
370
372
371 def dst():
373 def dst():
372 """Return 0 if DST is not in effect, or the DST offset (in minutes
374 """Return 0 if DST is not in effect, or the DST offset (in minutes
373 eastward) if DST is in effect.
375 eastward) if DST is in effect.
374 """
376 """
375
377
376 def tzname():
378 def tzname():
377 """Return the timezone name."""
379 """Return the timezone name."""
378
380
379 def timetuple():
381 def timetuple():
380 """Return a 9-element tuple of the form returned by time.localtime()."""
382 """Return a 9-element tuple of the form returned by time.localtime()."""
381
383
382 def utctimetuple():
384 def utctimetuple():
383 """Return UTC time tuple compatilble with time.gmtimr()."""
385 """Return UTC time tuple compatilble with time.gmtimr()."""
384
386
385 def toordinal():
387 def toordinal():
386 """Return the proleptic Gregorian ordinal of the date.
388 """Return the proleptic Gregorian ordinal of the date.
387
389
388 The same as self.date().toordinal().
390 The same as self.date().toordinal().
389 """
391 """
390
392
391 def weekday():
393 def weekday():
392 """Return the day of the week as an integer.
394 """Return the day of the week as an integer.
393
395
394 Monday is 0 and Sunday is 6. The same as self.date().weekday().
396 Monday is 0 and Sunday is 6. The same as self.date().weekday().
395 See also isoweekday().
397 See also isoweekday().
396 """
398 """
397
399
398 def isoweekday():
400 def isoweekday():
399 """Return the day of the week as an integer.
401 """Return the day of the week as an integer.
400
402
401 Monday is 1 and Sunday is 7. The same as self.date().isoweekday.
403 Monday is 1 and Sunday is 7. The same as self.date().isoweekday.
402 See also weekday(), isocalendar().
404 See also weekday(), isocalendar().
403 """
405 """
404
406
405 def isocalendar():
407 def isocalendar():
406 """Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
408 """Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
407
409
408 The same as self.date().isocalendar().
410 The same as self.date().isocalendar().
409 """
411 """
410
412
411 def isoformat(sep='T'):
413 def isoformat(sep='T'):
412 """Return a string representing the date and time in ISO 8601 format.
414 """Return a string representing the date and time in ISO 8601 format.
413
415
414 YYYY-MM-DDTHH:MM:SS.mmmmmm or YYYY-MM-DDTHH:MM:SS if microsecond is 0
416 YYYY-MM-DDTHH:MM:SS.mmmmmm or YYYY-MM-DDTHH:MM:SS if microsecond is 0
415
417
416 If utcoffset() does not return None, a 6-character string is appended,
418 If utcoffset() does not return None, a 6-character string is appended,
417 giving the UTC offset in (signed) hours and minutes:
419 giving the UTC offset in (signed) hours and minutes:
418
420
419 YYYY-MM-DDTHH:MM:SS.mmmmmm+HH:MM or YYYY-MM-DDTHH:MM:SS+HH:MM
421 YYYY-MM-DDTHH:MM:SS.mmmmmm+HH:MM or YYYY-MM-DDTHH:MM:SS+HH:MM
420 if microsecond is 0.
422 if microsecond is 0.
421
423
422 The optional argument sep (default 'T') is a one-character separator,
424 The optional argument sep (default 'T') is a one-character separator,
423 placed between the date and time portions of the result.
425 placed between the date and time portions of the result.
424 """
426 """
425
427
426 def __str__():
428 def __str__():
427 """For a datetime instance d, str(d) is equivalent to d.isoformat(' ').
429 """For a datetime instance d, str(d) is equivalent to d.isoformat(' ').
428 """
430 """
429
431
430 def ctime():
432 def ctime():
431 """Return a string representing the date and time.
433 """Return a string representing the date and time.
432
434
433 datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'.
435 datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'.
434 d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple())) on
436 d.ctime() is equivalent to time.ctime(time.mktime(d.timetuple())) on
435 platforms where the native C ctime() function (which time.ctime()
437 platforms where the native C ctime() function (which time.ctime()
436 invokes, but which datetime.ctime() does not invoke) conforms to the
438 invokes, but which datetime.ctime() does not invoke) conforms to the
437 C standard.
439 C standard.
438 """
440 """
439
441
440 def strftime(format):
442 def strftime(format):
441 """Return a string representing the date and time.
443 """Return a string representing the date and time.
442
444
443 This is controlled by an explicit format string.
445 This is controlled by an explicit format string.
444 """
446 """
445
447
446
448
447 class ITimeClass(Interface):
449 class ITimeClass(Interface):
448 """This is the time class interface."""
450 """This is the time class interface."""
449
451
450 min = Attribute("The earliest representable time")
452 min = Attribute("The earliest representable time")
451
453
452 max = Attribute("The latest representable time")
454 max = Attribute("The latest representable time")
453
455
454 resolution = Attribute(
456 resolution = Attribute(
455 "The smallest possible difference between non-equal time objects")
457 "The smallest possible difference between non-equal time objects")
456
458
457
459
458 class ITime(ITimeClass):
460 class ITime(ITimeClass):
459 """Represent time with time zone.
461 """Represent time with time zone.
460
462
461 Operators:
463 Operators:
462
464
463 __repr__, __str__
465 __repr__, __str__
464 __cmp__, __hash__
466 __cmp__, __hash__
465 """
467 """
466
468
467 hour = Attribute("Hour in range(24)")
469 hour = Attribute("Hour in range(24)")
468
470
469 minute = Attribute("Minute in range(60)")
471 minute = Attribute("Minute in range(60)")
470
472
471 second = Attribute("Second in range(60)")
473 second = Attribute("Second in range(60)")
472
474
473 microsecond = Attribute("Microsecond in range(1000000)")
475 microsecond = Attribute("Microsecond in range(1000000)")
474
476
475 tzinfo = Attribute(
477 tzinfo = Attribute(
476 """The object passed as the tzinfo argument to the time constructor
478 """The object passed as the tzinfo argument to the time constructor
477 or None if none was passed.""")
479 or None if none was passed.""")
478
480
479 def replace(hour, minute, second, microsecond, tzinfo):
481 def replace(hour, minute, second, microsecond, tzinfo):
480 """Return a time with the same value.
482 """Return a time with the same value.
481
483
482 Except for those members given new values by whichever keyword
484 Except for those members given new values by whichever keyword
483 arguments are specified. Note that tzinfo=None can be specified
485 arguments are specified. Note that tzinfo=None can be specified
484 to create a naive time from an aware time, without conversion of the
486 to create a naive time from an aware time, without conversion of the
485 time members.
487 time members.
486 """
488 """
487
489
488 def isoformat():
490 def isoformat():
489 """Return a string representing the time in ISO 8601 format.
491 """Return a string representing the time in ISO 8601 format.
490
492
491 That is HH:MM:SS.mmmmmm or, if self.microsecond is 0, HH:MM:SS
493 That is HH:MM:SS.mmmmmm or, if self.microsecond is 0, HH:MM:SS
492 If utcoffset() does not return None, a 6-character string is appended,
494 If utcoffset() does not return None, a 6-character string is appended,
493 giving the UTC offset in (signed) hours and minutes:
495 giving the UTC offset in (signed) hours and minutes:
494 HH:MM:SS.mmmmmm+HH:MM or, if self.microsecond is 0, HH:MM:SS+HH:MM
496 HH:MM:SS.mmmmmm+HH:MM or, if self.microsecond is 0, HH:MM:SS+HH:MM
495 """
497 """
496
498
497 def __str__():
499 def __str__():
498 """For a time t, str(t) is equivalent to t.isoformat()."""
500 """For a time t, str(t) is equivalent to t.isoformat()."""
499
501
500 def strftime(format):
502 def strftime(format):
501 """Return a string representing the time.
503 """Return a string representing the time.
502
504
503 This is controlled by an explicit format string.
505 This is controlled by an explicit format string.
504 """
506 """
505
507
506 def utcoffset():
508 def utcoffset():
507 """Return the timezone offset in minutes east of UTC (negative west of
509 """Return the timezone offset in minutes east of UTC (negative west of
508 UTC).
510 UTC).
509
511
510 If tzinfo is None, returns None, else returns
512 If tzinfo is None, returns None, else returns
511 self.tzinfo.utcoffset(None), and raises an exception if the latter
513 self.tzinfo.utcoffset(None), and raises an exception if the latter
512 doesn't return None or a timedelta object representing a whole number
514 doesn't return None or a timedelta object representing a whole number
513 of minutes with magnitude less than one day.
515 of minutes with magnitude less than one day.
514 """
516 """
515
517
516 def dst():
518 def dst():
517 """Return 0 if DST is not in effect, or the DST offset (in minutes
519 """Return 0 if DST is not in effect, or the DST offset (in minutes
518 eastward) if DST is in effect.
520 eastward) if DST is in effect.
519
521
520 If tzinfo is None, returns None, else returns self.tzinfo.dst(None),
522 If tzinfo is None, returns None, else returns self.tzinfo.dst(None),
521 and raises an exception if the latter doesn't return None, or a
523 and raises an exception if the latter doesn't return None, or a
522 timedelta object representing a whole number of minutes with
524 timedelta object representing a whole number of minutes with
523 magnitude less than one day.
525 magnitude less than one day.
524 """
526 """
525
527
526 def tzname():
528 def tzname():
527 """Return the timezone name.
529 """Return the timezone name.
528
530
529 If tzinfo is None, returns None, else returns self.tzinfo.tzname(None),
531 If tzinfo is None, returns None, else returns self.tzinfo.tzname(None),
530 or raises an exception if the latter doesn't return None or a string
532 or raises an exception if the latter doesn't return None or a string
531 object.
533 object.
532 """
534 """
533
535
534
536
535 class ITZInfo(Interface):
537 class ITZInfo(Interface):
536 """Time zone info class.
538 """Time zone info class.
537 """
539 """
538
540
539 def utcoffset(dt):
541 def utcoffset(dt):
540 """Return offset of local time from UTC, in minutes east of UTC.
542 """Return offset of local time from UTC, in minutes east of UTC.
541
543
542 If local time is west of UTC, this should be negative.
544 If local time is west of UTC, this should be negative.
543 Note that this is intended to be the total offset from UTC;
545 Note that this is intended to be the total offset from UTC;
544 for example, if a tzinfo object represents both time zone and DST
546 for example, if a tzinfo object represents both time zone and DST
545 adjustments, utcoffset() should return their sum. If the UTC offset
547 adjustments, utcoffset() should return their sum. If the UTC offset
546 isn't known, return None. Else the value returned must be a timedelta
548 isn't known, return None. Else the value returned must be a timedelta
547 object specifying a whole number of minutes in the range -1439 to 1439
549 object specifying a whole number of minutes in the range -1439 to 1439
548 inclusive (1440 = 24*60; the magnitude of the offset must be less
550 inclusive (1440 = 24*60; the magnitude of the offset must be less
549 than one day).
551 than one day).
550 """
552 """
551
553
552 def dst(dt):
554 def dst(dt):
553 """Return the daylight saving time (DST) adjustment, in minutes east
555 """Return the daylight saving time (DST) adjustment, in minutes east
554 of UTC, or None if DST information isn't known.
556 of UTC, or None if DST information isn't known.
555 """
557 """
556
558
557 def tzname(dt):
559 def tzname(dt):
558 """Return the time zone name corresponding to the datetime object as
560 """Return the time zone name corresponding to the datetime object as
559 a string.
561 a string.
560 """
562 """
561
563
562 def fromutc(dt):
564 def fromutc(dt):
563 """Return an equivalent datetime in self's local time."""
565 """Return an equivalent datetime in self's local time."""
564
566
565
567
566 classImplements(timedelta, ITimeDelta)
568 classImplements(timedelta, ITimeDelta)
567 classImplements(date, IDate)
569 classImplements(date, IDate)
568 classImplements(datetime, IDateTime)
570 classImplements(datetime, IDateTime)
569 classImplements(time, ITime)
571 classImplements(time, ITime)
570 classImplements(tzinfo, ITZInfo)
572 classImplements(tzinfo, ITZInfo)
571
573
572 ## directlyProvides(timedelta, ITimeDeltaClass)
574 ## directlyProvides(timedelta, ITimeDeltaClass)
573 ## directlyProvides(date, IDateClass)
575 ## directlyProvides(date, IDateClass)
574 ## directlyProvides(datetime, IDateTimeClass)
576 ## directlyProvides(datetime, IDateTimeClass)
575 ## directlyProvides(time, ITimeClass)
577 ## directlyProvides(time, ITimeClass)
@@ -1,102 +1,105 b''
1 ##############################################################################
1 ##############################################################################
2 #
2 #
3 # Copyright (c) 2003 Zope Foundation and Contributors.
3 # Copyright (c) 2003 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """Interfaces for standard python exceptions
14 """Interfaces for standard python exceptions
15 """
15 """
16 from zope.interface import Interface
16
17 from zope.interface import classImplements
17 from __future__ import absolute_import
18
19 from .. import Interface
20 from .. import classImplements
18
21
19 class IException(Interface): pass
22 class IException(Interface): pass
20 class IStandardError(IException): pass
23 class IStandardError(IException): pass
21 class IWarning(IException): pass
24 class IWarning(IException): pass
22 class ISyntaxError(IStandardError): pass
25 class ISyntaxError(IStandardError): pass
23 class ILookupError(IStandardError): pass
26 class ILookupError(IStandardError): pass
24 class IValueError(IStandardError): pass
27 class IValueError(IStandardError): pass
25 class IRuntimeError(IStandardError): pass
28 class IRuntimeError(IStandardError): pass
26 class IArithmeticError(IStandardError): pass
29 class IArithmeticError(IStandardError): pass
27 class IAssertionError(IStandardError): pass
30 class IAssertionError(IStandardError): pass
28 class IAttributeError(IStandardError): pass
31 class IAttributeError(IStandardError): pass
29 class IDeprecationWarning(IWarning): pass
32 class IDeprecationWarning(IWarning): pass
30 class IEOFError(IStandardError): pass
33 class IEOFError(IStandardError): pass
31 class IEnvironmentError(IStandardError): pass
34 class IEnvironmentError(IStandardError): pass
32 class IFloatingPointError(IArithmeticError): pass
35 class IFloatingPointError(IArithmeticError): pass
33 class IIOError(IEnvironmentError): pass
36 class IIOError(IEnvironmentError): pass
34 class IImportError(IStandardError): pass
37 class IImportError(IStandardError): pass
35 class IIndentationError(ISyntaxError): pass
38 class IIndentationError(ISyntaxError): pass
36 class IIndexError(ILookupError): pass
39 class IIndexError(ILookupError): pass
37 class IKeyError(ILookupError): pass
40 class IKeyError(ILookupError): pass
38 class IKeyboardInterrupt(IStandardError): pass
41 class IKeyboardInterrupt(IStandardError): pass
39 class IMemoryError(IStandardError): pass
42 class IMemoryError(IStandardError): pass
40 class INameError(IStandardError): pass
43 class INameError(IStandardError): pass
41 class INotImplementedError(IRuntimeError): pass
44 class INotImplementedError(IRuntimeError): pass
42 class IOSError(IEnvironmentError): pass
45 class IOSError(IEnvironmentError): pass
43 class IOverflowError(IArithmeticError): pass
46 class IOverflowError(IArithmeticError): pass
44 class IOverflowWarning(IWarning): pass
47 class IOverflowWarning(IWarning): pass
45 class IReferenceError(IStandardError): pass
48 class IReferenceError(IStandardError): pass
46 class IRuntimeWarning(IWarning): pass
49 class IRuntimeWarning(IWarning): pass
47 class IStopIteration(IException): pass
50 class IStopIteration(IException): pass
48 class ISyntaxWarning(IWarning): pass
51 class ISyntaxWarning(IWarning): pass
49 class ISystemError(IStandardError): pass
52 class ISystemError(IStandardError): pass
50 class ISystemExit(IException): pass
53 class ISystemExit(IException): pass
51 class ITabError(IIndentationError): pass
54 class ITabError(IIndentationError): pass
52 class ITypeError(IStandardError): pass
55 class ITypeError(IStandardError): pass
53 class IUnboundLocalError(INameError): pass
56 class IUnboundLocalError(INameError): pass
54 class IUnicodeError(IValueError): pass
57 class IUnicodeError(IValueError): pass
55 class IUserWarning(IWarning): pass
58 class IUserWarning(IWarning): pass
56 class IZeroDivisionError(IArithmeticError): pass
59 class IZeroDivisionError(IArithmeticError): pass
57
60
58 classImplements(ArithmeticError, IArithmeticError)
61 classImplements(ArithmeticError, IArithmeticError)
59 classImplements(AssertionError, IAssertionError)
62 classImplements(AssertionError, IAssertionError)
60 classImplements(AttributeError, IAttributeError)
63 classImplements(AttributeError, IAttributeError)
61 classImplements(DeprecationWarning, IDeprecationWarning)
64 classImplements(DeprecationWarning, IDeprecationWarning)
62 classImplements(EnvironmentError, IEnvironmentError)
65 classImplements(EnvironmentError, IEnvironmentError)
63 classImplements(EOFError, IEOFError)
66 classImplements(EOFError, IEOFError)
64 classImplements(Exception, IException)
67 classImplements(Exception, IException)
65 classImplements(FloatingPointError, IFloatingPointError)
68 classImplements(FloatingPointError, IFloatingPointError)
66 classImplements(ImportError, IImportError)
69 classImplements(ImportError, IImportError)
67 classImplements(IndentationError, IIndentationError)
70 classImplements(IndentationError, IIndentationError)
68 classImplements(IndexError, IIndexError)
71 classImplements(IndexError, IIndexError)
69 classImplements(IOError, IIOError)
72 classImplements(IOError, IIOError)
70 classImplements(KeyboardInterrupt, IKeyboardInterrupt)
73 classImplements(KeyboardInterrupt, IKeyboardInterrupt)
71 classImplements(KeyError, IKeyError)
74 classImplements(KeyError, IKeyError)
72 classImplements(LookupError, ILookupError)
75 classImplements(LookupError, ILookupError)
73 classImplements(MemoryError, IMemoryError)
76 classImplements(MemoryError, IMemoryError)
74 classImplements(NameError, INameError)
77 classImplements(NameError, INameError)
75 classImplements(NotImplementedError, INotImplementedError)
78 classImplements(NotImplementedError, INotImplementedError)
76 classImplements(OSError, IOSError)
79 classImplements(OSError, IOSError)
77 classImplements(OverflowError, IOverflowError)
80 classImplements(OverflowError, IOverflowError)
78 try:
81 try:
79 classImplements(OverflowWarning, IOverflowWarning)
82 classImplements(OverflowWarning, IOverflowWarning)
80 except NameError: #pragma NO COVER
83 except NameError: #pragma NO COVER
81 pass # OverflowWarning was removed in Python 2.5
84 pass # OverflowWarning was removed in Python 2.5
82 classImplements(ReferenceError, IReferenceError)
85 classImplements(ReferenceError, IReferenceError)
83 classImplements(RuntimeError, IRuntimeError)
86 classImplements(RuntimeError, IRuntimeError)
84 classImplements(RuntimeWarning, IRuntimeWarning)
87 classImplements(RuntimeWarning, IRuntimeWarning)
85 try:
88 try:
86 classImplements(StandardError, IStandardError)
89 classImplements(StandardError, IStandardError)
87 except NameError: #pragma NO COVER
90 except NameError: #pragma NO COVER
88 pass # StandardError does not exist in Python 3
91 pass # StandardError does not exist in Python 3
89 classImplements(StopIteration, IStopIteration)
92 classImplements(StopIteration, IStopIteration)
90 classImplements(SyntaxError, ISyntaxError)
93 classImplements(SyntaxError, ISyntaxError)
91 classImplements(SyntaxWarning, ISyntaxWarning)
94 classImplements(SyntaxWarning, ISyntaxWarning)
92 classImplements(SystemError, ISystemError)
95 classImplements(SystemError, ISystemError)
93 classImplements(SystemExit, ISystemExit)
96 classImplements(SystemExit, ISystemExit)
94 classImplements(TabError, ITabError)
97 classImplements(TabError, ITabError)
95 classImplements(TypeError, ITypeError)
98 classImplements(TypeError, ITypeError)
96 classImplements(UnboundLocalError, IUnboundLocalError)
99 classImplements(UnboundLocalError, IUnboundLocalError)
97 classImplements(UnicodeError, IUnicodeError)
100 classImplements(UnicodeError, IUnicodeError)
98 classImplements(UserWarning, IUserWarning)
101 classImplements(UserWarning, IUserWarning)
99 classImplements(ValueError, IValueError)
102 classImplements(ValueError, IValueError)
100 classImplements(Warning, IWarning)
103 classImplements(Warning, IWarning)
101 classImplements(ZeroDivisionError, IZeroDivisionError)
104 classImplements(ZeroDivisionError, IZeroDivisionError)
102
105
@@ -1,125 +1,128 b''
1 ##############################################################################
1 ##############################################################################
2 #
2 #
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """Mapping Interfaces
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 class IItemMapping(Interface):
21 class IItemMapping(Interface):
19 """Simplest readable mapping object
22 """Simplest readable mapping object
20 """
23 """
21
24
22 def __getitem__(key):
25 def __getitem__(key):
23 """Get a value for a key
26 """Get a value for a key
24
27
25 A KeyError is raised if there is no value for the key.
28 A KeyError is raised if there is no value for the key.
26 """
29 """
27
30
28
31
29 class IReadMapping(IItemMapping):
32 class IReadMapping(IItemMapping):
30 """Basic mapping interface
33 """Basic mapping interface
31 """
34 """
32
35
33 def get(key, default=None):
36 def get(key, default=None):
34 """Get a value for a key
37 """Get a value for a key
35
38
36 The default is returned if there is no value for the key.
39 The default is returned if there is no value for the key.
37 """
40 """
38
41
39 def __contains__(key):
42 def __contains__(key):
40 """Tell if a key exists in the mapping."""
43 """Tell if a key exists in the mapping."""
41
44
42
45
43 class IWriteMapping(Interface):
46 class IWriteMapping(Interface):
44 """Mapping methods for changing data"""
47 """Mapping methods for changing data"""
45
48
46 def __delitem__(key):
49 def __delitem__(key):
47 """Delete a value from the mapping using the key."""
50 """Delete a value from the mapping using the key."""
48
51
49 def __setitem__(key, value):
52 def __setitem__(key, value):
50 """Set a new item in the mapping."""
53 """Set a new item in the mapping."""
51
54
52
55
53 class IEnumerableMapping(IReadMapping):
56 class IEnumerableMapping(IReadMapping):
54 """Mapping objects whose items can be enumerated.
57 """Mapping objects whose items can be enumerated.
55 """
58 """
56
59
57 def keys():
60 def keys():
58 """Return the keys of the mapping object.
61 """Return the keys of the mapping object.
59 """
62 """
60
63
61 def __iter__():
64 def __iter__():
62 """Return an iterator for the keys of the mapping object.
65 """Return an iterator for the keys of the mapping object.
63 """
66 """
64
67
65 def values():
68 def values():
66 """Return the values of the mapping object.
69 """Return the values of the mapping object.
67 """
70 """
68
71
69 def items():
72 def items():
70 """Return the items of the mapping object.
73 """Return the items of the mapping object.
71 """
74 """
72
75
73 def __len__():
76 def __len__():
74 """Return the number of items.
77 """Return the number of items.
75 """
78 """
76
79
77 class IMapping(IWriteMapping, IEnumerableMapping):
80 class IMapping(IWriteMapping, IEnumerableMapping):
78 ''' Simple mapping interface '''
81 ''' Simple mapping interface '''
79
82
80 class IIterableMapping(IEnumerableMapping):
83 class IIterableMapping(IEnumerableMapping):
81
84
82 def iterkeys():
85 def iterkeys():
83 "iterate over keys; equivalent to __iter__"
86 "iterate over keys; equivalent to __iter__"
84
87
85 def itervalues():
88 def itervalues():
86 "iterate over values"
89 "iterate over values"
87
90
88 def iteritems():
91 def iteritems():
89 "iterate over items"
92 "iterate over items"
90
93
91 class IClonableMapping(Interface):
94 class IClonableMapping(Interface):
92
95
93 def copy():
96 def copy():
94 "return copy of dict"
97 "return copy of dict"
95
98
96 class IExtendedReadMapping(IIterableMapping):
99 class IExtendedReadMapping(IIterableMapping):
97
100
98 def has_key(key):
101 def has_key(key):
99 """Tell if a key exists in the mapping; equivalent to __contains__"""
102 """Tell if a key exists in the mapping; equivalent to __contains__"""
100
103
101 class IExtendedWriteMapping(IWriteMapping):
104 class IExtendedWriteMapping(IWriteMapping):
102
105
103 def clear():
106 def clear():
104 "delete all items"
107 "delete all items"
105
108
106 def update(d):
109 def update(d):
107 " Update D from E: for k in E.keys(): D[k] = E[k]"
110 " Update D from E: for k in E.keys(): D[k] = E[k]"
108
111
109 def setdefault(key, default=None):
112 def setdefault(key, default=None):
110 "D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D"
113 "D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D"
111
114
112 def pop(k, *args):
115 def pop(k, *args):
113 """remove specified key and return the corresponding value
116 """remove specified key and return the corresponding value
114 *args may contain a single default value, or may not be supplied.
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 KeyError is raised"""
119 KeyError is raised"""
117
120
118 def popitem():
121 def popitem():
119 """remove and return some (key, value) pair as a
122 """remove and return some (key, value) pair as a
120 2-tuple; but raise KeyError if mapping is empty"""
123 2-tuple; but raise KeyError if mapping is empty"""
121
124
122 class IFullMapping(
125 class IFullMapping(
123 IExtendedReadMapping, IExtendedWriteMapping, IClonableMapping, IMapping):
126 IExtendedReadMapping, IExtendedWriteMapping, IClonableMapping, IMapping):
124 ''' Full mapping interface ''' # IMapping included so tests for IMapping
127 ''' Full mapping interface ''' # IMapping included so tests for IMapping
125 # succeed with IFullMapping
128 # succeed with IFullMapping
@@ -1,160 +1,163 b''
1 ##############################################################################
1 ##############################################################################
2 #
2 #
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """Sequence Interfaces
14 """Sequence Interfaces
15 """
15 """
16
17 from __future__ import absolute_import
18
16 __docformat__ = 'restructuredtext'
19 __docformat__ = 'restructuredtext'
17 from zope.interface import Interface
20 from .. import Interface
18
21
19 class IMinimalSequence(Interface):
22 class IMinimalSequence(Interface):
20 """Most basic sequence interface.
23 """Most basic sequence interface.
21
24
22 All sequences are iterable. This requires at least one of the
25 All sequences are iterable. This requires at least one of the
23 following:
26 following:
24
27
25 - a `__getitem__()` method that takes a single argument; interger
28 - a `__getitem__()` method that takes a single argument; interger
26 values starting at 0 must be supported, and `IndexError` should
29 values starting at 0 must be supported, and `IndexError` should
27 be raised for the first index for which there is no value, or
30 be raised for the first index for which there is no value, or
28
31
29 - an `__iter__()` method that returns an iterator as defined in
32 - an `__iter__()` method that returns an iterator as defined in
30 the Python documentation (http://docs.python.org/lib/typeiter.html).
33 the Python documentation (http://docs.python.org/lib/typeiter.html).
31
34
32 """
35 """
33
36
34 def __getitem__(index):
37 def __getitem__(index):
35 """`x.__getitem__(index)` <==> `x[index]`
38 """`x.__getitem__(index)` <==> `x[index]`
36
39
37 Declaring this interface does not specify whether `__getitem__`
40 Declaring this interface does not specify whether `__getitem__`
38 supports slice objects."""
41 supports slice objects."""
39
42
40 class IFiniteSequence(IMinimalSequence):
43 class IFiniteSequence(IMinimalSequence):
41
44
42 def __len__():
45 def __len__():
43 """`x.__len__()` <==> `len(x)`"""
46 """`x.__len__()` <==> `len(x)`"""
44
47
45 class IReadSequence(IFiniteSequence):
48 class IReadSequence(IFiniteSequence):
46 """read interface shared by tuple and list"""
49 """read interface shared by tuple and list"""
47
50
48 def __contains__(item):
51 def __contains__(item):
49 """`x.__contains__(item)` <==> `item in x`"""
52 """`x.__contains__(item)` <==> `item in x`"""
50
53
51 def __lt__(other):
54 def __lt__(other):
52 """`x.__lt__(other)` <==> `x < other`"""
55 """`x.__lt__(other)` <==> `x < other`"""
53
56
54 def __le__(other):
57 def __le__(other):
55 """`x.__le__(other)` <==> `x <= other`"""
58 """`x.__le__(other)` <==> `x <= other`"""
56
59
57 def __eq__(other):
60 def __eq__(other):
58 """`x.__eq__(other)` <==> `x == other`"""
61 """`x.__eq__(other)` <==> `x == other`"""
59
62
60 def __ne__(other):
63 def __ne__(other):
61 """`x.__ne__(other)` <==> `x != other`"""
64 """`x.__ne__(other)` <==> `x != other`"""
62
65
63 def __gt__(other):
66 def __gt__(other):
64 """`x.__gt__(other)` <==> `x > other`"""
67 """`x.__gt__(other)` <==> `x > other`"""
65
68
66 def __ge__(other):
69 def __ge__(other):
67 """`x.__ge__(other)` <==> `x >= other`"""
70 """`x.__ge__(other)` <==> `x >= other`"""
68
71
69 def __add__(other):
72 def __add__(other):
70 """`x.__add__(other)` <==> `x + other`"""
73 """`x.__add__(other)` <==> `x + other`"""
71
74
72 def __mul__(n):
75 def __mul__(n):
73 """`x.__mul__(n)` <==> `x * n`"""
76 """`x.__mul__(n)` <==> `x * n`"""
74
77
75 def __rmul__(n):
78 def __rmul__(n):
76 """`x.__rmul__(n)` <==> `n * x`"""
79 """`x.__rmul__(n)` <==> `n * x`"""
77
80
78 def __getslice__(i, j):
81 def __getslice__(i, j):
79 """`x.__getslice__(i, j)` <==> `x[i:j]`
82 """`x.__getslice__(i, j)` <==> `x[i:j]`
80
83
81 Use of negative indices is not supported.
84 Use of negative indices is not supported.
82
85
83 Deprecated since Python 2.0 but still a part of `UserList`.
86 Deprecated since Python 2.0 but still a part of `UserList`.
84 """
87 """
85
88
86 class IExtendedReadSequence(IReadSequence):
89 class IExtendedReadSequence(IReadSequence):
87 """Full read interface for lists"""
90 """Full read interface for lists"""
88
91
89 def count(item):
92 def count(item):
90 """Return number of occurrences of value"""
93 """Return number of occurrences of value"""
91
94
92 def index(item, *args):
95 def index(item, *args):
93 """Return first index of value
96 """Return first index of value
94
97
95 `L.index(value, [start, [stop]])` -> integer"""
98 `L.index(value, [start, [stop]])` -> integer"""
96
99
97 class IUniqueMemberWriteSequence(Interface):
100 class IUniqueMemberWriteSequence(Interface):
98 """The write contract for a sequence that may enforce unique members"""
101 """The write contract for a sequence that may enforce unique members"""
99
102
100 def __setitem__(index, item):
103 def __setitem__(index, item):
101 """`x.__setitem__(index, item)` <==> `x[index] = item`
104 """`x.__setitem__(index, item)` <==> `x[index] = item`
102
105
103 Declaring this interface does not specify whether `__setitem__`
106 Declaring this interface does not specify whether `__setitem__`
104 supports slice objects.
107 supports slice objects.
105 """
108 """
106
109
107 def __delitem__(index):
110 def __delitem__(index):
108 """`x.__delitem__(index)` <==> `del x[index]`
111 """`x.__delitem__(index)` <==> `del x[index]`
109
112
110 Declaring this interface does not specify whether `__delitem__`
113 Declaring this interface does not specify whether `__delitem__`
111 supports slice objects.
114 supports slice objects.
112 """
115 """
113
116
114 def __setslice__(i, j, other):
117 def __setslice__(i, j, other):
115 """`x.__setslice__(i, j, other)` <==> `x[i:j]=other`
118 """`x.__setslice__(i, j, other)` <==> `x[i:j]=other`
116
119
117 Use of negative indices is not supported.
120 Use of negative indices is not supported.
118
121
119 Deprecated since Python 2.0 but still a part of `UserList`.
122 Deprecated since Python 2.0 but still a part of `UserList`.
120 """
123 """
121
124
122 def __delslice__(i, j):
125 def __delslice__(i, j):
123 """`x.__delslice__(i, j)` <==> `del x[i:j]`
126 """`x.__delslice__(i, j)` <==> `del x[i:j]`
124
127
125 Use of negative indices is not supported.
128 Use of negative indices is not supported.
126
129
127 Deprecated since Python 2.0 but still a part of `UserList`.
130 Deprecated since Python 2.0 but still a part of `UserList`.
128 """
131 """
129 def __iadd__(y):
132 def __iadd__(y):
130 """`x.__iadd__(y)` <==> `x += y`"""
133 """`x.__iadd__(y)` <==> `x += y`"""
131
134
132 def append(item):
135 def append(item):
133 """Append item to end"""
136 """Append item to end"""
134
137
135 def insert(index, item):
138 def insert(index, item):
136 """Insert item before index"""
139 """Insert item before index"""
137
140
138 def pop(index=-1):
141 def pop(index=-1):
139 """Remove and return item at index (default last)"""
142 """Remove and return item at index (default last)"""
140
143
141 def remove(item):
144 def remove(item):
142 """Remove first occurrence of value"""
145 """Remove first occurrence of value"""
143
146
144 def reverse():
147 def reverse():
145 """Reverse *IN PLACE*"""
148 """Reverse *IN PLACE*"""
146
149
147 def sort(cmpfunc=None):
150 def sort(cmpfunc=None):
148 """Stable sort *IN PLACE*; `cmpfunc(x, y)` -> -1, 0, 1"""
151 """Stable sort *IN PLACE*; `cmpfunc(x, y)` -> -1, 0, 1"""
149
152
150 def extend(iterable):
153 def extend(iterable):
151 """Extend list by appending elements from the iterable"""
154 """Extend list by appending elements from the iterable"""
152
155
153 class IWriteSequence(IUniqueMemberWriteSequence):
156 class IWriteSequence(IUniqueMemberWriteSequence):
154 """Full write contract for sequences"""
157 """Full write contract for sequences"""
155
158
156 def __imul__(n):
159 def __imul__(n):
157 """`x.__imul__(n)` <==> `x *= n`"""
160 """`x.__imul__(n)` <==> `x *= n`"""
158
161
159 class ISequence(IReadSequence, IWriteSequence):
162 class ISequence(IReadSequence, IWriteSequence):
160 """Full sequence contract"""
163 """Full sequence contract"""
@@ -1,929 +1,931 b''
1 ##############################################################################
1 ##############################################################################
2 # Copyright (c) 2003 Zope Foundation and Contributors.
2 # Copyright (c) 2003 Zope Foundation and Contributors.
3 # All Rights Reserved.
3 # All Rights Reserved.
4 #
4 #
5 # This software is subject to the provisions of the Zope Public License,
5 # This software is subject to the provisions of the Zope Public License,
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # FOR A PARTICULAR PURPOSE.
10 # FOR A PARTICULAR PURPOSE.
11 ##############################################################################
11 ##############################################################################
12 """Implementation of interface declarations
12 """Implementation of interface declarations
13
13
14 There are three flavors of declarations:
14 There are three flavors of declarations:
15
15
16 - Declarations are used to simply name declared interfaces.
16 - Declarations are used to simply name declared interfaces.
17
17
18 - ImplementsDeclarations are used to express the interfaces that a
18 - ImplementsDeclarations are used to express the interfaces that a
19 class implements (that instances of the class provides).
19 class implements (that instances of the class provides).
20
20
21 Implements specifications support inheriting interfaces.
21 Implements specifications support inheriting interfaces.
22
22
23 - ProvidesDeclarations are used to express interfaces directly
23 - ProvidesDeclarations are used to express interfaces directly
24 provided by objects.
24 provided by objects.
25
25
26 """
26 """
27 from __future__ import absolute_import
28
27 __docformat__ = 'restructuredtext'
29 __docformat__ = 'restructuredtext'
28
30
29 import sys
31 import sys
30 from types import FunctionType
32 from types import FunctionType
31 from types import MethodType
33 from types import MethodType
32 from types import ModuleType
34 from types import ModuleType
33 import weakref
35 import weakref
34
36
35 from zope.interface.advice import addClassAdvisor
37 from .advice import addClassAdvisor
36 from zope.interface.interface import InterfaceClass
38 from .interface import InterfaceClass
37 from zope.interface.interface import SpecificationBase
39 from .interface import SpecificationBase
38 from zope.interface.interface import Specification
40 from .interface import Specification
39 from zope.interface._compat import CLASS_TYPES as DescriptorAwareMetaClasses
41 from ._compat import CLASS_TYPES as DescriptorAwareMetaClasses
40 from zope.interface._compat import PYTHON3
42 from ._compat import PYTHON3
41
43
42 # Registry of class-implementation specifications
44 # Registry of class-implementation specifications
43 BuiltinImplementationSpecifications = {}
45 BuiltinImplementationSpecifications = {}
44
46
45 _ADVICE_ERROR = ('Class advice impossible in Python3. '
47 _ADVICE_ERROR = ('Class advice impossible in Python3. '
46 'Use the @%s class decorator instead.')
48 'Use the @%s class decorator instead.')
47
49
48 _ADVICE_WARNING = ('The %s API is deprecated, and will not work in Python3 '
50 _ADVICE_WARNING = ('The %s API is deprecated, and will not work in Python3 '
49 'Use the @%s class decorator instead.')
51 'Use the @%s class decorator instead.')
50
52
51 class named(object):
53 class named(object):
52
54
53 def __init__(self, name):
55 def __init__(self, name):
54 self.name = name
56 self.name = name
55
57
56 def __call__(self, ob):
58 def __call__(self, ob):
57 ob.__component_name__ = self.name
59 ob.__component_name__ = self.name
58 return ob
60 return ob
59
61
60 class Declaration(Specification):
62 class Declaration(Specification):
61 """Interface declarations"""
63 """Interface declarations"""
62
64
63 def __init__(self, *interfaces):
65 def __init__(self, *interfaces):
64 Specification.__init__(self, _normalizeargs(interfaces))
66 Specification.__init__(self, _normalizeargs(interfaces))
65
67
66 def changed(self, originally_changed):
68 def changed(self, originally_changed):
67 Specification.changed(self, originally_changed)
69 Specification.changed(self, originally_changed)
68 try:
70 try:
69 del self._v_attrs
71 del self._v_attrs
70 except AttributeError:
72 except AttributeError:
71 pass
73 pass
72
74
73 def __contains__(self, interface):
75 def __contains__(self, interface):
74 """Test whether an interface is in the specification
76 """Test whether an interface is in the specification
75 """
77 """
76
78
77 return self.extends(interface) and interface in self.interfaces()
79 return self.extends(interface) and interface in self.interfaces()
78
80
79 def __iter__(self):
81 def __iter__(self):
80 """Return an iterator for the interfaces in the specification
82 """Return an iterator for the interfaces in the specification
81 """
83 """
82 return self.interfaces()
84 return self.interfaces()
83
85
84 def flattened(self):
86 def flattened(self):
85 """Return an iterator of all included and extended interfaces
87 """Return an iterator of all included and extended interfaces
86 """
88 """
87 return iter(self.__iro__)
89 return iter(self.__iro__)
88
90
89 def __sub__(self, other):
91 def __sub__(self, other):
90 """Remove interfaces from a specification
92 """Remove interfaces from a specification
91 """
93 """
92 return Declaration(
94 return Declaration(
93 *[i for i in self.interfaces()
95 *[i for i in self.interfaces()
94 if not [j for j in other.interfaces()
96 if not [j for j in other.interfaces()
95 if i.extends(j, 0)]
97 if i.extends(j, 0)]
96 ]
98 ]
97 )
99 )
98
100
99 def __add__(self, other):
101 def __add__(self, other):
100 """Add two specifications or a specification and an interface
102 """Add two specifications or a specification and an interface
101 """
103 """
102 seen = {}
104 seen = {}
103 result = []
105 result = []
104 for i in self.interfaces():
106 for i in self.interfaces():
105 seen[i] = 1
107 seen[i] = 1
106 result.append(i)
108 result.append(i)
107 for i in other.interfaces():
109 for i in other.interfaces():
108 if i not in seen:
110 if i not in seen:
109 seen[i] = 1
111 seen[i] = 1
110 result.append(i)
112 result.append(i)
111
113
112 return Declaration(*result)
114 return Declaration(*result)
113
115
114 __radd__ = __add__
116 __radd__ = __add__
115
117
116
118
117 ##############################################################################
119 ##############################################################################
118 #
120 #
119 # Implementation specifications
121 # Implementation specifications
120 #
122 #
121 # These specify interfaces implemented by instances of classes
123 # These specify interfaces implemented by instances of classes
122
124
123 class Implements(Declaration):
125 class Implements(Declaration):
124
126
125 # class whose specification should be used as additional base
127 # class whose specification should be used as additional base
126 inherit = None
128 inherit = None
127
129
128 # interfaces actually declared for a class
130 # interfaces actually declared for a class
129 declared = ()
131 declared = ()
130
132
131 __name__ = '?'
133 __name__ = '?'
132
134
133 @classmethod
135 @classmethod
134 def named(cls, name, *interfaces):
136 def named(cls, name, *interfaces):
135 # Implementation method: Produce an Implements interface with
137 # Implementation method: Produce an Implements interface with
136 # a fully fleshed out __name__ before calling the constructor, which
138 # a fully fleshed out __name__ before calling the constructor, which
137 # sets bases to the given interfaces and which may pass this object to
139 # sets bases to the given interfaces and which may pass this object to
138 # other objects (e.g., to adjust dependents). If they're sorting or comparing
140 # other objects (e.g., to adjust dependents). If they're sorting or comparing
139 # by name, this needs to be set.
141 # by name, this needs to be set.
140 inst = cls.__new__(cls)
142 inst = cls.__new__(cls)
141 inst.__name__ = name
143 inst.__name__ = name
142 inst.__init__(*interfaces)
144 inst.__init__(*interfaces)
143 return inst
145 return inst
144
146
145 def __repr__(self):
147 def __repr__(self):
146 return '<implementedBy %s>' % (self.__name__)
148 return '<implementedBy %s>' % (self.__name__)
147
149
148 def __reduce__(self):
150 def __reduce__(self):
149 return implementedBy, (self.inherit, )
151 return implementedBy, (self.inherit, )
150
152
151 def __cmp(self, other):
153 def __cmp(self, other):
152 # Yes, I did mean to name this __cmp, rather than __cmp__.
154 # Yes, I did mean to name this __cmp, rather than __cmp__.
153 # It is a private method used by __lt__ and __gt__.
155 # It is a private method used by __lt__ and __gt__.
154 # This is based on, and compatible with, InterfaceClass.
156 # This is based on, and compatible with, InterfaceClass.
155 # (The two must be mutually comparable to be able to work in e.g., BTrees.)
157 # (The two must be mutually comparable to be able to work in e.g., BTrees.)
156 # Instances of this class generally don't have a __module__ other than
158 # Instances of this class generally don't have a __module__ other than
157 # `zope.interface.declarations`, whereas they *do* have a __name__ that is the
159 # `zope.interface.declarations`, whereas they *do* have a __name__ that is the
158 # fully qualified name of the object they are representing.
160 # fully qualified name of the object they are representing.
159
161
160 # Note, though, that equality and hashing are still identity based. This
162 # Note, though, that equality and hashing are still identity based. This
161 # accounts for things like nested objects that have the same name (typically
163 # accounts for things like nested objects that have the same name (typically
162 # only in tests) and is consistent with pickling. As far as comparisons to InterfaceClass
164 # only in tests) and is consistent with pickling. As far as comparisons to InterfaceClass
163 # goes, we'll never have equal name and module to those, so we're still consistent there.
165 # goes, we'll never have equal name and module to those, so we're still consistent there.
164 # Instances of this class are essentially intended to be unique and are
166 # Instances of this class are essentially intended to be unique and are
165 # heavily cached (note how our __reduce__ handles this) so having identity
167 # heavily cached (note how our __reduce__ handles this) so having identity
166 # based hash and eq should also work.
168 # based hash and eq should also work.
167 if other is None:
169 if other is None:
168 return -1
170 return -1
169
171
170 n1 = (self.__name__, self.__module__)
172 n1 = (self.__name__, self.__module__)
171 n2 = (getattr(other, '__name__', ''), getattr(other, '__module__', ''))
173 n2 = (getattr(other, '__name__', ''), getattr(other, '__module__', ''))
172
174
173 # This spelling works under Python3, which doesn't have cmp().
175 # This spelling works under Python3, which doesn't have cmp().
174 return (n1 > n2) - (n1 < n2)
176 return (n1 > n2) - (n1 < n2)
175
177
176 def __hash__(self):
178 def __hash__(self):
177 return Declaration.__hash__(self)
179 return Declaration.__hash__(self)
178
180
179 # We want equality to be based on identity. However, we can't actually
181 # We want equality to be based on identity. However, we can't actually
180 # implement __eq__/__ne__ to do this because sometimes we get wrapped in a proxy.
182 # implement __eq__/__ne__ to do this because sometimes we get wrapped in a proxy.
181 # We need to let the proxy types implement these methods so they can handle unwrapping
183 # We need to let the proxy types implement these methods so they can handle unwrapping
182 # and then rely on: (1) the interpreter automatically changing `implements == proxy` into
184 # and then rely on: (1) the interpreter automatically changing `implements == proxy` into
183 # `proxy == implements` (which will call proxy.__eq__ to do the unwrapping) and then
185 # `proxy == implements` (which will call proxy.__eq__ to do the unwrapping) and then
184 # (2) the default equality semantics being identity based.
186 # (2) the default equality semantics being identity based.
185
187
186 def __lt__(self, other):
188 def __lt__(self, other):
187 c = self.__cmp(other)
189 c = self.__cmp(other)
188 return c < 0
190 return c < 0
189
191
190 def __le__(self, other):
192 def __le__(self, other):
191 c = self.__cmp(other)
193 c = self.__cmp(other)
192 return c <= 0
194 return c <= 0
193
195
194 def __gt__(self, other):
196 def __gt__(self, other):
195 c = self.__cmp(other)
197 c = self.__cmp(other)
196 return c > 0
198 return c > 0
197
199
198 def __ge__(self, other):
200 def __ge__(self, other):
199 c = self.__cmp(other)
201 c = self.__cmp(other)
200 return c >= 0
202 return c >= 0
201
203
202 def _implements_name(ob):
204 def _implements_name(ob):
203 # Return the __name__ attribute to be used by its __implemented__
205 # Return the __name__ attribute to be used by its __implemented__
204 # property.
206 # property.
205 # This must be stable for the "same" object across processes
207 # This must be stable for the "same" object across processes
206 # because it is used for sorting. It needn't be unique, though, in cases
208 # because it is used for sorting. It needn't be unique, though, in cases
207 # like nested classes named Foo created by different functions, because
209 # like nested classes named Foo created by different functions, because
208 # equality and hashing is still based on identity.
210 # equality and hashing is still based on identity.
209 # It might be nice to use __qualname__ on Python 3, but that would produce
211 # It might be nice to use __qualname__ on Python 3, but that would produce
210 # different values between Py2 and Py3.
212 # different values between Py2 and Py3.
211 return (getattr(ob, '__module__', '?') or '?') + \
213 return (getattr(ob, '__module__', '?') or '?') + \
212 '.' + (getattr(ob, '__name__', '?') or '?')
214 '.' + (getattr(ob, '__name__', '?') or '?')
213
215
214 def implementedByFallback(cls):
216 def implementedByFallback(cls):
215 """Return the interfaces implemented for a class' instances
217 """Return the interfaces implemented for a class' instances
216
218
217 The value returned is an IDeclaration.
219 The value returned is an IDeclaration.
218 """
220 """
219 try:
221 try:
220 spec = cls.__dict__.get('__implemented__')
222 spec = cls.__dict__.get('__implemented__')
221 except AttributeError:
223 except AttributeError:
222
224
223 # we can't get the class dict. This is probably due to a
225 # we can't get the class dict. This is probably due to a
224 # security proxy. If this is the case, then probably no
226 # security proxy. If this is the case, then probably no
225 # descriptor was installed for the class.
227 # descriptor was installed for the class.
226
228
227 # We don't want to depend directly on zope.security in
229 # We don't want to depend directly on zope.security in
228 # zope.interface, but we'll try to make reasonable
230 # zope.interface, but we'll try to make reasonable
229 # accommodations in an indirect way.
231 # accommodations in an indirect way.
230
232
231 # We'll check to see if there's an implements:
233 # We'll check to see if there's an implements:
232
234
233 spec = getattr(cls, '__implemented__', None)
235 spec = getattr(cls, '__implemented__', None)
234 if spec is None:
236 if spec is None:
235 # There's no spec stred in the class. Maybe its a builtin:
237 # There's no spec stred in the class. Maybe its a builtin:
236 spec = BuiltinImplementationSpecifications.get(cls)
238 spec = BuiltinImplementationSpecifications.get(cls)
237 if spec is not None:
239 if spec is not None:
238 return spec
240 return spec
239 return _empty
241 return _empty
240
242
241 if spec.__class__ == Implements:
243 if spec.__class__ == Implements:
242 # we defaulted to _empty or there was a spec. Good enough.
244 # we defaulted to _empty or there was a spec. Good enough.
243 # Return it.
245 # Return it.
244 return spec
246 return spec
245
247
246 # TODO: need old style __implements__ compatibility?
248 # TODO: need old style __implements__ compatibility?
247 # Hm, there's an __implemented__, but it's not a spec. Must be
249 # Hm, there's an __implemented__, but it's not a spec. Must be
248 # an old-style declaration. Just compute a spec for it
250 # an old-style declaration. Just compute a spec for it
249 return Declaration(*_normalizeargs((spec, )))
251 return Declaration(*_normalizeargs((spec, )))
250
252
251 if isinstance(spec, Implements):
253 if isinstance(spec, Implements):
252 return spec
254 return spec
253
255
254 if spec is None:
256 if spec is None:
255 spec = BuiltinImplementationSpecifications.get(cls)
257 spec = BuiltinImplementationSpecifications.get(cls)
256 if spec is not None:
258 if spec is not None:
257 return spec
259 return spec
258
260
259 # TODO: need old style __implements__ compatibility?
261 # TODO: need old style __implements__ compatibility?
260 spec_name = _implements_name(cls)
262 spec_name = _implements_name(cls)
261 if spec is not None:
263 if spec is not None:
262 # old-style __implemented__ = foo declaration
264 # old-style __implemented__ = foo declaration
263 spec = (spec, ) # tuplefy, as it might be just an int
265 spec = (spec, ) # tuplefy, as it might be just an int
264 spec = Implements.named(spec_name, *_normalizeargs(spec))
266 spec = Implements.named(spec_name, *_normalizeargs(spec))
265 spec.inherit = None # old-style implies no inherit
267 spec.inherit = None # old-style implies no inherit
266 del cls.__implemented__ # get rid of the old-style declaration
268 del cls.__implemented__ # get rid of the old-style declaration
267 else:
269 else:
268 try:
270 try:
269 bases = cls.__bases__
271 bases = cls.__bases__
270 except AttributeError:
272 except AttributeError:
271 if not callable(cls):
273 if not callable(cls):
272 raise TypeError("ImplementedBy called for non-factory", cls)
274 raise TypeError("ImplementedBy called for non-factory", cls)
273 bases = ()
275 bases = ()
274
276
275 spec = Implements.named(spec_name, *[implementedBy(c) for c in bases])
277 spec = Implements.named(spec_name, *[implementedBy(c) for c in bases])
276 spec.inherit = cls
278 spec.inherit = cls
277
279
278 try:
280 try:
279 cls.__implemented__ = spec
281 cls.__implemented__ = spec
280 if not hasattr(cls, '__providedBy__'):
282 if not hasattr(cls, '__providedBy__'):
281 cls.__providedBy__ = objectSpecificationDescriptor
283 cls.__providedBy__ = objectSpecificationDescriptor
282
284
283 if (isinstance(cls, DescriptorAwareMetaClasses)
285 if (isinstance(cls, DescriptorAwareMetaClasses)
284 and
286 and
285 '__provides__' not in cls.__dict__):
287 '__provides__' not in cls.__dict__):
286 # Make sure we get a __provides__ descriptor
288 # Make sure we get a __provides__ descriptor
287 cls.__provides__ = ClassProvides(
289 cls.__provides__ = ClassProvides(
288 cls,
290 cls,
289 getattr(cls, '__class__', type(cls)),
291 getattr(cls, '__class__', type(cls)),
290 )
292 )
291
293
292 except TypeError:
294 except TypeError:
293 if not isinstance(cls, type):
295 if not isinstance(cls, type):
294 raise TypeError("ImplementedBy called for non-type", cls)
296 raise TypeError("ImplementedBy called for non-type", cls)
295 BuiltinImplementationSpecifications[cls] = spec
297 BuiltinImplementationSpecifications[cls] = spec
296
298
297 return spec
299 return spec
298
300
299 implementedBy = implementedByFallback
301 implementedBy = implementedByFallback
300
302
301 def classImplementsOnly(cls, *interfaces):
303 def classImplementsOnly(cls, *interfaces):
302 """Declare the only interfaces implemented by instances of a class
304 """Declare the only interfaces implemented by instances of a class
303
305
304 The arguments after the class are one or more interfaces or interface
306 The arguments after the class are one or more interfaces or interface
305 specifications (``IDeclaration`` objects).
307 specifications (``IDeclaration`` objects).
306
308
307 The interfaces given (including the interfaces in the specifications)
309 The interfaces given (including the interfaces in the specifications)
308 replace any previous declarations.
310 replace any previous declarations.
309 """
311 """
310 spec = implementedBy(cls)
312 spec = implementedBy(cls)
311 spec.declared = ()
313 spec.declared = ()
312 spec.inherit = None
314 spec.inherit = None
313 classImplements(cls, *interfaces)
315 classImplements(cls, *interfaces)
314
316
315 def classImplements(cls, *interfaces):
317 def classImplements(cls, *interfaces):
316 """Declare additional interfaces implemented for instances of a class
318 """Declare additional interfaces implemented for instances of a class
317
319
318 The arguments after the class are one or more interfaces or
320 The arguments after the class are one or more interfaces or
319 interface specifications (``IDeclaration`` objects).
321 interface specifications (``IDeclaration`` objects).
320
322
321 The interfaces given (including the interfaces in the specifications)
323 The interfaces given (including the interfaces in the specifications)
322 are added to any interfaces previously declared.
324 are added to any interfaces previously declared.
323 """
325 """
324 spec = implementedBy(cls)
326 spec = implementedBy(cls)
325 spec.declared += tuple(_normalizeargs(interfaces))
327 spec.declared += tuple(_normalizeargs(interfaces))
326
328
327 # compute the bases
329 # compute the bases
328 bases = []
330 bases = []
329 seen = {}
331 seen = {}
330 for b in spec.declared:
332 for b in spec.declared:
331 if b not in seen:
333 if b not in seen:
332 seen[b] = 1
334 seen[b] = 1
333 bases.append(b)
335 bases.append(b)
334
336
335 if spec.inherit is not None:
337 if spec.inherit is not None:
336
338
337 for c in spec.inherit.__bases__:
339 for c in spec.inherit.__bases__:
338 b = implementedBy(c)
340 b = implementedBy(c)
339 if b not in seen:
341 if b not in seen:
340 seen[b] = 1
342 seen[b] = 1
341 bases.append(b)
343 bases.append(b)
342
344
343 spec.__bases__ = tuple(bases)
345 spec.__bases__ = tuple(bases)
344
346
345 def _implements_advice(cls):
347 def _implements_advice(cls):
346 interfaces, classImplements = cls.__dict__['__implements_advice_data__']
348 interfaces, classImplements = cls.__dict__['__implements_advice_data__']
347 del cls.__implements_advice_data__
349 del cls.__implements_advice_data__
348 classImplements(cls, *interfaces)
350 classImplements(cls, *interfaces)
349 return cls
351 return cls
350
352
351
353
352 class implementer:
354 class implementer:
353 """Declare the interfaces implemented by instances of a class.
355 """Declare the interfaces implemented by instances of a class.
354
356
355 This function is called as a class decorator.
357 This function is called as a class decorator.
356
358
357 The arguments are one or more interfaces or interface
359 The arguments are one or more interfaces or interface
358 specifications (IDeclaration objects).
360 specifications (IDeclaration objects).
359
361
360 The interfaces given (including the interfaces in the
362 The interfaces given (including the interfaces in the
361 specifications) are added to any interfaces previously
363 specifications) are added to any interfaces previously
362 declared.
364 declared.
363
365
364 Previous declarations include declarations for base classes
366 Previous declarations include declarations for base classes
365 unless implementsOnly was used.
367 unless implementsOnly was used.
366
368
367 This function is provided for convenience. It provides a more
369 This function is provided for convenience. It provides a more
368 convenient way to call classImplements. For example::
370 convenient way to call classImplements. For example::
369
371
370 @implementer(I1)
372 @implementer(I1)
371 class C(object):
373 class C(object):
372 pass
374 pass
373
375
374 is equivalent to calling::
376 is equivalent to calling::
375
377
376 classImplements(C, I1)
378 classImplements(C, I1)
377
379
378 after the class has been created.
380 after the class has been created.
379 """
381 """
380
382
381 def __init__(self, *interfaces):
383 def __init__(self, *interfaces):
382 self.interfaces = interfaces
384 self.interfaces = interfaces
383
385
384 def __call__(self, ob):
386 def __call__(self, ob):
385 if isinstance(ob, DescriptorAwareMetaClasses):
387 if isinstance(ob, DescriptorAwareMetaClasses):
386 classImplements(ob, *self.interfaces)
388 classImplements(ob, *self.interfaces)
387 return ob
389 return ob
388
390
389 spec_name = _implements_name(ob)
391 spec_name = _implements_name(ob)
390 spec = Implements.named(spec_name, *self.interfaces)
392 spec = Implements.named(spec_name, *self.interfaces)
391 try:
393 try:
392 ob.__implemented__ = spec
394 ob.__implemented__ = spec
393 except AttributeError:
395 except AttributeError:
394 raise TypeError("Can't declare implements", ob)
396 raise TypeError("Can't declare implements", ob)
395 return ob
397 return ob
396
398
397 class implementer_only:
399 class implementer_only:
398 """Declare the only interfaces implemented by instances of a class
400 """Declare the only interfaces implemented by instances of a class
399
401
400 This function is called as a class decorator.
402 This function is called as a class decorator.
401
403
402 The arguments are one or more interfaces or interface
404 The arguments are one or more interfaces or interface
403 specifications (IDeclaration objects).
405 specifications (IDeclaration objects).
404
406
405 Previous declarations including declarations for base classes
407 Previous declarations including declarations for base classes
406 are overridden.
408 are overridden.
407
409
408 This function is provided for convenience. It provides a more
410 This function is provided for convenience. It provides a more
409 convenient way to call classImplementsOnly. For example::
411 convenient way to call classImplementsOnly. For example::
410
412
411 @implementer_only(I1)
413 @implementer_only(I1)
412 class C(object): pass
414 class C(object): pass
413
415
414 is equivalent to calling::
416 is equivalent to calling::
415
417
416 classImplementsOnly(I1)
418 classImplementsOnly(I1)
417
419
418 after the class has been created.
420 after the class has been created.
419 """
421 """
420
422
421 def __init__(self, *interfaces):
423 def __init__(self, *interfaces):
422 self.interfaces = interfaces
424 self.interfaces = interfaces
423
425
424 def __call__(self, ob):
426 def __call__(self, ob):
425 if isinstance(ob, (FunctionType, MethodType)):
427 if isinstance(ob, (FunctionType, MethodType)):
426 # XXX Does this decorator make sense for anything but classes?
428 # XXX Does this decorator make sense for anything but classes?
427 # I don't think so. There can be no inheritance of interfaces
429 # I don't think so. There can be no inheritance of interfaces
428 # on a method pr function....
430 # on a method pr function....
429 raise ValueError('The implementer_only decorator is not '
431 raise ValueError('The implementer_only decorator is not '
430 'supported for methods or functions.')
432 'supported for methods or functions.')
431 else:
433 else:
432 # Assume it's a class:
434 # Assume it's a class:
433 classImplementsOnly(ob, *self.interfaces)
435 classImplementsOnly(ob, *self.interfaces)
434 return ob
436 return ob
435
437
436 def _implements(name, interfaces, classImplements):
438 def _implements(name, interfaces, classImplements):
437 # This entire approach is invalid under Py3K. Don't even try to fix
439 # This entire approach is invalid under Py3K. Don't even try to fix
438 # the coverage for this block there. :(
440 # the coverage for this block there. :(
439 frame = sys._getframe(2)
441 frame = sys._getframe(2)
440 locals = frame.f_locals
442 locals = frame.f_locals
441
443
442 # Try to make sure we were called from a class def. In 2.2.0 we can't
444 # Try to make sure we were called from a class def. In 2.2.0 we can't
443 # check for __module__ since it doesn't seem to be added to the locals
445 # check for __module__ since it doesn't seem to be added to the locals
444 # until later on.
446 # until later on.
445 if locals is frame.f_globals or '__module__' not in locals:
447 if locals is frame.f_globals or '__module__' not in locals:
446 raise TypeError(name+" can be used only from a class definition.")
448 raise TypeError(name+" can be used only from a class definition.")
447
449
448 if '__implements_advice_data__' in locals:
450 if '__implements_advice_data__' in locals:
449 raise TypeError(name+" can be used only once in a class definition.")
451 raise TypeError(name+" can be used only once in a class definition.")
450
452
451 locals['__implements_advice_data__'] = interfaces, classImplements
453 locals['__implements_advice_data__'] = interfaces, classImplements
452 addClassAdvisor(_implements_advice, depth=3)
454 addClassAdvisor(_implements_advice, depth=3)
453
455
454 def implements(*interfaces):
456 def implements(*interfaces):
455 """Declare interfaces implemented by instances of a class
457 """Declare interfaces implemented by instances of a class
456
458
457 This function is called in a class definition.
459 This function is called in a class definition.
458
460
459 The arguments are one or more interfaces or interface
461 The arguments are one or more interfaces or interface
460 specifications (IDeclaration objects).
462 specifications (IDeclaration objects).
461
463
462 The interfaces given (including the interfaces in the
464 The interfaces given (including the interfaces in the
463 specifications) are added to any interfaces previously
465 specifications) are added to any interfaces previously
464 declared.
466 declared.
465
467
466 Previous declarations include declarations for base classes
468 Previous declarations include declarations for base classes
467 unless implementsOnly was used.
469 unless implementsOnly was used.
468
470
469 This function is provided for convenience. It provides a more
471 This function is provided for convenience. It provides a more
470 convenient way to call classImplements. For example::
472 convenient way to call classImplements. For example::
471
473
472 implements(I1)
474 implements(I1)
473
475
474 is equivalent to calling::
476 is equivalent to calling::
475
477
476 classImplements(C, I1)
478 classImplements(C, I1)
477
479
478 after the class has been created.
480 after the class has been created.
479 """
481 """
480 # This entire approach is invalid under Py3K. Don't even try to fix
482 # This entire approach is invalid under Py3K. Don't even try to fix
481 # the coverage for this block there. :(
483 # the coverage for this block there. :(
482 if PYTHON3:
484 if PYTHON3:
483 raise TypeError(_ADVICE_ERROR % 'implementer')
485 raise TypeError(_ADVICE_ERROR % 'implementer')
484 _implements("implements", interfaces, classImplements)
486 _implements("implements", interfaces, classImplements)
485
487
486 def implementsOnly(*interfaces):
488 def implementsOnly(*interfaces):
487 """Declare the only interfaces implemented by instances of a class
489 """Declare the only interfaces implemented by instances of a class
488
490
489 This function is called in a class definition.
491 This function is called in a class definition.
490
492
491 The arguments are one or more interfaces or interface
493 The arguments are one or more interfaces or interface
492 specifications (IDeclaration objects).
494 specifications (IDeclaration objects).
493
495
494 Previous declarations including declarations for base classes
496 Previous declarations including declarations for base classes
495 are overridden.
497 are overridden.
496
498
497 This function is provided for convenience. It provides a more
499 This function is provided for convenience. It provides a more
498 convenient way to call classImplementsOnly. For example::
500 convenient way to call classImplementsOnly. For example::
499
501
500 implementsOnly(I1)
502 implementsOnly(I1)
501
503
502 is equivalent to calling::
504 is equivalent to calling::
503
505
504 classImplementsOnly(I1)
506 classImplementsOnly(I1)
505
507
506 after the class has been created.
508 after the class has been created.
507 """
509 """
508 # This entire approach is invalid under Py3K. Don't even try to fix
510 # This entire approach is invalid under Py3K. Don't even try to fix
509 # the coverage for this block there. :(
511 # the coverage for this block there. :(
510 if PYTHON3:
512 if PYTHON3:
511 raise TypeError(_ADVICE_ERROR % 'implementer_only')
513 raise TypeError(_ADVICE_ERROR % 'implementer_only')
512 _implements("implementsOnly", interfaces, classImplementsOnly)
514 _implements("implementsOnly", interfaces, classImplementsOnly)
513
515
514 ##############################################################################
516 ##############################################################################
515 #
517 #
516 # Instance declarations
518 # Instance declarations
517
519
518 class Provides(Declaration): # Really named ProvidesClass
520 class Provides(Declaration): # Really named ProvidesClass
519 """Implement __provides__, the instance-specific specification
521 """Implement __provides__, the instance-specific specification
520
522
521 When an object is pickled, we pickle the interfaces that it implements.
523 When an object is pickled, we pickle the interfaces that it implements.
522 """
524 """
523
525
524 def __init__(self, cls, *interfaces):
526 def __init__(self, cls, *interfaces):
525 self.__args = (cls, ) + interfaces
527 self.__args = (cls, ) + interfaces
526 self._cls = cls
528 self._cls = cls
527 Declaration.__init__(self, *(interfaces + (implementedBy(cls), )))
529 Declaration.__init__(self, *(interfaces + (implementedBy(cls), )))
528
530
529 def __reduce__(self):
531 def __reduce__(self):
530 return Provides, self.__args
532 return Provides, self.__args
531
533
532 __module__ = 'zope.interface'
534 __module__ = 'zope.interface'
533
535
534 def __get__(self, inst, cls):
536 def __get__(self, inst, cls):
535 """Make sure that a class __provides__ doesn't leak to an instance
537 """Make sure that a class __provides__ doesn't leak to an instance
536 """
538 """
537 if inst is None and cls is self._cls:
539 if inst is None and cls is self._cls:
538 # We were accessed through a class, so we are the class'
540 # We were accessed through a class, so we are the class'
539 # provides spec. Just return this object, but only if we are
541 # provides spec. Just return this object, but only if we are
540 # being called on the same class that we were defined for:
542 # being called on the same class that we were defined for:
541 return self
543 return self
542
544
543 raise AttributeError('__provides__')
545 raise AttributeError('__provides__')
544
546
545 ProvidesClass = Provides
547 ProvidesClass = Provides
546
548
547 # Registry of instance declarations
549 # Registry of instance declarations
548 # This is a memory optimization to allow objects to share specifications.
550 # This is a memory optimization to allow objects to share specifications.
549 InstanceDeclarations = weakref.WeakValueDictionary()
551 InstanceDeclarations = weakref.WeakValueDictionary()
550
552
551 def Provides(*interfaces):
553 def Provides(*interfaces):
552 """Cache instance declarations
554 """Cache instance declarations
553
555
554 Instance declarations are shared among instances that have the same
556 Instance declarations are shared among instances that have the same
555 declaration. The declarations are cached in a weak value dictionary.
557 declaration. The declarations are cached in a weak value dictionary.
556 """
558 """
557 spec = InstanceDeclarations.get(interfaces)
559 spec = InstanceDeclarations.get(interfaces)
558 if spec is None:
560 if spec is None:
559 spec = ProvidesClass(*interfaces)
561 spec = ProvidesClass(*interfaces)
560 InstanceDeclarations[interfaces] = spec
562 InstanceDeclarations[interfaces] = spec
561
563
562 return spec
564 return spec
563
565
564 Provides.__safe_for_unpickling__ = True
566 Provides.__safe_for_unpickling__ = True
565
567
566
568
567 def directlyProvides(object, *interfaces):
569 def directlyProvides(object, *interfaces):
568 """Declare interfaces declared directly for an object
570 """Declare interfaces declared directly for an object
569
571
570 The arguments after the object are one or more interfaces or interface
572 The arguments after the object are one or more interfaces or interface
571 specifications (``IDeclaration`` objects).
573 specifications (``IDeclaration`` objects).
572
574
573 The interfaces given (including the interfaces in the specifications)
575 The interfaces given (including the interfaces in the specifications)
574 replace interfaces previously declared for the object.
576 replace interfaces previously declared for the object.
575 """
577 """
576 cls = getattr(object, '__class__', None)
578 cls = getattr(object, '__class__', None)
577 if cls is not None and getattr(cls, '__class__', None) is cls:
579 if cls is not None and getattr(cls, '__class__', None) is cls:
578 # It's a meta class (well, at least it it could be an extension class)
580 # It's a meta class (well, at least it it could be an extension class)
579 # Note that we can't get here from Py3k tests: there is no normal
581 # Note that we can't get here from Py3k tests: there is no normal
580 # class which isn't descriptor aware.
582 # class which isn't descriptor aware.
581 if not isinstance(object,
583 if not isinstance(object,
582 DescriptorAwareMetaClasses):
584 DescriptorAwareMetaClasses):
583 raise TypeError("Attempt to make an interface declaration on a "
585 raise TypeError("Attempt to make an interface declaration on a "
584 "non-descriptor-aware class")
586 "non-descriptor-aware class")
585
587
586 interfaces = _normalizeargs(interfaces)
588 interfaces = _normalizeargs(interfaces)
587 if cls is None:
589 if cls is None:
588 cls = type(object)
590 cls = type(object)
589
591
590 issub = False
592 issub = False
591 for damc in DescriptorAwareMetaClasses:
593 for damc in DescriptorAwareMetaClasses:
592 if issubclass(cls, damc):
594 if issubclass(cls, damc):
593 issub = True
595 issub = True
594 break
596 break
595 if issub:
597 if issub:
596 # we have a class or type. We'll use a special descriptor
598 # we have a class or type. We'll use a special descriptor
597 # that provides some extra caching
599 # that provides some extra caching
598 object.__provides__ = ClassProvides(object, cls, *interfaces)
600 object.__provides__ = ClassProvides(object, cls, *interfaces)
599 else:
601 else:
600 object.__provides__ = Provides(cls, *interfaces)
602 object.__provides__ = Provides(cls, *interfaces)
601
603
602
604
603 def alsoProvides(object, *interfaces):
605 def alsoProvides(object, *interfaces):
604 """Declare interfaces declared directly for an object
606 """Declare interfaces declared directly for an object
605
607
606 The arguments after the object are one or more interfaces or interface
608 The arguments after the object are one or more interfaces or interface
607 specifications (``IDeclaration`` objects).
609 specifications (``IDeclaration`` objects).
608
610
609 The interfaces given (including the interfaces in the specifications) are
611 The interfaces given (including the interfaces in the specifications) are
610 added to the interfaces previously declared for the object.
612 added to the interfaces previously declared for the object.
611 """
613 """
612 directlyProvides(object, directlyProvidedBy(object), *interfaces)
614 directlyProvides(object, directlyProvidedBy(object), *interfaces)
613
615
614 def noLongerProvides(object, interface):
616 def noLongerProvides(object, interface):
615 """ Removes a directly provided interface from an object.
617 """ Removes a directly provided interface from an object.
616 """
618 """
617 directlyProvides(object, directlyProvidedBy(object) - interface)
619 directlyProvides(object, directlyProvidedBy(object) - interface)
618 if interface.providedBy(object):
620 if interface.providedBy(object):
619 raise ValueError("Can only remove directly provided interfaces.")
621 raise ValueError("Can only remove directly provided interfaces.")
620
622
621 class ClassProvidesBaseFallback(object):
623 class ClassProvidesBaseFallback(object):
622
624
623 def __get__(self, inst, cls):
625 def __get__(self, inst, cls):
624 if cls is self._cls:
626 if cls is self._cls:
625 # We only work if called on the class we were defined for
627 # We only work if called on the class we were defined for
626
628
627 if inst is None:
629 if inst is None:
628 # We were accessed through a class, so we are the class'
630 # We were accessed through a class, so we are the class'
629 # provides spec. Just return this object as is:
631 # provides spec. Just return this object as is:
630 return self
632 return self
631
633
632 return self._implements
634 return self._implements
633
635
634 raise AttributeError('__provides__')
636 raise AttributeError('__provides__')
635
637
636 ClassProvidesBasePy = ClassProvidesBaseFallback # BBB
638 ClassProvidesBasePy = ClassProvidesBaseFallback # BBB
637 ClassProvidesBase = ClassProvidesBaseFallback
639 ClassProvidesBase = ClassProvidesBaseFallback
638
640
639 # Try to get C base:
641 # Try to get C base:
640 try:
642 try:
641 import zope.interface._zope_interface_coptimizations
643 from . import _zope_interface_coptimizations
642 except ImportError:
644 except ImportError:
643 pass
645 pass
644 else:
646 else:
645 from zope.interface._zope_interface_coptimizations import ClassProvidesBase
647 from ._zope_interface_coptimizations import ClassProvidesBase
646
648
647
649
648 class ClassProvides(Declaration, ClassProvidesBase):
650 class ClassProvides(Declaration, ClassProvidesBase):
649 """Special descriptor for class __provides__
651 """Special descriptor for class __provides__
650
652
651 The descriptor caches the implementedBy info, so that
653 The descriptor caches the implementedBy info, so that
652 we can get declarations for objects without instance-specific
654 we can get declarations for objects without instance-specific
653 interfaces a bit quicker.
655 interfaces a bit quicker.
654 """
656 """
655 def __init__(self, cls, metacls, *interfaces):
657 def __init__(self, cls, metacls, *interfaces):
656 self._cls = cls
658 self._cls = cls
657 self._implements = implementedBy(cls)
659 self._implements = implementedBy(cls)
658 self.__args = (cls, metacls, ) + interfaces
660 self.__args = (cls, metacls, ) + interfaces
659 Declaration.__init__(self, *(interfaces + (implementedBy(metacls), )))
661 Declaration.__init__(self, *(interfaces + (implementedBy(metacls), )))
660
662
661 def __reduce__(self):
663 def __reduce__(self):
662 return self.__class__, self.__args
664 return self.__class__, self.__args
663
665
664 # Copy base-class method for speed
666 # Copy base-class method for speed
665 __get__ = ClassProvidesBase.__get__
667 __get__ = ClassProvidesBase.__get__
666
668
667 def directlyProvidedBy(object):
669 def directlyProvidedBy(object):
668 """Return the interfaces directly provided by the given object
670 """Return the interfaces directly provided by the given object
669
671
670 The value returned is an ``IDeclaration``.
672 The value returned is an ``IDeclaration``.
671 """
673 """
672 provides = getattr(object, "__provides__", None)
674 provides = getattr(object, "__provides__", None)
673 if (provides is None # no spec
675 if (provides is None # no spec
674 or
676 or
675 # We might have gotten the implements spec, as an
677 # We might have gotten the implements spec, as an
676 # optimization. If so, it's like having only one base, that we
678 # optimization. If so, it's like having only one base, that we
677 # lop off to exclude class-supplied declarations:
679 # lop off to exclude class-supplied declarations:
678 isinstance(provides, Implements)
680 isinstance(provides, Implements)
679 ):
681 ):
680 return _empty
682 return _empty
681
683
682 # Strip off the class part of the spec:
684 # Strip off the class part of the spec:
683 return Declaration(provides.__bases__[:-1])
685 return Declaration(provides.__bases__[:-1])
684
686
685 def classProvides(*interfaces):
687 def classProvides(*interfaces):
686 """Declare interfaces provided directly by a class
688 """Declare interfaces provided directly by a class
687
689
688 This function is called in a class definition.
690 This function is called in a class definition.
689
691
690 The arguments are one or more interfaces or interface specifications
692 The arguments are one or more interfaces or interface specifications
691 (``IDeclaration`` objects).
693 (``IDeclaration`` objects).
692
694
693 The given interfaces (including the interfaces in the specifications)
695 The given interfaces (including the interfaces in the specifications)
694 are used to create the class's direct-object interface specification.
696 are used to create the class's direct-object interface specification.
695 An error will be raised if the module class has an direct interface
697 An error will be raised if the module class has an direct interface
696 specification. In other words, it is an error to call this function more
698 specification. In other words, it is an error to call this function more
697 than once in a class definition.
699 than once in a class definition.
698
700
699 Note that the given interfaces have nothing to do with the interfaces
701 Note that the given interfaces have nothing to do with the interfaces
700 implemented by instances of the class.
702 implemented by instances of the class.
701
703
702 This function is provided for convenience. It provides a more convenient
704 This function is provided for convenience. It provides a more convenient
703 way to call directlyProvides for a class. For example::
705 way to call directlyProvides for a class. For example::
704
706
705 classProvides(I1)
707 classProvides(I1)
706
708
707 is equivalent to calling::
709 is equivalent to calling::
708
710
709 directlyProvides(theclass, I1)
711 directlyProvides(theclass, I1)
710
712
711 after the class has been created.
713 after the class has been created.
712 """
714 """
713 # This entire approach is invalid under Py3K. Don't even try to fix
715 # This entire approach is invalid under Py3K. Don't even try to fix
714 # the coverage for this block there. :(
716 # the coverage for this block there. :(
715
717
716 if PYTHON3:
718 if PYTHON3:
717 raise TypeError(_ADVICE_ERROR % 'provider')
719 raise TypeError(_ADVICE_ERROR % 'provider')
718
720
719 frame = sys._getframe(1)
721 frame = sys._getframe(1)
720 locals = frame.f_locals
722 locals = frame.f_locals
721
723
722 # Try to make sure we were called from a class def
724 # Try to make sure we were called from a class def
723 if (locals is frame.f_globals) or ('__module__' not in locals):
725 if (locals is frame.f_globals) or ('__module__' not in locals):
724 raise TypeError("classProvides can be used only from a "
726 raise TypeError("classProvides can be used only from a "
725 "class definition.")
727 "class definition.")
726
728
727 if '__provides__' in locals:
729 if '__provides__' in locals:
728 raise TypeError(
730 raise TypeError(
729 "classProvides can only be used once in a class definition.")
731 "classProvides can only be used once in a class definition.")
730
732
731 locals["__provides__"] = _normalizeargs(interfaces)
733 locals["__provides__"] = _normalizeargs(interfaces)
732
734
733 addClassAdvisor(_classProvides_advice, depth=2)
735 addClassAdvisor(_classProvides_advice, depth=2)
734
736
735 def _classProvides_advice(cls):
737 def _classProvides_advice(cls):
736 # This entire approach is invalid under Py3K. Don't even try to fix
738 # This entire approach is invalid under Py3K. Don't even try to fix
737 # the coverage for this block there. :(
739 # the coverage for this block there. :(
738 interfaces = cls.__dict__['__provides__']
740 interfaces = cls.__dict__['__provides__']
739 del cls.__provides__
741 del cls.__provides__
740 directlyProvides(cls, *interfaces)
742 directlyProvides(cls, *interfaces)
741 return cls
743 return cls
742
744
743 class provider:
745 class provider:
744 """Class decorator version of classProvides"""
746 """Class decorator version of classProvides"""
745
747
746 def __init__(self, *interfaces):
748 def __init__(self, *interfaces):
747 self.interfaces = interfaces
749 self.interfaces = interfaces
748
750
749 def __call__(self, ob):
751 def __call__(self, ob):
750 directlyProvides(ob, *self.interfaces)
752 directlyProvides(ob, *self.interfaces)
751 return ob
753 return ob
752
754
753 def moduleProvides(*interfaces):
755 def moduleProvides(*interfaces):
754 """Declare interfaces provided by a module
756 """Declare interfaces provided by a module
755
757
756 This function is used in a module definition.
758 This function is used in a module definition.
757
759
758 The arguments are one or more interfaces or interface specifications
760 The arguments are one or more interfaces or interface specifications
759 (``IDeclaration`` objects).
761 (``IDeclaration`` objects).
760
762
761 The given interfaces (including the interfaces in the specifications) are
763 The given interfaces (including the interfaces in the specifications) are
762 used to create the module's direct-object interface specification. An
764 used to create the module's direct-object interface specification. An
763 error will be raised if the module already has an interface specification.
765 error will be raised if the module already has an interface specification.
764 In other words, it is an error to call this function more than once in a
766 In other words, it is an error to call this function more than once in a
765 module definition.
767 module definition.
766
768
767 This function is provided for convenience. It provides a more convenient
769 This function is provided for convenience. It provides a more convenient
768 way to call directlyProvides. For example::
770 way to call directlyProvides. For example::
769
771
770 moduleImplements(I1)
772 moduleImplements(I1)
771
773
772 is equivalent to::
774 is equivalent to::
773
775
774 directlyProvides(sys.modules[__name__], I1)
776 directlyProvides(sys.modules[__name__], I1)
775 """
777 """
776 frame = sys._getframe(1)
778 frame = sys._getframe(1)
777 locals = frame.f_locals
779 locals = frame.f_locals
778
780
779 # Try to make sure we were called from a class def
781 # Try to make sure we were called from a class def
780 if (locals is not frame.f_globals) or ('__name__' not in locals):
782 if (locals is not frame.f_globals) or ('__name__' not in locals):
781 raise TypeError(
783 raise TypeError(
782 "moduleProvides can only be used from a module definition.")
784 "moduleProvides can only be used from a module definition.")
783
785
784 if '__provides__' in locals:
786 if '__provides__' in locals:
785 raise TypeError(
787 raise TypeError(
786 "moduleProvides can only be used once in a module definition.")
788 "moduleProvides can only be used once in a module definition.")
787
789
788 locals["__provides__"] = Provides(ModuleType,
790 locals["__provides__"] = Provides(ModuleType,
789 *_normalizeargs(interfaces))
791 *_normalizeargs(interfaces))
790
792
791 ##############################################################################
793 ##############################################################################
792 #
794 #
793 # Declaration querying support
795 # Declaration querying support
794
796
795 # XXX: is this a fossil? Nobody calls it, no unit tests exercise it, no
797 # XXX: is this a fossil? Nobody calls it, no unit tests exercise it, no
796 # doctests import it, and the package __init__ doesn't import it.
798 # doctests import it, and the package __init__ doesn't import it.
797 def ObjectSpecification(direct, cls):
799 def ObjectSpecification(direct, cls):
798 """Provide object specifications
800 """Provide object specifications
799
801
800 These combine information for the object and for it's classes.
802 These combine information for the object and for it's classes.
801 """
803 """
802 return Provides(cls, direct) # pragma: no cover fossil
804 return Provides(cls, direct) # pragma: no cover fossil
803
805
804 def getObjectSpecificationFallback(ob):
806 def getObjectSpecificationFallback(ob):
805
807
806 provides = getattr(ob, '__provides__', None)
808 provides = getattr(ob, '__provides__', None)
807 if provides is not None:
809 if provides is not None:
808 if isinstance(provides, SpecificationBase):
810 if isinstance(provides, SpecificationBase):
809 return provides
811 return provides
810
812
811 try:
813 try:
812 cls = ob.__class__
814 cls = ob.__class__
813 except AttributeError:
815 except AttributeError:
814 # We can't get the class, so just consider provides
816 # We can't get the class, so just consider provides
815 return _empty
817 return _empty
816
818
817 return implementedBy(cls)
819 return implementedBy(cls)
818
820
819 getObjectSpecification = getObjectSpecificationFallback
821 getObjectSpecification = getObjectSpecificationFallback
820
822
821 def providedByFallback(ob):
823 def providedByFallback(ob):
822
824
823 # Here we have either a special object, an old-style declaration
825 # Here we have either a special object, an old-style declaration
824 # or a descriptor
826 # or a descriptor
825
827
826 # Try to get __providedBy__
828 # Try to get __providedBy__
827 try:
829 try:
828 r = ob.__providedBy__
830 r = ob.__providedBy__
829 except AttributeError:
831 except AttributeError:
830 # Not set yet. Fall back to lower-level thing that computes it
832 # Not set yet. Fall back to lower-level thing that computes it
831 return getObjectSpecification(ob)
833 return getObjectSpecification(ob)
832
834
833 try:
835 try:
834 # We might have gotten a descriptor from an instance of a
836 # We might have gotten a descriptor from an instance of a
835 # class (like an ExtensionClass) that doesn't support
837 # class (like an ExtensionClass) that doesn't support
836 # descriptors. We'll make sure we got one by trying to get
838 # descriptors. We'll make sure we got one by trying to get
837 # the only attribute, which all specs have.
839 # the only attribute, which all specs have.
838 r.extends
840 r.extends
839
841
840 except AttributeError:
842 except AttributeError:
841
843
842 # The object's class doesn't understand descriptors.
844 # The object's class doesn't understand descriptors.
843 # Sigh. We need to get an object descriptor, but we have to be
845 # Sigh. We need to get an object descriptor, but we have to be
844 # careful. We want to use the instance's __provides__, if
846 # careful. We want to use the instance's __provides__, if
845 # there is one, but only if it didn't come from the class.
847 # there is one, but only if it didn't come from the class.
846
848
847 try:
849 try:
848 r = ob.__provides__
850 r = ob.__provides__
849 except AttributeError:
851 except AttributeError:
850 # No __provides__, so just fall back to implementedBy
852 # No __provides__, so just fall back to implementedBy
851 return implementedBy(ob.__class__)
853 return implementedBy(ob.__class__)
852
854
853 # We need to make sure we got the __provides__ from the
855 # We need to make sure we got the __provides__ from the
854 # instance. We'll do this by making sure we don't get the same
856 # instance. We'll do this by making sure we don't get the same
855 # thing from the class:
857 # thing from the class:
856
858
857 try:
859 try:
858 cp = ob.__class__.__provides__
860 cp = ob.__class__.__provides__
859 except AttributeError:
861 except AttributeError:
860 # The ob doesn't have a class or the class has no
862 # The ob doesn't have a class or the class has no
861 # provides, assume we're done:
863 # provides, assume we're done:
862 return r
864 return r
863
865
864 if r is cp:
866 if r is cp:
865 # Oops, we got the provides from the class. This means
867 # Oops, we got the provides from the class. This means
866 # the object doesn't have it's own. We should use implementedBy
868 # the object doesn't have it's own. We should use implementedBy
867 return implementedBy(ob.__class__)
869 return implementedBy(ob.__class__)
868
870
869 return r
871 return r
870 providedBy = providedByFallback
872 providedBy = providedByFallback
871
873
872 class ObjectSpecificationDescriptorFallback(object):
874 class ObjectSpecificationDescriptorFallback(object):
873 """Implement the `__providedBy__` attribute
875 """Implement the `__providedBy__` attribute
874
876
875 The `__providedBy__` attribute computes the interfaces peovided by
877 The `__providedBy__` attribute computes the interfaces peovided by
876 an object.
878 an object.
877 """
879 """
878
880
879 def __get__(self, inst, cls):
881 def __get__(self, inst, cls):
880 """Get an object specification for an object
882 """Get an object specification for an object
881 """
883 """
882 if inst is None:
884 if inst is None:
883 return getObjectSpecification(cls)
885 return getObjectSpecification(cls)
884
886
885 provides = getattr(inst, '__provides__', None)
887 provides = getattr(inst, '__provides__', None)
886 if provides is not None:
888 if provides is not None:
887 return provides
889 return provides
888
890
889 return implementedBy(cls)
891 return implementedBy(cls)
890
892
891 ObjectSpecificationDescriptor = ObjectSpecificationDescriptorFallback
893 ObjectSpecificationDescriptor = ObjectSpecificationDescriptorFallback
892
894
893 ##############################################################################
895 ##############################################################################
894
896
895 def _normalizeargs(sequence, output = None):
897 def _normalizeargs(sequence, output = None):
896 """Normalize declaration arguments
898 """Normalize declaration arguments
897
899
898 Normalization arguments might contain Declarions, tuples, or single
900 Normalization arguments might contain Declarions, tuples, or single
899 interfaces.
901 interfaces.
900
902
901 Anything but individial interfaces or implements specs will be expanded.
903 Anything but individial interfaces or implements specs will be expanded.
902 """
904 """
903 if output is None:
905 if output is None:
904 output = []
906 output = []
905
907
906 cls = sequence.__class__
908 cls = sequence.__class__
907 if InterfaceClass in cls.__mro__ or Implements in cls.__mro__:
909 if InterfaceClass in cls.__mro__ or Implements in cls.__mro__:
908 output.append(sequence)
910 output.append(sequence)
909 else:
911 else:
910 for v in sequence:
912 for v in sequence:
911 _normalizeargs(v, output)
913 _normalizeargs(v, output)
912
914
913 return output
915 return output
914
916
915 _empty = Declaration()
917 _empty = Declaration()
916
918
917 try:
919 try:
918 import zope.interface._zope_interface_coptimizations
920 from . import _zope_interface_coptimizations
919 except ImportError:
921 except ImportError:
920 pass
922 pass
921 else:
923 else:
922 from zope.interface._zope_interface_coptimizations import implementedBy
924 from ._zope_interface_coptimizations import implementedBy
923 from zope.interface._zope_interface_coptimizations import providedBy
925 from ._zope_interface_coptimizations import providedBy
924 from zope.interface._zope_interface_coptimizations import (
926 from ._zope_interface_coptimizations import (
925 getObjectSpecification)
927 getObjectSpecification)
926 from zope.interface._zope_interface_coptimizations import (
928 from ._zope_interface_coptimizations import (
927 ObjectSpecificationDescriptor)
929 ObjectSpecificationDescriptor)
928
930
929 objectSpecificationDescriptor = ObjectSpecificationDescriptor()
931 objectSpecificationDescriptor = ObjectSpecificationDescriptor()
@@ -1,120 +1,122 b''
1 ##############################################################################
1 ##############################################################################
2 #
2 #
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """ Pretty-Print an Interface object as structured text (Yum)
14 """ Pretty-Print an Interface object as structured text (Yum)
15
15
16 This module provides a function, asStructuredText, for rendering an
16 This module provides a function, asStructuredText, for rendering an
17 interface as structured text.
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 def asStructuredText(I, munge=0, rst=False):
24 def asStructuredText(I, munge=0, rst=False):
23 """ Output structured text format. Note, this will whack any existing
25 """ Output structured text format. Note, this will whack any existing
24 'structured' format of the text.
26 'structured' format of the text.
25
27
26 If `rst=True`, then the output will quote all code as inline literals in
28 If `rst=True`, then the output will quote all code as inline literals in
27 accordance with 'reStructuredText' markup principles.
29 accordance with 'reStructuredText' markup principles.
28 """
30 """
29
31
30 if rst:
32 if rst:
31 inline_literal = lambda s: "``%s``" % (s,)
33 inline_literal = lambda s: "``%s``" % (s,)
32 else:
34 else:
33 inline_literal = lambda s: s
35 inline_literal = lambda s: s
34
36
35 r = [inline_literal(I.getName())]
37 r = [inline_literal(I.getName())]
36 outp = r.append
38 outp = r.append
37 level = 1
39 level = 1
38
40
39 if I.getDoc():
41 if I.getDoc():
40 outp(_justify_and_indent(_trim_doc_string(I.getDoc()), level))
42 outp(_justify_and_indent(_trim_doc_string(I.getDoc()), level))
41
43
42 bases = [base
44 bases = [base
43 for base in I.__bases__
45 for base in I.__bases__
44 if base is not zope.interface.Interface
46 if base is not Interface
45 ]
47 ]
46 if bases:
48 if bases:
47 outp(_justify_and_indent("This interface extends:", level, munge))
49 outp(_justify_and_indent("This interface extends:", level, munge))
48 level += 1
50 level += 1
49 for b in bases:
51 for b in bases:
50 item = "o %s" % inline_literal(b.getName())
52 item = "o %s" % inline_literal(b.getName())
51 outp(_justify_and_indent(_trim_doc_string(item), level, munge))
53 outp(_justify_and_indent(_trim_doc_string(item), level, munge))
52 level -= 1
54 level -= 1
53
55
54 namesAndDescriptions = sorted(I.namesAndDescriptions())
56 namesAndDescriptions = sorted(I.namesAndDescriptions())
55
57
56 outp(_justify_and_indent("Attributes:", level, munge))
58 outp(_justify_and_indent("Attributes:", level, munge))
57 level += 1
59 level += 1
58 for name, desc in namesAndDescriptions:
60 for name, desc in namesAndDescriptions:
59 if not hasattr(desc, 'getSignatureString'): # ugh...
61 if not hasattr(desc, 'getSignatureString'): # ugh...
60 item = "%s -- %s" % (inline_literal(desc.getName()),
62 item = "%s -- %s" % (inline_literal(desc.getName()),
61 desc.getDoc() or 'no documentation')
63 desc.getDoc() or 'no documentation')
62 outp(_justify_and_indent(_trim_doc_string(item), level, munge))
64 outp(_justify_and_indent(_trim_doc_string(item), level, munge))
63 level -= 1
65 level -= 1
64
66
65 outp(_justify_and_indent("Methods:", level, munge))
67 outp(_justify_and_indent("Methods:", level, munge))
66 level += 1
68 level += 1
67 for name, desc in namesAndDescriptions:
69 for name, desc in namesAndDescriptions:
68 if hasattr(desc, 'getSignatureString'): # ugh...
70 if hasattr(desc, 'getSignatureString'): # ugh...
69 _call = "%s%s" % (desc.getName(), desc.getSignatureString())
71 _call = "%s%s" % (desc.getName(), desc.getSignatureString())
70 item = "%s -- %s" % (inline_literal(_call),
72 item = "%s -- %s" % (inline_literal(_call),
71 desc.getDoc() or 'no documentation')
73 desc.getDoc() or 'no documentation')
72 outp(_justify_and_indent(_trim_doc_string(item), level, munge))
74 outp(_justify_and_indent(_trim_doc_string(item), level, munge))
73
75
74 return "\n\n".join(r) + "\n\n"
76 return "\n\n".join(r) + "\n\n"
75
77
76
78
77 def asReStructuredText(I, munge=0):
79 def asReStructuredText(I, munge=0):
78 """ Output reStructuredText format. Note, this will whack any existing
80 """ Output reStructuredText format. Note, this will whack any existing
79 'structured' format of the text."""
81 'structured' format of the text."""
80 return asStructuredText(I, munge=munge, rst=True)
82 return asStructuredText(I, munge=munge, rst=True)
81
83
82
84
83 def _trim_doc_string(text):
85 def _trim_doc_string(text):
84 """ Trims a doc string to make it format
86 """ Trims a doc string to make it format
85 correctly with structured text. """
87 correctly with structured text. """
86
88
87 lines = text.replace('\r\n', '\n').split('\n')
89 lines = text.replace('\r\n', '\n').split('\n')
88 nlines = [lines.pop(0)]
90 nlines = [lines.pop(0)]
89 if lines:
91 if lines:
90 min_indent = min([len(line) - len(line.lstrip())
92 min_indent = min([len(line) - len(line.lstrip())
91 for line in lines])
93 for line in lines])
92 for line in lines:
94 for line in lines:
93 nlines.append(line[min_indent:])
95 nlines.append(line[min_indent:])
94
96
95 return '\n'.join(nlines)
97 return '\n'.join(nlines)
96
98
97
99
98 def _justify_and_indent(text, level, munge=0, width=72):
100 def _justify_and_indent(text, level, munge=0, width=72):
99 """ indent and justify text, rejustify (munge) if specified """
101 """ indent and justify text, rejustify (munge) if specified """
100
102
101 indent = " " * level
103 indent = " " * level
102
104
103 if munge:
105 if munge:
104 lines = []
106 lines = []
105 line = indent
107 line = indent
106 text = text.split()
108 text = text.split()
107
109
108 for word in text:
110 for word in text:
109 line = ' '.join([line, word])
111 line = ' '.join([line, word])
110 if len(line) > width:
112 if len(line) > width:
111 lines.append(line)
113 lines.append(line)
112 line = indent
114 line = indent
113 else:
115 else:
114 lines.append(line)
116 lines.append(line)
115
117
116 return '\n'.join(lines)
118 return '\n'.join(lines)
117
119
118 else:
120 else:
119 return indent + \
121 return indent + \
120 text.strip().replace("\r\n", "\n") .replace("\n", "\n" + indent)
122 text.strip().replace("\r\n", "\n") .replace("\n", "\n" + indent)
@@ -1,67 +1,69 b''
1 ##############################################################################
1 ##############################################################################
2 #
2 #
3 # Copyright (c) 2002 Zope Foundation and Contributors.
3 # Copyright (c) 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """Interface-specific exceptions
14 """Interface-specific exceptions
15 """
15 """
16
16
17 from __future__ import absolute_import
18
17 class Invalid(Exception):
19 class Invalid(Exception):
18 """A specification is violated
20 """A specification is violated
19 """
21 """
20
22
21 class DoesNotImplement(Invalid):
23 class DoesNotImplement(Invalid):
22 """ This object does not implement """
24 """ This object does not implement """
23 def __init__(self, interface):
25 def __init__(self, interface):
24 self.interface = interface
26 self.interface = interface
25
27
26 def __str__(self):
28 def __str__(self):
27 return """An object does not implement interface %(interface)s
29 return """An object does not implement interface %(interface)s
28
30
29 """ % self.__dict__
31 """ % self.__dict__
30
32
31 class BrokenImplementation(Invalid):
33 class BrokenImplementation(Invalid):
32 """An attribute is not completely implemented.
34 """An attribute is not completely implemented.
33 """
35 """
34
36
35 def __init__(self, interface, name):
37 def __init__(self, interface, name):
36 self.interface=interface
38 self.interface=interface
37 self.name=name
39 self.name=name
38
40
39 def __str__(self):
41 def __str__(self):
40 return """An object has failed to implement interface %(interface)s
42 return """An object has failed to implement interface %(interface)s
41
43
42 The %(name)s attribute was not provided.
44 The %(name)s attribute was not provided.
43 """ % self.__dict__
45 """ % self.__dict__
44
46
45 class BrokenMethodImplementation(Invalid):
47 class BrokenMethodImplementation(Invalid):
46 """An method is not completely implemented.
48 """An method is not completely implemented.
47 """
49 """
48
50
49 def __init__(self, method, mess):
51 def __init__(self, method, mess):
50 self.method=method
52 self.method=method
51 self.mess=mess
53 self.mess=mess
52
54
53 def __str__(self):
55 def __str__(self):
54 return """The implementation of %(method)s violates its contract
56 return """The implementation of %(method)s violates its contract
55 because %(mess)s.
57 because %(mess)s.
56 """ % self.__dict__
58 """ % self.__dict__
57
59
58 class InvalidInterface(Exception):
60 class InvalidInterface(Exception):
59 """The interface has invalid contents
61 """The interface has invalid contents
60 """
62 """
61
63
62 class BadImplements(TypeError):
64 class BadImplements(TypeError):
63 """An implementation assertion is invalid
65 """An implementation assertion is invalid
64
66
65 because it doesn't contain an interface or a sequence of valid
67 because it doesn't contain an interface or a sequence of valid
66 implementation assertions.
68 implementation assertions.
67 """
69 """
@@ -1,686 +1,686 b''
1 ##############################################################################
1 ##############################################################################
2 #
2 #
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """Interface object implementation
14 """Interface object implementation
15 """
15 """
16 from __future__ import generators
16 from __future__ import absolute_import, generators
17
17
18 import sys
18 import sys
19 from types import MethodType
19 from types import MethodType
20 from types import FunctionType
20 from types import FunctionType
21 import warnings
21 import warnings
22 import weakref
22 import weakref
23
23
24 from zope.interface.exceptions import Invalid
24 from .exceptions import Invalid
25 from zope.interface.ro import ro
25 from .ro import ro
26
26
27
27
28 CO_VARARGS = 4
28 CO_VARARGS = 4
29 CO_VARKEYWORDS = 8
29 CO_VARKEYWORDS = 8
30 TAGGED_DATA = '__interface_tagged_values__'
30 TAGGED_DATA = '__interface_tagged_values__'
31
31
32 _decorator_non_return = object()
32 _decorator_non_return = object()
33
33
34 def invariant(call):
34 def invariant(call):
35 f_locals = sys._getframe(1).f_locals
35 f_locals = sys._getframe(1).f_locals
36 tags = f_locals.setdefault(TAGGED_DATA, {})
36 tags = f_locals.setdefault(TAGGED_DATA, {})
37 invariants = tags.setdefault('invariants', [])
37 invariants = tags.setdefault('invariants', [])
38 invariants.append(call)
38 invariants.append(call)
39 return _decorator_non_return
39 return _decorator_non_return
40
40
41
41
42 def taggedValue(key, value):
42 def taggedValue(key, value):
43 """Attaches a tagged value to an interface at definition time."""
43 """Attaches a tagged value to an interface at definition time."""
44 f_locals = sys._getframe(1).f_locals
44 f_locals = sys._getframe(1).f_locals
45 tagged_values = f_locals.setdefault(TAGGED_DATA, {})
45 tagged_values = f_locals.setdefault(TAGGED_DATA, {})
46 tagged_values[key] = value
46 tagged_values[key] = value
47 return _decorator_non_return
47 return _decorator_non_return
48
48
49
49
50 class Element(object):
50 class Element(object):
51
51
52 # We can't say this yet because we don't have enough
52 # We can't say this yet because we don't have enough
53 # infrastructure in place.
53 # infrastructure in place.
54 #
54 #
55 #implements(IElement)
55 #implements(IElement)
56
56
57 def __init__(self, __name__, __doc__=''):
57 def __init__(self, __name__, __doc__=''):
58 """Create an 'attribute' description
58 """Create an 'attribute' description
59 """
59 """
60 if not __doc__ and __name__.find(' ') >= 0:
60 if not __doc__ and __name__.find(' ') >= 0:
61 __doc__ = __name__
61 __doc__ = __name__
62 __name__ = None
62 __name__ = None
63
63
64 self.__name__=__name__
64 self.__name__=__name__
65 self.__doc__=__doc__
65 self.__doc__=__doc__
66 self.__tagged_values = {}
66 self.__tagged_values = {}
67
67
68 def getName(self):
68 def getName(self):
69 """ Returns the name of the object. """
69 """ Returns the name of the object. """
70 return self.__name__
70 return self.__name__
71
71
72 def getDoc(self):
72 def getDoc(self):
73 """ Returns the documentation for the object. """
73 """ Returns the documentation for the object. """
74 return self.__doc__
74 return self.__doc__
75
75
76 def getTaggedValue(self, tag):
76 def getTaggedValue(self, tag):
77 """ Returns the value associated with 'tag'. """
77 """ Returns the value associated with 'tag'. """
78 return self.__tagged_values[tag]
78 return self.__tagged_values[tag]
79
79
80 def queryTaggedValue(self, tag, default=None):
80 def queryTaggedValue(self, tag, default=None):
81 """ Returns the value associated with 'tag'. """
81 """ Returns the value associated with 'tag'. """
82 return self.__tagged_values.get(tag, default)
82 return self.__tagged_values.get(tag, default)
83
83
84 def getTaggedValueTags(self):
84 def getTaggedValueTags(self):
85 """ Returns a list of all tags. """
85 """ Returns a list of all tags. """
86 return self.__tagged_values.keys()
86 return self.__tagged_values.keys()
87
87
88 def setTaggedValue(self, tag, value):
88 def setTaggedValue(self, tag, value):
89 """ Associates 'value' with 'key'. """
89 """ Associates 'value' with 'key'. """
90 self.__tagged_values[tag] = value
90 self.__tagged_values[tag] = value
91
91
92 class SpecificationBasePy(object):
92 class SpecificationBasePy(object):
93
93
94 def providedBy(self, ob):
94 def providedBy(self, ob):
95 """Is the interface implemented by an object
95 """Is the interface implemented by an object
96 """
96 """
97 spec = providedBy(ob)
97 spec = providedBy(ob)
98 return self in spec._implied
98 return self in spec._implied
99
99
100 def implementedBy(self, cls):
100 def implementedBy(self, cls):
101 """Test whether the specification is implemented by a class or factory.
101 """Test whether the specification is implemented by a class or factory.
102
102
103 Raise TypeError if argument is neither a class nor a callable.
103 Raise TypeError if argument is neither a class nor a callable.
104 """
104 """
105 spec = implementedBy(cls)
105 spec = implementedBy(cls)
106 return self in spec._implied
106 return self in spec._implied
107
107
108 def isOrExtends(self, interface):
108 def isOrExtends(self, interface):
109 """Is the interface the same as or extend the given interface
109 """Is the interface the same as or extend the given interface
110 """
110 """
111 return interface in self._implied
111 return interface in self._implied
112
112
113 __call__ = isOrExtends
113 __call__ = isOrExtends
114
114
115 SpecificationBase = SpecificationBasePy
115 SpecificationBase = SpecificationBasePy
116 try:
116 try:
117 from zope.interface._zope_interface_coptimizations import SpecificationBase
117 from ._zope_interface_coptimizations import SpecificationBase
118 except ImportError:
118 except ImportError:
119 pass
119 pass
120
120
121 _marker = object()
121 _marker = object()
122 class InterfaceBasePy(object):
122 class InterfaceBasePy(object):
123 """Base class that wants to be replaced with a C base :)
123 """Base class that wants to be replaced with a C base :)
124 """
124 """
125
125
126 def __call__(self, obj, alternate=_marker):
126 def __call__(self, obj, alternate=_marker):
127 """Adapt an object to the interface
127 """Adapt an object to the interface
128 """
128 """
129 conform = getattr(obj, '__conform__', None)
129 conform = getattr(obj, '__conform__', None)
130 if conform is not None:
130 if conform is not None:
131 adapter = self._call_conform(conform)
131 adapter = self._call_conform(conform)
132 if adapter is not None:
132 if adapter is not None:
133 return adapter
133 return adapter
134
134
135 adapter = self.__adapt__(obj)
135 adapter = self.__adapt__(obj)
136
136
137 if adapter is not None:
137 if adapter is not None:
138 return adapter
138 return adapter
139 elif alternate is not _marker:
139 elif alternate is not _marker:
140 return alternate
140 return alternate
141 else:
141 else:
142 raise TypeError("Could not adapt", obj, self)
142 raise TypeError("Could not adapt", obj, self)
143
143
144 def __adapt__(self, obj):
144 def __adapt__(self, obj):
145 """Adapt an object to the reciever
145 """Adapt an object to the reciever
146 """
146 """
147 if self.providedBy(obj):
147 if self.providedBy(obj):
148 return obj
148 return obj
149
149
150 for hook in adapter_hooks:
150 for hook in adapter_hooks:
151 adapter = hook(self, obj)
151 adapter = hook(self, obj)
152 if adapter is not None:
152 if adapter is not None:
153 return adapter
153 return adapter
154
154
155
155
156 InterfaceBase = InterfaceBasePy
156 InterfaceBase = InterfaceBasePy
157 try:
157 try:
158 from zope.interface._zope_interface_coptimizations import InterfaceBase
158 from ._zope_interface_coptimizations import InterfaceBase
159 except ImportError:
159 except ImportError:
160 pass
160 pass
161
161
162
162
163 adapter_hooks = []
163 adapter_hooks = []
164 try:
164 try:
165 from zope.interface._zope_interface_coptimizations import adapter_hooks
165 from ._zope_interface_coptimizations import adapter_hooks
166 except ImportError:
166 except ImportError:
167 pass
167 pass
168
168
169
169
170 class Specification(SpecificationBase):
170 class Specification(SpecificationBase):
171 """Specifications
171 """Specifications
172
172
173 An interface specification is used to track interface declarations
173 An interface specification is used to track interface declarations
174 and component registrations.
174 and component registrations.
175
175
176 This class is a base class for both interfaces themselves and for
176 This class is a base class for both interfaces themselves and for
177 interface specifications (declarations).
177 interface specifications (declarations).
178
178
179 Specifications are mutable. If you reassign their bases, their
179 Specifications are mutable. If you reassign their bases, their
180 relations with other specifications are adjusted accordingly.
180 relations with other specifications are adjusted accordingly.
181 """
181 """
182
182
183 # Copy some base class methods for speed
183 # Copy some base class methods for speed
184 isOrExtends = SpecificationBase.isOrExtends
184 isOrExtends = SpecificationBase.isOrExtends
185 providedBy = SpecificationBase.providedBy
185 providedBy = SpecificationBase.providedBy
186
186
187 def __init__(self, bases=()):
187 def __init__(self, bases=()):
188 self._implied = {}
188 self._implied = {}
189 self.dependents = weakref.WeakKeyDictionary()
189 self.dependents = weakref.WeakKeyDictionary()
190 self.__bases__ = tuple(bases)
190 self.__bases__ = tuple(bases)
191
191
192 def subscribe(self, dependent):
192 def subscribe(self, dependent):
193 self.dependents[dependent] = self.dependents.get(dependent, 0) + 1
193 self.dependents[dependent] = self.dependents.get(dependent, 0) + 1
194
194
195 def unsubscribe(self, dependent):
195 def unsubscribe(self, dependent):
196 n = self.dependents.get(dependent, 0) - 1
196 n = self.dependents.get(dependent, 0) - 1
197 if not n:
197 if not n:
198 del self.dependents[dependent]
198 del self.dependents[dependent]
199 elif n > 0:
199 elif n > 0:
200 self.dependents[dependent] = n
200 self.dependents[dependent] = n
201 else:
201 else:
202 raise KeyError(dependent)
202 raise KeyError(dependent)
203
203
204 def __setBases(self, bases):
204 def __setBases(self, bases):
205 # Register ourselves as a dependent of our old bases
205 # Register ourselves as a dependent of our old bases
206 for b in self.__bases__:
206 for b in self.__bases__:
207 b.unsubscribe(self)
207 b.unsubscribe(self)
208
208
209 # Register ourselves as a dependent of our bases
209 # Register ourselves as a dependent of our bases
210 self.__dict__['__bases__'] = bases
210 self.__dict__['__bases__'] = bases
211 for b in bases:
211 for b in bases:
212 b.subscribe(self)
212 b.subscribe(self)
213
213
214 self.changed(self)
214 self.changed(self)
215
215
216 __bases__ = property(
216 __bases__ = property(
217
217
218 lambda self: self.__dict__.get('__bases__', ()),
218 lambda self: self.__dict__.get('__bases__', ()),
219 __setBases,
219 __setBases,
220 )
220 )
221
221
222 def changed(self, originally_changed):
222 def changed(self, originally_changed):
223 """We, or something we depend on, have changed
223 """We, or something we depend on, have changed
224 """
224 """
225 try:
225 try:
226 del self._v_attrs
226 del self._v_attrs
227 except AttributeError:
227 except AttributeError:
228 pass
228 pass
229
229
230 implied = self._implied
230 implied = self._implied
231 implied.clear()
231 implied.clear()
232
232
233 ancestors = ro(self)
233 ancestors = ro(self)
234
234
235 try:
235 try:
236 if Interface not in ancestors:
236 if Interface not in ancestors:
237 ancestors.append(Interface)
237 ancestors.append(Interface)
238 except NameError:
238 except NameError:
239 pass # defining Interface itself
239 pass # defining Interface itself
240
240
241 self.__sro__ = tuple(ancestors)
241 self.__sro__ = tuple(ancestors)
242 self.__iro__ = tuple([ancestor for ancestor in ancestors
242 self.__iro__ = tuple([ancestor for ancestor in ancestors
243 if isinstance(ancestor, InterfaceClass)
243 if isinstance(ancestor, InterfaceClass)
244 ])
244 ])
245
245
246 for ancestor in ancestors:
246 for ancestor in ancestors:
247 # We directly imply our ancestors:
247 # We directly imply our ancestors:
248 implied[ancestor] = ()
248 implied[ancestor] = ()
249
249
250 # Now, advise our dependents of change:
250 # Now, advise our dependents of change:
251 for dependent in tuple(self.dependents.keys()):
251 for dependent in tuple(self.dependents.keys()):
252 dependent.changed(originally_changed)
252 dependent.changed(originally_changed)
253
253
254
254
255 def interfaces(self):
255 def interfaces(self):
256 """Return an iterator for the interfaces in the specification.
256 """Return an iterator for the interfaces in the specification.
257 """
257 """
258 seen = {}
258 seen = {}
259 for base in self.__bases__:
259 for base in self.__bases__:
260 for interface in base.interfaces():
260 for interface in base.interfaces():
261 if interface not in seen:
261 if interface not in seen:
262 seen[interface] = 1
262 seen[interface] = 1
263 yield interface
263 yield interface
264
264
265
265
266 def extends(self, interface, strict=True):
266 def extends(self, interface, strict=True):
267 """Does the specification extend the given interface?
267 """Does the specification extend the given interface?
268
268
269 Test whether an interface in the specification extends the
269 Test whether an interface in the specification extends the
270 given interface
270 given interface
271 """
271 """
272 return ((interface in self._implied)
272 return ((interface in self._implied)
273 and
273 and
274 ((not strict) or (self != interface))
274 ((not strict) or (self != interface))
275 )
275 )
276
276
277 def weakref(self, callback=None):
277 def weakref(self, callback=None):
278 return weakref.ref(self, callback)
278 return weakref.ref(self, callback)
279
279
280 def get(self, name, default=None):
280 def get(self, name, default=None):
281 """Query for an attribute description
281 """Query for an attribute description
282 """
282 """
283 try:
283 try:
284 attrs = self._v_attrs
284 attrs = self._v_attrs
285 except AttributeError:
285 except AttributeError:
286 attrs = self._v_attrs = {}
286 attrs = self._v_attrs = {}
287 attr = attrs.get(name)
287 attr = attrs.get(name)
288 if attr is None:
288 if attr is None:
289 for iface in self.__iro__:
289 for iface in self.__iro__:
290 attr = iface.direct(name)
290 attr = iface.direct(name)
291 if attr is not None:
291 if attr is not None:
292 attrs[name] = attr
292 attrs[name] = attr
293 break
293 break
294
294
295 if attr is None:
295 if attr is None:
296 return default
296 return default
297 else:
297 else:
298 return attr
298 return attr
299
299
300 class InterfaceClass(Element, InterfaceBase, Specification):
300 class InterfaceClass(Element, InterfaceBase, Specification):
301 """Prototype (scarecrow) Interfaces Implementation."""
301 """Prototype (scarecrow) Interfaces Implementation."""
302
302
303 # We can't say this yet because we don't have enough
303 # We can't say this yet because we don't have enough
304 # infrastructure in place.
304 # infrastructure in place.
305 #
305 #
306 #implements(IInterface)
306 #implements(IInterface)
307
307
308 def __init__(self, name, bases=(), attrs=None, __doc__=None,
308 def __init__(self, name, bases=(), attrs=None, __doc__=None,
309 __module__=None):
309 __module__=None):
310
310
311 if attrs is None:
311 if attrs is None:
312 attrs = {}
312 attrs = {}
313
313
314 if __module__ is None:
314 if __module__ is None:
315 __module__ = attrs.get('__module__')
315 __module__ = attrs.get('__module__')
316 if isinstance(__module__, str):
316 if isinstance(__module__, str):
317 del attrs['__module__']
317 del attrs['__module__']
318 else:
318 else:
319 try:
319 try:
320 # Figure out what module defined the interface.
320 # Figure out what module defined the interface.
321 # This is how cPython figures out the module of
321 # This is how cPython figures out the module of
322 # a class, but of course it does it in C. :-/
322 # a class, but of course it does it in C. :-/
323 __module__ = sys._getframe(1).f_globals['__name__']
323 __module__ = sys._getframe(1).f_globals['__name__']
324 except (AttributeError, KeyError): # pragma: no cover
324 except (AttributeError, KeyError): # pragma: no cover
325 pass
325 pass
326
326
327 self.__module__ = __module__
327 self.__module__ = __module__
328
328
329 d = attrs.get('__doc__')
329 d = attrs.get('__doc__')
330 if d is not None:
330 if d is not None:
331 if not isinstance(d, Attribute):
331 if not isinstance(d, Attribute):
332 if __doc__ is None:
332 if __doc__ is None:
333 __doc__ = d
333 __doc__ = d
334 del attrs['__doc__']
334 del attrs['__doc__']
335
335
336 if __doc__ is None:
336 if __doc__ is None:
337 __doc__ = ''
337 __doc__ = ''
338
338
339 Element.__init__(self, name, __doc__)
339 Element.__init__(self, name, __doc__)
340
340
341 tagged_data = attrs.pop(TAGGED_DATA, None)
341 tagged_data = attrs.pop(TAGGED_DATA, None)
342 if tagged_data is not None:
342 if tagged_data is not None:
343 for key, val in tagged_data.items():
343 for key, val in tagged_data.items():
344 self.setTaggedValue(key, val)
344 self.setTaggedValue(key, val)
345
345
346 for base in bases:
346 for base in bases:
347 if not isinstance(base, InterfaceClass):
347 if not isinstance(base, InterfaceClass):
348 raise TypeError('Expected base interfaces')
348 raise TypeError('Expected base interfaces')
349
349
350 Specification.__init__(self, bases)
350 Specification.__init__(self, bases)
351
351
352 # Make sure that all recorded attributes (and methods) are of type
352 # Make sure that all recorded attributes (and methods) are of type
353 # `Attribute` and `Method`
353 # `Attribute` and `Method`
354 for name, attr in list(attrs.items()):
354 for name, attr in list(attrs.items()):
355 if name in ('__locals__', '__qualname__', '__annotations__'):
355 if name in ('__locals__', '__qualname__', '__annotations__'):
356 # __locals__: Python 3 sometimes adds this.
356 # __locals__: Python 3 sometimes adds this.
357 # __qualname__: PEP 3155 (Python 3.3+)
357 # __qualname__: PEP 3155 (Python 3.3+)
358 # __annotations__: PEP 3107 (Python 3.0+)
358 # __annotations__: PEP 3107 (Python 3.0+)
359 del attrs[name]
359 del attrs[name]
360 continue
360 continue
361 if isinstance(attr, Attribute):
361 if isinstance(attr, Attribute):
362 attr.interface = self
362 attr.interface = self
363 if not attr.__name__:
363 if not attr.__name__:
364 attr.__name__ = name
364 attr.__name__ = name
365 elif isinstance(attr, FunctionType):
365 elif isinstance(attr, FunctionType):
366 attrs[name] = fromFunction(attr, self, name=name)
366 attrs[name] = fromFunction(attr, self, name=name)
367 elif attr is _decorator_non_return:
367 elif attr is _decorator_non_return:
368 del attrs[name]
368 del attrs[name]
369 else:
369 else:
370 raise InvalidInterface("Concrete attribute, " + name)
370 raise InvalidInterface("Concrete attribute, " + name)
371
371
372 self.__attrs = attrs
372 self.__attrs = attrs
373
373
374 self.__identifier__ = "%s.%s" % (self.__module__, self.__name__)
374 self.__identifier__ = "%s.%s" % (self.__module__, self.__name__)
375
375
376 def interfaces(self):
376 def interfaces(self):
377 """Return an iterator for the interfaces in the specification.
377 """Return an iterator for the interfaces in the specification.
378 """
378 """
379 yield self
379 yield self
380
380
381 def getBases(self):
381 def getBases(self):
382 return self.__bases__
382 return self.__bases__
383
383
384 def isEqualOrExtendedBy(self, other):
384 def isEqualOrExtendedBy(self, other):
385 """Same interface or extends?"""
385 """Same interface or extends?"""
386 return self == other or other.extends(self)
386 return self == other or other.extends(self)
387
387
388 def names(self, all=False):
388 def names(self, all=False):
389 """Return the attribute names defined by the interface."""
389 """Return the attribute names defined by the interface."""
390 if not all:
390 if not all:
391 return self.__attrs.keys()
391 return self.__attrs.keys()
392
392
393 r = self.__attrs.copy()
393 r = self.__attrs.copy()
394
394
395 for base in self.__bases__:
395 for base in self.__bases__:
396 r.update(dict.fromkeys(base.names(all)))
396 r.update(dict.fromkeys(base.names(all)))
397
397
398 return r.keys()
398 return r.keys()
399
399
400 def __iter__(self):
400 def __iter__(self):
401 return iter(self.names(all=True))
401 return iter(self.names(all=True))
402
402
403 def namesAndDescriptions(self, all=False):
403 def namesAndDescriptions(self, all=False):
404 """Return attribute names and descriptions defined by interface."""
404 """Return attribute names and descriptions defined by interface."""
405 if not all:
405 if not all:
406 return self.__attrs.items()
406 return self.__attrs.items()
407
407
408 r = {}
408 r = {}
409 for base in self.__bases__[::-1]:
409 for base in self.__bases__[::-1]:
410 r.update(dict(base.namesAndDescriptions(all)))
410 r.update(dict(base.namesAndDescriptions(all)))
411
411
412 r.update(self.__attrs)
412 r.update(self.__attrs)
413
413
414 return r.items()
414 return r.items()
415
415
416 def getDescriptionFor(self, name):
416 def getDescriptionFor(self, name):
417 """Return the attribute description for the given name."""
417 """Return the attribute description for the given name."""
418 r = self.get(name)
418 r = self.get(name)
419 if r is not None:
419 if r is not None:
420 return r
420 return r
421
421
422 raise KeyError(name)
422 raise KeyError(name)
423
423
424 __getitem__ = getDescriptionFor
424 __getitem__ = getDescriptionFor
425
425
426 def __contains__(self, name):
426 def __contains__(self, name):
427 return self.get(name) is not None
427 return self.get(name) is not None
428
428
429 def direct(self, name):
429 def direct(self, name):
430 return self.__attrs.get(name)
430 return self.__attrs.get(name)
431
431
432 def queryDescriptionFor(self, name, default=None):
432 def queryDescriptionFor(self, name, default=None):
433 return self.get(name, default)
433 return self.get(name, default)
434
434
435 def validateInvariants(self, obj, errors=None):
435 def validateInvariants(self, obj, errors=None):
436 """validate object to defined invariants."""
436 """validate object to defined invariants."""
437 for call in self.queryTaggedValue('invariants', []):
437 for call in self.queryTaggedValue('invariants', []):
438 try:
438 try:
439 call(obj)
439 call(obj)
440 except Invalid as e:
440 except Invalid as e:
441 if errors is None:
441 if errors is None:
442 raise
442 raise
443 else:
443 else:
444 errors.append(e)
444 errors.append(e)
445 for base in self.__bases__:
445 for base in self.__bases__:
446 try:
446 try:
447 base.validateInvariants(obj, errors)
447 base.validateInvariants(obj, errors)
448 except Invalid:
448 except Invalid:
449 if errors is None:
449 if errors is None:
450 raise
450 raise
451 if errors:
451 if errors:
452 raise Invalid(errors)
452 raise Invalid(errors)
453
453
454 def __repr__(self): # pragma: no cover
454 def __repr__(self): # pragma: no cover
455 try:
455 try:
456 return self._v_repr
456 return self._v_repr
457 except AttributeError:
457 except AttributeError:
458 name = self.__name__
458 name = self.__name__
459 m = self.__module__
459 m = self.__module__
460 if m:
460 if m:
461 name = '%s.%s' % (m, name)
461 name = '%s.%s' % (m, name)
462 r = "<%s %s>" % (self.__class__.__name__, name)
462 r = "<%s %s>" % (self.__class__.__name__, name)
463 self._v_repr = r
463 self._v_repr = r
464 return r
464 return r
465
465
466 def _call_conform(self, conform):
466 def _call_conform(self, conform):
467 try:
467 try:
468 return conform(self)
468 return conform(self)
469 except TypeError: # pragma: no cover
469 except TypeError: # pragma: no cover
470 # We got a TypeError. It might be an error raised by
470 # We got a TypeError. It might be an error raised by
471 # the __conform__ implementation, or *we* may have
471 # the __conform__ implementation, or *we* may have
472 # made the TypeError by calling an unbound method
472 # made the TypeError by calling an unbound method
473 # (object is a class). In the later case, we behave
473 # (object is a class). In the later case, we behave
474 # as though there is no __conform__ method. We can
474 # as though there is no __conform__ method. We can
475 # detect this case by checking whether there is more
475 # detect this case by checking whether there is more
476 # than one traceback object in the traceback chain:
476 # than one traceback object in the traceback chain:
477 if sys.exc_info()[2].tb_next is not None:
477 if sys.exc_info()[2].tb_next is not None:
478 # There is more than one entry in the chain, so
478 # There is more than one entry in the chain, so
479 # reraise the error:
479 # reraise the error:
480 raise
480 raise
481 # This clever trick is from Phillip Eby
481 # This clever trick is from Phillip Eby
482
482
483 return None # pragma: no cover
483 return None # pragma: no cover
484
484
485 def __reduce__(self):
485 def __reduce__(self):
486 return self.__name__
486 return self.__name__
487
487
488 def __cmp(self, other):
488 def __cmp(self, other):
489 # Yes, I did mean to name this __cmp, rather than __cmp__.
489 # Yes, I did mean to name this __cmp, rather than __cmp__.
490 # It is a private method used by __lt__ and __gt__.
490 # It is a private method used by __lt__ and __gt__.
491 # I don't want to override __eq__ because I want the default
491 # I don't want to override __eq__ because I want the default
492 # __eq__, which is really fast.
492 # __eq__, which is really fast.
493 """Make interfaces sortable
493 """Make interfaces sortable
494
494
495 TODO: It would ne nice if:
495 TODO: It would ne nice if:
496
496
497 More specific interfaces should sort before less specific ones.
497 More specific interfaces should sort before less specific ones.
498 Otherwise, sort on name and module.
498 Otherwise, sort on name and module.
499
499
500 But this is too complicated, and we're going to punt on it
500 But this is too complicated, and we're going to punt on it
501 for now.
501 for now.
502
502
503 For now, sort on interface and module name.
503 For now, sort on interface and module name.
504
504
505 None is treated as a pseudo interface that implies the loosest
505 None is treated as a pseudo interface that implies the loosest
506 contact possible, no contract. For that reason, all interfaces
506 contact possible, no contract. For that reason, all interfaces
507 sort before None.
507 sort before None.
508
508
509 """
509 """
510 if other is None:
510 if other is None:
511 return -1
511 return -1
512
512
513 n1 = (getattr(self, '__name__', ''), getattr(self, '__module__', ''))
513 n1 = (getattr(self, '__name__', ''), getattr(self, '__module__', ''))
514 n2 = (getattr(other, '__name__', ''), getattr(other, '__module__', ''))
514 n2 = (getattr(other, '__name__', ''), getattr(other, '__module__', ''))
515
515
516 # This spelling works under Python3, which doesn't have cmp().
516 # This spelling works under Python3, which doesn't have cmp().
517 return (n1 > n2) - (n1 < n2)
517 return (n1 > n2) - (n1 < n2)
518
518
519 def __hash__(self):
519 def __hash__(self):
520 d = self.__dict__
520 d = self.__dict__
521 if '__module__' not in d or '__name__' not in d: # pragma: no cover
521 if '__module__' not in d or '__name__' not in d: # pragma: no cover
522 warnings.warn('Hashing uninitialized InterfaceClass instance')
522 warnings.warn('Hashing uninitialized InterfaceClass instance')
523 return 1
523 return 1
524 return hash((self.__name__, self.__module__))
524 return hash((self.__name__, self.__module__))
525
525
526 def __eq__(self, other):
526 def __eq__(self, other):
527 c = self.__cmp(other)
527 c = self.__cmp(other)
528 return c == 0
528 return c == 0
529
529
530 def __ne__(self, other):
530 def __ne__(self, other):
531 c = self.__cmp(other)
531 c = self.__cmp(other)
532 return c != 0
532 return c != 0
533
533
534 def __lt__(self, other):
534 def __lt__(self, other):
535 c = self.__cmp(other)
535 c = self.__cmp(other)
536 return c < 0
536 return c < 0
537
537
538 def __le__(self, other):
538 def __le__(self, other):
539 c = self.__cmp(other)
539 c = self.__cmp(other)
540 return c <= 0
540 return c <= 0
541
541
542 def __gt__(self, other):
542 def __gt__(self, other):
543 c = self.__cmp(other)
543 c = self.__cmp(other)
544 return c > 0
544 return c > 0
545
545
546 def __ge__(self, other):
546 def __ge__(self, other):
547 c = self.__cmp(other)
547 c = self.__cmp(other)
548 return c >= 0
548 return c >= 0
549
549
550
550
551 Interface = InterfaceClass("Interface", __module__ = 'zope.interface')
551 Interface = InterfaceClass("Interface", __module__ = 'zope.interface')
552
552
553 class Attribute(Element):
553 class Attribute(Element):
554 """Attribute descriptions
554 """Attribute descriptions
555 """
555 """
556
556
557 # We can't say this yet because we don't have enough
557 # We can't say this yet because we don't have enough
558 # infrastructure in place.
558 # infrastructure in place.
559 #
559 #
560 # implements(IAttribute)
560 # implements(IAttribute)
561
561
562 interface = None
562 interface = None
563
563
564
564
565 class Method(Attribute):
565 class Method(Attribute):
566 """Method interfaces
566 """Method interfaces
567
567
568 The idea here is that you have objects that describe methods.
568 The idea here is that you have objects that describe methods.
569 This provides an opportunity for rich meta-data.
569 This provides an opportunity for rich meta-data.
570 """
570 """
571
571
572 # We can't say this yet because we don't have enough
572 # We can't say this yet because we don't have enough
573 # infrastructure in place.
573 # infrastructure in place.
574 #
574 #
575 # implements(IMethod)
575 # implements(IMethod)
576
576
577 positional = required = ()
577 positional = required = ()
578 _optional = varargs = kwargs = None
578 _optional = varargs = kwargs = None
579 def _get_optional(self):
579 def _get_optional(self):
580 if self._optional is None:
580 if self._optional is None:
581 return {}
581 return {}
582 return self._optional
582 return self._optional
583 def _set_optional(self, opt):
583 def _set_optional(self, opt):
584 self._optional = opt
584 self._optional = opt
585 def _del_optional(self):
585 def _del_optional(self):
586 self._optional = None
586 self._optional = None
587 optional = property(_get_optional, _set_optional, _del_optional)
587 optional = property(_get_optional, _set_optional, _del_optional)
588
588
589 def __call__(self, *args, **kw):
589 def __call__(self, *args, **kw):
590 raise BrokenImplementation(self.interface, self.__name__)
590 raise BrokenImplementation(self.interface, self.__name__)
591
591
592 def getSignatureInfo(self):
592 def getSignatureInfo(self):
593 return {'positional': self.positional,
593 return {'positional': self.positional,
594 'required': self.required,
594 'required': self.required,
595 'optional': self.optional,
595 'optional': self.optional,
596 'varargs': self.varargs,
596 'varargs': self.varargs,
597 'kwargs': self.kwargs,
597 'kwargs': self.kwargs,
598 }
598 }
599
599
600 def getSignatureString(self):
600 def getSignatureString(self):
601 sig = []
601 sig = []
602 for v in self.positional:
602 for v in self.positional:
603 sig.append(v)
603 sig.append(v)
604 if v in self.optional.keys():
604 if v in self.optional.keys():
605 sig[-1] += "=" + repr(self.optional[v])
605 sig[-1] += "=" + repr(self.optional[v])
606 if self.varargs:
606 if self.varargs:
607 sig.append("*" + self.varargs)
607 sig.append("*" + self.varargs)
608 if self.kwargs:
608 if self.kwargs:
609 sig.append("**" + self.kwargs)
609 sig.append("**" + self.kwargs)
610
610
611 return "(%s)" % ", ".join(sig)
611 return "(%s)" % ", ".join(sig)
612
612
613 def fromFunction(func, interface=None, imlevel=0, name=None):
613 def fromFunction(func, interface=None, imlevel=0, name=None):
614 name = name or func.__name__
614 name = name or func.__name__
615 method = Method(name, func.__doc__)
615 method = Method(name, func.__doc__)
616 defaults = getattr(func, '__defaults__', None) or ()
616 defaults = getattr(func, '__defaults__', None) or ()
617 code = func.__code__
617 code = func.__code__
618 # Number of positional arguments
618 # Number of positional arguments
619 na = code.co_argcount-imlevel
619 na = code.co_argcount-imlevel
620 names = code.co_varnames[imlevel:]
620 names = code.co_varnames[imlevel:]
621 opt = {}
621 opt = {}
622 # Number of required arguments
622 # Number of required arguments
623 nr = na-len(defaults)
623 nr = na-len(defaults)
624 if nr < 0:
624 if nr < 0:
625 defaults=defaults[-nr:]
625 defaults=defaults[-nr:]
626 nr = 0
626 nr = 0
627
627
628 # Determine the optional arguments.
628 # Determine the optional arguments.
629 opt.update(dict(zip(names[nr:], defaults)))
629 opt.update(dict(zip(names[nr:], defaults)))
630
630
631 method.positional = names[:na]
631 method.positional = names[:na]
632 method.required = names[:nr]
632 method.required = names[:nr]
633 method.optional = opt
633 method.optional = opt
634
634
635 argno = na
635 argno = na
636
636
637 # Determine the function's variable argument's name (i.e. *args)
637 # Determine the function's variable argument's name (i.e. *args)
638 if code.co_flags & CO_VARARGS:
638 if code.co_flags & CO_VARARGS:
639 method.varargs = names[argno]
639 method.varargs = names[argno]
640 argno = argno + 1
640 argno = argno + 1
641 else:
641 else:
642 method.varargs = None
642 method.varargs = None
643
643
644 # Determine the function's keyword argument's name (i.e. **kw)
644 # Determine the function's keyword argument's name (i.e. **kw)
645 if code.co_flags & CO_VARKEYWORDS:
645 if code.co_flags & CO_VARKEYWORDS:
646 method.kwargs = names[argno]
646 method.kwargs = names[argno]
647 else:
647 else:
648 method.kwargs = None
648 method.kwargs = None
649
649
650 method.interface = interface
650 method.interface = interface
651
651
652 for key, value in func.__dict__.items():
652 for key, value in func.__dict__.items():
653 method.setTaggedValue(key, value)
653 method.setTaggedValue(key, value)
654
654
655 return method
655 return method
656
656
657
657
658 def fromMethod(meth, interface=None, name=None):
658 def fromMethod(meth, interface=None, name=None):
659 if isinstance(meth, MethodType):
659 if isinstance(meth, MethodType):
660 func = meth.__func__
660 func = meth.__func__
661 else:
661 else:
662 func = meth
662 func = meth
663 return fromFunction(func, interface, imlevel=1, name=name)
663 return fromFunction(func, interface, imlevel=1, name=name)
664
664
665
665
666 # Now we can create the interesting interfaces and wire them up:
666 # Now we can create the interesting interfaces and wire them up:
667 def _wire():
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 classImplements(Attribute, IAttribute)
671 classImplements(Attribute, IAttribute)
672
672
673 from zope.interface.interfaces import IMethod
673 from .interfaces import IMethod
674 classImplements(Method, IMethod)
674 classImplements(Method, IMethod)
675
675
676 from zope.interface.interfaces import IInterface
676 from .interfaces import IInterface
677 classImplements(InterfaceClass, IInterface)
677 classImplements(InterfaceClass, IInterface)
678
678
679 from zope.interface.interfaces import ISpecification
679 from .interfaces import ISpecification
680 classImplements(Specification, ISpecification)
680 classImplements(Specification, ISpecification)
681
681
682 # We import this here to deal with module dependencies.
682 # We import this here to deal with module dependencies.
683 from zope.interface.declarations import implementedBy
683 from .declarations import implementedBy
684 from zope.interface.declarations import providedBy
684 from .declarations import providedBy
685 from zope.interface.exceptions import InvalidInterface
685 from .exceptions import InvalidInterface
686 from zope.interface.exceptions import BrokenImplementation
686 from .exceptions import BrokenImplementation
@@ -1,1294 +1,1297 b''
1 ##############################################################################
1 ##############################################################################
2 #
2 #
3 # Copyright (c) 2002 Zope Foundation and Contributors.
3 # Copyright (c) 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """Interface Package Interfaces
14 """Interface Package Interfaces
15 """
15 """
16
17 from __future__ import absolute_import
18
16 __docformat__ = 'restructuredtext'
19 __docformat__ = 'restructuredtext'
17
20
18 from zope.interface.interface import Attribute
21 from .interface import Attribute
19 from zope.interface.interface import Interface
22 from .interface import Interface
20 from zope.interface.declarations import implementer
23 from .declarations import implementer
21
24
22
25
23 _BLANK = u''
26 _BLANK = u''
24
27
25 class IElement(Interface):
28 class IElement(Interface):
26 """Objects that have basic documentation and tagged values.
29 """Objects that have basic documentation and tagged values.
27 """
30 """
28
31
29 __name__ = Attribute('__name__', 'The object name')
32 __name__ = Attribute('__name__', 'The object name')
30 __doc__ = Attribute('__doc__', 'The object doc string')
33 __doc__ = Attribute('__doc__', 'The object doc string')
31
34
32 def getTaggedValue(tag):
35 def getTaggedValue(tag):
33 """Returns the value associated with `tag`.
36 """Returns the value associated with `tag`.
34
37
35 Raise a `KeyError` of the tag isn't set.
38 Raise a `KeyError` of the tag isn't set.
36 """
39 """
37
40
38 def queryTaggedValue(tag, default=None):
41 def queryTaggedValue(tag, default=None):
39 """Returns the value associated with `tag`.
42 """Returns the value associated with `tag`.
40
43
41 Return the default value of the tag isn't set.
44 Return the default value of the tag isn't set.
42 """
45 """
43
46
44 def getTaggedValueTags():
47 def getTaggedValueTags():
45 """Returns a list of all tags."""
48 """Returns a list of all tags."""
46
49
47 def setTaggedValue(tag, value):
50 def setTaggedValue(tag, value):
48 """Associates `value` with `key`."""
51 """Associates `value` with `key`."""
49
52
50
53
51 class IAttribute(IElement):
54 class IAttribute(IElement):
52 """Attribute descriptors"""
55 """Attribute descriptors"""
53
56
54 interface = Attribute('interface',
57 interface = Attribute('interface',
55 'Stores the interface instance in which the '
58 'Stores the interface instance in which the '
56 'attribute is located.')
59 'attribute is located.')
57
60
58
61
59 class IMethod(IAttribute):
62 class IMethod(IAttribute):
60 """Method attributes"""
63 """Method attributes"""
61
64
62 def getSignatureInfo():
65 def getSignatureInfo():
63 """Returns the signature information.
66 """Returns the signature information.
64
67
65 This method returns a dictionary with the following keys:
68 This method returns a dictionary with the following keys:
66
69
67 o `positional` - All positional arguments.
70 o `positional` - All positional arguments.
68
71
69 o `required` - A list of all required arguments.
72 o `required` - A list of all required arguments.
70
73
71 o `optional` - A list of all optional arguments.
74 o `optional` - A list of all optional arguments.
72
75
73 o `varargs` - The name of the varargs argument.
76 o `varargs` - The name of the varargs argument.
74
77
75 o `kwargs` - The name of the kwargs argument.
78 o `kwargs` - The name of the kwargs argument.
76 """
79 """
77
80
78 def getSignatureString():
81 def getSignatureString():
79 """Return a signature string suitable for inclusion in documentation.
82 """Return a signature string suitable for inclusion in documentation.
80
83
81 This method returns the function signature string. For example, if you
84 This method returns the function signature string. For example, if you
82 have `func(a, b, c=1, d='f')`, then the signature string is `(a, b,
85 have `func(a, b, c=1, d='f')`, then the signature string is `(a, b,
83 c=1, d='f')`.
86 c=1, d='f')`.
84 """
87 """
85
88
86 class ISpecification(Interface):
89 class ISpecification(Interface):
87 """Object Behavioral specifications"""
90 """Object Behavioral specifications"""
88
91
89 def providedBy(object):
92 def providedBy(object):
90 """Test whether the interface is implemented by the object
93 """Test whether the interface is implemented by the object
91
94
92 Return true of the object asserts that it implements the
95 Return true of the object asserts that it implements the
93 interface, including asserting that it implements an extended
96 interface, including asserting that it implements an extended
94 interface.
97 interface.
95 """
98 """
96
99
97 def implementedBy(class_):
100 def implementedBy(class_):
98 """Test whether the interface is implemented by instances of the class
101 """Test whether the interface is implemented by instances of the class
99
102
100 Return true of the class asserts that its instances implement the
103 Return true of the class asserts that its instances implement the
101 interface, including asserting that they implement an extended
104 interface, including asserting that they implement an extended
102 interface.
105 interface.
103 """
106 """
104
107
105 def isOrExtends(other):
108 def isOrExtends(other):
106 """Test whether the specification is or extends another
109 """Test whether the specification is or extends another
107 """
110 """
108
111
109 def extends(other, strict=True):
112 def extends(other, strict=True):
110 """Test whether a specification extends another
113 """Test whether a specification extends another
111
114
112 The specification extends other if it has other as a base
115 The specification extends other if it has other as a base
113 interface or if one of it's bases extends other.
116 interface or if one of it's bases extends other.
114
117
115 If strict is false, then the specification extends itself.
118 If strict is false, then the specification extends itself.
116 """
119 """
117
120
118 def weakref(callback=None):
121 def weakref(callback=None):
119 """Return a weakref to the specification
122 """Return a weakref to the specification
120
123
121 This method is, regrettably, needed to allow weakrefs to be
124 This method is, regrettably, needed to allow weakrefs to be
122 computed to security-proxied specifications. While the
125 computed to security-proxied specifications. While the
123 zope.interface package does not require zope.security or
126 zope.interface package does not require zope.security or
124 zope.proxy, it has to be able to coexist with it.
127 zope.proxy, it has to be able to coexist with it.
125
128
126 """
129 """
127
130
128 __bases__ = Attribute("""Base specifications
131 __bases__ = Attribute("""Base specifications
129
132
130 A tuple if specifications from which this specification is
133 A tuple if specifications from which this specification is
131 directly derived.
134 directly derived.
132
135
133 """)
136 """)
134
137
135 __sro__ = Attribute("""Specification-resolution order
138 __sro__ = Attribute("""Specification-resolution order
136
139
137 A tuple of the specification and all of it's ancestor
140 A tuple of the specification and all of it's ancestor
138 specifications from most specific to least specific.
141 specifications from most specific to least specific.
139
142
140 (This is similar to the method-resolution order for new-style classes.)
143 (This is similar to the method-resolution order for new-style classes.)
141 """)
144 """)
142
145
143 __iro__ = Attribute("""Interface-resolution order
146 __iro__ = Attribute("""Interface-resolution order
144
147
145 A tuple of the of the specification's ancestor interfaces from
148 A tuple of the of the specification's ancestor interfaces from
146 most specific to least specific. The specification itself is
149 most specific to least specific. The specification itself is
147 included if it is an interface.
150 included if it is an interface.
148
151
149 (This is similar to the method-resolution order for new-style classes.)
152 (This is similar to the method-resolution order for new-style classes.)
150 """)
153 """)
151
154
152 def get(name, default=None):
155 def get(name, default=None):
153 """Look up the description for a name
156 """Look up the description for a name
154
157
155 If the named attribute is not defined, the default is
158 If the named attribute is not defined, the default is
156 returned.
159 returned.
157 """
160 """
158
161
159
162
160 class IInterface(ISpecification, IElement):
163 class IInterface(ISpecification, IElement):
161 """Interface objects
164 """Interface objects
162
165
163 Interface objects describe the behavior of an object by containing
166 Interface objects describe the behavior of an object by containing
164 useful information about the object. This information includes:
167 useful information about the object. This information includes:
165
168
166 o Prose documentation about the object. In Python terms, this
169 o Prose documentation about the object. In Python terms, this
167 is called the "doc string" of the interface. In this element,
170 is called the "doc string" of the interface. In this element,
168 you describe how the object works in prose language and any
171 you describe how the object works in prose language and any
169 other useful information about the object.
172 other useful information about the object.
170
173
171 o Descriptions of attributes. Attribute descriptions include
174 o Descriptions of attributes. Attribute descriptions include
172 the name of the attribute and prose documentation describing
175 the name of the attribute and prose documentation describing
173 the attributes usage.
176 the attributes usage.
174
177
175 o Descriptions of methods. Method descriptions can include:
178 o Descriptions of methods. Method descriptions can include:
176
179
177 - Prose "doc string" documentation about the method and its
180 - Prose "doc string" documentation about the method and its
178 usage.
181 usage.
179
182
180 - A description of the methods arguments; how many arguments
183 - A description of the methods arguments; how many arguments
181 are expected, optional arguments and their default values,
184 are expected, optional arguments and their default values,
182 the position or arguments in the signature, whether the
185 the position or arguments in the signature, whether the
183 method accepts arbitrary arguments and whether the method
186 method accepts arbitrary arguments and whether the method
184 accepts arbitrary keyword arguments.
187 accepts arbitrary keyword arguments.
185
188
186 o Optional tagged data. Interface objects (and their attributes and
189 o Optional tagged data. Interface objects (and their attributes and
187 methods) can have optional, application specific tagged data
190 methods) can have optional, application specific tagged data
188 associated with them. Examples uses for this are examples,
191 associated with them. Examples uses for this are examples,
189 security assertions, pre/post conditions, and other possible
192 security assertions, pre/post conditions, and other possible
190 information you may want to associate with an Interface or its
193 information you may want to associate with an Interface or its
191 attributes.
194 attributes.
192
195
193 Not all of this information is mandatory. For example, you may
196 Not all of this information is mandatory. For example, you may
194 only want the methods of your interface to have prose
197 only want the methods of your interface to have prose
195 documentation and not describe the arguments of the method in
198 documentation and not describe the arguments of the method in
196 exact detail. Interface objects are flexible and let you give or
199 exact detail. Interface objects are flexible and let you give or
197 take any of these components.
200 take any of these components.
198
201
199 Interfaces are created with the Python class statement using
202 Interfaces are created with the Python class statement using
200 either Interface.Interface or another interface, as in::
203 either Interface.Interface or another interface, as in::
201
204
202 from zope.interface import Interface
205 from zope.interface import Interface
203
206
204 class IMyInterface(Interface):
207 class IMyInterface(Interface):
205 '''Interface documentation'''
208 '''Interface documentation'''
206
209
207 def meth(arg1, arg2):
210 def meth(arg1, arg2):
208 '''Documentation for meth'''
211 '''Documentation for meth'''
209
212
210 # Note that there is no self argument
213 # Note that there is no self argument
211
214
212 class IMySubInterface(IMyInterface):
215 class IMySubInterface(IMyInterface):
213 '''Interface documentation'''
216 '''Interface documentation'''
214
217
215 def meth2():
218 def meth2():
216 '''Documentation for meth2'''
219 '''Documentation for meth2'''
217
220
218 You use interfaces in two ways:
221 You use interfaces in two ways:
219
222
220 o You assert that your object implement the interfaces.
223 o You assert that your object implement the interfaces.
221
224
222 There are several ways that you can assert that an object
225 There are several ways that you can assert that an object
223 implements an interface:
226 implements an interface:
224
227
225 1. Call zope.interface.implements in your class definition.
228 1. Call zope.interface.implements in your class definition.
226
229
227 2. Call zope.interfaces.directlyProvides on your object.
230 2. Call zope.interfaces.directlyProvides on your object.
228
231
229 3. Call 'zope.interface.classImplements' to assert that instances
232 3. Call 'zope.interface.classImplements' to assert that instances
230 of a class implement an interface.
233 of a class implement an interface.
231
234
232 For example::
235 For example::
233
236
234 from zope.interface import classImplements
237 from zope.interface import classImplements
235
238
236 classImplements(some_class, some_interface)
239 classImplements(some_class, some_interface)
237
240
238 This approach is useful when it is not an option to modify
241 This approach is useful when it is not an option to modify
239 the class source. Note that this doesn't affect what the
242 the class source. Note that this doesn't affect what the
240 class itself implements, but only what its instances
243 class itself implements, but only what its instances
241 implement.
244 implement.
242
245
243 o You query interface meta-data. See the IInterface methods and
246 o You query interface meta-data. See the IInterface methods and
244 attributes for details.
247 attributes for details.
245
248
246 """
249 """
247
250
248 def names(all=False):
251 def names(all=False):
249 """Get the interface attribute names
252 """Get the interface attribute names
250
253
251 Return a sequence of the names of the attributes, including
254 Return a sequence of the names of the attributes, including
252 methods, included in the interface definition.
255 methods, included in the interface definition.
253
256
254 Normally, only directly defined attributes are included. If
257 Normally, only directly defined attributes are included. If
255 a true positional or keyword argument is given, then
258 a true positional or keyword argument is given, then
256 attributes defined by base classes will be included.
259 attributes defined by base classes will be included.
257 """
260 """
258
261
259 def namesAndDescriptions(all=False):
262 def namesAndDescriptions(all=False):
260 """Get the interface attribute names and descriptions
263 """Get the interface attribute names and descriptions
261
264
262 Return a sequence of the names and descriptions of the
265 Return a sequence of the names and descriptions of the
263 attributes, including methods, as name-value pairs, included
266 attributes, including methods, as name-value pairs, included
264 in the interface definition.
267 in the interface definition.
265
268
266 Normally, only directly defined attributes are included. If
269 Normally, only directly defined attributes are included. If
267 a true positional or keyword argument is given, then
270 a true positional or keyword argument is given, then
268 attributes defined by base classes will be included.
271 attributes defined by base classes will be included.
269 """
272 """
270
273
271 def __getitem__(name):
274 def __getitem__(name):
272 """Get the description for a name
275 """Get the description for a name
273
276
274 If the named attribute is not defined, a KeyError is raised.
277 If the named attribute is not defined, a KeyError is raised.
275 """
278 """
276
279
277 def direct(name):
280 def direct(name):
278 """Get the description for the name if it was defined by the interface
281 """Get the description for the name if it was defined by the interface
279
282
280 If the interface doesn't define the name, returns None.
283 If the interface doesn't define the name, returns None.
281 """
284 """
282
285
283 def validateInvariants(obj, errors=None):
286 def validateInvariants(obj, errors=None):
284 """Validate invariants
287 """Validate invariants
285
288
286 Validate object to defined invariants. If errors is None,
289 Validate object to defined invariants. If errors is None,
287 raises first Invalid error; if errors is a list, appends all errors
290 raises first Invalid error; if errors is a list, appends all errors
288 to list, then raises Invalid with the errors as the first element
291 to list, then raises Invalid with the errors as the first element
289 of the "args" tuple."""
292 of the "args" tuple."""
290
293
291 def __contains__(name):
294 def __contains__(name):
292 """Test whether the name is defined by the interface"""
295 """Test whether the name is defined by the interface"""
293
296
294 def __iter__():
297 def __iter__():
295 """Return an iterator over the names defined by the interface
298 """Return an iterator over the names defined by the interface
296
299
297 The names iterated include all of the names defined by the
300 The names iterated include all of the names defined by the
298 interface directly and indirectly by base interfaces.
301 interface directly and indirectly by base interfaces.
299 """
302 """
300
303
301 __module__ = Attribute("""The name of the module defining the interface""")
304 __module__ = Attribute("""The name of the module defining the interface""")
302
305
303 class IDeclaration(ISpecification):
306 class IDeclaration(ISpecification):
304 """Interface declaration
307 """Interface declaration
305
308
306 Declarations are used to express the interfaces implemented by
309 Declarations are used to express the interfaces implemented by
307 classes or provided by objects.
310 classes or provided by objects.
308 """
311 """
309
312
310 def __contains__(interface):
313 def __contains__(interface):
311 """Test whether an interface is in the specification
314 """Test whether an interface is in the specification
312
315
313 Return true if the given interface is one of the interfaces in
316 Return true if the given interface is one of the interfaces in
314 the specification and false otherwise.
317 the specification and false otherwise.
315 """
318 """
316
319
317 def __iter__():
320 def __iter__():
318 """Return an iterator for the interfaces in the specification
321 """Return an iterator for the interfaces in the specification
319 """
322 """
320
323
321 def flattened():
324 def flattened():
322 """Return an iterator of all included and extended interfaces
325 """Return an iterator of all included and extended interfaces
323
326
324 An iterator is returned for all interfaces either included in
327 An iterator is returned for all interfaces either included in
325 or extended by interfaces included in the specifications
328 or extended by interfaces included in the specifications
326 without duplicates. The interfaces are in "interface
329 without duplicates. The interfaces are in "interface
327 resolution order". The interface resolution order is such that
330 resolution order". The interface resolution order is such that
328 base interfaces are listed after interfaces that extend them
331 base interfaces are listed after interfaces that extend them
329 and, otherwise, interfaces are included in the order that they
332 and, otherwise, interfaces are included in the order that they
330 were defined in the specification.
333 were defined in the specification.
331 """
334 """
332
335
333 def __sub__(interfaces):
336 def __sub__(interfaces):
334 """Create an interface specification with some interfaces excluded
337 """Create an interface specification with some interfaces excluded
335
338
336 The argument can be an interface or an interface
339 The argument can be an interface or an interface
337 specifications. The interface or interfaces given in a
340 specifications. The interface or interfaces given in a
338 specification are subtracted from the interface specification.
341 specification are subtracted from the interface specification.
339
342
340 Removing an interface that is not in the specification does
343 Removing an interface that is not in the specification does
341 not raise an error. Doing so has no effect.
344 not raise an error. Doing so has no effect.
342
345
343 Removing an interface also removes sub-interfaces of the interface.
346 Removing an interface also removes sub-interfaces of the interface.
344
347
345 """
348 """
346
349
347 def __add__(interfaces):
350 def __add__(interfaces):
348 """Create an interface specification with some interfaces added
351 """Create an interface specification with some interfaces added
349
352
350 The argument can be an interface or an interface
353 The argument can be an interface or an interface
351 specifications. The interface or interfaces given in a
354 specifications. The interface or interfaces given in a
352 specification are added to the interface specification.
355 specification are added to the interface specification.
353
356
354 Adding an interface that is already in the specification does
357 Adding an interface that is already in the specification does
355 not raise an error. Doing so has no effect.
358 not raise an error. Doing so has no effect.
356 """
359 """
357
360
358 def __nonzero__():
361 def __nonzero__():
359 """Return a true value of the interface specification is non-empty
362 """Return a true value of the interface specification is non-empty
360 """
363 """
361
364
362 class IInterfaceDeclaration(Interface):
365 class IInterfaceDeclaration(Interface):
363 """Declare and check the interfaces of objects
366 """Declare and check the interfaces of objects
364
367
365 The functions defined in this interface are used to declare the
368 The functions defined in this interface are used to declare the
366 interfaces that objects provide and to query the interfaces that have
369 interfaces that objects provide and to query the interfaces that have
367 been declared.
370 been declared.
368
371
369 Interfaces can be declared for objects in two ways:
372 Interfaces can be declared for objects in two ways:
370
373
371 - Interfaces are declared for instances of the object's class
374 - Interfaces are declared for instances of the object's class
372
375
373 - Interfaces are declared for the object directly.
376 - Interfaces are declared for the object directly.
374
377
375 The interfaces declared for an object are, therefore, the union of
378 The interfaces declared for an object are, therefore, the union of
376 interfaces declared for the object directly and the interfaces
379 interfaces declared for the object directly and the interfaces
377 declared for instances of the object's class.
380 declared for instances of the object's class.
378
381
379 Note that we say that a class implements the interfaces provided
382 Note that we say that a class implements the interfaces provided
380 by it's instances. An instance can also provide interfaces
383 by it's instances. An instance can also provide interfaces
381 directly. The interfaces provided by an object are the union of
384 directly. The interfaces provided by an object are the union of
382 the interfaces provided directly and the interfaces implemented by
385 the interfaces provided directly and the interfaces implemented by
383 the class.
386 the class.
384 """
387 """
385
388
386 def providedBy(ob):
389 def providedBy(ob):
387 """Return the interfaces provided by an object
390 """Return the interfaces provided by an object
388
391
389 This is the union of the interfaces directly provided by an
392 This is the union of the interfaces directly provided by an
390 object and interfaces implemented by it's class.
393 object and interfaces implemented by it's class.
391
394
392 The value returned is an IDeclaration.
395 The value returned is an IDeclaration.
393 """
396 """
394
397
395 def implementedBy(class_):
398 def implementedBy(class_):
396 """Return the interfaces implemented for a class' instances
399 """Return the interfaces implemented for a class' instances
397
400
398 The value returned is an IDeclaration.
401 The value returned is an IDeclaration.
399 """
402 """
400
403
401 def classImplements(class_, *interfaces):
404 def classImplements(class_, *interfaces):
402 """Declare additional interfaces implemented for instances of a class
405 """Declare additional interfaces implemented for instances of a class
403
406
404 The arguments after the class are one or more interfaces or
407 The arguments after the class are one or more interfaces or
405 interface specifications (IDeclaration objects).
408 interface specifications (IDeclaration objects).
406
409
407 The interfaces given (including the interfaces in the
410 The interfaces given (including the interfaces in the
408 specifications) are added to any interfaces previously
411 specifications) are added to any interfaces previously
409 declared.
412 declared.
410
413
411 Consider the following example::
414 Consider the following example::
412
415
413 class C(A, B):
416 class C(A, B):
414 ...
417 ...
415
418
416 classImplements(C, I1, I2)
419 classImplements(C, I1, I2)
417
420
418
421
419 Instances of ``C`` provide ``I1``, ``I2``, and whatever interfaces
422 Instances of ``C`` provide ``I1``, ``I2``, and whatever interfaces
420 instances of ``A`` and ``B`` provide.
423 instances of ``A`` and ``B`` provide.
421 """
424 """
422
425
423 def implementer(*interfaces):
426 def implementer(*interfaces):
424 """Create a decorator for declaring interfaces implemented by a facory
427 """Create a decorator for declaring interfaces implemented by a facory
425
428
426 A callable is returned that makes an implements declaration on
429 A callable is returned that makes an implements declaration on
427 objects passed to it.
430 objects passed to it.
428 """
431 """
429
432
430 def classImplementsOnly(class_, *interfaces):
433 def classImplementsOnly(class_, *interfaces):
431 """Declare the only interfaces implemented by instances of a class
434 """Declare the only interfaces implemented by instances of a class
432
435
433 The arguments after the class are one or more interfaces or
436 The arguments after the class are one or more interfaces or
434 interface specifications (IDeclaration objects).
437 interface specifications (IDeclaration objects).
435
438
436 The interfaces given (including the interfaces in the
439 The interfaces given (including the interfaces in the
437 specifications) replace any previous declarations.
440 specifications) replace any previous declarations.
438
441
439 Consider the following example::
442 Consider the following example::
440
443
441 class C(A, B):
444 class C(A, B):
442 ...
445 ...
443
446
444 classImplements(C, IA, IB. IC)
447 classImplements(C, IA, IB. IC)
445 classImplementsOnly(C. I1, I2)
448 classImplementsOnly(C. I1, I2)
446
449
447 Instances of ``C`` provide only ``I1``, ``I2``, and regardless of
450 Instances of ``C`` provide only ``I1``, ``I2``, and regardless of
448 whatever interfaces instances of ``A`` and ``B`` implement.
451 whatever interfaces instances of ``A`` and ``B`` implement.
449 """
452 """
450
453
451 def implementer_only(*interfaces):
454 def implementer_only(*interfaces):
452 """Create a decorator for declaring the only interfaces implemented
455 """Create a decorator for declaring the only interfaces implemented
453
456
454 A callable is returned that makes an implements declaration on
457 A callable is returned that makes an implements declaration on
455 objects passed to it.
458 objects passed to it.
456 """
459 """
457
460
458 def directlyProvidedBy(object):
461 def directlyProvidedBy(object):
459 """Return the interfaces directly provided by the given object
462 """Return the interfaces directly provided by the given object
460
463
461 The value returned is an IDeclaration.
464 The value returned is an IDeclaration.
462 """
465 """
463
466
464 def directlyProvides(object, *interfaces):
467 def directlyProvides(object, *interfaces):
465 """Declare interfaces declared directly for an object
468 """Declare interfaces declared directly for an object
466
469
467 The arguments after the object are one or more interfaces or
470 The arguments after the object are one or more interfaces or
468 interface specifications (IDeclaration objects).
471 interface specifications (IDeclaration objects).
469
472
470 The interfaces given (including the interfaces in the
473 The interfaces given (including the interfaces in the
471 specifications) replace interfaces previously
474 specifications) replace interfaces previously
472 declared for the object.
475 declared for the object.
473
476
474 Consider the following example::
477 Consider the following example::
475
478
476 class C(A, B):
479 class C(A, B):
477 ...
480 ...
478
481
479 ob = C()
482 ob = C()
480 directlyProvides(ob, I1, I2)
483 directlyProvides(ob, I1, I2)
481
484
482 The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces
485 The object, ``ob`` provides ``I1``, ``I2``, and whatever interfaces
483 instances have been declared for instances of ``C``.
486 instances have been declared for instances of ``C``.
484
487
485 To remove directly provided interfaces, use ``directlyProvidedBy`` and
488 To remove directly provided interfaces, use ``directlyProvidedBy`` and
486 subtract the unwanted interfaces. For example::
489 subtract the unwanted interfaces. For example::
487
490
488 directlyProvides(ob, directlyProvidedBy(ob)-I2)
491 directlyProvides(ob, directlyProvidedBy(ob)-I2)
489
492
490 removes I2 from the interfaces directly provided by
493 removes I2 from the interfaces directly provided by
491 ``ob``. The object, ``ob`` no longer directly provides ``I2``,
494 ``ob``. The object, ``ob`` no longer directly provides ``I2``,
492 although it might still provide ``I2`` if it's class
495 although it might still provide ``I2`` if it's class
493 implements ``I2``.
496 implements ``I2``.
494
497
495 To add directly provided interfaces, use ``directlyProvidedBy`` and
498 To add directly provided interfaces, use ``directlyProvidedBy`` and
496 include additional interfaces. For example::
499 include additional interfaces. For example::
497
500
498 directlyProvides(ob, directlyProvidedBy(ob), I2)
501 directlyProvides(ob, directlyProvidedBy(ob), I2)
499
502
500 adds I2 to the interfaces directly provided by ob.
503 adds I2 to the interfaces directly provided by ob.
501 """
504 """
502
505
503 def alsoProvides(object, *interfaces):
506 def alsoProvides(object, *interfaces):
504 """Declare additional interfaces directly for an object::
507 """Declare additional interfaces directly for an object::
505
508
506 alsoProvides(ob, I1)
509 alsoProvides(ob, I1)
507
510
508 is equivalent to::
511 is equivalent to::
509
512
510 directlyProvides(ob, directlyProvidedBy(ob), I1)
513 directlyProvides(ob, directlyProvidedBy(ob), I1)
511 """
514 """
512
515
513 def noLongerProvides(object, interface):
516 def noLongerProvides(object, interface):
514 """Remove an interface from the list of an object's directly
517 """Remove an interface from the list of an object's directly
515 provided interfaces::
518 provided interfaces::
516
519
517 noLongerProvides(ob, I1)
520 noLongerProvides(ob, I1)
518
521
519 is equivalent to::
522 is equivalent to::
520
523
521 directlyProvides(ob, directlyProvidedBy(ob)-I1)
524 directlyProvides(ob, directlyProvidedBy(ob)-I1)
522
525
523 with the exception that if ``I1`` is an interface that is
526 with the exception that if ``I1`` is an interface that is
524 provided by ``ob`` through the class's implementation,
527 provided by ``ob`` through the class's implementation,
525 ValueError is raised.
528 ValueError is raised.
526 """
529 """
527
530
528 def implements(*interfaces):
531 def implements(*interfaces):
529 """Declare interfaces implemented by instances of a class
532 """Declare interfaces implemented by instances of a class
530
533
531 This function is called in a class definition (Python 2.x only).
534 This function is called in a class definition (Python 2.x only).
532
535
533 The arguments are one or more interfaces or interface
536 The arguments are one or more interfaces or interface
534 specifications (IDeclaration objects).
537 specifications (IDeclaration objects).
535
538
536 The interfaces given (including the interfaces in the
539 The interfaces given (including the interfaces in the
537 specifications) are added to any interfaces previously
540 specifications) are added to any interfaces previously
538 declared.
541 declared.
539
542
540 Previous declarations include declarations for base classes
543 Previous declarations include declarations for base classes
541 unless implementsOnly was used.
544 unless implementsOnly was used.
542
545
543 This function is provided for convenience. It provides a more
546 This function is provided for convenience. It provides a more
544 convenient way to call classImplements. For example::
547 convenient way to call classImplements. For example::
545
548
546 implements(I1)
549 implements(I1)
547
550
548 is equivalent to calling::
551 is equivalent to calling::
549
552
550 classImplements(C, I1)
553 classImplements(C, I1)
551
554
552 after the class has been created.
555 after the class has been created.
553
556
554 Consider the following example (Python 2.x only)::
557 Consider the following example (Python 2.x only)::
555
558
556 class C(A, B):
559 class C(A, B):
557 implements(I1, I2)
560 implements(I1, I2)
558
561
559
562
560 Instances of ``C`` implement ``I1``, ``I2``, and whatever interfaces
563 Instances of ``C`` implement ``I1``, ``I2``, and whatever interfaces
561 instances of ``A`` and ``B`` implement.
564 instances of ``A`` and ``B`` implement.
562 """
565 """
563
566
564 def implementsOnly(*interfaces):
567 def implementsOnly(*interfaces):
565 """Declare the only interfaces implemented by instances of a class
568 """Declare the only interfaces implemented by instances of a class
566
569
567 This function is called in a class definition (Python 2.x only).
570 This function is called in a class definition (Python 2.x only).
568
571
569 The arguments are one or more interfaces or interface
572 The arguments are one or more interfaces or interface
570 specifications (IDeclaration objects).
573 specifications (IDeclaration objects).
571
574
572 Previous declarations including declarations for base classes
575 Previous declarations including declarations for base classes
573 are overridden.
576 are overridden.
574
577
575 This function is provided for convenience. It provides a more
578 This function is provided for convenience. It provides a more
576 convenient way to call classImplementsOnly. For example::
579 convenient way to call classImplementsOnly. For example::
577
580
578 implementsOnly(I1)
581 implementsOnly(I1)
579
582
580 is equivalent to calling::
583 is equivalent to calling::
581
584
582 classImplementsOnly(I1)
585 classImplementsOnly(I1)
583
586
584 after the class has been created.
587 after the class has been created.
585
588
586 Consider the following example (Python 2.x only)::
589 Consider the following example (Python 2.x only)::
587
590
588 class C(A, B):
591 class C(A, B):
589 implementsOnly(I1, I2)
592 implementsOnly(I1, I2)
590
593
591
594
592 Instances of ``C`` implement ``I1``, ``I2``, regardless of what
595 Instances of ``C`` implement ``I1``, ``I2``, regardless of what
593 instances of ``A`` and ``B`` implement.
596 instances of ``A`` and ``B`` implement.
594 """
597 """
595
598
596 def classProvides(*interfaces):
599 def classProvides(*interfaces):
597 """Declare interfaces provided directly by a class
600 """Declare interfaces provided directly by a class
598
601
599 This function is called in a class definition.
602 This function is called in a class definition.
600
603
601 The arguments are one or more interfaces or interface
604 The arguments are one or more interfaces or interface
602 specifications (IDeclaration objects).
605 specifications (IDeclaration objects).
603
606
604 The given interfaces (including the interfaces in the
607 The given interfaces (including the interfaces in the
605 specifications) are used to create the class's direct-object
608 specifications) are used to create the class's direct-object
606 interface specification. An error will be raised if the module
609 interface specification. An error will be raised if the module
607 class has an direct interface specification. In other words, it is
610 class has an direct interface specification. In other words, it is
608 an error to call this function more than once in a class
611 an error to call this function more than once in a class
609 definition.
612 definition.
610
613
611 Note that the given interfaces have nothing to do with the
614 Note that the given interfaces have nothing to do with the
612 interfaces implemented by instances of the class.
615 interfaces implemented by instances of the class.
613
616
614 This function is provided for convenience. It provides a more
617 This function is provided for convenience. It provides a more
615 convenient way to call directlyProvides for a class. For example::
618 convenient way to call directlyProvides for a class. For example::
616
619
617 classProvides(I1)
620 classProvides(I1)
618
621
619 is equivalent to calling::
622 is equivalent to calling::
620
623
621 directlyProvides(theclass, I1)
624 directlyProvides(theclass, I1)
622
625
623 after the class has been created.
626 after the class has been created.
624 """
627 """
625 def provider(*interfaces):
628 def provider(*interfaces):
626 """A class decorator version of classProvides"""
629 """A class decorator version of classProvides"""
627
630
628 def moduleProvides(*interfaces):
631 def moduleProvides(*interfaces):
629 """Declare interfaces provided by a module
632 """Declare interfaces provided by a module
630
633
631 This function is used in a module definition.
634 This function is used in a module definition.
632
635
633 The arguments are one or more interfaces or interface
636 The arguments are one or more interfaces or interface
634 specifications (IDeclaration objects).
637 specifications (IDeclaration objects).
635
638
636 The given interfaces (including the interfaces in the
639 The given interfaces (including the interfaces in the
637 specifications) are used to create the module's direct-object
640 specifications) are used to create the module's direct-object
638 interface specification. An error will be raised if the module
641 interface specification. An error will be raised if the module
639 already has an interface specification. In other words, it is
642 already has an interface specification. In other words, it is
640 an error to call this function more than once in a module
643 an error to call this function more than once in a module
641 definition.
644 definition.
642
645
643 This function is provided for convenience. It provides a more
646 This function is provided for convenience. It provides a more
644 convenient way to call directlyProvides for a module. For example::
647 convenient way to call directlyProvides for a module. For example::
645
648
646 moduleImplements(I1)
649 moduleImplements(I1)
647
650
648 is equivalent to::
651 is equivalent to::
649
652
650 directlyProvides(sys.modules[__name__], I1)
653 directlyProvides(sys.modules[__name__], I1)
651 """
654 """
652
655
653 def Declaration(*interfaces):
656 def Declaration(*interfaces):
654 """Create an interface specification
657 """Create an interface specification
655
658
656 The arguments are one or more interfaces or interface
659 The arguments are one or more interfaces or interface
657 specifications (IDeclaration objects).
660 specifications (IDeclaration objects).
658
661
659 A new interface specification (IDeclaration) with
662 A new interface specification (IDeclaration) with
660 the given interfaces is returned.
663 the given interfaces is returned.
661 """
664 """
662
665
663 class IAdapterRegistry(Interface):
666 class IAdapterRegistry(Interface):
664 """Provide an interface-based registry for adapters
667 """Provide an interface-based registry for adapters
665
668
666 This registry registers objects that are in some sense "from" a
669 This registry registers objects that are in some sense "from" a
667 sequence of specification to an interface and a name.
670 sequence of specification to an interface and a name.
668
671
669 No specific semantics are assumed for the registered objects,
672 No specific semantics are assumed for the registered objects,
670 however, the most common application will be to register factories
673 however, the most common application will be to register factories
671 that adapt objects providing required specifications to a provided
674 that adapt objects providing required specifications to a provided
672 interface.
675 interface.
673 """
676 """
674
677
675 def register(required, provided, name, value):
678 def register(required, provided, name, value):
676 """Register a value
679 """Register a value
677
680
678 A value is registered for a *sequence* of required specifications, a
681 A value is registered for a *sequence* of required specifications, a
679 provided interface, and a name, which must be text.
682 provided interface, and a name, which must be text.
680 """
683 """
681
684
682 def registered(required, provided, name=_BLANK):
685 def registered(required, provided, name=_BLANK):
683 """Return the component registered for the given interfaces and name
686 """Return the component registered for the given interfaces and name
684
687
685 name must be text.
688 name must be text.
686
689
687 Unlike the lookup method, this methods won't retrieve
690 Unlike the lookup method, this methods won't retrieve
688 components registered for more specific required interfaces or
691 components registered for more specific required interfaces or
689 less specific provided interfaces.
692 less specific provided interfaces.
690
693
691 If no component was registered exactly for the given
694 If no component was registered exactly for the given
692 interfaces and name, then None is returned.
695 interfaces and name, then None is returned.
693
696
694 """
697 """
695
698
696 def lookup(required, provided, name='', default=None):
699 def lookup(required, provided, name='', default=None):
697 """Lookup a value
700 """Lookup a value
698
701
699 A value is looked up based on a *sequence* of required
702 A value is looked up based on a *sequence* of required
700 specifications, a provided interface, and a name, which must be
703 specifications, a provided interface, and a name, which must be
701 text.
704 text.
702 """
705 """
703
706
704 def queryMultiAdapter(objects, provided, name=_BLANK, default=None):
707 def queryMultiAdapter(objects, provided, name=_BLANK, default=None):
705 """Adapt a sequence of objects to a named, provided, interface
708 """Adapt a sequence of objects to a named, provided, interface
706 """
709 """
707
710
708 def lookup1(required, provided, name=_BLANK, default=None):
711 def lookup1(required, provided, name=_BLANK, default=None):
709 """Lookup a value using a single required interface
712 """Lookup a value using a single required interface
710
713
711 A value is looked up based on a single required
714 A value is looked up based on a single required
712 specifications, a provided interface, and a name, which must be
715 specifications, a provided interface, and a name, which must be
713 text.
716 text.
714 """
717 """
715
718
716 def queryAdapter(object, provided, name=_BLANK, default=None):
719 def queryAdapter(object, provided, name=_BLANK, default=None):
717 """Adapt an object using a registered adapter factory.
720 """Adapt an object using a registered adapter factory.
718 """
721 """
719
722
720 def adapter_hook(provided, object, name=_BLANK, default=None):
723 def adapter_hook(provided, object, name=_BLANK, default=None):
721 """Adapt an object using a registered adapter factory.
724 """Adapt an object using a registered adapter factory.
722
725
723 name must be text.
726 name must be text.
724 """
727 """
725
728
726 def lookupAll(required, provided):
729 def lookupAll(required, provided):
727 """Find all adapters from the required to the provided interfaces
730 """Find all adapters from the required to the provided interfaces
728
731
729 An iterable object is returned that provides name-value two-tuples.
732 An iterable object is returned that provides name-value two-tuples.
730 """
733 """
731
734
732 def names(required, provided):
735 def names(required, provided):
733 """Return the names for which there are registered objects
736 """Return the names for which there are registered objects
734 """
737 """
735
738
736 def subscribe(required, provided, subscriber, name=_BLANK):
739 def subscribe(required, provided, subscriber, name=_BLANK):
737 """Register a subscriber
740 """Register a subscriber
738
741
739 A subscriber is registered for a *sequence* of required
742 A subscriber is registered for a *sequence* of required
740 specifications, a provided interface, and a name.
743 specifications, a provided interface, and a name.
741
744
742 Multiple subscribers may be registered for the same (or
745 Multiple subscribers may be registered for the same (or
743 equivalent) interfaces.
746 equivalent) interfaces.
744 """
747 """
745
748
746 def subscriptions(required, provided, name=_BLANK):
749 def subscriptions(required, provided, name=_BLANK):
747 """Get a sequence of subscribers
750 """Get a sequence of subscribers
748
751
749 Subscribers for a *sequence* of required interfaces, and a provided
752 Subscribers for a *sequence* of required interfaces, and a provided
750 interface are returned.
753 interface are returned.
751 """
754 """
752
755
753 def subscribers(objects, provided, name=_BLANK):
756 def subscribers(objects, provided, name=_BLANK):
754 """Get a sequence of subscription adapters
757 """Get a sequence of subscription adapters
755 """
758 """
756
759
757 # begin formerly in zope.component
760 # begin formerly in zope.component
758
761
759 class ComponentLookupError(LookupError):
762 class ComponentLookupError(LookupError):
760 """A component could not be found."""
763 """A component could not be found."""
761
764
762 class Invalid(Exception):
765 class Invalid(Exception):
763 """A component doesn't satisfy a promise."""
766 """A component doesn't satisfy a promise."""
764
767
765 class IObjectEvent(Interface):
768 class IObjectEvent(Interface):
766 """An event related to an object.
769 """An event related to an object.
767
770
768 The object that generated this event is not necessarily the object
771 The object that generated this event is not necessarily the object
769 refered to by location.
772 refered to by location.
770 """
773 """
771
774
772 object = Attribute("The subject of the event.")
775 object = Attribute("The subject of the event.")
773
776
774
777
775 @implementer(IObjectEvent)
778 @implementer(IObjectEvent)
776 class ObjectEvent(object):
779 class ObjectEvent(object):
777
780
778 def __init__(self, object):
781 def __init__(self, object):
779 self.object = object
782 self.object = object
780
783
781 class IComponentLookup(Interface):
784 class IComponentLookup(Interface):
782 """Component Manager for a Site
785 """Component Manager for a Site
783
786
784 This object manages the components registered at a particular site. The
787 This object manages the components registered at a particular site. The
785 definition of a site is intentionally vague.
788 definition of a site is intentionally vague.
786 """
789 """
787
790
788 adapters = Attribute(
791 adapters = Attribute(
789 "Adapter Registry to manage all registered adapters.")
792 "Adapter Registry to manage all registered adapters.")
790
793
791 utilities = Attribute(
794 utilities = Attribute(
792 "Adapter Registry to manage all registered utilities.")
795 "Adapter Registry to manage all registered utilities.")
793
796
794 def queryAdapter(object, interface, name=_BLANK, default=None):
797 def queryAdapter(object, interface, name=_BLANK, default=None):
795 """Look for a named adapter to an interface for an object
798 """Look for a named adapter to an interface for an object
796
799
797 If a matching adapter cannot be found, returns the default.
800 If a matching adapter cannot be found, returns the default.
798 """
801 """
799
802
800 def getAdapter(object, interface, name=_BLANK):
803 def getAdapter(object, interface, name=_BLANK):
801 """Look for a named adapter to an interface for an object
804 """Look for a named adapter to an interface for an object
802
805
803 If a matching adapter cannot be found, a ComponentLookupError
806 If a matching adapter cannot be found, a ComponentLookupError
804 is raised.
807 is raised.
805 """
808 """
806
809
807 def queryMultiAdapter(objects, interface, name=_BLANK, default=None):
810 def queryMultiAdapter(objects, interface, name=_BLANK, default=None):
808 """Look for a multi-adapter to an interface for multiple objects
811 """Look for a multi-adapter to an interface for multiple objects
809
812
810 If a matching adapter cannot be found, returns the default.
813 If a matching adapter cannot be found, returns the default.
811 """
814 """
812
815
813 def getMultiAdapter(objects, interface, name=_BLANK):
816 def getMultiAdapter(objects, interface, name=_BLANK):
814 """Look for a multi-adapter to an interface for multiple objects
817 """Look for a multi-adapter to an interface for multiple objects
815
818
816 If a matching adapter cannot be found, a ComponentLookupError
819 If a matching adapter cannot be found, a ComponentLookupError
817 is raised.
820 is raised.
818 """
821 """
819
822
820 def getAdapters(objects, provided):
823 def getAdapters(objects, provided):
821 """Look for all matching adapters to a provided interface for objects
824 """Look for all matching adapters to a provided interface for objects
822
825
823 Return an iterable of name-adapter pairs for adapters that
826 Return an iterable of name-adapter pairs for adapters that
824 provide the given interface.
827 provide the given interface.
825 """
828 """
826
829
827 def subscribers(objects, provided):
830 def subscribers(objects, provided):
828 """Get subscribers
831 """Get subscribers
829
832
830 Subscribers are returned that provide the provided interface
833 Subscribers are returned that provide the provided interface
831 and that depend on and are comuted from the sequence of
834 and that depend on and are comuted from the sequence of
832 required objects.
835 required objects.
833 """
836 """
834
837
835 def handle(*objects):
838 def handle(*objects):
836 """Call handlers for the given objects
839 """Call handlers for the given objects
837
840
838 Handlers registered for the given objects are called.
841 Handlers registered for the given objects are called.
839 """
842 """
840
843
841 def queryUtility(interface, name='', default=None):
844 def queryUtility(interface, name='', default=None):
842 """Look up a utility that provides an interface.
845 """Look up a utility that provides an interface.
843
846
844 If one is not found, returns default.
847 If one is not found, returns default.
845 """
848 """
846
849
847 def getUtilitiesFor(interface):
850 def getUtilitiesFor(interface):
848 """Look up the registered utilities that provide an interface.
851 """Look up the registered utilities that provide an interface.
849
852
850 Returns an iterable of name-utility pairs.
853 Returns an iterable of name-utility pairs.
851 """
854 """
852
855
853 def getAllUtilitiesRegisteredFor(interface):
856 def getAllUtilitiesRegisteredFor(interface):
854 """Return all registered utilities for an interface
857 """Return all registered utilities for an interface
855
858
856 This includes overridden utilities.
859 This includes overridden utilities.
857
860
858 An iterable of utility instances is returned. No names are
861 An iterable of utility instances is returned. No names are
859 returned.
862 returned.
860 """
863 """
861
864
862 class IRegistration(Interface):
865 class IRegistration(Interface):
863 """A registration-information object
866 """A registration-information object
864 """
867 """
865
868
866 registry = Attribute("The registry having the registration")
869 registry = Attribute("The registry having the registration")
867
870
868 name = Attribute("The registration name")
871 name = Attribute("The registration name")
869
872
870 info = Attribute("""Information about the registration
873 info = Attribute("""Information about the registration
871
874
872 This is information deemed useful to people browsing the
875 This is information deemed useful to people browsing the
873 configuration of a system. It could, for example, include
876 configuration of a system. It could, for example, include
874 commentary or information about the source of the configuration.
877 commentary or information about the source of the configuration.
875 """)
878 """)
876
879
877 class IUtilityRegistration(IRegistration):
880 class IUtilityRegistration(IRegistration):
878 """Information about the registration of a utility
881 """Information about the registration of a utility
879 """
882 """
880
883
881 factory = Attribute("The factory used to create the utility. Optional.")
884 factory = Attribute("The factory used to create the utility. Optional.")
882 component = Attribute("The object registered")
885 component = Attribute("The object registered")
883 provided = Attribute("The interface provided by the component")
886 provided = Attribute("The interface provided by the component")
884
887
885 class _IBaseAdapterRegistration(IRegistration):
888 class _IBaseAdapterRegistration(IRegistration):
886 """Information about the registration of an adapter
889 """Information about the registration of an adapter
887 """
890 """
888
891
889 factory = Attribute("The factory used to create adapters")
892 factory = Attribute("The factory used to create adapters")
890
893
891 required = Attribute("""The adapted interfaces
894 required = Attribute("""The adapted interfaces
892
895
893 This is a sequence of interfaces adapters by the registered
896 This is a sequence of interfaces adapters by the registered
894 factory. The factory will be caled with a sequence of objects, as
897 factory. The factory will be caled with a sequence of objects, as
895 positional arguments, that provide these interfaces.
898 positional arguments, that provide these interfaces.
896 """)
899 """)
897
900
898 provided = Attribute("""The interface provided by the adapters.
901 provided = Attribute("""The interface provided by the adapters.
899
902
900 This interface is implemented by the factory
903 This interface is implemented by the factory
901 """)
904 """)
902
905
903 class IAdapterRegistration(_IBaseAdapterRegistration):
906 class IAdapterRegistration(_IBaseAdapterRegistration):
904 """Information about the registration of an adapter
907 """Information about the registration of an adapter
905 """
908 """
906
909
907 class ISubscriptionAdapterRegistration(_IBaseAdapterRegistration):
910 class ISubscriptionAdapterRegistration(_IBaseAdapterRegistration):
908 """Information about the registration of a subscription adapter
911 """Information about the registration of a subscription adapter
909 """
912 """
910
913
911 class IHandlerRegistration(IRegistration):
914 class IHandlerRegistration(IRegistration):
912
915
913 handler = Attribute("An object called used to handle an event")
916 handler = Attribute("An object called used to handle an event")
914
917
915 required = Attribute("""The handled interfaces
918 required = Attribute("""The handled interfaces
916
919
917 This is a sequence of interfaces handled by the registered
920 This is a sequence of interfaces handled by the registered
918 handler. The handler will be caled with a sequence of objects, as
921 handler. The handler will be caled with a sequence of objects, as
919 positional arguments, that provide these interfaces.
922 positional arguments, that provide these interfaces.
920 """)
923 """)
921
924
922 class IRegistrationEvent(IObjectEvent):
925 class IRegistrationEvent(IObjectEvent):
923 """An event that involves a registration"""
926 """An event that involves a registration"""
924
927
925
928
926 @implementer(IRegistrationEvent)
929 @implementer(IRegistrationEvent)
927 class RegistrationEvent(ObjectEvent):
930 class RegistrationEvent(ObjectEvent):
928 """There has been a change in a registration
931 """There has been a change in a registration
929 """
932 """
930 def __repr__(self):
933 def __repr__(self):
931 return "%s event:\n%r" % (self.__class__.__name__, self.object)
934 return "%s event:\n%r" % (self.__class__.__name__, self.object)
932
935
933 class IRegistered(IRegistrationEvent):
936 class IRegistered(IRegistrationEvent):
934 """A component or factory was registered
937 """A component or factory was registered
935 """
938 """
936
939
937 @implementer(IRegistered)
940 @implementer(IRegistered)
938 class Registered(RegistrationEvent):
941 class Registered(RegistrationEvent):
939 pass
942 pass
940
943
941 class IUnregistered(IRegistrationEvent):
944 class IUnregistered(IRegistrationEvent):
942 """A component or factory was unregistered
945 """A component or factory was unregistered
943 """
946 """
944
947
945 @implementer(IUnregistered)
948 @implementer(IUnregistered)
946 class Unregistered(RegistrationEvent):
949 class Unregistered(RegistrationEvent):
947 """A component or factory was unregistered
950 """A component or factory was unregistered
948 """
951 """
949 pass
952 pass
950
953
951 class IComponentRegistry(Interface):
954 class IComponentRegistry(Interface):
952 """Register components
955 """Register components
953 """
956 """
954
957
955 def registerUtility(component=None, provided=None, name=_BLANK,
958 def registerUtility(component=None, provided=None, name=_BLANK,
956 info=_BLANK, factory=None):
959 info=_BLANK, factory=None):
957 """Register a utility
960 """Register a utility
958
961
959 factory
962 factory
960 Factory for the component to be registerd.
963 Factory for the component to be registerd.
961
964
962 component
965 component
963 The registered component
966 The registered component
964
967
965 provided
968 provided
966 This is the interface provided by the utility. If the
969 This is the interface provided by the utility. If the
967 component provides a single interface, then this
970 component provides a single interface, then this
968 argument is optional and the component-implemented
971 argument is optional and the component-implemented
969 interface will be used.
972 interface will be used.
970
973
971 name
974 name
972 The utility name.
975 The utility name.
973
976
974 info
977 info
975 An object that can be converted to a string to provide
978 An object that can be converted to a string to provide
976 information about the registration.
979 information about the registration.
977
980
978 Only one of component and factory can be used.
981 Only one of component and factory can be used.
979 A Registered event is generated with an IUtilityRegistration.
982 A Registered event is generated with an IUtilityRegistration.
980 """
983 """
981
984
982 def unregisterUtility(component=None, provided=None, name=_BLANK,
985 def unregisterUtility(component=None, provided=None, name=_BLANK,
983 factory=None):
986 factory=None):
984 """Unregister a utility
987 """Unregister a utility
985
988
986 A boolean is returned indicating whether the registry was
989 A boolean is returned indicating whether the registry was
987 changed. If the given component is None and there is no
990 changed. If the given component is None and there is no
988 component registered, or if the given component is not
991 component registered, or if the given component is not
989 None and is not registered, then the function returns
992 None and is not registered, then the function returns
990 False, otherwise it returns True.
993 False, otherwise it returns True.
991
994
992 factory
995 factory
993 Factory for the component to be unregisterd.
996 Factory for the component to be unregisterd.
994
997
995 component
998 component
996 The registered component The given component can be
999 The registered component The given component can be
997 None, in which case any component registered to provide
1000 None, in which case any component registered to provide
998 the given provided interface with the given name is
1001 the given provided interface with the given name is
999 unregistered.
1002 unregistered.
1000
1003
1001 provided
1004 provided
1002 This is the interface provided by the utility. If the
1005 This is the interface provided by the utility. If the
1003 component is not None and provides a single interface,
1006 component is not None and provides a single interface,
1004 then this argument is optional and the
1007 then this argument is optional and the
1005 component-implemented interface will be used.
1008 component-implemented interface will be used.
1006
1009
1007 name
1010 name
1008 The utility name.
1011 The utility name.
1009
1012
1010 Only one of component and factory can be used.
1013 Only one of component and factory can be used.
1011 An UnRegistered event is generated with an IUtilityRegistration.
1014 An UnRegistered event is generated with an IUtilityRegistration.
1012 """
1015 """
1013
1016
1014 def registeredUtilities():
1017 def registeredUtilities():
1015 """Return an iterable of IUtilityRegistration instances.
1018 """Return an iterable of IUtilityRegistration instances.
1016
1019
1017 These registrations describe the current utility registrations
1020 These registrations describe the current utility registrations
1018 in the object.
1021 in the object.
1019 """
1022 """
1020
1023
1021 def registerAdapter(factory, required=None, provided=None, name=_BLANK,
1024 def registerAdapter(factory, required=None, provided=None, name=_BLANK,
1022 info=_BLANK):
1025 info=_BLANK):
1023 """Register an adapter factory
1026 """Register an adapter factory
1024
1027
1025 Parameters:
1028 Parameters:
1026
1029
1027 factory
1030 factory
1028 The object used to compute the adapter
1031 The object used to compute the adapter
1029
1032
1030 required
1033 required
1031 This is a sequence of specifications for objects to be
1034 This is a sequence of specifications for objects to be
1032 adapted. If omitted, then the value of the factory's
1035 adapted. If omitted, then the value of the factory's
1033 __component_adapts__ attribute will be used. The
1036 __component_adapts__ attribute will be used. The
1034 __component_adapts__ attribute is usually attribute is
1037 __component_adapts__ attribute is usually attribute is
1035 normally set in class definitions using adapts
1038 normally set in class definitions using adapts
1036 function, or for callables using the adapter
1039 function, or for callables using the adapter
1037 decorator. If the factory doesn't have a
1040 decorator. If the factory doesn't have a
1038 __component_adapts__ adapts attribute, then this
1041 __component_adapts__ adapts attribute, then this
1039 argument is required.
1042 argument is required.
1040
1043
1041 provided
1044 provided
1042 This is the interface provided by the adapter and
1045 This is the interface provided by the adapter and
1043 implemented by the factory. If the factory
1046 implemented by the factory. If the factory
1044 implements a single interface, then this argument is
1047 implements a single interface, then this argument is
1045 optional and the factory-implemented interface will be
1048 optional and the factory-implemented interface will be
1046 used.
1049 used.
1047
1050
1048 name
1051 name
1049 The adapter name.
1052 The adapter name.
1050
1053
1051 info
1054 info
1052 An object that can be converted to a string to provide
1055 An object that can be converted to a string to provide
1053 information about the registration.
1056 information about the registration.
1054
1057
1055 A Registered event is generated with an IAdapterRegistration.
1058 A Registered event is generated with an IAdapterRegistration.
1056 """
1059 """
1057
1060
1058 def unregisterAdapter(factory=None, required=None,
1061 def unregisterAdapter(factory=None, required=None,
1059 provided=None, name=_BLANK):
1062 provided=None, name=_BLANK):
1060 """Unregister an adapter factory
1063 """Unregister an adapter factory
1061
1064
1062 A boolean is returned indicating whether the registry was
1065 A boolean is returned indicating whether the registry was
1063 changed. If the given component is None and there is no
1066 changed. If the given component is None and there is no
1064 component registered, or if the given component is not
1067 component registered, or if the given component is not
1065 None and is not registered, then the function returns
1068 None and is not registered, then the function returns
1066 False, otherwise it returns True.
1069 False, otherwise it returns True.
1067
1070
1068 Parameters:
1071 Parameters:
1069
1072
1070 factory
1073 factory
1071 This is the object used to compute the adapter. The
1074 This is the object used to compute the adapter. The
1072 factory can be None, in which case any factory
1075 factory can be None, in which case any factory
1073 registered to implement the given provided interface
1076 registered to implement the given provided interface
1074 for the given required specifications with the given
1077 for the given required specifications with the given
1075 name is unregistered.
1078 name is unregistered.
1076
1079
1077 required
1080 required
1078 This is a sequence of specifications for objects to be
1081 This is a sequence of specifications for objects to be
1079 adapted. If the factory is not None and the required
1082 adapted. If the factory is not None and the required
1080 arguments is omitted, then the value of the factory's
1083 arguments is omitted, then the value of the factory's
1081 __component_adapts__ attribute will be used. The
1084 __component_adapts__ attribute will be used. The
1082 __component_adapts__ attribute attribute is normally
1085 __component_adapts__ attribute attribute is normally
1083 set in class definitions using adapts function, or for
1086 set in class definitions using adapts function, or for
1084 callables using the adapter decorator. If the factory
1087 callables using the adapter decorator. If the factory
1085 is None or doesn't have a __component_adapts__ adapts
1088 is None or doesn't have a __component_adapts__ adapts
1086 attribute, then this argument is required.
1089 attribute, then this argument is required.
1087
1090
1088 provided
1091 provided
1089 This is the interface provided by the adapter and
1092 This is the interface provided by the adapter and
1090 implemented by the factory. If the factory is not
1093 implemented by the factory. If the factory is not
1091 None and implements a single interface, then this
1094 None and implements a single interface, then this
1092 argument is optional and the factory-implemented
1095 argument is optional and the factory-implemented
1093 interface will be used.
1096 interface will be used.
1094
1097
1095 name
1098 name
1096 The adapter name.
1099 The adapter name.
1097
1100
1098 An Unregistered event is generated with an IAdapterRegistration.
1101 An Unregistered event is generated with an IAdapterRegistration.
1099 """
1102 """
1100
1103
1101 def registeredAdapters():
1104 def registeredAdapters():
1102 """Return an iterable of IAdapterRegistration instances.
1105 """Return an iterable of IAdapterRegistration instances.
1103
1106
1104 These registrations describe the current adapter registrations
1107 These registrations describe the current adapter registrations
1105 in the object.
1108 in the object.
1106 """
1109 """
1107
1110
1108 def registerSubscriptionAdapter(factory, required=None, provides=None,
1111 def registerSubscriptionAdapter(factory, required=None, provides=None,
1109 name=_BLANK, info=''):
1112 name=_BLANK, info=''):
1110 """Register a subscriber factory
1113 """Register a subscriber factory
1111
1114
1112 Parameters:
1115 Parameters:
1113
1116
1114 factory
1117 factory
1115 The object used to compute the adapter
1118 The object used to compute the adapter
1116
1119
1117 required
1120 required
1118 This is a sequence of specifications for objects to be
1121 This is a sequence of specifications for objects to be
1119 adapted. If omitted, then the value of the factory's
1122 adapted. If omitted, then the value of the factory's
1120 __component_adapts__ attribute will be used. The
1123 __component_adapts__ attribute will be used. The
1121 __component_adapts__ attribute is usually attribute is
1124 __component_adapts__ attribute is usually attribute is
1122 normally set in class definitions using adapts
1125 normally set in class definitions using adapts
1123 function, or for callables using the adapter
1126 function, or for callables using the adapter
1124 decorator. If the factory doesn't have a
1127 decorator. If the factory doesn't have a
1125 __component_adapts__ adapts attribute, then this
1128 __component_adapts__ adapts attribute, then this
1126 argument is required.
1129 argument is required.
1127
1130
1128 provided
1131 provided
1129 This is the interface provided by the adapter and
1132 This is the interface provided by the adapter and
1130 implemented by the factory. If the factory implements
1133 implemented by the factory. If the factory implements
1131 a single interface, then this argument is optional and
1134 a single interface, then this argument is optional and
1132 the factory-implemented interface will be used.
1135 the factory-implemented interface will be used.
1133
1136
1134 name
1137 name
1135 The adapter name.
1138 The adapter name.
1136
1139
1137 Currently, only the empty string is accepted. Other
1140 Currently, only the empty string is accepted. Other
1138 strings will be accepted in the future when support for
1141 strings will be accepted in the future when support for
1139 named subscribers is added.
1142 named subscribers is added.
1140
1143
1141 info
1144 info
1142 An object that can be converted to a string to provide
1145 An object that can be converted to a string to provide
1143 information about the registration.
1146 information about the registration.
1144
1147
1145 A Registered event is generated with an
1148 A Registered event is generated with an
1146 ISubscriptionAdapterRegistration.
1149 ISubscriptionAdapterRegistration.
1147 """
1150 """
1148
1151
1149 def unregisterSubscriptionAdapter(factory=None, required=None,
1152 def unregisterSubscriptionAdapter(factory=None, required=None,
1150 provides=None, name=_BLANK):
1153 provides=None, name=_BLANK):
1151 """Unregister a subscriber factory.
1154 """Unregister a subscriber factory.
1152
1155
1153 A boolean is returned indicating whether the registry was
1156 A boolean is returned indicating whether the registry was
1154 changed. If the given component is None and there is no
1157 changed. If the given component is None and there is no
1155 component registered, or if the given component is not
1158 component registered, or if the given component is not
1156 None and is not registered, then the function returns
1159 None and is not registered, then the function returns
1157 False, otherwise it returns True.
1160 False, otherwise it returns True.
1158
1161
1159 Parameters:
1162 Parameters:
1160
1163
1161 factory
1164 factory
1162 This is the object used to compute the adapter. The
1165 This is the object used to compute the adapter. The
1163 factory can be None, in which case any factories
1166 factory can be None, in which case any factories
1164 registered to implement the given provided interface
1167 registered to implement the given provided interface
1165 for the given required specifications with the given
1168 for the given required specifications with the given
1166 name are unregistered.
1169 name are unregistered.
1167
1170
1168 required
1171 required
1169 This is a sequence of specifications for objects to be
1172 This is a sequence of specifications for objects to be
1170 adapted. If the factory is not None and the required
1173 adapted. If the factory is not None and the required
1171 arguments is omitted, then the value of the factory's
1174 arguments is omitted, then the value of the factory's
1172 __component_adapts__ attribute will be used. The
1175 __component_adapts__ attribute will be used. The
1173 __component_adapts__ attribute attribute is normally
1176 __component_adapts__ attribute attribute is normally
1174 set in class definitions using adapts function, or for
1177 set in class definitions using adapts function, or for
1175 callables using the adapter decorator. If the factory
1178 callables using the adapter decorator. If the factory
1176 is None or doesn't have a __component_adapts__ adapts
1179 is None or doesn't have a __component_adapts__ adapts
1177 attribute, then this argument is required.
1180 attribute, then this argument is required.
1178
1181
1179 provided
1182 provided
1180 This is the interface provided by the adapter and
1183 This is the interface provided by the adapter and
1181 implemented by the factory. If the factory is not
1184 implemented by the factory. If the factory is not
1182 None implements a single interface, then this argument
1185 None implements a single interface, then this argument
1183 is optional and the factory-implemented interface will
1186 is optional and the factory-implemented interface will
1184 be used.
1187 be used.
1185
1188
1186 name
1189 name
1187 The adapter name.
1190 The adapter name.
1188
1191
1189 Currently, only the empty string is accepted. Other
1192 Currently, only the empty string is accepted. Other
1190 strings will be accepted in the future when support for
1193 strings will be accepted in the future when support for
1191 named subscribers is added.
1194 named subscribers is added.
1192
1195
1193 An Unregistered event is generated with an
1196 An Unregistered event is generated with an
1194 ISubscriptionAdapterRegistration.
1197 ISubscriptionAdapterRegistration.
1195 """
1198 """
1196
1199
1197 def registeredSubscriptionAdapters():
1200 def registeredSubscriptionAdapters():
1198 """Return an iterable of ISubscriptionAdapterRegistration instances.
1201 """Return an iterable of ISubscriptionAdapterRegistration instances.
1199
1202
1200 These registrations describe the current subscription adapter
1203 These registrations describe the current subscription adapter
1201 registrations in the object.
1204 registrations in the object.
1202 """
1205 """
1203
1206
1204 def registerHandler(handler, required=None, name=_BLANK, info=''):
1207 def registerHandler(handler, required=None, name=_BLANK, info=''):
1205 """Register a handler.
1208 """Register a handler.
1206
1209
1207 A handler is a subscriber that doesn't compute an adapter
1210 A handler is a subscriber that doesn't compute an adapter
1208 but performs some function when called.
1211 but performs some function when called.
1209
1212
1210 Parameters:
1213 Parameters:
1211
1214
1212 handler
1215 handler
1213 The object used to handle some event represented by
1216 The object used to handle some event represented by
1214 the objects passed to it.
1217 the objects passed to it.
1215
1218
1216 required
1219 required
1217 This is a sequence of specifications for objects to be
1220 This is a sequence of specifications for objects to be
1218 adapted. If omitted, then the value of the factory's
1221 adapted. If omitted, then the value of the factory's
1219 __component_adapts__ attribute will be used. The
1222 __component_adapts__ attribute will be used. The
1220 __component_adapts__ attribute is usually attribute is
1223 __component_adapts__ attribute is usually attribute is
1221 normally set in class definitions using adapts
1224 normally set in class definitions using adapts
1222 function, or for callables using the adapter
1225 function, or for callables using the adapter
1223 decorator. If the factory doesn't have a
1226 decorator. If the factory doesn't have a
1224 __component_adapts__ adapts attribute, then this
1227 __component_adapts__ adapts attribute, then this
1225 argument is required.
1228 argument is required.
1226
1229
1227 name
1230 name
1228 The handler name.
1231 The handler name.
1229
1232
1230 Currently, only the empty string is accepted. Other
1233 Currently, only the empty string is accepted. Other
1231 strings will be accepted in the future when support for
1234 strings will be accepted in the future when support for
1232 named handlers is added.
1235 named handlers is added.
1233
1236
1234 info
1237 info
1235 An object that can be converted to a string to provide
1238 An object that can be converted to a string to provide
1236 information about the registration.
1239 information about the registration.
1237
1240
1238
1241
1239 A Registered event is generated with an IHandlerRegistration.
1242 A Registered event is generated with an IHandlerRegistration.
1240 """
1243 """
1241
1244
1242 def unregisterHandler(handler=None, required=None, name=_BLANK):
1245 def unregisterHandler(handler=None, required=None, name=_BLANK):
1243 """Unregister a handler.
1246 """Unregister a handler.
1244
1247
1245 A handler is a subscriber that doesn't compute an adapter
1248 A handler is a subscriber that doesn't compute an adapter
1246 but performs some function when called.
1249 but performs some function when called.
1247
1250
1248 A boolean is returned indicating whether the registry was
1251 A boolean is returned indicating whether the registry was
1249 changed.
1252 changed.
1250
1253
1251 Parameters:
1254 Parameters:
1252
1255
1253 handler
1256 handler
1254 This is the object used to handle some event
1257 This is the object used to handle some event
1255 represented by the objects passed to it. The handler
1258 represented by the objects passed to it. The handler
1256 can be None, in which case any handlers registered for
1259 can be None, in which case any handlers registered for
1257 the given required specifications with the given are
1260 the given required specifications with the given are
1258 unregistered.
1261 unregistered.
1259
1262
1260 required
1263 required
1261 This is a sequence of specifications for objects to be
1264 This is a sequence of specifications for objects to be
1262 adapted. If omitted, then the value of the factory's
1265 adapted. If omitted, then the value of the factory's
1263 __component_adapts__ attribute will be used. The
1266 __component_adapts__ attribute will be used. The
1264 __component_adapts__ attribute is usually attribute is
1267 __component_adapts__ attribute is usually attribute is
1265 normally set in class definitions using adapts
1268 normally set in class definitions using adapts
1266 function, or for callables using the adapter
1269 function, or for callables using the adapter
1267 decorator. If the factory doesn't have a
1270 decorator. If the factory doesn't have a
1268 __component_adapts__ adapts attribute, then this
1271 __component_adapts__ adapts attribute, then this
1269 argument is required.
1272 argument is required.
1270
1273
1271 name
1274 name
1272 The handler name.
1275 The handler name.
1273
1276
1274 Currently, only the empty string is accepted. Other
1277 Currently, only the empty string is accepted. Other
1275 strings will be accepted in the future when support for
1278 strings will be accepted in the future when support for
1276 named handlers is added.
1279 named handlers is added.
1277
1280
1278 An Unregistered event is generated with an IHandlerRegistration.
1281 An Unregistered event is generated with an IHandlerRegistration.
1279 """
1282 """
1280
1283
1281 def registeredHandlers():
1284 def registeredHandlers():
1282 """Return an iterable of IHandlerRegistration instances.
1285 """Return an iterable of IHandlerRegistration instances.
1283
1286
1284 These registrations describe the current handler registrations
1287 These registrations describe the current handler registrations
1285 in the object.
1288 in the object.
1286 """
1289 """
1287
1290
1288
1291
1289 class IComponents(IComponentLookup, IComponentRegistry):
1292 class IComponents(IComponentLookup, IComponentRegistry):
1290 """Component registration and access
1293 """Component registration and access
1291 """
1294 """
1292
1295
1293
1296
1294 # end formerly in zope.component
1297 # end formerly in zope.component
@@ -1,654 +1,657 b''
1 ##############################################################################
1 ##############################################################################
2 #
2 #
3 # Copyright (c) 2006 Zope Foundation and Contributors.
3 # Copyright (c) 2006 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """Basic components support
14 """Basic components support
15 """
15 """
16
17 from __future__ import absolute_import
18
16 from collections import defaultdict
19 from collections import defaultdict
17
20
18 try:
21 try:
19 from zope.event import notify
22 from ..event import notify
20 except ImportError: # pragma: no cover
23 except ImportError: # pragma: no cover
21 def notify(*arg, **kw): pass
24 def notify(*arg, **kw): pass
22
25
23 from zope.interface.interfaces import ISpecification
26 from .interfaces import ISpecification
24 from zope.interface.interfaces import ComponentLookupError
27 from .interfaces import ComponentLookupError
25 from zope.interface.interfaces import IAdapterRegistration
28 from .interfaces import IAdapterRegistration
26 from zope.interface.interfaces import IComponents
29 from .interfaces import IComponents
27 from zope.interface.interfaces import IHandlerRegistration
30 from .interfaces import IHandlerRegistration
28 from zope.interface.interfaces import ISubscriptionAdapterRegistration
31 from .interfaces import ISubscriptionAdapterRegistration
29 from zope.interface.interfaces import IUtilityRegistration
32 from .interfaces import IUtilityRegistration
30 from zope.interface.interfaces import Registered
33 from .interfaces import Registered
31 from zope.interface.interfaces import Unregistered
34 from .interfaces import Unregistered
32
35
33 from zope.interface.interface import Interface
36 from .interface import Interface
34 from zope.interface.declarations import implementedBy
37 from .declarations import implementedBy
35 from zope.interface.declarations import implementer
38 from .declarations import implementer
36 from zope.interface.declarations import implementer_only
39 from .declarations import implementer_only
37 from zope.interface.declarations import providedBy
40 from .declarations import providedBy
38 from zope.interface.adapter import AdapterRegistry
41 from .adapter import AdapterRegistry
39 from zope.interface._compat import CLASS_TYPES
42 from ._compat import CLASS_TYPES
40 from zope.interface._compat import STRING_TYPES
43 from ._compat import STRING_TYPES
41
44
42
45
43 class _UnhashableComponentCounter(object):
46 class _UnhashableComponentCounter(object):
44 # defaultdict(int)-like object for unhashable components
47 # defaultdict(int)-like object for unhashable components
45
48
46 def __init__(self, otherdict):
49 def __init__(self, otherdict):
47 # [(component, count)]
50 # [(component, count)]
48 self._data = [item for item in otherdict.items()]
51 self._data = [item for item in otherdict.items()]
49
52
50 def __getitem__(self, key):
53 def __getitem__(self, key):
51 for component, count in self._data:
54 for component, count in self._data:
52 if component == key:
55 if component == key:
53 return count
56 return count
54 return 0
57 return 0
55
58
56 def __setitem__(self, component, count):
59 def __setitem__(self, component, count):
57 for i, data in enumerate(self._data):
60 for i, data in enumerate(self._data):
58 if data[0] == component:
61 if data[0] == component:
59 self._data[i] = component, count
62 self._data[i] = component, count
60 return
63 return
61 self._data.append((component, count))
64 self._data.append((component, count))
62
65
63 def __delitem__(self, component):
66 def __delitem__(self, component):
64 for i, data in enumerate(self._data):
67 for i, data in enumerate(self._data):
65 if data[0] == component:
68 if data[0] == component:
66 del self._data[i]
69 del self._data[i]
67 return
70 return
68 raise KeyError(component) # pragma: no cover
71 raise KeyError(component) # pragma: no cover
69
72
70 def _defaultdict_int():
73 def _defaultdict_int():
71 return defaultdict(int)
74 return defaultdict(int)
72
75
73 class _UtilityRegistrations(object):
76 class _UtilityRegistrations(object):
74
77
75 def __init__(self, utilities, utility_registrations):
78 def __init__(self, utilities, utility_registrations):
76 # {provided -> {component: count}}
79 # {provided -> {component: count}}
77 self._cache = defaultdict(_defaultdict_int)
80 self._cache = defaultdict(_defaultdict_int)
78 self._utilities = utilities
81 self._utilities = utilities
79 self._utility_registrations = utility_registrations
82 self._utility_registrations = utility_registrations
80
83
81 self.__populate_cache()
84 self.__populate_cache()
82
85
83 def __populate_cache(self):
86 def __populate_cache(self):
84 for ((p, _), data) in iter(self._utility_registrations.items()):
87 for ((p, _), data) in iter(self._utility_registrations.items()):
85 component = data[0]
88 component = data[0]
86 self.__cache_utility(p, component)
89 self.__cache_utility(p, component)
87
90
88 def __cache_utility(self, provided, component):
91 def __cache_utility(self, provided, component):
89 try:
92 try:
90 self._cache[provided][component] += 1
93 self._cache[provided][component] += 1
91 except TypeError:
94 except TypeError:
92 # The component is not hashable, and we have a dict. Switch to a strategy
95 # The component is not hashable, and we have a dict. Switch to a strategy
93 # that doesn't use hashing.
96 # that doesn't use hashing.
94 prov = self._cache[provided] = _UnhashableComponentCounter(self._cache[provided])
97 prov = self._cache[provided] = _UnhashableComponentCounter(self._cache[provided])
95 prov[component] += 1
98 prov[component] += 1
96
99
97 def __uncache_utility(self, provided, component):
100 def __uncache_utility(self, provided, component):
98 provided = self._cache[provided]
101 provided = self._cache[provided]
99 # It seems like this line could raise a TypeError if component isn't
102 # It seems like this line could raise a TypeError if component isn't
100 # hashable and we haven't yet switched to _UnhashableComponentCounter. However,
103 # hashable and we haven't yet switched to _UnhashableComponentCounter. However,
101 # we can't actually get in that situation. In order to get here, we would
104 # we can't actually get in that situation. In order to get here, we would
102 # have had to cache the utility already which would have switched
105 # have had to cache the utility already which would have switched
103 # the datastructure if needed.
106 # the datastructure if needed.
104 count = provided[component]
107 count = provided[component]
105 count -= 1
108 count -= 1
106 if count == 0:
109 if count == 0:
107 del provided[component]
110 del provided[component]
108 else:
111 else:
109 provided[component] = count
112 provided[component] = count
110 return count > 0
113 return count > 0
111
114
112 def _is_utility_subscribed(self, provided, component):
115 def _is_utility_subscribed(self, provided, component):
113 try:
116 try:
114 return self._cache[provided][component] > 0
117 return self._cache[provided][component] > 0
115 except TypeError:
118 except TypeError:
116 # Not hashable and we're still using a dict
119 # Not hashable and we're still using a dict
117 return False
120 return False
118
121
119 def registerUtility(self, provided, name, component, info, factory):
122 def registerUtility(self, provided, name, component, info, factory):
120 subscribed = self._is_utility_subscribed(provided, component)
123 subscribed = self._is_utility_subscribed(provided, component)
121
124
122 self._utility_registrations[(provided, name)] = component, info, factory
125 self._utility_registrations[(provided, name)] = component, info, factory
123 self._utilities.register((), provided, name, component)
126 self._utilities.register((), provided, name, component)
124
127
125 if not subscribed:
128 if not subscribed:
126 self._utilities.subscribe((), provided, component)
129 self._utilities.subscribe((), provided, component)
127
130
128 self.__cache_utility(provided, component)
131 self.__cache_utility(provided, component)
129
132
130 def unregisterUtility(self, provided, name, component):
133 def unregisterUtility(self, provided, name, component):
131 del self._utility_registrations[(provided, name)]
134 del self._utility_registrations[(provided, name)]
132 self._utilities.unregister((), provided, name)
135 self._utilities.unregister((), provided, name)
133
136
134 subscribed = self.__uncache_utility(provided, component)
137 subscribed = self.__uncache_utility(provided, component)
135
138
136 if not subscribed:
139 if not subscribed:
137 self._utilities.unsubscribe((), provided, component)
140 self._utilities.unsubscribe((), provided, component)
138
141
139
142
140 @implementer(IComponents)
143 @implementer(IComponents)
141 class Components(object):
144 class Components(object):
142
145
143 _v_utility_registrations_cache = None
146 _v_utility_registrations_cache = None
144
147
145 def __init__(self, name='', bases=()):
148 def __init__(self, name='', bases=()):
146 # __init__ is used for test cleanup as well as initialization.
149 # __init__ is used for test cleanup as well as initialization.
147 # XXX add a separate API for test cleanup.
150 # XXX add a separate API for test cleanup.
148 assert isinstance(name, STRING_TYPES)
151 assert isinstance(name, STRING_TYPES)
149 self.__name__ = name
152 self.__name__ = name
150 self._init_registries()
153 self._init_registries()
151 self._init_registrations()
154 self._init_registrations()
152 self.__bases__ = tuple(bases)
155 self.__bases__ = tuple(bases)
153 self._v_utility_registrations_cache = None
156 self._v_utility_registrations_cache = None
154
157
155 def __repr__(self):
158 def __repr__(self):
156 return "<%s %s>" % (self.__class__.__name__, self.__name__)
159 return "<%s %s>" % (self.__class__.__name__, self.__name__)
157
160
158 def __reduce__(self):
161 def __reduce__(self):
159 # Mimic what a persistent.Persistent object does and elide
162 # Mimic what a persistent.Persistent object does and elide
160 # _v_ attributes so that they don't get saved in ZODB.
163 # _v_ attributes so that they don't get saved in ZODB.
161 # This allows us to store things that cannot be pickled in such
164 # This allows us to store things that cannot be pickled in such
162 # attributes.
165 # attributes.
163 reduction = super(Components, self).__reduce__()
166 reduction = super(Components, self).__reduce__()
164 # (callable, args, state, listiter, dictiter)
167 # (callable, args, state, listiter, dictiter)
165 # We assume the state is always a dict; the last three items
168 # We assume the state is always a dict; the last three items
166 # are technically optional and can be missing or None.
169 # are technically optional and can be missing or None.
167 filtered_state = {k: v for k, v in reduction[2].items()
170 filtered_state = {k: v for k, v in reduction[2].items()
168 if not k.startswith('_v_')}
171 if not k.startswith('_v_')}
169 reduction = list(reduction)
172 reduction = list(reduction)
170 reduction[2] = filtered_state
173 reduction[2] = filtered_state
171 return tuple(reduction)
174 return tuple(reduction)
172
175
173 def _init_registries(self):
176 def _init_registries(self):
174 # Subclasses have never been required to call this method
177 # Subclasses have never been required to call this method
175 # if they override it, merely to fill in these two attributes.
178 # if they override it, merely to fill in these two attributes.
176 self.adapters = AdapterRegistry()
179 self.adapters = AdapterRegistry()
177 self.utilities = AdapterRegistry()
180 self.utilities = AdapterRegistry()
178
181
179 def _init_registrations(self):
182 def _init_registrations(self):
180 self._utility_registrations = {}
183 self._utility_registrations = {}
181 self._adapter_registrations = {}
184 self._adapter_registrations = {}
182 self._subscription_registrations = []
185 self._subscription_registrations = []
183 self._handler_registrations = []
186 self._handler_registrations = []
184
187
185 @property
188 @property
186 def _utility_registrations_cache(self):
189 def _utility_registrations_cache(self):
187 # We use a _v_ attribute internally so that data aren't saved in ZODB,
190 # We use a _v_ attribute internally so that data aren't saved in ZODB,
188 # because this object cannot be pickled.
191 # because this object cannot be pickled.
189 cache = self._v_utility_registrations_cache
192 cache = self._v_utility_registrations_cache
190 if (cache is None
193 if (cache is None
191 or cache._utilities is not self.utilities
194 or cache._utilities is not self.utilities
192 or cache._utility_registrations is not self._utility_registrations):
195 or cache._utility_registrations is not self._utility_registrations):
193 cache = self._v_utility_registrations_cache = _UtilityRegistrations(
196 cache = self._v_utility_registrations_cache = _UtilityRegistrations(
194 self.utilities,
197 self.utilities,
195 self._utility_registrations)
198 self._utility_registrations)
196 return cache
199 return cache
197
200
198 def _getBases(self):
201 def _getBases(self):
199 # Subclasses might override
202 # Subclasses might override
200 return self.__dict__.get('__bases__', ())
203 return self.__dict__.get('__bases__', ())
201
204
202 def _setBases(self, bases):
205 def _setBases(self, bases):
203 # Subclasses might override
206 # Subclasses might override
204 self.adapters.__bases__ = tuple([
207 self.adapters.__bases__ = tuple([
205 base.adapters for base in bases])
208 base.adapters for base in bases])
206 self.utilities.__bases__ = tuple([
209 self.utilities.__bases__ = tuple([
207 base.utilities for base in bases])
210 base.utilities for base in bases])
208 self.__dict__['__bases__'] = tuple(bases)
211 self.__dict__['__bases__'] = tuple(bases)
209
212
210 __bases__ = property(
213 __bases__ = property(
211 lambda self: self._getBases(),
214 lambda self: self._getBases(),
212 lambda self, bases: self._setBases(bases),
215 lambda self, bases: self._setBases(bases),
213 )
216 )
214
217
215 def registerUtility(self, component=None, provided=None, name=u'',
218 def registerUtility(self, component=None, provided=None, name=u'',
216 info=u'', event=True, factory=None):
219 info=u'', event=True, factory=None):
217 if factory:
220 if factory:
218 if component:
221 if component:
219 raise TypeError("Can't specify factory and component.")
222 raise TypeError("Can't specify factory and component.")
220 component = factory()
223 component = factory()
221
224
222 if provided is None:
225 if provided is None:
223 provided = _getUtilityProvided(component)
226 provided = _getUtilityProvided(component)
224
227
225 if name == u'':
228 if name == u'':
226 name = _getName(component)
229 name = _getName(component)
227
230
228 reg = self._utility_registrations.get((provided, name))
231 reg = self._utility_registrations.get((provided, name))
229 if reg is not None:
232 if reg is not None:
230 if reg[:2] == (component, info):
233 if reg[:2] == (component, info):
231 # already registered
234 # already registered
232 return
235 return
233 self.unregisterUtility(reg[0], provided, name)
236 self.unregisterUtility(reg[0], provided, name)
234
237
235 self._utility_registrations_cache.registerUtility(
238 self._utility_registrations_cache.registerUtility(
236 provided, name, component, info, factory)
239 provided, name, component, info, factory)
237
240
238 if event:
241 if event:
239 notify(Registered(
242 notify(Registered(
240 UtilityRegistration(self, provided, name, component, info,
243 UtilityRegistration(self, provided, name, component, info,
241 factory)
244 factory)
242 ))
245 ))
243
246
244 def unregisterUtility(self, component=None, provided=None, name=u'',
247 def unregisterUtility(self, component=None, provided=None, name=u'',
245 factory=None):
248 factory=None):
246 if factory:
249 if factory:
247 if component:
250 if component:
248 raise TypeError("Can't specify factory and component.")
251 raise TypeError("Can't specify factory and component.")
249 component = factory()
252 component = factory()
250
253
251 if provided is None:
254 if provided is None:
252 if component is None:
255 if component is None:
253 raise TypeError("Must specify one of component, factory and "
256 raise TypeError("Must specify one of component, factory and "
254 "provided")
257 "provided")
255 provided = _getUtilityProvided(component)
258 provided = _getUtilityProvided(component)
256
259
257 old = self._utility_registrations.get((provided, name))
260 old = self._utility_registrations.get((provided, name))
258 if (old is None) or ((component is not None) and
261 if (old is None) or ((component is not None) and
259 (component != old[0])):
262 (component != old[0])):
260 return False
263 return False
261
264
262 if component is None:
265 if component is None:
263 component = old[0]
266 component = old[0]
264
267
265 # Note that component is now the old thing registered
268 # Note that component is now the old thing registered
266 self._utility_registrations_cache.unregisterUtility(
269 self._utility_registrations_cache.unregisterUtility(
267 provided, name, component)
270 provided, name, component)
268
271
269 notify(Unregistered(
272 notify(Unregistered(
270 UtilityRegistration(self, provided, name, component, *old[1:])
273 UtilityRegistration(self, provided, name, component, *old[1:])
271 ))
274 ))
272
275
273 return True
276 return True
274
277
275 def registeredUtilities(self):
278 def registeredUtilities(self):
276 for ((provided, name), data
279 for ((provided, name), data
277 ) in iter(self._utility_registrations.items()):
280 ) in iter(self._utility_registrations.items()):
278 yield UtilityRegistration(self, provided, name, *data)
281 yield UtilityRegistration(self, provided, name, *data)
279
282
280 def queryUtility(self, provided, name=u'', default=None):
283 def queryUtility(self, provided, name=u'', default=None):
281 return self.utilities.lookup((), provided, name, default)
284 return self.utilities.lookup((), provided, name, default)
282
285
283 def getUtility(self, provided, name=u''):
286 def getUtility(self, provided, name=u''):
284 utility = self.utilities.lookup((), provided, name)
287 utility = self.utilities.lookup((), provided, name)
285 if utility is None:
288 if utility is None:
286 raise ComponentLookupError(provided, name)
289 raise ComponentLookupError(provided, name)
287 return utility
290 return utility
288
291
289 def getUtilitiesFor(self, interface):
292 def getUtilitiesFor(self, interface):
290 for name, utility in self.utilities.lookupAll((), interface):
293 for name, utility in self.utilities.lookupAll((), interface):
291 yield name, utility
294 yield name, utility
292
295
293 def getAllUtilitiesRegisteredFor(self, interface):
296 def getAllUtilitiesRegisteredFor(self, interface):
294 return self.utilities.subscriptions((), interface)
297 return self.utilities.subscriptions((), interface)
295
298
296 def registerAdapter(self, factory, required=None, provided=None,
299 def registerAdapter(self, factory, required=None, provided=None,
297 name=u'', info=u'', event=True):
300 name=u'', info=u'', event=True):
298 if provided is None:
301 if provided is None:
299 provided = _getAdapterProvided(factory)
302 provided = _getAdapterProvided(factory)
300 required = _getAdapterRequired(factory, required)
303 required = _getAdapterRequired(factory, required)
301 if name == u'':
304 if name == u'':
302 name = _getName(factory)
305 name = _getName(factory)
303 self._adapter_registrations[(required, provided, name)
306 self._adapter_registrations[(required, provided, name)
304 ] = factory, info
307 ] = factory, info
305 self.adapters.register(required, provided, name, factory)
308 self.adapters.register(required, provided, name, factory)
306
309
307 if event:
310 if event:
308 notify(Registered(
311 notify(Registered(
309 AdapterRegistration(self, required, provided, name,
312 AdapterRegistration(self, required, provided, name,
310 factory, info)
313 factory, info)
311 ))
314 ))
312
315
313
316
314 def unregisterAdapter(self, factory=None,
317 def unregisterAdapter(self, factory=None,
315 required=None, provided=None, name=u'',
318 required=None, provided=None, name=u'',
316 ):
319 ):
317 if provided is None:
320 if provided is None:
318 if factory is None:
321 if factory is None:
319 raise TypeError("Must specify one of factory and provided")
322 raise TypeError("Must specify one of factory and provided")
320 provided = _getAdapterProvided(factory)
323 provided = _getAdapterProvided(factory)
321
324
322 if (required is None) and (factory is None):
325 if (required is None) and (factory is None):
323 raise TypeError("Must specify one of factory and required")
326 raise TypeError("Must specify one of factory and required")
324
327
325 required = _getAdapterRequired(factory, required)
328 required = _getAdapterRequired(factory, required)
326 old = self._adapter_registrations.get((required, provided, name))
329 old = self._adapter_registrations.get((required, provided, name))
327 if (old is None) or ((factory is not None) and
330 if (old is None) or ((factory is not None) and
328 (factory != old[0])):
331 (factory != old[0])):
329 return False
332 return False
330
333
331 del self._adapter_registrations[(required, provided, name)]
334 del self._adapter_registrations[(required, provided, name)]
332 self.adapters.unregister(required, provided, name)
335 self.adapters.unregister(required, provided, name)
333
336
334 notify(Unregistered(
337 notify(Unregistered(
335 AdapterRegistration(self, required, provided, name,
338 AdapterRegistration(self, required, provided, name,
336 *old)
339 *old)
337 ))
340 ))
338
341
339 return True
342 return True
340
343
341 def registeredAdapters(self):
344 def registeredAdapters(self):
342 for ((required, provided, name), (component, info)
345 for ((required, provided, name), (component, info)
343 ) in iter(self._adapter_registrations.items()):
346 ) in iter(self._adapter_registrations.items()):
344 yield AdapterRegistration(self, required, provided, name,
347 yield AdapterRegistration(self, required, provided, name,
345 component, info)
348 component, info)
346
349
347 def queryAdapter(self, object, interface, name=u'', default=None):
350 def queryAdapter(self, object, interface, name=u'', default=None):
348 return self.adapters.queryAdapter(object, interface, name, default)
351 return self.adapters.queryAdapter(object, interface, name, default)
349
352
350 def getAdapter(self, object, interface, name=u''):
353 def getAdapter(self, object, interface, name=u''):
351 adapter = self.adapters.queryAdapter(object, interface, name)
354 adapter = self.adapters.queryAdapter(object, interface, name)
352 if adapter is None:
355 if adapter is None:
353 raise ComponentLookupError(object, interface, name)
356 raise ComponentLookupError(object, interface, name)
354 return adapter
357 return adapter
355
358
356 def queryMultiAdapter(self, objects, interface, name=u'',
359 def queryMultiAdapter(self, objects, interface, name=u'',
357 default=None):
360 default=None):
358 return self.adapters.queryMultiAdapter(
361 return self.adapters.queryMultiAdapter(
359 objects, interface, name, default)
362 objects, interface, name, default)
360
363
361 def getMultiAdapter(self, objects, interface, name=u''):
364 def getMultiAdapter(self, objects, interface, name=u''):
362 adapter = self.adapters.queryMultiAdapter(objects, interface, name)
365 adapter = self.adapters.queryMultiAdapter(objects, interface, name)
363 if adapter is None:
366 if adapter is None:
364 raise ComponentLookupError(objects, interface, name)
367 raise ComponentLookupError(objects, interface, name)
365 return adapter
368 return adapter
366
369
367 def getAdapters(self, objects, provided):
370 def getAdapters(self, objects, provided):
368 for name, factory in self.adapters.lookupAll(
371 for name, factory in self.adapters.lookupAll(
369 list(map(providedBy, objects)),
372 list(map(providedBy, objects)),
370 provided):
373 provided):
371 adapter = factory(*objects)
374 adapter = factory(*objects)
372 if adapter is not None:
375 if adapter is not None:
373 yield name, adapter
376 yield name, adapter
374
377
375 def registerSubscriptionAdapter(self,
378 def registerSubscriptionAdapter(self,
376 factory, required=None, provided=None,
379 factory, required=None, provided=None,
377 name=u'', info=u'',
380 name=u'', info=u'',
378 event=True):
381 event=True):
379 if name:
382 if name:
380 raise TypeError("Named subscribers are not yet supported")
383 raise TypeError("Named subscribers are not yet supported")
381 if provided is None:
384 if provided is None:
382 provided = _getAdapterProvided(factory)
385 provided = _getAdapterProvided(factory)
383 required = _getAdapterRequired(factory, required)
386 required = _getAdapterRequired(factory, required)
384 self._subscription_registrations.append(
387 self._subscription_registrations.append(
385 (required, provided, name, factory, info)
388 (required, provided, name, factory, info)
386 )
389 )
387 self.adapters.subscribe(required, provided, factory)
390 self.adapters.subscribe(required, provided, factory)
388
391
389 if event:
392 if event:
390 notify(Registered(
393 notify(Registered(
391 SubscriptionRegistration(self, required, provided, name,
394 SubscriptionRegistration(self, required, provided, name,
392 factory, info)
395 factory, info)
393 ))
396 ))
394
397
395 def registeredSubscriptionAdapters(self):
398 def registeredSubscriptionAdapters(self):
396 for data in self._subscription_registrations:
399 for data in self._subscription_registrations:
397 yield SubscriptionRegistration(self, *data)
400 yield SubscriptionRegistration(self, *data)
398
401
399 def unregisterSubscriptionAdapter(self, factory=None,
402 def unregisterSubscriptionAdapter(self, factory=None,
400 required=None, provided=None, name=u'',
403 required=None, provided=None, name=u'',
401 ):
404 ):
402 if name:
405 if name:
403 raise TypeError("Named subscribers are not yet supported")
406 raise TypeError("Named subscribers are not yet supported")
404 if provided is None:
407 if provided is None:
405 if factory is None:
408 if factory is None:
406 raise TypeError("Must specify one of factory and provided")
409 raise TypeError("Must specify one of factory and provided")
407 provided = _getAdapterProvided(factory)
410 provided = _getAdapterProvided(factory)
408
411
409 if (required is None) and (factory is None):
412 if (required is None) and (factory is None):
410 raise TypeError("Must specify one of factory and required")
413 raise TypeError("Must specify one of factory and required")
411
414
412 required = _getAdapterRequired(factory, required)
415 required = _getAdapterRequired(factory, required)
413
416
414 if factory is None:
417 if factory is None:
415 new = [(r, p, n, f, i)
418 new = [(r, p, n, f, i)
416 for (r, p, n, f, i)
419 for (r, p, n, f, i)
417 in self._subscription_registrations
420 in self._subscription_registrations
418 if not (r == required and p == provided)
421 if not (r == required and p == provided)
419 ]
422 ]
420 else:
423 else:
421 new = [(r, p, n, f, i)
424 new = [(r, p, n, f, i)
422 for (r, p, n, f, i)
425 for (r, p, n, f, i)
423 in self._subscription_registrations
426 in self._subscription_registrations
424 if not (r == required and p == provided and f == factory)
427 if not (r == required and p == provided and f == factory)
425 ]
428 ]
426
429
427 if len(new) == len(self._subscription_registrations):
430 if len(new) == len(self._subscription_registrations):
428 return False
431 return False
429
432
430
433
431 self._subscription_registrations[:] = new
434 self._subscription_registrations[:] = new
432 self.adapters.unsubscribe(required, provided, factory)
435 self.adapters.unsubscribe(required, provided, factory)
433
436
434 notify(Unregistered(
437 notify(Unregistered(
435 SubscriptionRegistration(self, required, provided, name,
438 SubscriptionRegistration(self, required, provided, name,
436 factory, '')
439 factory, '')
437 ))
440 ))
438
441
439 return True
442 return True
440
443
441 def subscribers(self, objects, provided):
444 def subscribers(self, objects, provided):
442 return self.adapters.subscribers(objects, provided)
445 return self.adapters.subscribers(objects, provided)
443
446
444 def registerHandler(self,
447 def registerHandler(self,
445 factory, required=None,
448 factory, required=None,
446 name=u'', info=u'',
449 name=u'', info=u'',
447 event=True):
450 event=True):
448 if name:
451 if name:
449 raise TypeError("Named handlers are not yet supported")
452 raise TypeError("Named handlers are not yet supported")
450 required = _getAdapterRequired(factory, required)
453 required = _getAdapterRequired(factory, required)
451 self._handler_registrations.append(
454 self._handler_registrations.append(
452 (required, name, factory, info)
455 (required, name, factory, info)
453 )
456 )
454 self.adapters.subscribe(required, None, factory)
457 self.adapters.subscribe(required, None, factory)
455
458
456 if event:
459 if event:
457 notify(Registered(
460 notify(Registered(
458 HandlerRegistration(self, required, name, factory, info)
461 HandlerRegistration(self, required, name, factory, info)
459 ))
462 ))
460
463
461 def registeredHandlers(self):
464 def registeredHandlers(self):
462 for data in self._handler_registrations:
465 for data in self._handler_registrations:
463 yield HandlerRegistration(self, *data)
466 yield HandlerRegistration(self, *data)
464
467
465 def unregisterHandler(self, factory=None, required=None, name=u''):
468 def unregisterHandler(self, factory=None, required=None, name=u''):
466 if name:
469 if name:
467 raise TypeError("Named subscribers are not yet supported")
470 raise TypeError("Named subscribers are not yet supported")
468
471
469 if (required is None) and (factory is None):
472 if (required is None) and (factory is None):
470 raise TypeError("Must specify one of factory and required")
473 raise TypeError("Must specify one of factory and required")
471
474
472 required = _getAdapterRequired(factory, required)
475 required = _getAdapterRequired(factory, required)
473
476
474 if factory is None:
477 if factory is None:
475 new = [(r, n, f, i)
478 new = [(r, n, f, i)
476 for (r, n, f, i)
479 for (r, n, f, i)
477 in self._handler_registrations
480 in self._handler_registrations
478 if r != required
481 if r != required
479 ]
482 ]
480 else:
483 else:
481 new = [(r, n, f, i)
484 new = [(r, n, f, i)
482 for (r, n, f, i)
485 for (r, n, f, i)
483 in self._handler_registrations
486 in self._handler_registrations
484 if not (r == required and f == factory)
487 if not (r == required and f == factory)
485 ]
488 ]
486
489
487 if len(new) == len(self._handler_registrations):
490 if len(new) == len(self._handler_registrations):
488 return False
491 return False
489
492
490 self._handler_registrations[:] = new
493 self._handler_registrations[:] = new
491 self.adapters.unsubscribe(required, None, factory)
494 self.adapters.unsubscribe(required, None, factory)
492
495
493 notify(Unregistered(
496 notify(Unregistered(
494 HandlerRegistration(self, required, name, factory, '')
497 HandlerRegistration(self, required, name, factory, '')
495 ))
498 ))
496
499
497 return True
500 return True
498
501
499 def handle(self, *objects):
502 def handle(self, *objects):
500 self.adapters.subscribers(objects, None)
503 self.adapters.subscribers(objects, None)
501
504
502
505
503 def _getName(component):
506 def _getName(component):
504 try:
507 try:
505 return component.__component_name__
508 return component.__component_name__
506 except AttributeError:
509 except AttributeError:
507 return u''
510 return u''
508
511
509 def _getUtilityProvided(component):
512 def _getUtilityProvided(component):
510 provided = list(providedBy(component))
513 provided = list(providedBy(component))
511 if len(provided) == 1:
514 if len(provided) == 1:
512 return provided[0]
515 return provided[0]
513 raise TypeError(
516 raise TypeError(
514 "The utility doesn't provide a single interface "
517 "The utility doesn't provide a single interface "
515 "and no provided interface was specified.")
518 "and no provided interface was specified.")
516
519
517 def _getAdapterProvided(factory):
520 def _getAdapterProvided(factory):
518 provided = list(implementedBy(factory))
521 provided = list(implementedBy(factory))
519 if len(provided) == 1:
522 if len(provided) == 1:
520 return provided[0]
523 return provided[0]
521 raise TypeError(
524 raise TypeError(
522 "The adapter factory doesn't implement a single interface "
525 "The adapter factory doesn't implement a single interface "
523 "and no provided interface was specified.")
526 "and no provided interface was specified.")
524
527
525 def _getAdapterRequired(factory, required):
528 def _getAdapterRequired(factory, required):
526 if required is None:
529 if required is None:
527 try:
530 try:
528 required = factory.__component_adapts__
531 required = factory.__component_adapts__
529 except AttributeError:
532 except AttributeError:
530 raise TypeError(
533 raise TypeError(
531 "The adapter factory doesn't have a __component_adapts__ "
534 "The adapter factory doesn't have a __component_adapts__ "
532 "attribute and no required specifications were specified"
535 "attribute and no required specifications were specified"
533 )
536 )
534 elif ISpecification.providedBy(required):
537 elif ISpecification.providedBy(required):
535 raise TypeError("the required argument should be a list of "
538 raise TypeError("the required argument should be a list of "
536 "interfaces, not a single interface")
539 "interfaces, not a single interface")
537
540
538 result = []
541 result = []
539 for r in required:
542 for r in required:
540 if r is None:
543 if r is None:
541 r = Interface
544 r = Interface
542 elif not ISpecification.providedBy(r):
545 elif not ISpecification.providedBy(r):
543 if isinstance(r, CLASS_TYPES):
546 if isinstance(r, CLASS_TYPES):
544 r = implementedBy(r)
547 r = implementedBy(r)
545 else:
548 else:
546 raise TypeError("Required specification must be a "
549 raise TypeError("Required specification must be a "
547 "specification or class."
550 "specification or class."
548 )
551 )
549 result.append(r)
552 result.append(r)
550 return tuple(result)
553 return tuple(result)
551
554
552
555
553 @implementer(IUtilityRegistration)
556 @implementer(IUtilityRegistration)
554 class UtilityRegistration(object):
557 class UtilityRegistration(object):
555
558
556 def __init__(self, registry, provided, name, component, doc, factory=None):
559 def __init__(self, registry, provided, name, component, doc, factory=None):
557 (self.registry, self.provided, self.name, self.component, self.info,
560 (self.registry, self.provided, self.name, self.component, self.info,
558 self.factory
561 self.factory
559 ) = registry, provided, name, component, doc, factory
562 ) = registry, provided, name, component, doc, factory
560
563
561 def __repr__(self):
564 def __repr__(self):
562 return '%s(%r, %s, %r, %s, %r, %r)' % (
565 return '%s(%r, %s, %r, %s, %r, %r)' % (
563 self.__class__.__name__,
566 self.__class__.__name__,
564 self.registry,
567 self.registry,
565 getattr(self.provided, '__name__', None), self.name,
568 getattr(self.provided, '__name__', None), self.name,
566 getattr(self.component, '__name__', repr(self.component)),
569 getattr(self.component, '__name__', repr(self.component)),
567 self.factory, self.info,
570 self.factory, self.info,
568 )
571 )
569
572
570 def __hash__(self):
573 def __hash__(self):
571 return id(self)
574 return id(self)
572
575
573 def __eq__(self, other):
576 def __eq__(self, other):
574 return repr(self) == repr(other)
577 return repr(self) == repr(other)
575
578
576 def __ne__(self, other):
579 def __ne__(self, other):
577 return repr(self) != repr(other)
580 return repr(self) != repr(other)
578
581
579 def __lt__(self, other):
582 def __lt__(self, other):
580 return repr(self) < repr(other)
583 return repr(self) < repr(other)
581
584
582 def __le__(self, other):
585 def __le__(self, other):
583 return repr(self) <= repr(other)
586 return repr(self) <= repr(other)
584
587
585 def __gt__(self, other):
588 def __gt__(self, other):
586 return repr(self) > repr(other)
589 return repr(self) > repr(other)
587
590
588 def __ge__(self, other):
591 def __ge__(self, other):
589 return repr(self) >= repr(other)
592 return repr(self) >= repr(other)
590
593
591 @implementer(IAdapterRegistration)
594 @implementer(IAdapterRegistration)
592 class AdapterRegistration(object):
595 class AdapterRegistration(object):
593
596
594 def __init__(self, registry, required, provided, name, component, doc):
597 def __init__(self, registry, required, provided, name, component, doc):
595 (self.registry, self.required, self.provided, self.name,
598 (self.registry, self.required, self.provided, self.name,
596 self.factory, self.info
599 self.factory, self.info
597 ) = registry, required, provided, name, component, doc
600 ) = registry, required, provided, name, component, doc
598
601
599 def __repr__(self):
602 def __repr__(self):
600 return '%s(%r, %s, %s, %r, %s, %r)' % (
603 return '%s(%r, %s, %s, %r, %s, %r)' % (
601 self.__class__.__name__,
604 self.__class__.__name__,
602 self.registry,
605 self.registry,
603 '[' + ", ".join([r.__name__ for r in self.required]) + ']',
606 '[' + ", ".join([r.__name__ for r in self.required]) + ']',
604 getattr(self.provided, '__name__', None), self.name,
607 getattr(self.provided, '__name__', None), self.name,
605 getattr(self.factory, '__name__', repr(self.factory)), self.info,
608 getattr(self.factory, '__name__', repr(self.factory)), self.info,
606 )
609 )
607
610
608 def __hash__(self):
611 def __hash__(self):
609 return id(self)
612 return id(self)
610
613
611 def __eq__(self, other):
614 def __eq__(self, other):
612 return repr(self) == repr(other)
615 return repr(self) == repr(other)
613
616
614 def __ne__(self, other):
617 def __ne__(self, other):
615 return repr(self) != repr(other)
618 return repr(self) != repr(other)
616
619
617 def __lt__(self, other):
620 def __lt__(self, other):
618 return repr(self) < repr(other)
621 return repr(self) < repr(other)
619
622
620 def __le__(self, other):
623 def __le__(self, other):
621 return repr(self) <= repr(other)
624 return repr(self) <= repr(other)
622
625
623 def __gt__(self, other):
626 def __gt__(self, other):
624 return repr(self) > repr(other)
627 return repr(self) > repr(other)
625
628
626 def __ge__(self, other):
629 def __ge__(self, other):
627 return repr(self) >= repr(other)
630 return repr(self) >= repr(other)
628
631
629 @implementer_only(ISubscriptionAdapterRegistration)
632 @implementer_only(ISubscriptionAdapterRegistration)
630 class SubscriptionRegistration(AdapterRegistration):
633 class SubscriptionRegistration(AdapterRegistration):
631 pass
634 pass
632
635
633
636
634 @implementer_only(IHandlerRegistration)
637 @implementer_only(IHandlerRegistration)
635 class HandlerRegistration(AdapterRegistration):
638 class HandlerRegistration(AdapterRegistration):
636
639
637 def __init__(self, registry, required, name, handler, doc):
640 def __init__(self, registry, required, name, handler, doc):
638 (self.registry, self.required, self.name, self.handler, self.info
641 (self.registry, self.required, self.name, self.handler, self.info
639 ) = registry, required, name, handler, doc
642 ) = registry, required, name, handler, doc
640
643
641 @property
644 @property
642 def factory(self):
645 def factory(self):
643 return self.handler
646 return self.handler
644
647
645 provided = None
648 provided = None
646
649
647 def __repr__(self):
650 def __repr__(self):
648 return '%s(%r, %s, %r, %s, %r)' % (
651 return '%s(%r, %s, %r, %s, %r)' % (
649 self.__class__.__name__,
652 self.__class__.__name__,
650 self.registry,
653 self.registry,
651 '[' + ", ".join([r.__name__ for r in self.required]) + ']',
654 '[' + ", ".join([r.__name__ for r in self.required]) + ']',
652 self.name,
655 self.name,
653 getattr(self.factory, '__name__', repr(self.factory)), self.info,
656 getattr(self.factory, '__name__', repr(self.factory)), self.info,
654 )
657 )
@@ -1,64 +1,67 b''
1 ##############################################################################
1 ##############################################################################
2 #
2 #
3 # Copyright (c) 2003 Zope Foundation and Contributors.
3 # Copyright (c) 2003 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """Compute a resolution order for an object and its bases
14 """Compute a resolution order for an object and its bases
15 """
15 """
16
17 from __future__ import absolute_import
18
16 __docformat__ = 'restructuredtext'
19 __docformat__ = 'restructuredtext'
17
20
18 def _mergeOrderings(orderings):
21 def _mergeOrderings(orderings):
19 """Merge multiple orderings so that within-ordering order is preserved
22 """Merge multiple orderings so that within-ordering order is preserved
20
23
21 Orderings are constrained in such a way that if an object appears
24 Orderings are constrained in such a way that if an object appears
22 in two or more orderings, then the suffix that begins with the
25 in two or more orderings, then the suffix that begins with the
23 object must be in both orderings.
26 object must be in both orderings.
24
27
25 For example:
28 For example:
26
29
27 >>> _mergeOrderings([
30 >>> _mergeOrderings([
28 ... ['x', 'y', 'z'],
31 ... ['x', 'y', 'z'],
29 ... ['q', 'z'],
32 ... ['q', 'z'],
30 ... [1, 3, 5],
33 ... [1, 3, 5],
31 ... ['z']
34 ... ['z']
32 ... ])
35 ... ])
33 ['x', 'y', 'q', 1, 3, 5, 'z']
36 ['x', 'y', 'q', 1, 3, 5, 'z']
34
37
35 """
38 """
36
39
37 seen = {}
40 seen = {}
38 result = []
41 result = []
39 for ordering in reversed(orderings):
42 for ordering in reversed(orderings):
40 for o in reversed(ordering):
43 for o in reversed(ordering):
41 if o not in seen:
44 if o not in seen:
42 seen[o] = 1
45 seen[o] = 1
43 result.insert(0, o)
46 result.insert(0, o)
44
47
45 return result
48 return result
46
49
47 def _flatten(ob):
50 def _flatten(ob):
48 result = [ob]
51 result = [ob]
49 i = 0
52 i = 0
50 for ob in iter(result):
53 for ob in iter(result):
51 i += 1
54 i += 1
52 # The recursive calls can be avoided by inserting the base classes
55 # The recursive calls can be avoided by inserting the base classes
53 # into the dynamically growing list directly after the currently
56 # into the dynamically growing list directly after the currently
54 # considered object; the iterator makes sure this will keep working
57 # considered object; the iterator makes sure this will keep working
55 # in the future, since it cannot rely on the length of the list
58 # in the future, since it cannot rely on the length of the list
56 # by definition.
59 # by definition.
57 result[i:i] = ob.__bases__
60 result[i:i] = ob.__bases__
58 return result
61 return result
59
62
60
63
61 def ro(object):
64 def ro(object):
62 """Compute a "resolution order" for an object
65 """Compute a "resolution order" for an object
63 """
66 """
64 return _mergeOrderings([_flatten(object)])
67 return _mergeOrderings([_flatten(object)])
@@ -1,120 +1,122 b''
1 ##############################################################################
1 ##############################################################################
2 #
2 #
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
3 # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4 # All Rights Reserved.
4 # All Rights Reserved.
5 #
5 #
6 # This software is subject to the provisions of the Zope Public License,
6 # This software is subject to the provisions of the Zope Public License,
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11 # FOR A PARTICULAR PURPOSE.
11 # FOR A PARTICULAR PURPOSE.
12 #
12 #
13 ##############################################################################
13 ##############################################################################
14 """Verify interface implementations
14 """Verify interface implementations
15 """
15 """
16 from zope.interface.exceptions import BrokenImplementation, DoesNotImplement
16 from __future__ import absolute_import
17 from zope.interface.exceptions import BrokenMethodImplementation
17
18 from .exceptions import BrokenImplementation, DoesNotImplement
19 from .exceptions import BrokenMethodImplementation
18 from types import FunctionType, MethodType
20 from types import FunctionType, MethodType
19 from zope.interface.interface import fromMethod, fromFunction, Method
21 from .interface import fromMethod, fromFunction, Method
20 import sys
22 import sys
21
23
22 # This will be monkey-patched when running under Zope 2, so leave this
24 # This will be monkey-patched when running under Zope 2, so leave this
23 # here:
25 # here:
24 MethodTypes = (MethodType, )
26 MethodTypes = (MethodType, )
25
27
26
28
27 def _verify(iface, candidate, tentative=0, vtype=None):
29 def _verify(iface, candidate, tentative=0, vtype=None):
28 """Verify that 'candidate' might correctly implements 'iface'.
30 """Verify that 'candidate' might correctly implements 'iface'.
29
31
30 This involves:
32 This involves:
31
33
32 o Making sure the candidate defines all the necessary methods
34 o Making sure the candidate defines all the necessary methods
33
35
34 o Making sure the methods have the correct signature
36 o Making sure the methods have the correct signature
35
37
36 o Making sure the candidate asserts that it implements the interface
38 o Making sure the candidate asserts that it implements the interface
37
39
38 Note that this isn't the same as verifying that the class does
40 Note that this isn't the same as verifying that the class does
39 implement the interface.
41 implement the interface.
40
42
41 If optional tentative is true, suppress the "is implemented by" test.
43 If optional tentative is true, suppress the "is implemented by" test.
42 """
44 """
43
45
44 if vtype == 'c':
46 if vtype == 'c':
45 tester = iface.implementedBy
47 tester = iface.implementedBy
46 else:
48 else:
47 tester = iface.providedBy
49 tester = iface.providedBy
48
50
49 if not tentative and not tester(candidate):
51 if not tentative and not tester(candidate):
50 raise DoesNotImplement(iface)
52 raise DoesNotImplement(iface)
51
53
52 # Here the `desc` is either an `Attribute` or `Method` instance
54 # Here the `desc` is either an `Attribute` or `Method` instance
53 for name, desc in iface.namesAndDescriptions(1):
55 for name, desc in iface.namesAndDescriptions(1):
54 try:
56 try:
55 attr = getattr(candidate, name)
57 attr = getattr(candidate, name)
56 except AttributeError:
58 except AttributeError:
57 if (not isinstance(desc, Method)) and vtype == 'c':
59 if (not isinstance(desc, Method)) and vtype == 'c':
58 # We can't verify non-methods on classes, since the
60 # We can't verify non-methods on classes, since the
59 # class may provide attrs in it's __init__.
61 # class may provide attrs in it's __init__.
60 continue
62 continue
61
63
62 raise BrokenImplementation(iface, name)
64 raise BrokenImplementation(iface, name)
63
65
64 if not isinstance(desc, Method):
66 if not isinstance(desc, Method):
65 # If it's not a method, there's nothing else we can test
67 # If it's not a method, there's nothing else we can test
66 continue
68 continue
67
69
68 if isinstance(attr, FunctionType):
70 if isinstance(attr, FunctionType):
69 if sys.version_info[0] >= 3 and isinstance(candidate, type):
71 if sys.version_info[0] >= 3 and isinstance(candidate, type):
70 # This is an "unbound method" in Python 3.
72 # This is an "unbound method" in Python 3.
71 meth = fromFunction(attr, iface, name=name,
73 meth = fromFunction(attr, iface, name=name,
72 imlevel=1)
74 imlevel=1)
73 else:
75 else:
74 # Nope, just a normal function
76 # Nope, just a normal function
75 meth = fromFunction(attr, iface, name=name)
77 meth = fromFunction(attr, iface, name=name)
76 elif (isinstance(attr, MethodTypes)
78 elif (isinstance(attr, MethodTypes)
77 and type(attr.__func__) is FunctionType):
79 and type(attr.__func__) is FunctionType):
78 meth = fromMethod(attr, iface, name)
80 meth = fromMethod(attr, iface, name)
79 elif isinstance(attr, property) and vtype == 'c':
81 elif isinstance(attr, property) and vtype == 'c':
80 # We without an instance we cannot be sure it's not a
82 # We without an instance we cannot be sure it's not a
81 # callable.
83 # callable.
82 continue
84 continue
83 else:
85 else:
84 if not callable(attr):
86 if not callable(attr):
85 raise BrokenMethodImplementation(name, "Not a method")
87 raise BrokenMethodImplementation(name, "Not a method")
86 # sigh, it's callable, but we don't know how to introspect it, so
88 # sigh, it's callable, but we don't know how to introspect it, so
87 # we have to give it a pass.
89 # we have to give it a pass.
88 continue
90 continue
89
91
90 # Make sure that the required and implemented method signatures are
92 # Make sure that the required and implemented method signatures are
91 # the same.
93 # the same.
92 desc = desc.getSignatureInfo()
94 desc = desc.getSignatureInfo()
93 meth = meth.getSignatureInfo()
95 meth = meth.getSignatureInfo()
94
96
95 mess = _incompat(desc, meth)
97 mess = _incompat(desc, meth)
96 if mess:
98 if mess:
97 raise BrokenMethodImplementation(name, mess)
99 raise BrokenMethodImplementation(name, mess)
98
100
99 return True
101 return True
100
102
101 def verifyClass(iface, candidate, tentative=0):
103 def verifyClass(iface, candidate, tentative=0):
102 return _verify(iface, candidate, tentative, vtype='c')
104 return _verify(iface, candidate, tentative, vtype='c')
103
105
104 def verifyObject(iface, candidate, tentative=0):
106 def verifyObject(iface, candidate, tentative=0):
105 return _verify(iface, candidate, tentative, vtype='o')
107 return _verify(iface, candidate, tentative, vtype='o')
106
108
107 def _incompat(required, implemented):
109 def _incompat(required, implemented):
108 #if (required['positional'] !=
110 #if (required['positional'] !=
109 # implemented['positional'][:len(required['positional'])]
111 # implemented['positional'][:len(required['positional'])]
110 # and implemented['kwargs'] is None):
112 # and implemented['kwargs'] is None):
111 # return 'imlementation has different argument names'
113 # return 'imlementation has different argument names'
112 if len(implemented['required']) > len(required['required']):
114 if len(implemented['required']) > len(required['required']):
113 return 'implementation requires too many arguments'
115 return 'implementation requires too many arguments'
114 if ((len(implemented['positional']) < len(required['positional']))
116 if ((len(implemented['positional']) < len(required['positional']))
115 and not implemented['varargs']):
117 and not implemented['varargs']):
116 return "implementation doesn't allow enough arguments"
118 return "implementation doesn't allow enough arguments"
117 if required['kwargs'] and not implemented['kwargs']:
119 if required['kwargs'] and not implemented['kwargs']:
118 return "implementation doesn't support keyword arguments"
120 return "implementation doesn't support keyword arguments"
119 if required['varargs'] and not implemented['varargs']:
121 if required['varargs'] and not implemented['varargs']:
120 return "implementation doesn't support variable arguments"
122 return "implementation doesn't support variable arguments"
General Comments 0
You need to be logged in to leave comments. Login now