comparison mercurial/thirdparty/zope/interface/declarations.py @ 37176:943d77fc07a3

thirdparty: vendor zope.interface 4.4.3 I've been trying to formalize interfaces for various components of Mercurial. So far, we've been using the "abc" package. This package is "good enough" for a lot of tasks. But it quickly falls over. For example, if you declare an @abc.abstractproperty, you must implement that attribute with a @property or the class compile time checking performed by abc will complain. This often forces you to implement dumb @property wrappers to return a _ prefixed attribute of the sane name. That's ugly. I've also wanted to implement automated checking that classes conform to various interfaces and don't expose other "public" attributes. After doing a bit of research and asking around, the general consensus seems to be that zope.interface is the best package for doing interface-based programming in Python. It has built-in support for verifying classes and objects conform to interfaces. It allows an interface's properties to be defined during __init__. There's even an "adapter registry" that allow you to register interfaces and look up which classes implement them. That could potentially be useful for places where our custom registry.py modules currently facilitates central registrations, but at a type level. Imagine extensions providing alternate implementations of things like the local repository interface to allow opening repositories with custom requirements. Anyway, this commit vendors zope.interface 4.4.3. The contents of the source tarball have been copied into mercurial/thirdparty/zope/ without modifications. Test modules have been removed because they are not interesting to us. The LICENSE.txt file has been copied so it lives next to the source. The Python modules don't use relative imports. zope/__init__.py defines a namespace package. So we'll need to modify the source code before this package is usable inside Mercurial. This will be done in subsequent commits. # no-check-commit for various style failures Differential Revision: https://phab.mercurial-scm.org/D2928
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 21 Mar 2018 19:48:50 -0700
parents
children 68ee61822182
comparison
equal deleted inserted replaced
37175:fbe34945220d 37176:943d77fc07a3
1 ##############################################################################
2 # Copyright (c) 2003 Zope Foundation and Contributors.
3 # All Rights Reserved.
4 #
5 # This software is subject to the provisions of the Zope Public License,
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # FOR A PARTICULAR PURPOSE.
11 ##############################################################################
12 """Implementation of interface declarations
13
14 There are three flavors of declarations:
15
16 - Declarations are used to simply name declared interfaces.
17
18 - ImplementsDeclarations are used to express the interfaces that a
19 class implements (that instances of the class provides).
20
21 Implements specifications support inheriting interfaces.
22
23 - ProvidesDeclarations are used to express interfaces directly
24 provided by objects.
25
26 """
27 __docformat__ = 'restructuredtext'
28
29 import sys
30 from types import FunctionType
31 from types import MethodType
32 from types import ModuleType
33 import weakref
34
35 from zope.interface.advice import addClassAdvisor
36 from zope.interface.interface import InterfaceClass
37 from zope.interface.interface import SpecificationBase
38 from zope.interface.interface import Specification
39 from zope.interface._compat import CLASS_TYPES as DescriptorAwareMetaClasses
40 from zope.interface._compat import PYTHON3
41
42 # Registry of class-implementation specifications
43 BuiltinImplementationSpecifications = {}
44
45 _ADVICE_ERROR = ('Class advice impossible in Python3. '
46 'Use the @%s class decorator instead.')
47
48 _ADVICE_WARNING = ('The %s API is deprecated, and will not work in Python3 '
49 'Use the @%s class decorator instead.')
50
51 class named(object):
52
53 def __init__(self, name):
54 self.name = name
55
56 def __call__(self, ob):
57 ob.__component_name__ = self.name
58 return ob
59
60 class Declaration(Specification):
61 """Interface declarations"""
62
63 def __init__(self, *interfaces):
64 Specification.__init__(self, _normalizeargs(interfaces))
65
66 def changed(self, originally_changed):
67 Specification.changed(self, originally_changed)
68 try:
69 del self._v_attrs
70 except AttributeError:
71 pass
72
73 def __contains__(self, interface):
74 """Test whether an interface is in the specification
75 """
76
77 return self.extends(interface) and interface in self.interfaces()
78
79 def __iter__(self):
80 """Return an iterator for the interfaces in the specification
81 """
82 return self.interfaces()
83
84 def flattened(self):
85 """Return an iterator of all included and extended interfaces
86 """
87 return iter(self.__iro__)
88
89 def __sub__(self, other):
90 """Remove interfaces from a specification
91 """
92 return Declaration(
93 *[i for i in self.interfaces()
94 if not [j for j in other.interfaces()
95 if i.extends(j, 0)]
96 ]
97 )
98
99 def __add__(self, other):
100 """Add two specifications or a specification and an interface
101 """
102 seen = {}
103 result = []
104 for i in self.interfaces():
105 seen[i] = 1
106 result.append(i)
107 for i in other.interfaces():
108 if i not in seen:
109 seen[i] = 1
110 result.append(i)
111
112 return Declaration(*result)
113
114 __radd__ = __add__
115
116
117 ##############################################################################
118 #
119 # Implementation specifications
120 #
121 # These specify interfaces implemented by instances of classes
122
123 class Implements(Declaration):
124
125 # class whose specification should be used as additional base
126 inherit = None
127
128 # interfaces actually declared for a class
129 declared = ()
130
131 __name__ = '?'
132
133 @classmethod
134 def named(cls, name, *interfaces):
135 # Implementation method: Produce an Implements interface with
136 # a fully fleshed out __name__ before calling the constructor, which
137 # sets bases to the given interfaces and which may pass this object to
138 # other objects (e.g., to adjust dependents). If they're sorting or comparing
139 # by name, this needs to be set.
140 inst = cls.__new__(cls)
141 inst.__name__ = name
142 inst.__init__(*interfaces)
143 return inst
144
145 def __repr__(self):
146 return '<implementedBy %s>' % (self.__name__)
147
148 def __reduce__(self):
149 return implementedBy, (self.inherit, )
150
151 def __cmp(self, other):
152 # Yes, I did mean to name this __cmp, rather than __cmp__.
153 # It is a private method used by __lt__ and __gt__.
154 # This is based on, and compatible with, InterfaceClass.
155 # (The two must be mutually comparable to be able to work in e.g., BTrees.)
156 # Instances of this class generally don't have a __module__ other than
157 # `zope.interface.declarations`, whereas they *do* have a __name__ that is the
158 # fully qualified name of the object they are representing.
159
160 # Note, though, that equality and hashing are still identity based. This
161 # accounts for things like nested objects that have the same name (typically
162 # only in tests) and is consistent with pickling. As far as comparisons to InterfaceClass
163 # goes, we'll never have equal name and module to those, so we're still consistent there.
164 # Instances of this class are essentially intended to be unique and are
165 # heavily cached (note how our __reduce__ handles this) so having identity
166 # based hash and eq should also work.
167 if other is None:
168 return -1
169
170 n1 = (self.__name__, self.__module__)
171 n2 = (getattr(other, '__name__', ''), getattr(other, '__module__', ''))
172
173 # This spelling works under Python3, which doesn't have cmp().
174 return (n1 > n2) - (n1 < n2)
175
176 def __hash__(self):
177 return Declaration.__hash__(self)
178
179 # We want equality to be based on identity. However, we can't actually
180 # implement __eq__/__ne__ to do this because sometimes we get wrapped in a proxy.
181 # We need to let the proxy types implement these methods so they can handle unwrapping
182 # and then rely on: (1) the interpreter automatically changing `implements == proxy` into
183 # `proxy == implements` (which will call proxy.__eq__ to do the unwrapping) and then
184 # (2) the default equality semantics being identity based.
185
186 def __lt__(self, other):
187 c = self.__cmp(other)
188 return c < 0
189
190 def __le__(self, other):
191 c = self.__cmp(other)
192 return c <= 0
193
194 def __gt__(self, other):
195 c = self.__cmp(other)
196 return c > 0
197
198 def __ge__(self, other):
199 c = self.__cmp(other)
200 return c >= 0
201
202 def _implements_name(ob):
203 # Return the __name__ attribute to be used by its __implemented__
204 # property.
205 # This must be stable for the "same" object across processes
206 # because it is used for sorting. It needn't be unique, though, in cases
207 # like nested classes named Foo created by different functions, because
208 # equality and hashing is still based on identity.
209 # It might be nice to use __qualname__ on Python 3, but that would produce
210 # different values between Py2 and Py3.
211 return (getattr(ob, '__module__', '?') or '?') + \
212 '.' + (getattr(ob, '__name__', '?') or '?')
213
214 def implementedByFallback(cls):
215 """Return the interfaces implemented for a class' instances
216
217 The value returned is an IDeclaration.
218 """
219 try:
220 spec = cls.__dict__.get('__implemented__')
221 except AttributeError:
222
223 # we can't get the class dict. This is probably due to a
224 # security proxy. If this is the case, then probably no
225 # descriptor was installed for the class.
226
227 # We don't want to depend directly on zope.security in
228 # zope.interface, but we'll try to make reasonable
229 # accommodations in an indirect way.
230
231 # We'll check to see if there's an implements:
232
233 spec = getattr(cls, '__implemented__', None)
234 if spec is None:
235 # There's no spec stred in the class. Maybe its a builtin:
236 spec = BuiltinImplementationSpecifications.get(cls)
237 if spec is not None:
238 return spec
239 return _empty
240
241 if spec.__class__ == Implements:
242 # we defaulted to _empty or there was a spec. Good enough.
243 # Return it.
244 return spec
245
246 # TODO: need old style __implements__ compatibility?
247 # Hm, there's an __implemented__, but it's not a spec. Must be
248 # an old-style declaration. Just compute a spec for it
249 return Declaration(*_normalizeargs((spec, )))
250
251 if isinstance(spec, Implements):
252 return spec
253
254 if spec is None:
255 spec = BuiltinImplementationSpecifications.get(cls)
256 if spec is not None:
257 return spec
258
259 # TODO: need old style __implements__ compatibility?
260 spec_name = _implements_name(cls)
261 if spec is not None:
262 # old-style __implemented__ = foo declaration
263 spec = (spec, ) # tuplefy, as it might be just an int
264 spec = Implements.named(spec_name, *_normalizeargs(spec))
265 spec.inherit = None # old-style implies no inherit
266 del cls.__implemented__ # get rid of the old-style declaration
267 else:
268 try:
269 bases = cls.__bases__
270 except AttributeError:
271 if not callable(cls):
272 raise TypeError("ImplementedBy called for non-factory", cls)
273 bases = ()
274
275 spec = Implements.named(spec_name, *[implementedBy(c) for c in bases])
276 spec.inherit = cls
277
278 try:
279 cls.__implemented__ = spec
280 if not hasattr(cls, '__providedBy__'):
281 cls.__providedBy__ = objectSpecificationDescriptor
282
283 if (isinstance(cls, DescriptorAwareMetaClasses)
284 and
285 '__provides__' not in cls.__dict__):
286 # Make sure we get a __provides__ descriptor
287 cls.__provides__ = ClassProvides(
288 cls,
289 getattr(cls, '__class__', type(cls)),
290 )
291
292 except TypeError:
293 if not isinstance(cls, type):
294 raise TypeError("ImplementedBy called for non-type", cls)
295 BuiltinImplementationSpecifications[cls] = spec
296
297 return spec
298
299 implementedBy = implementedByFallback
300
301 def classImplementsOnly(cls, *interfaces):
302 """Declare the only interfaces implemented by instances of a class
303
304 The arguments after the class are one or more interfaces or interface
305 specifications (``IDeclaration`` objects).
306
307 The interfaces given (including the interfaces in the specifications)
308 replace any previous declarations.
309 """
310 spec = implementedBy(cls)
311 spec.declared = ()
312 spec.inherit = None
313 classImplements(cls, *interfaces)
314
315 def classImplements(cls, *interfaces):
316 """Declare additional interfaces implemented for instances of a class
317
318 The arguments after the class are one or more interfaces or
319 interface specifications (``IDeclaration`` objects).
320
321 The interfaces given (including the interfaces in the specifications)
322 are added to any interfaces previously declared.
323 """
324 spec = implementedBy(cls)
325 spec.declared += tuple(_normalizeargs(interfaces))
326
327 # compute the bases
328 bases = []
329 seen = {}
330 for b in spec.declared:
331 if b not in seen:
332 seen[b] = 1
333 bases.append(b)
334
335 if spec.inherit is not None:
336
337 for c in spec.inherit.__bases__:
338 b = implementedBy(c)
339 if b not in seen:
340 seen[b] = 1
341 bases.append(b)
342
343 spec.__bases__ = tuple(bases)
344
345 def _implements_advice(cls):
346 interfaces, classImplements = cls.__dict__['__implements_advice_data__']
347 del cls.__implements_advice_data__
348 classImplements(cls, *interfaces)
349 return cls
350
351
352 class implementer:
353 """Declare the interfaces implemented by instances of a class.
354
355 This function is called as a class decorator.
356
357 The arguments are one or more interfaces or interface
358 specifications (IDeclaration objects).
359
360 The interfaces given (including the interfaces in the
361 specifications) are added to any interfaces previously
362 declared.
363
364 Previous declarations include declarations for base classes
365 unless implementsOnly was used.
366
367 This function is provided for convenience. It provides a more
368 convenient way to call classImplements. For example::
369
370 @implementer(I1)
371 class C(object):
372 pass
373
374 is equivalent to calling::
375
376 classImplements(C, I1)
377
378 after the class has been created.
379 """
380
381 def __init__(self, *interfaces):
382 self.interfaces = interfaces
383
384 def __call__(self, ob):
385 if isinstance(ob, DescriptorAwareMetaClasses):
386 classImplements(ob, *self.interfaces)
387 return ob
388
389 spec_name = _implements_name(ob)
390 spec = Implements.named(spec_name, *self.interfaces)
391 try:
392 ob.__implemented__ = spec
393 except AttributeError:
394 raise TypeError("Can't declare implements", ob)
395 return ob
396
397 class implementer_only:
398 """Declare the only interfaces implemented by instances of a class
399
400 This function is called as a class decorator.
401
402 The arguments are one or more interfaces or interface
403 specifications (IDeclaration objects).
404
405 Previous declarations including declarations for base classes
406 are overridden.
407
408 This function is provided for convenience. It provides a more
409 convenient way to call classImplementsOnly. For example::
410
411 @implementer_only(I1)
412 class C(object): pass
413
414 is equivalent to calling::
415
416 classImplementsOnly(I1)
417
418 after the class has been created.
419 """
420
421 def __init__(self, *interfaces):
422 self.interfaces = interfaces
423
424 def __call__(self, ob):
425 if isinstance(ob, (FunctionType, MethodType)):
426 # XXX Does this decorator make sense for anything but classes?
427 # I don't think so. There can be no inheritance of interfaces
428 # on a method pr function....
429 raise ValueError('The implementer_only decorator is not '
430 'supported for methods or functions.')
431 else:
432 # Assume it's a class:
433 classImplementsOnly(ob, *self.interfaces)
434 return ob
435
436 def _implements(name, interfaces, classImplements):
437 # This entire approach is invalid under Py3K. Don't even try to fix
438 # the coverage for this block there. :(
439 frame = sys._getframe(2)
440 locals = frame.f_locals
441
442 # Try to make sure we were called from a class def. In 2.2.0 we can't
443 # check for __module__ since it doesn't seem to be added to the locals
444 # until later on.
445 if locals is frame.f_globals or '__module__' not in locals:
446 raise TypeError(name+" can be used only from a class definition.")
447
448 if '__implements_advice_data__' in locals:
449 raise TypeError(name+" can be used only once in a class definition.")
450
451 locals['__implements_advice_data__'] = interfaces, classImplements
452 addClassAdvisor(_implements_advice, depth=3)
453
454 def implements(*interfaces):
455 """Declare interfaces implemented by instances of a class
456
457 This function is called in a class definition.
458
459 The arguments are one or more interfaces or interface
460 specifications (IDeclaration objects).
461
462 The interfaces given (including the interfaces in the
463 specifications) are added to any interfaces previously
464 declared.
465
466 Previous declarations include declarations for base classes
467 unless implementsOnly was used.
468
469 This function is provided for convenience. It provides a more
470 convenient way to call classImplements. For example::
471
472 implements(I1)
473
474 is equivalent to calling::
475
476 classImplements(C, I1)
477
478 after the class has been created.
479 """
480 # This entire approach is invalid under Py3K. Don't even try to fix
481 # the coverage for this block there. :(
482 if PYTHON3:
483 raise TypeError(_ADVICE_ERROR % 'implementer')
484 _implements("implements", interfaces, classImplements)
485
486 def implementsOnly(*interfaces):
487 """Declare the only interfaces implemented by instances of a class
488
489 This function is called in a class definition.
490
491 The arguments are one or more interfaces or interface
492 specifications (IDeclaration objects).
493
494 Previous declarations including declarations for base classes
495 are overridden.
496
497 This function is provided for convenience. It provides a more
498 convenient way to call classImplementsOnly. For example::
499
500 implementsOnly(I1)
501
502 is equivalent to calling::
503
504 classImplementsOnly(I1)
505
506 after the class has been created.
507 """
508 # This entire approach is invalid under Py3K. Don't even try to fix
509 # the coverage for this block there. :(
510 if PYTHON3:
511 raise TypeError(_ADVICE_ERROR % 'implementer_only')
512 _implements("implementsOnly", interfaces, classImplementsOnly)
513
514 ##############################################################################
515 #
516 # Instance declarations
517
518 class Provides(Declaration): # Really named ProvidesClass
519 """Implement __provides__, the instance-specific specification
520
521 When an object is pickled, we pickle the interfaces that it implements.
522 """
523
524 def __init__(self, cls, *interfaces):
525 self.__args = (cls, ) + interfaces
526 self._cls = cls
527 Declaration.__init__(self, *(interfaces + (implementedBy(cls), )))
528
529 def __reduce__(self):
530 return Provides, self.__args
531
532 __module__ = 'zope.interface'
533
534 def __get__(self, inst, cls):
535 """Make sure that a class __provides__ doesn't leak to an instance
536 """
537 if inst is None and cls is self._cls:
538 # We were accessed through a class, so we are the class'
539 # provides spec. Just return this object, but only if we are
540 # being called on the same class that we were defined for:
541 return self
542
543 raise AttributeError('__provides__')
544
545 ProvidesClass = Provides
546
547 # Registry of instance declarations
548 # This is a memory optimization to allow objects to share specifications.
549 InstanceDeclarations = weakref.WeakValueDictionary()
550
551 def Provides(*interfaces):
552 """Cache instance declarations
553
554 Instance declarations are shared among instances that have the same
555 declaration. The declarations are cached in a weak value dictionary.
556 """
557 spec = InstanceDeclarations.get(interfaces)
558 if spec is None:
559 spec = ProvidesClass(*interfaces)
560 InstanceDeclarations[interfaces] = spec
561
562 return spec
563
564 Provides.__safe_for_unpickling__ = True
565
566
567 def directlyProvides(object, *interfaces):
568 """Declare interfaces declared directly for an object
569
570 The arguments after the object are one or more interfaces or interface
571 specifications (``IDeclaration`` objects).
572
573 The interfaces given (including the interfaces in the specifications)
574 replace interfaces previously declared for the object.
575 """
576 cls = getattr(object, '__class__', None)
577 if cls is not None and getattr(cls, '__class__', None) is cls:
578 # It's a meta class (well, at least it it could be an extension class)
579 # Note that we can't get here from Py3k tests: there is no normal
580 # class which isn't descriptor aware.
581 if not isinstance(object,
582 DescriptorAwareMetaClasses):
583 raise TypeError("Attempt to make an interface declaration on a "
584 "non-descriptor-aware class")
585
586 interfaces = _normalizeargs(interfaces)
587 if cls is None:
588 cls = type(object)
589
590 issub = False
591 for damc in DescriptorAwareMetaClasses:
592 if issubclass(cls, damc):
593 issub = True
594 break
595 if issub:
596 # we have a class or type. We'll use a special descriptor
597 # that provides some extra caching
598 object.__provides__ = ClassProvides(object, cls, *interfaces)
599 else:
600 object.__provides__ = Provides(cls, *interfaces)
601
602
603 def alsoProvides(object, *interfaces):
604 """Declare interfaces declared directly for an object
605
606 The arguments after the object are one or more interfaces or interface
607 specifications (``IDeclaration`` objects).
608
609 The interfaces given (including the interfaces in the specifications) are
610 added to the interfaces previously declared for the object.
611 """
612 directlyProvides(object, directlyProvidedBy(object), *interfaces)
613
614 def noLongerProvides(object, interface):
615 """ Removes a directly provided interface from an object.
616 """
617 directlyProvides(object, directlyProvidedBy(object) - interface)
618 if interface.providedBy(object):
619 raise ValueError("Can only remove directly provided interfaces.")
620
621 class ClassProvidesBaseFallback(object):
622
623 def __get__(self, inst, cls):
624 if cls is self._cls:
625 # We only work if called on the class we were defined for
626
627 if inst is None:
628 # We were accessed through a class, so we are the class'
629 # provides spec. Just return this object as is:
630 return self
631
632 return self._implements
633
634 raise AttributeError('__provides__')
635
636 ClassProvidesBasePy = ClassProvidesBaseFallback # BBB
637 ClassProvidesBase = ClassProvidesBaseFallback
638
639 # Try to get C base:
640 try:
641 import zope.interface._zope_interface_coptimizations
642 except ImportError:
643 pass
644 else:
645 from zope.interface._zope_interface_coptimizations import ClassProvidesBase
646
647
648 class ClassProvides(Declaration, ClassProvidesBase):
649 """Special descriptor for class __provides__
650
651 The descriptor caches the implementedBy info, so that
652 we can get declarations for objects without instance-specific
653 interfaces a bit quicker.
654 """
655 def __init__(self, cls, metacls, *interfaces):
656 self._cls = cls
657 self._implements = implementedBy(cls)
658 self.__args = (cls, metacls, ) + interfaces
659 Declaration.__init__(self, *(interfaces + (implementedBy(metacls), )))
660
661 def __reduce__(self):
662 return self.__class__, self.__args
663
664 # Copy base-class method for speed
665 __get__ = ClassProvidesBase.__get__
666
667 def directlyProvidedBy(object):
668 """Return the interfaces directly provided by the given object
669
670 The value returned is an ``IDeclaration``.
671 """
672 provides = getattr(object, "__provides__", None)
673 if (provides is None # no spec
674 or
675 # We might have gotten the implements spec, as an
676 # optimization. If so, it's like having only one base, that we
677 # lop off to exclude class-supplied declarations:
678 isinstance(provides, Implements)
679 ):
680 return _empty
681
682 # Strip off the class part of the spec:
683 return Declaration(provides.__bases__[:-1])
684
685 def classProvides(*interfaces):
686 """Declare interfaces provided directly by a class
687
688 This function is called in a class definition.
689
690 The arguments are one or more interfaces or interface specifications
691 (``IDeclaration`` objects).
692
693 The given interfaces (including the interfaces in the specifications)
694 are used to create the class's direct-object interface specification.
695 An error will be raised if the module class has an direct interface
696 specification. In other words, it is an error to call this function more
697 than once in a class definition.
698
699 Note that the given interfaces have nothing to do with the interfaces
700 implemented by instances of the class.
701
702 This function is provided for convenience. It provides a more convenient
703 way to call directlyProvides for a class. For example::
704
705 classProvides(I1)
706
707 is equivalent to calling::
708
709 directlyProvides(theclass, I1)
710
711 after the class has been created.
712 """
713 # This entire approach is invalid under Py3K. Don't even try to fix
714 # the coverage for this block there. :(
715
716 if PYTHON3:
717 raise TypeError(_ADVICE_ERROR % 'provider')
718
719 frame = sys._getframe(1)
720 locals = frame.f_locals
721
722 # Try to make sure we were called from a class def
723 if (locals is frame.f_globals) or ('__module__' not in locals):
724 raise TypeError("classProvides can be used only from a "
725 "class definition.")
726
727 if '__provides__' in locals:
728 raise TypeError(
729 "classProvides can only be used once in a class definition.")
730
731 locals["__provides__"] = _normalizeargs(interfaces)
732
733 addClassAdvisor(_classProvides_advice, depth=2)
734
735 def _classProvides_advice(cls):
736 # This entire approach is invalid under Py3K. Don't even try to fix
737 # the coverage for this block there. :(
738 interfaces = cls.__dict__['__provides__']
739 del cls.__provides__
740 directlyProvides(cls, *interfaces)
741 return cls
742
743 class provider:
744 """Class decorator version of classProvides"""
745
746 def __init__(self, *interfaces):
747 self.interfaces = interfaces
748
749 def __call__(self, ob):
750 directlyProvides(ob, *self.interfaces)
751 return ob
752
753 def moduleProvides(*interfaces):
754 """Declare interfaces provided by a module
755
756 This function is used in a module definition.
757
758 The arguments are one or more interfaces or interface specifications
759 (``IDeclaration`` objects).
760
761 The given interfaces (including the interfaces in the specifications) are
762 used to create the module's direct-object interface specification. An
763 error will be raised if the module already has an interface specification.
764 In other words, it is an error to call this function more than once in a
765 module definition.
766
767 This function is provided for convenience. It provides a more convenient
768 way to call directlyProvides. For example::
769
770 moduleImplements(I1)
771
772 is equivalent to::
773
774 directlyProvides(sys.modules[__name__], I1)
775 """
776 frame = sys._getframe(1)
777 locals = frame.f_locals
778
779 # Try to make sure we were called from a class def
780 if (locals is not frame.f_globals) or ('__name__' not in locals):
781 raise TypeError(
782 "moduleProvides can only be used from a module definition.")
783
784 if '__provides__' in locals:
785 raise TypeError(
786 "moduleProvides can only be used once in a module definition.")
787
788 locals["__provides__"] = Provides(ModuleType,
789 *_normalizeargs(interfaces))
790
791 ##############################################################################
792 #
793 # Declaration querying support
794
795 # XXX: is this a fossil? Nobody calls it, no unit tests exercise it, no
796 # doctests import it, and the package __init__ doesn't import it.
797 def ObjectSpecification(direct, cls):
798 """Provide object specifications
799
800 These combine information for the object and for it's classes.
801 """
802 return Provides(cls, direct) # pragma: no cover fossil
803
804 def getObjectSpecificationFallback(ob):
805
806 provides = getattr(ob, '__provides__', None)
807 if provides is not None:
808 if isinstance(provides, SpecificationBase):
809 return provides
810
811 try:
812 cls = ob.__class__
813 except AttributeError:
814 # We can't get the class, so just consider provides
815 return _empty
816
817 return implementedBy(cls)
818
819 getObjectSpecification = getObjectSpecificationFallback
820
821 def providedByFallback(ob):
822
823 # Here we have either a special object, an old-style declaration
824 # or a descriptor
825
826 # Try to get __providedBy__
827 try:
828 r = ob.__providedBy__
829 except AttributeError:
830 # Not set yet. Fall back to lower-level thing that computes it
831 return getObjectSpecification(ob)
832
833 try:
834 # We might have gotten a descriptor from an instance of a
835 # class (like an ExtensionClass) that doesn't support
836 # descriptors. We'll make sure we got one by trying to get
837 # the only attribute, which all specs have.
838 r.extends
839
840 except AttributeError:
841
842 # The object's class doesn't understand descriptors.
843 # Sigh. We need to get an object descriptor, but we have to be
844 # careful. We want to use the instance's __provides__, if
845 # there is one, but only if it didn't come from the class.
846
847 try:
848 r = ob.__provides__
849 except AttributeError:
850 # No __provides__, so just fall back to implementedBy
851 return implementedBy(ob.__class__)
852
853 # We need to make sure we got the __provides__ from the
854 # instance. We'll do this by making sure we don't get the same
855 # thing from the class:
856
857 try:
858 cp = ob.__class__.__provides__
859 except AttributeError:
860 # The ob doesn't have a class or the class has no
861 # provides, assume we're done:
862 return r
863
864 if r is cp:
865 # Oops, we got the provides from the class. This means
866 # the object doesn't have it's own. We should use implementedBy
867 return implementedBy(ob.__class__)
868
869 return r
870 providedBy = providedByFallback
871
872 class ObjectSpecificationDescriptorFallback(object):
873 """Implement the `__providedBy__` attribute
874
875 The `__providedBy__` attribute computes the interfaces peovided by
876 an object.
877 """
878
879 def __get__(self, inst, cls):
880 """Get an object specification for an object
881 """
882 if inst is None:
883 return getObjectSpecification(cls)
884
885 provides = getattr(inst, '__provides__', None)
886 if provides is not None:
887 return provides
888
889 return implementedBy(cls)
890
891 ObjectSpecificationDescriptor = ObjectSpecificationDescriptorFallback
892
893 ##############################################################################
894
895 def _normalizeargs(sequence, output = None):
896 """Normalize declaration arguments
897
898 Normalization arguments might contain Declarions, tuples, or single
899 interfaces.
900
901 Anything but individial interfaces or implements specs will be expanded.
902 """
903 if output is None:
904 output = []
905
906 cls = sequence.__class__
907 if InterfaceClass in cls.__mro__ or Implements in cls.__mro__:
908 output.append(sequence)
909 else:
910 for v in sequence:
911 _normalizeargs(v, output)
912
913 return output
914
915 _empty = Declaration()
916
917 try:
918 import zope.interface._zope_interface_coptimizations
919 except ImportError:
920 pass
921 else:
922 from zope.interface._zope_interface_coptimizations import implementedBy
923 from zope.interface._zope_interface_coptimizations import providedBy
924 from zope.interface._zope_interface_coptimizations import (
925 getObjectSpecification)
926 from zope.interface._zope_interface_coptimizations import (
927 ObjectSpecificationDescriptor)
928
929 objectSpecificationDescriptor = ObjectSpecificationDescriptor()