Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

interface.py 38KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131
  1. ##############################################################################
  2. #
  3. # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
  4. # All Rights Reserved.
  5. #
  6. # This software is subject to the provisions of the Zope Public License,
  7. # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
  8. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
  9. # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  10. # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
  11. # FOR A PARTICULAR PURPOSE.
  12. #
  13. ##############################################################################
  14. """Interface object implementation
  15. """
  16. # pylint:disable=protected-access
  17. import sys
  18. from types import MethodType
  19. from types import FunctionType
  20. import weakref
  21. from zope.interface._compat import _use_c_impl
  22. from zope.interface.exceptions import Invalid
  23. from zope.interface.ro import ro as calculate_ro
  24. from zope.interface import ro
  25. __all__ = [
  26. # Most of the public API from this module is directly exported
  27. # from zope.interface. The only remaining public API intended to
  28. # be imported from here should be those few things documented as
  29. # such.
  30. 'InterfaceClass',
  31. 'Specification',
  32. 'adapter_hooks',
  33. ]
  34. CO_VARARGS = 4
  35. CO_VARKEYWORDS = 8
  36. # Put in the attrs dict of an interface by ``taggedValue`` and ``invariants``
  37. TAGGED_DATA = '__interface_tagged_values__'
  38. # Put in the attrs dict of an interface by ``interfacemethod``
  39. INTERFACE_METHODS = '__interface_methods__'
  40. _decorator_non_return = object()
  41. _marker = object()
  42. def invariant(call):
  43. f_locals = sys._getframe(1).f_locals
  44. tags = f_locals.setdefault(TAGGED_DATA, {})
  45. invariants = tags.setdefault('invariants', [])
  46. invariants.append(call)
  47. return _decorator_non_return
  48. def taggedValue(key, value):
  49. """Attaches a tagged value to an interface at definition time."""
  50. f_locals = sys._getframe(1).f_locals
  51. tagged_values = f_locals.setdefault(TAGGED_DATA, {})
  52. tagged_values[key] = value
  53. return _decorator_non_return
  54. class Element:
  55. """
  56. Default implementation of `zope.interface.interfaces.IElement`.
  57. """
  58. # We can't say this yet because we don't have enough
  59. # infrastructure in place.
  60. #
  61. #implements(IElement)
  62. def __init__(self, __name__, __doc__=''): # pylint:disable=redefined-builtin
  63. if not __doc__ and __name__.find(' ') >= 0:
  64. __doc__ = __name__
  65. __name__ = None
  66. self.__name__ = __name__
  67. self.__doc__ = __doc__
  68. # Tagged values are rare, especially on methods or attributes.
  69. # Deferring the allocation can save substantial memory.
  70. self.__tagged_values = None
  71. def getName(self):
  72. """ Returns the name of the object. """
  73. return self.__name__
  74. def getDoc(self):
  75. """ Returns the documentation for the object. """
  76. return self.__doc__
  77. ###
  78. # Tagged values.
  79. #
  80. # Direct tagged values are set only in this instance. Others
  81. # may be inherited (for those subclasses that have that concept).
  82. ###
  83. def getTaggedValue(self, tag):
  84. """ Returns the value associated with 'tag'. """
  85. if not self.__tagged_values:
  86. raise KeyError(tag)
  87. return self.__tagged_values[tag]
  88. def queryTaggedValue(self, tag, default=None):
  89. """ Returns the value associated with 'tag'. """
  90. return self.__tagged_values.get(tag, default) if self.__tagged_values else default
  91. def getTaggedValueTags(self):
  92. """ Returns a collection of all tags. """
  93. return self.__tagged_values.keys() if self.__tagged_values else ()
  94. def setTaggedValue(self, tag, value):
  95. """ Associates 'value' with 'key'. """
  96. if self.__tagged_values is None:
  97. self.__tagged_values = {}
  98. self.__tagged_values[tag] = value
  99. queryDirectTaggedValue = queryTaggedValue
  100. getDirectTaggedValue = getTaggedValue
  101. getDirectTaggedValueTags = getTaggedValueTags
  102. SpecificationBasePy = object # filled by _use_c_impl.
  103. @_use_c_impl
  104. class SpecificationBase:
  105. # This object is the base of the inheritance hierarchy for ClassProvides:
  106. #
  107. # ClassProvides < ClassProvidesBase, Declaration
  108. # Declaration < Specification < SpecificationBase
  109. # ClassProvidesBase < SpecificationBase
  110. #
  111. # In order to have compatible instance layouts, we need to declare
  112. # the storage used by Specification and Declaration here (and
  113. # those classes must have ``__slots__ = ()``); fortunately this is
  114. # not a waste of space because those are the only two inheritance
  115. # trees. These all translate into tp_members in C.
  116. __slots__ = (
  117. # Things used here.
  118. '_implied',
  119. # Things used in Specification.
  120. '_dependents',
  121. '_bases',
  122. '_v_attrs',
  123. '__iro__',
  124. '__sro__',
  125. '__weakref__',
  126. )
  127. def providedBy(self, ob):
  128. """Is the interface implemented by an object
  129. """
  130. spec = providedBy(ob)
  131. return self in spec._implied
  132. def implementedBy(self, cls):
  133. """Test whether the specification is implemented by a class or factory.
  134. Raise TypeError if argument is neither a class nor a callable.
  135. """
  136. spec = implementedBy(cls)
  137. return self in spec._implied
  138. def isOrExtends(self, interface):
  139. """Is the interface the same as or extend the given interface
  140. """
  141. return interface in self._implied # pylint:disable=no-member
  142. __call__ = isOrExtends
  143. class NameAndModuleComparisonMixin:
  144. # Internal use. Implement the basic sorting operators (but not (in)equality
  145. # or hashing). Subclasses must provide ``__name__`` and ``__module__``
  146. # attributes. Subclasses will be mutually comparable; but because equality
  147. # and hashing semantics are missing from this class, take care in how
  148. # you define those two attributes: If you stick with the default equality
  149. # and hashing (identity based) you should make sure that all possible ``__name__``
  150. # and ``__module__`` pairs are unique ACROSS ALL SUBCLASSES. (Actually, pretty
  151. # much the same thing goes if you define equality and hashing to be based on
  152. # those two attributes: they must still be consistent ACROSS ALL SUBCLASSES.)
  153. # pylint:disable=assigning-non-slot
  154. __slots__ = ()
  155. def _compare(self, other):
  156. """
  157. Compare *self* to *other* based on ``__name__`` and ``__module__``.
  158. Return 0 if they are equal, return 1 if *self* is
  159. greater than *other*, and return -1 if *self* is less than
  160. *other*.
  161. If *other* does not have ``__name__`` or ``__module__``, then
  162. return ``NotImplemented``.
  163. .. caution::
  164. This allows comparison to things well outside the type hierarchy,
  165. perhaps not symmetrically.
  166. For example, ``class Foo(object)`` and ``class Foo(Interface)``
  167. in the same file would compare equal, depending on the order of
  168. operands. Writing code like this by hand would be unusual, but it could
  169. happen with dynamic creation of types and interfaces.
  170. None is treated as a pseudo interface that implies the loosest
  171. contact possible, no contract. For that reason, all interfaces
  172. sort before None.
  173. """
  174. if other is self:
  175. return 0
  176. if other is None:
  177. return -1
  178. n1 = (self.__name__, self.__module__)
  179. try:
  180. n2 = (other.__name__, other.__module__)
  181. except AttributeError:
  182. return NotImplemented
  183. # This spelling works under Python3, which doesn't have cmp().
  184. return (n1 > n2) - (n1 < n2)
  185. def __lt__(self, other):
  186. c = self._compare(other)
  187. if c is NotImplemented:
  188. return c
  189. return c < 0
  190. def __le__(self, other):
  191. c = self._compare(other)
  192. if c is NotImplemented:
  193. return c
  194. return c <= 0
  195. def __gt__(self, other):
  196. c = self._compare(other)
  197. if c is NotImplemented:
  198. return c
  199. return c > 0
  200. def __ge__(self, other):
  201. c = self._compare(other)
  202. if c is NotImplemented:
  203. return c
  204. return c >= 0
  205. @_use_c_impl
  206. class InterfaceBase(NameAndModuleComparisonMixin, SpecificationBasePy):
  207. """Base class that wants to be replaced with a C base :)
  208. """
  209. __slots__ = (
  210. '__name__',
  211. '__ibmodule__',
  212. '_v_cached_hash',
  213. )
  214. def __init__(self, name=None, module=None):
  215. self.__name__ = name
  216. self.__ibmodule__ = module
  217. def _call_conform(self, conform):
  218. raise NotImplementedError
  219. @property
  220. def __module_property__(self):
  221. # This is for _InterfaceMetaClass
  222. return self.__ibmodule__
  223. def __call__(self, obj, alternate=_marker):
  224. """Adapt an object to the interface
  225. """
  226. try:
  227. conform = obj.__conform__
  228. except AttributeError:
  229. conform = None
  230. if conform is not None:
  231. adapter = self._call_conform(conform)
  232. if adapter is not None:
  233. return adapter
  234. adapter = self.__adapt__(obj)
  235. if adapter is not None:
  236. return adapter
  237. if alternate is not _marker:
  238. return alternate
  239. raise TypeError("Could not adapt", obj, self)
  240. def __adapt__(self, obj):
  241. """Adapt an object to the receiver
  242. """
  243. if self.providedBy(obj):
  244. return obj
  245. for hook in adapter_hooks:
  246. adapter = hook(self, obj)
  247. if adapter is not None:
  248. return adapter
  249. return None
  250. def __hash__(self):
  251. # pylint:disable=assigning-non-slot,attribute-defined-outside-init
  252. try:
  253. return self._v_cached_hash
  254. except AttributeError:
  255. self._v_cached_hash = hash((self.__name__, self.__module__))
  256. return self._v_cached_hash
  257. def __eq__(self, other):
  258. c = self._compare(other)
  259. if c is NotImplemented:
  260. return c
  261. return c == 0
  262. def __ne__(self, other):
  263. if other is self:
  264. return False
  265. c = self._compare(other)
  266. if c is NotImplemented:
  267. return c
  268. return c != 0
  269. adapter_hooks = _use_c_impl([], 'adapter_hooks')
  270. class Specification(SpecificationBase):
  271. """Specifications
  272. An interface specification is used to track interface declarations
  273. and component registrations.
  274. This class is a base class for both interfaces themselves and for
  275. interface specifications (declarations).
  276. Specifications are mutable. If you reassign their bases, their
  277. relations with other specifications are adjusted accordingly.
  278. """
  279. __slots__ = ()
  280. # The root of all Specifications. This will be assigned `Interface`,
  281. # once it is defined.
  282. _ROOT = None
  283. # Copy some base class methods for speed
  284. isOrExtends = SpecificationBase.isOrExtends
  285. providedBy = SpecificationBase.providedBy
  286. def __init__(self, bases=()):
  287. # There are many leaf interfaces with no dependents,
  288. # and a few with very many. It's a heavily left-skewed
  289. # distribution. In a survey of Plone and Zope related packages
  290. # that loaded 2245 InterfaceClass objects and 2235 ClassProvides
  291. # instances, there were a total of 7000 Specification objects created.
  292. # 4700 had 0 dependents, 1400 had 1, 382 had 2 and so on. Only one
  293. # for <type> had 1664. So there's savings to be had deferring
  294. # the creation of dependents.
  295. self._dependents = None # type: weakref.WeakKeyDictionary
  296. self._bases = ()
  297. self._implied = {}
  298. self._v_attrs = None
  299. self.__iro__ = ()
  300. self.__sro__ = ()
  301. self.__bases__ = tuple(bases)
  302. @property
  303. def dependents(self):
  304. if self._dependents is None:
  305. self._dependents = weakref.WeakKeyDictionary()
  306. return self._dependents
  307. def subscribe(self, dependent):
  308. self._dependents[dependent] = self.dependents.get(dependent, 0) + 1
  309. def unsubscribe(self, dependent):
  310. try:
  311. n = self._dependents[dependent]
  312. except TypeError:
  313. raise KeyError(dependent)
  314. n -= 1
  315. if not n:
  316. del self.dependents[dependent]
  317. else:
  318. assert n > 0
  319. self.dependents[dependent] = n
  320. def __setBases(self, bases):
  321. # Remove ourselves as a dependent of our old bases
  322. for b in self.__bases__:
  323. b.unsubscribe(self)
  324. # Register ourselves as a dependent of our new bases
  325. self._bases = bases
  326. for b in bases:
  327. b.subscribe(self)
  328. self.changed(self)
  329. __bases__ = property(
  330. lambda self: self._bases,
  331. __setBases,
  332. )
  333. # This method exists for tests to override the way we call
  334. # ro.calculate_ro(), usually by adding extra kwargs. We don't
  335. # want to have a mutable dictionary as a class member that we pass
  336. # ourself because mutability is bad, and passing **kw is slower than
  337. # calling the bound function.
  338. _do_calculate_ro = calculate_ro
  339. def _calculate_sro(self):
  340. """
  341. Calculate and return the resolution order for this object, using its ``__bases__``.
  342. Ensures that ``Interface`` is always the last (lowest priority) element.
  343. """
  344. # We'd like to make Interface the lowest priority as a
  345. # property of the resolution order algorithm. That almost
  346. # works out naturally, but it fails when class inheritance has
  347. # some bases that DO implement an interface, and some that DO
  348. # NOT. In such a mixed scenario, you wind up with a set of
  349. # bases to consider that look like this: [[..., Interface],
  350. # [..., object], ...]. Depending on the order of inheritance,
  351. # Interface can wind up before or after object, and that can
  352. # happen at any point in the tree, meaning Interface can wind
  353. # up somewhere in the middle of the order. Since Interface is
  354. # treated as something that everything winds up implementing
  355. # anyway (a catch-all for things like adapters), having it high up
  356. # the order is bad. It's also bad to have it at the end, just before
  357. # some concrete class: concrete classes should be HIGHER priority than
  358. # interfaces (because there's only one class, but many implementations).
  359. #
  360. # One technically nice way to fix this would be to have
  361. # ``implementedBy(object).__bases__ = (Interface,)``
  362. #
  363. # But: (1) That fails for old-style classes and (2) that causes
  364. # everything to appear to *explicitly* implement Interface, when up
  365. # to this point it's been an implicit virtual sort of relationship.
  366. #
  367. # So we force the issue by mutating the resolution order.
  368. # Note that we let C3 use pre-computed __sro__ for our bases.
  369. # This requires that by the time this method is invoked, our bases
  370. # have settled their SROs. Thus, ``changed()`` must first
  371. # update itself before telling its descendents of changes.
  372. sro = self._do_calculate_ro(base_mros={
  373. b: b.__sro__
  374. for b in self.__bases__
  375. })
  376. root = self._ROOT
  377. if root is not None and sro and sro[-1] is not root:
  378. # In one dataset of 1823 Interface objects, 1117 ClassProvides objects,
  379. # sro[-1] was root 4496 times, and only not root 118 times. So it's
  380. # probably worth checking.
  381. # Once we don't have to deal with old-style classes,
  382. # we can add a check and only do this if base_count > 1,
  383. # if we tweak the bootstrapping for ``<implementedBy object>``
  384. sro = [
  385. x
  386. for x in sro
  387. if x is not root
  388. ]
  389. sro.append(root)
  390. return sro
  391. def changed(self, originally_changed):
  392. """
  393. We, or something we depend on, have changed.
  394. By the time this is called, the things we depend on,
  395. such as our bases, should themselves be stable.
  396. """
  397. self._v_attrs = None
  398. implied = self._implied
  399. implied.clear()
  400. ancestors = self._calculate_sro()
  401. self.__sro__ = tuple(ancestors)
  402. self.__iro__ = tuple([ancestor for ancestor in ancestors
  403. if isinstance(ancestor, InterfaceClass)
  404. ])
  405. for ancestor in ancestors:
  406. # We directly imply our ancestors:
  407. implied[ancestor] = ()
  408. # Now, advise our dependents of change
  409. # (being careful not to create the WeakKeyDictionary if not needed):
  410. for dependent in tuple(self._dependents.keys() if self._dependents else ()):
  411. dependent.changed(originally_changed)
  412. # Just in case something called get() at some point
  413. # during that process and we have a cycle of some sort
  414. # make sure we didn't cache incomplete results.
  415. self._v_attrs = None
  416. def interfaces(self):
  417. """Return an iterator for the interfaces in the specification.
  418. """
  419. seen = {}
  420. for base in self.__bases__:
  421. for interface in base.interfaces():
  422. if interface not in seen:
  423. seen[interface] = 1
  424. yield interface
  425. def extends(self, interface, strict=True):
  426. """Does the specification extend the given interface?
  427. Test whether an interface in the specification extends the
  428. given interface
  429. """
  430. return ((interface in self._implied)
  431. and
  432. ((not strict) or (self != interface))
  433. )
  434. def weakref(self, callback=None):
  435. return weakref.ref(self, callback)
  436. def get(self, name, default=None):
  437. """Query for an attribute description
  438. """
  439. attrs = self._v_attrs
  440. if attrs is None:
  441. attrs = self._v_attrs = {}
  442. attr = attrs.get(name)
  443. if attr is None:
  444. for iface in self.__iro__:
  445. attr = iface.direct(name)
  446. if attr is not None:
  447. attrs[name] = attr
  448. break
  449. return default if attr is None else attr
  450. class _InterfaceMetaClass(type):
  451. # Handling ``__module__`` on ``InterfaceClass`` is tricky. We need
  452. # to be able to read it on a type and get the expected string. We
  453. # also need to be able to set it on an instance and get the value
  454. # we set. So far so good. But what gets tricky is that we'd like
  455. # to store the value in the C structure (``InterfaceBase.__ibmodule__``) for
  456. # direct access during equality, sorting, and hashing. "No
  457. # problem, you think, I'll just use a property" (well, the C
  458. # equivalents, ``PyMemberDef`` or ``PyGetSetDef``).
  459. #
  460. # Except there is a problem. When a subclass is created, the
  461. # metaclass (``type``) always automatically puts the expected
  462. # string in the class's dictionary under ``__module__``, thus
  463. # overriding the property inherited from the superclass. Writing
  464. # ``Subclass.__module__`` still works, but
  465. # ``Subclass().__module__`` fails.
  466. #
  467. # There are multiple ways to work around this:
  468. #
  469. # (1) Define ``InterfaceBase.__getattribute__`` to watch for
  470. # ``__module__`` and return the C storage.
  471. #
  472. # This works, but slows down *all* attribute access (except,
  473. # ironically, to ``__module__``) by about 25% (40ns becomes 50ns)
  474. # (when implemented in C). Since that includes methods like
  475. # ``providedBy``, that's probably not acceptable.
  476. #
  477. # All the other methods involve modifying subclasses. This can be
  478. # done either on the fly in some cases, as instances are
  479. # constructed, or by using a metaclass. These next few can be done on the fly.
  480. #
  481. # (2) Make ``__module__`` a descriptor in each subclass dictionary.
  482. # It can't be a straight up ``@property`` descriptor, though, because accessing
  483. # it on the class returns a ``property`` object, not the desired string.
  484. #
  485. # (3) Implement a data descriptor (``__get__`` and ``__set__``)
  486. # that is both a subclass of string, and also does the redirect of
  487. # ``__module__`` to ``__ibmodule__`` and does the correct thing
  488. # with the ``instance`` argument to ``__get__`` is None (returns
  489. # the class's value.) (Why must it be a subclass of string? Because
  490. # when it' s in the class's dict, it's defined on an *instance* of the
  491. # metaclass; descriptors in an instance's dict aren't honored --- their
  492. # ``__get__`` is never invoked --- so it must also *be* the value we want
  493. # returned.)
  494. #
  495. # This works, preserves the ability to read and write
  496. # ``__module__``, and eliminates any penalty accessing other
  497. # attributes. But it slows down accessing ``__module__`` of
  498. # instances by 200% (40ns to 124ns), requires editing class dicts on the fly
  499. # (in InterfaceClass.__init__), thus slightly slowing down all interface creation,
  500. # and is ugly.
  501. #
  502. # (4) As in the last step, but make it a non-data descriptor (no ``__set__``).
  503. #
  504. # If you then *also* store a copy of ``__ibmodule__`` in
  505. # ``__module__`` in the instance's dict, reading works for both
  506. # class and instance and is full speed for instances. But the cost
  507. # is storage space, and you can't write to it anymore, not without
  508. # things getting out of sync.
  509. #
  510. # (Actually, ``__module__`` was never meant to be writable. Doing
  511. # so would break BTrees and normal dictionaries, as well as the
  512. # repr, maybe more.)
  513. #
  514. # That leaves us with a metaclass. (Recall that a class is an
  515. # instance of its metaclass, so properties/descriptors defined in
  516. # the metaclass are used when accessing attributes on the
  517. # instance/class. We'll use that to define ``__module__``.) Here
  518. # we can have our cake and eat it too: no extra storage, and
  519. # C-speed access to the underlying storage. The only substantial
  520. # cost is that metaclasses tend to make people's heads hurt. (But
  521. # still less than the descriptor-is-string, hopefully.)
  522. __slots__ = ()
  523. def __new__(cls, name, bases, attrs):
  524. # Figure out what module defined the interface.
  525. # This is copied from ``InterfaceClass.__init__``;
  526. # reviewers aren't sure how AttributeError or KeyError
  527. # could be raised.
  528. __module__ = sys._getframe(1).f_globals['__name__']
  529. # Get the C optimized __module__ accessor and give it
  530. # to the new class.
  531. moduledescr = InterfaceBase.__dict__['__module__']
  532. if isinstance(moduledescr, str):
  533. # We're working with the Python implementation,
  534. # not the C version
  535. moduledescr = InterfaceBase.__dict__['__module_property__']
  536. attrs['__module__'] = moduledescr
  537. kind = type.__new__(cls, name, bases, attrs)
  538. kind.__module = __module__
  539. return kind
  540. @property
  541. def __module__(cls):
  542. return cls.__module
  543. def __repr__(cls):
  544. return "<class '{}.{}'>".format(
  545. cls.__module,
  546. cls.__name__,
  547. )
  548. _InterfaceClassBase = _InterfaceMetaClass(
  549. 'InterfaceClass',
  550. # From least specific to most specific.
  551. (InterfaceBase, Specification, Element),
  552. {'__slots__': ()}
  553. )
  554. def interfacemethod(func):
  555. """
  556. Convert a method specification to an actual method of the interface.
  557. This is a decorator that functions like `staticmethod` et al.
  558. The primary use of this decorator is to allow interface definitions to
  559. define the ``__adapt__`` method, but other interface methods can be
  560. overridden this way too.
  561. .. seealso:: `zope.interface.interfaces.IInterfaceDeclaration.interfacemethod`
  562. """
  563. f_locals = sys._getframe(1).f_locals
  564. methods = f_locals.setdefault(INTERFACE_METHODS, {})
  565. methods[func.__name__] = func
  566. return _decorator_non_return
  567. class InterfaceClass(_InterfaceClassBase):
  568. """
  569. Prototype (scarecrow) Interfaces Implementation.
  570. Note that it is not possible to change the ``__name__`` or ``__module__``
  571. after an instance of this object has been constructed.
  572. """
  573. # We can't say this yet because we don't have enough
  574. # infrastructure in place.
  575. #
  576. #implements(IInterface)
  577. def __new__(cls, name=None, bases=(), attrs=None, __doc__=None, # pylint:disable=redefined-builtin
  578. __module__=None):
  579. assert isinstance(bases, tuple)
  580. attrs = attrs or {}
  581. needs_custom_class = attrs.pop(INTERFACE_METHODS, None)
  582. if needs_custom_class:
  583. needs_custom_class.update(
  584. {'__classcell__': attrs.pop('__classcell__')}
  585. if '__classcell__' in attrs
  586. else {}
  587. )
  588. if '__adapt__' in needs_custom_class:
  589. # We need to tell the C code to call this.
  590. needs_custom_class['_CALL_CUSTOM_ADAPT'] = 1
  591. if issubclass(cls, _InterfaceClassWithCustomMethods):
  592. cls_bases = (cls,)
  593. elif cls is InterfaceClass:
  594. cls_bases = (_InterfaceClassWithCustomMethods,)
  595. else:
  596. cls_bases = (cls, _InterfaceClassWithCustomMethods)
  597. cls = type(cls)( # pylint:disable=self-cls-assignment
  598. name + "<WithCustomMethods>",
  599. cls_bases,
  600. needs_custom_class
  601. )
  602. return _InterfaceClassBase.__new__(cls)
  603. def __init__(self, name, bases=(), attrs=None, __doc__=None, # pylint:disable=redefined-builtin
  604. __module__=None):
  605. # We don't call our metaclass parent directly
  606. # pylint:disable=non-parent-init-called
  607. # pylint:disable=super-init-not-called
  608. if not all(isinstance(base, InterfaceClass) for base in bases):
  609. raise TypeError('Expected base interfaces')
  610. if attrs is None:
  611. attrs = {}
  612. if __module__ is None:
  613. __module__ = attrs.get('__module__')
  614. if isinstance(__module__, str):
  615. del attrs['__module__']
  616. else:
  617. try:
  618. # Figure out what module defined the interface.
  619. # This is how cPython figures out the module of
  620. # a class, but of course it does it in C. :-/
  621. __module__ = sys._getframe(1).f_globals['__name__']
  622. except (AttributeError, KeyError): # pragma: no cover
  623. pass
  624. InterfaceBase.__init__(self, name, __module__)
  625. # These asserts assisted debugging the metaclass
  626. # assert '__module__' not in self.__dict__
  627. # assert self.__ibmodule__ is self.__module__ is __module__
  628. d = attrs.get('__doc__')
  629. if d is not None:
  630. if not isinstance(d, Attribute):
  631. if __doc__ is None:
  632. __doc__ = d
  633. del attrs['__doc__']
  634. if __doc__ is None:
  635. __doc__ = ''
  636. Element.__init__(self, name, __doc__)
  637. tagged_data = attrs.pop(TAGGED_DATA, None)
  638. if tagged_data is not None:
  639. for key, val in tagged_data.items():
  640. self.setTaggedValue(key, val)
  641. Specification.__init__(self, bases)
  642. self.__attrs = self.__compute_attrs(attrs)
  643. self.__identifier__ = "{}.{}".format(__module__, name)
  644. def __compute_attrs(self, attrs):
  645. # Make sure that all recorded attributes (and methods) are of type
  646. # `Attribute` and `Method`
  647. def update_value(aname, aval):
  648. if isinstance(aval, Attribute):
  649. aval.interface = self
  650. if not aval.__name__:
  651. aval.__name__ = aname
  652. elif isinstance(aval, FunctionType):
  653. aval = fromFunction(aval, self, name=aname)
  654. else:
  655. raise InvalidInterface("Concrete attribute, " + aname)
  656. return aval
  657. return {
  658. aname: update_value(aname, aval)
  659. for aname, aval in attrs.items()
  660. if aname not in (
  661. # __locals__: Python 3 sometimes adds this.
  662. '__locals__',
  663. # __qualname__: PEP 3155 (Python 3.3+)
  664. '__qualname__',
  665. # __annotations__: PEP 3107 (Python 3.0+)
  666. '__annotations__',
  667. )
  668. and aval is not _decorator_non_return
  669. }
  670. def interfaces(self):
  671. """Return an iterator for the interfaces in the specification.
  672. """
  673. yield self
  674. def getBases(self):
  675. return self.__bases__
  676. def isEqualOrExtendedBy(self, other):
  677. """Same interface or extends?"""
  678. return self == other or other.extends(self)
  679. def names(self, all=False): # pylint:disable=redefined-builtin
  680. """Return the attribute names defined by the interface."""
  681. if not all:
  682. return self.__attrs.keys()
  683. r = self.__attrs.copy()
  684. for base in self.__bases__:
  685. r.update(dict.fromkeys(base.names(all)))
  686. return r.keys()
  687. def __iter__(self):
  688. return iter(self.names(all=True))
  689. def namesAndDescriptions(self, all=False): # pylint:disable=redefined-builtin
  690. """Return attribute names and descriptions defined by interface."""
  691. if not all:
  692. return self.__attrs.items()
  693. r = {}
  694. for base in self.__bases__[::-1]:
  695. r.update(dict(base.namesAndDescriptions(all)))
  696. r.update(self.__attrs)
  697. return r.items()
  698. def getDescriptionFor(self, name):
  699. """Return the attribute description for the given name."""
  700. r = self.get(name)
  701. if r is not None:
  702. return r
  703. raise KeyError(name)
  704. __getitem__ = getDescriptionFor
  705. def __contains__(self, name):
  706. return self.get(name) is not None
  707. def direct(self, name):
  708. return self.__attrs.get(name)
  709. def queryDescriptionFor(self, name, default=None):
  710. return self.get(name, default)
  711. def validateInvariants(self, obj, errors=None):
  712. """validate object to defined invariants."""
  713. for iface in self.__iro__:
  714. for invariant in iface.queryDirectTaggedValue('invariants', ()):
  715. try:
  716. invariant(obj)
  717. except Invalid as error:
  718. if errors is not None:
  719. errors.append(error)
  720. else:
  721. raise
  722. if errors:
  723. raise Invalid(errors)
  724. def queryTaggedValue(self, tag, default=None):
  725. """
  726. Queries for the value associated with *tag*, returning it from the nearest
  727. interface in the ``__iro__``.
  728. If not found, returns *default*.
  729. """
  730. for iface in self.__iro__:
  731. value = iface.queryDirectTaggedValue(tag, _marker)
  732. if value is not _marker:
  733. return value
  734. return default
  735. def getTaggedValue(self, tag):
  736. """ Returns the value associated with 'tag'. """
  737. value = self.queryTaggedValue(tag, default=_marker)
  738. if value is _marker:
  739. raise KeyError(tag)
  740. return value
  741. def getTaggedValueTags(self):
  742. """ Returns a list of all tags. """
  743. keys = set()
  744. for base in self.__iro__:
  745. keys.update(base.getDirectTaggedValueTags())
  746. return keys
  747. def __repr__(self):
  748. try:
  749. return self._v_repr
  750. except AttributeError:
  751. name = str(self)
  752. r = "<{} {}>".format(self.__class__.__name__, name)
  753. self._v_repr = r # pylint:disable=attribute-defined-outside-init
  754. return r
  755. def __str__(self):
  756. name = self.__name__
  757. m = self.__ibmodule__
  758. if m:
  759. name = '{}.{}'.format(m, name)
  760. return name
  761. def _call_conform(self, conform):
  762. try:
  763. return conform(self)
  764. except TypeError: # pragma: no cover
  765. # We got a TypeError. It might be an error raised by
  766. # the __conform__ implementation, or *we* may have
  767. # made the TypeError by calling an unbound method
  768. # (object is a class). In the later case, we behave
  769. # as though there is no __conform__ method. We can
  770. # detect this case by checking whether there is more
  771. # than one traceback object in the traceback chain:
  772. if sys.exc_info()[2].tb_next is not None:
  773. # There is more than one entry in the chain, so
  774. # reraise the error:
  775. raise
  776. # This clever trick is from Phillip Eby
  777. return None # pragma: no cover
  778. def __reduce__(self):
  779. return self.__name__
  780. Interface = InterfaceClass("Interface", __module__='zope.interface')
  781. # Interface is the only member of its own SRO.
  782. Interface._calculate_sro = lambda: (Interface,)
  783. Interface.changed(Interface)
  784. assert Interface.__sro__ == (Interface,)
  785. Specification._ROOT = Interface
  786. ro._ROOT = Interface
  787. class _InterfaceClassWithCustomMethods(InterfaceClass):
  788. """
  789. Marker class for interfaces with custom methods that override InterfaceClass methods.
  790. """
  791. class Attribute(Element):
  792. """Attribute descriptions
  793. """
  794. # We can't say this yet because we don't have enough
  795. # infrastructure in place.
  796. #
  797. # implements(IAttribute)
  798. interface = None
  799. def _get_str_info(self):
  800. """Return extra data to put at the end of __str__."""
  801. return ""
  802. def __str__(self):
  803. of = ''
  804. if self.interface is not None:
  805. of = self.interface.__module__ + '.' + self.interface.__name__ + '.'
  806. # self.__name__ may be None during construction (e.g., debugging)
  807. return of + (self.__name__ or '<unknown>') + self._get_str_info()
  808. def __repr__(self):
  809. return "<{}.{} object at 0x{:x} {}>".format(
  810. type(self).__module__,
  811. type(self).__name__,
  812. id(self),
  813. self
  814. )
  815. class Method(Attribute):
  816. """Method interfaces
  817. The idea here is that you have objects that describe methods.
  818. This provides an opportunity for rich meta-data.
  819. """
  820. # We can't say this yet because we don't have enough
  821. # infrastructure in place.
  822. #
  823. # implements(IMethod)
  824. positional = required = ()
  825. _optional = varargs = kwargs = None
  826. def _get_optional(self):
  827. if self._optional is None:
  828. return {}
  829. return self._optional
  830. def _set_optional(self, opt):
  831. self._optional = opt
  832. def _del_optional(self):
  833. self._optional = None
  834. optional = property(_get_optional, _set_optional, _del_optional)
  835. def __call__(self, *args, **kw):
  836. raise BrokenImplementation(self.interface, self.__name__)
  837. def getSignatureInfo(self):
  838. return {'positional': self.positional,
  839. 'required': self.required,
  840. 'optional': self.optional,
  841. 'varargs': self.varargs,
  842. 'kwargs': self.kwargs,
  843. }
  844. def getSignatureString(self):
  845. sig = []
  846. for v in self.positional:
  847. sig.append(v)
  848. if v in self.optional.keys():
  849. sig[-1] += "=" + repr(self.optional[v])
  850. if self.varargs:
  851. sig.append("*" + self.varargs)
  852. if self.kwargs:
  853. sig.append("**" + self.kwargs)
  854. return "(%s)" % ", ".join(sig)
  855. _get_str_info = getSignatureString
  856. def fromFunction(func, interface=None, imlevel=0, name=None):
  857. name = name or func.__name__
  858. method = Method(name, func.__doc__)
  859. defaults = getattr(func, '__defaults__', None) or ()
  860. code = func.__code__
  861. # Number of positional arguments
  862. na = code.co_argcount - imlevel
  863. names = code.co_varnames[imlevel:]
  864. opt = {}
  865. # Number of required arguments
  866. defaults_count = len(defaults)
  867. if not defaults_count:
  868. # PyPy3 uses ``__defaults_count__`` for builtin methods
  869. # like ``dict.pop``. Surprisingly, these don't have recorded
  870. # ``__defaults__``
  871. defaults_count = getattr(func, '__defaults_count__', 0)
  872. nr = na - defaults_count
  873. if nr < 0:
  874. defaults = defaults[-nr:]
  875. nr = 0
  876. # Determine the optional arguments.
  877. opt.update(dict(zip(names[nr:], defaults)))
  878. method.positional = names[:na]
  879. method.required = names[:nr]
  880. method.optional = opt
  881. argno = na
  882. # Determine the function's variable argument's name (i.e. *args)
  883. if code.co_flags & CO_VARARGS:
  884. method.varargs = names[argno]
  885. argno = argno + 1
  886. else:
  887. method.varargs = None
  888. # Determine the function's keyword argument's name (i.e. **kw)
  889. if code.co_flags & CO_VARKEYWORDS:
  890. method.kwargs = names[argno]
  891. else:
  892. method.kwargs = None
  893. method.interface = interface
  894. for key, value in func.__dict__.items():
  895. method.setTaggedValue(key, value)
  896. return method
  897. def fromMethod(meth, interface=None, name=None):
  898. if isinstance(meth, MethodType):
  899. func = meth.__func__
  900. else:
  901. func = meth
  902. return fromFunction(func, interface, imlevel=1, name=name)
  903. # Now we can create the interesting interfaces and wire them up:
  904. def _wire():
  905. from zope.interface.declarations import classImplements
  906. # From lest specific to most specific.
  907. from zope.interface.interfaces import IElement
  908. classImplements(Element, IElement)
  909. from zope.interface.interfaces import IAttribute
  910. classImplements(Attribute, IAttribute)
  911. from zope.interface.interfaces import IMethod
  912. classImplements(Method, IMethod)
  913. from zope.interface.interfaces import ISpecification
  914. classImplements(Specification, ISpecification)
  915. from zope.interface.interfaces import IInterface
  916. classImplements(InterfaceClass, IInterface)
  917. # We import this here to deal with module dependencies.
  918. # pylint:disable=wrong-import-position
  919. from zope.interface.declarations import implementedBy
  920. from zope.interface.declarations import providedBy
  921. from zope.interface.exceptions import InvalidInterface
  922. from zope.interface.exceptions import BrokenImplementation
  923. # This ensures that ``Interface`` winds up in the flattened()
  924. # list of the immutable declaration. It correctly overrides changed()
  925. # as a no-op, so we bypass that.
  926. from zope.interface.declarations import _empty
  927. Specification.changed(_empty, _empty)