PKG-INFO 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706
  1. Metadata-Version: 1.0
  2. Name: zope.interface
  3. Version: 3.5.2
  4. Summary: Interfaces for Python
  5. Home-page: http://pypi.python.org/pypi/zope.interface
  6. Author: Zope Corporation and Contributors
  7. Author-email: zope-dev@zope.org
  8. License: ZPL 2.1
  9. Description: *This package is intended to be independently reusable in any Python
  10. project. It is maintained by the* `Zope Toolkit project <http://docs.zope.org/zopetoolkit/>`_.
  11. This package provides an implementation of `object interfaces` for Python.
  12. Interfaces are a mechanism for labeling objects as conforming to a given
  13. API or contract. So, this package can be considered as implementation of
  14. the `Design By Contract`_ methodology support in Python.
  15. .. _Design By Contract: http://en.wikipedia.org/wiki/Design_by_contract
  16. Detailed Documentation
  17. **********************
  18. .. contents::
  19. ==========
  20. Interfaces
  21. ==========
  22. Interfaces are objects that specify (document) the external behavior
  23. of objects that "provide" them. An interface specifies behavior
  24. through:
  25. - Informal documentation in a doc string
  26. - Attribute definitions
  27. - Invariants, which are conditions that must hold for objects that
  28. provide the interface
  29. Attribute definitions specify specific attributes. They define the
  30. attribute name and provide documentation and constraints of attribute
  31. values. Attribute definitions can take a number of forms, as we'll
  32. see below.
  33. Defining interfaces
  34. ===================
  35. Interfaces are defined using Python class statements::
  36. >>> import zope.interface
  37. >>> class IFoo(zope.interface.Interface):
  38. ... """Foo blah blah"""
  39. ...
  40. ... x = zope.interface.Attribute("""X blah blah""")
  41. ...
  42. ... def bar(q, r=None):
  43. ... """bar blah blah"""
  44. In the example above, we've created an interface, `IFoo`. We
  45. subclassed `zope.interface.Interface`, which is an ancestor interface for
  46. all interfaces, much as `object` is an ancestor of all new-style
  47. classes [#create]_. The interface is not a class, it's an Interface,
  48. an instance of `InterfaceClass`::
  49. >>> type(IFoo)
  50. <class 'zope.interface.interface.InterfaceClass'>
  51. We can ask for the interface's documentation::
  52. >>> IFoo.__doc__
  53. 'Foo blah blah'
  54. and its name::
  55. >>> IFoo.__name__
  56. 'IFoo'
  57. and even its module::
  58. >>> IFoo.__module__
  59. '__main__'
  60. The interface defined two attributes:
  61. `x`
  62. This is the simplest form of attribute definition. It has a name
  63. and a doc string. It doesn't formally specify anything else.
  64. `bar`
  65. This is a method. A method is defined via a function definition. A
  66. method is simply an attribute constrained to be a callable with a
  67. particular signature, as provided by the function definition.
  68. Note that `bar` doesn't take a `self` argument. Interfaces document
  69. how an object is *used*. When calling instance methods, you don't
  70. pass a `self` argument, so a `self` argument isn't included in the
  71. interface signature. The `self` argument in instance methods is
  72. really an implementation detail of Python instances. Other objects,
  73. besides instances can provide interfaces and their methods might not
  74. be instance methods. For example, modules can provide interfaces and
  75. their methods are usually just functions. Even instances can have
  76. methods that are not instance methods.
  77. You can access the attributes defined by an interface using mapping
  78. syntax::
  79. >>> x = IFoo['x']
  80. >>> type(x)
  81. <class 'zope.interface.interface.Attribute'>
  82. >>> x.__name__
  83. 'x'
  84. >>> x.__doc__
  85. 'X blah blah'
  86. >>> IFoo.get('x').__name__
  87. 'x'
  88. >>> IFoo.get('y')
  89. You can use `in` to determine if an interface defines a name::
  90. >>> 'x' in IFoo
  91. True
  92. You can iterate over interfaces to get the names they define::
  93. >>> names = list(IFoo)
  94. >>> names.sort()
  95. >>> names
  96. ['bar', 'x']
  97. Remember that interfaces aren't classes. You can't access attribute
  98. definitions as attributes of interfaces::
  99. >>> IFoo.x
  100. Traceback (most recent call last):
  101. File "<stdin>", line 1, in ?
  102. AttributeError: 'InterfaceClass' object has no attribute 'x'
  103. Methods provide access to the method signature::
  104. >>> bar = IFoo['bar']
  105. >>> bar.getSignatureString()
  106. '(q, r=None)'
  107. TODO
  108. Methods really should have a better API. This is something that
  109. needs to be improved.
  110. Declaring interfaces
  111. ====================
  112. Having defined interfaces, we can *declare* that objects provide
  113. them. Before we describe the details, lets define some terms:
  114. *provide*
  115. We say that objects *provide* interfaces. If an object provides an
  116. interface, then the interface specifies the behavior of the
  117. object. In other words, interfaces specify the behavior of the
  118. objects that provide them.
  119. *implement*
  120. We normally say that classes *implement* interfaces. If a class
  121. implements an interface, then the instances of the class provide
  122. the interface. Objects provide interfaces that their classes
  123. implement [#factory]_. (Objects can provide interfaces directly,
  124. in addition to what their classes implement.)
  125. It is important to note that classes don't usually provide the
  126. interfaces that they implement.
  127. We can generalize this to factories. For any callable object we
  128. can declare that it produces objects that provide some interfaces
  129. by saying that the factory implements the interfaces.
  130. Now that we've defined these terms, we can talk about the API for
  131. declaring interfaces.
  132. Declaring implemented interfaces
  133. --------------------------------
  134. The most common way to declare interfaces is using the implements
  135. function in a class statement::
  136. >>> class Foo:
  137. ... zope.interface.implements(IFoo)
  138. ...
  139. ... def __init__(self, x=None):
  140. ... self.x = x
  141. ...
  142. ... def bar(self, q, r=None):
  143. ... return q, r, self.x
  144. ...
  145. ... def __repr__(self):
  146. ... return "Foo(%s)" % self.x
  147. In this example, we declared that `Foo` implements `IFoo`. This means
  148. that instances of `Foo` provide `IFoo`. Having made this declaration,
  149. there are several ways we can introspect the declarations. First, we
  150. can ask an interface whether it is implemented by a class::
  151. >>> IFoo.implementedBy(Foo)
  152. True
  153. And we can ask whether an interface is provided by an object::
  154. >>> foo = Foo()
  155. >>> IFoo.providedBy(foo)
  156. True
  157. Of course, `Foo` doesn't provide `IFoo`, it implements it::
  158. >>> IFoo.providedBy(Foo)
  159. False
  160. We can also ask what interfaces are implemented by an object::
  161. >>> list(zope.interface.implementedBy(Foo))
  162. [<InterfaceClass __main__.IFoo>]
  163. It's an error to ask for interfaces implemented by a non-callable
  164. object::
  165. >>> IFoo.implementedBy(foo)
  166. Traceback (most recent call last):
  167. ...
  168. TypeError: ('ImplementedBy called for non-factory', Foo(None))
  169. >>> list(zope.interface.implementedBy(foo))
  170. Traceback (most recent call last):
  171. ...
  172. TypeError: ('ImplementedBy called for non-factory', Foo(None))
  173. Similarly, we can ask what interfaces are provided by an object::
  174. >>> list(zope.interface.providedBy(foo))
  175. [<InterfaceClass __main__.IFoo>]
  176. >>> list(zope.interface.providedBy(Foo))
  177. []
  178. We can declare interfaces implemented by other factories (besides
  179. classes). We do this using a Python-2.4-style decorator named
  180. `implementer`. In versions of Python before 2.4, this looks like::
  181. >>> def yfoo(y):
  182. ... foo = Foo()
  183. ... foo.y = y
  184. ... return foo
  185. >>> yfoo = zope.interface.implementer(IFoo)(yfoo)
  186. >>> list(zope.interface.implementedBy(yfoo))
  187. [<InterfaceClass __main__.IFoo>]
  188. Note that the implementer decorator may modify it's argument. Callers
  189. should not assume that a new object is created.
  190. Also note that, at least for now, implementer can't be used with
  191. classes::
  192. >>> zope.interface.implementer(IFoo)(Foo)
  193. ... # doctest: +NORMALIZE_WHITESPACE
  194. Traceback (most recent call last):
  195. ...
  196. TypeError: Can't use implementer with classes.
  197. Use one of the class-declaration functions instead.
  198. Declaring provided interfaces
  199. -----------------------------
  200. We can declare interfaces directly provided by objects. Suppose that
  201. we want to document what the `__init__` method of the `Foo` class
  202. does. It's not *really* part of `IFoo`. You wouldn't normally call
  203. the `__init__` method on Foo instances. Rather, the `__init__` method
  204. is part of the `Foo`'s `__call__` method::
  205. >>> class IFooFactory(zope.interface.Interface):
  206. ... """Create foos"""
  207. ...
  208. ... def __call__(x=None):
  209. ... """Create a foo
  210. ...
  211. ... The argument provides the initial value for x ...
  212. ... """
  213. It's the class that provides this interface, so we declare the
  214. interface on the class::
  215. >>> zope.interface.directlyProvides(Foo, IFooFactory)
  216. And then, we'll see that Foo provides some interfaces::
  217. >>> list(zope.interface.providedBy(Foo))
  218. [<InterfaceClass __main__.IFooFactory>]
  219. >>> IFooFactory.providedBy(Foo)
  220. True
  221. Declaring class interfaces is common enough that there's a special
  222. declaration function for it, `classProvides`, that allows the
  223. declaration from within a class statement::
  224. >>> class Foo2:
  225. ... zope.interface.implements(IFoo)
  226. ... zope.interface.classProvides(IFooFactory)
  227. ...
  228. ... def __init__(self, x=None):
  229. ... self.x = x
  230. ...
  231. ... def bar(self, q, r=None):
  232. ... return q, r, self.x
  233. ...
  234. ... def __repr__(self):
  235. ... return "Foo(%s)" % self.x
  236. >>> list(zope.interface.providedBy(Foo2))
  237. [<InterfaceClass __main__.IFooFactory>]
  238. >>> IFooFactory.providedBy(Foo2)
  239. True
  240. There's a similar function, `moduleProvides`, that supports interface
  241. declarations from within module definitions. For example, see the use
  242. of `moduleProvides` call in `zope.interface.__init__`, which declares that
  243. the package `zope.interface` provides `IInterfaceDeclaration`.
  244. Sometimes, we want to declare interfaces on instances, even though
  245. those instances get interfaces from their classes. Suppose we create
  246. a new interface, `ISpecial`::
  247. >>> class ISpecial(zope.interface.Interface):
  248. ... reason = zope.interface.Attribute("Reason why we're special")
  249. ... def brag():
  250. ... "Brag about being special"
  251. We can make an existing foo instance special by providing `reason`
  252. and `brag` attributes::
  253. >>> foo.reason = 'I just am'
  254. >>> def brag():
  255. ... return "I'm special!"
  256. >>> foo.brag = brag
  257. >>> foo.reason
  258. 'I just am'
  259. >>> foo.brag()
  260. "I'm special!"
  261. and by declaring the interface::
  262. >>> zope.interface.directlyProvides(foo, ISpecial)
  263. then the new interface is included in the provided interfaces::
  264. >>> ISpecial.providedBy(foo)
  265. True
  266. >>> list(zope.interface.providedBy(foo))
  267. [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
  268. We can find out what interfaces are directly provided by an object::
  269. >>> list(zope.interface.directlyProvidedBy(foo))
  270. [<InterfaceClass __main__.ISpecial>]
  271. >>> newfoo = Foo()
  272. >>> list(zope.interface.directlyProvidedBy(newfoo))
  273. []
  274. Inherited declarations
  275. ----------------------
  276. Normally, declarations are inherited::
  277. >>> class SpecialFoo(Foo):
  278. ... zope.interface.implements(ISpecial)
  279. ... reason = 'I just am'
  280. ... def brag(self):
  281. ... return "I'm special because %s" % self.reason
  282. >>> list(zope.interface.implementedBy(SpecialFoo))
  283. [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
  284. >>> list(zope.interface.providedBy(SpecialFoo()))
  285. [<InterfaceClass __main__.ISpecial>, <InterfaceClass __main__.IFoo>]
  286. Sometimes, you don't want to inherit declarations. In that case, you
  287. can use `implementsOnly`, instead of `implements`::
  288. >>> class Special(Foo):
  289. ... zope.interface.implementsOnly(ISpecial)
  290. ... reason = 'I just am'
  291. ... def brag(self):
  292. ... return "I'm special because %s" % self.reason
  293. >>> list(zope.interface.implementedBy(Special))
  294. [<InterfaceClass __main__.ISpecial>]
  295. >>> list(zope.interface.providedBy(Special()))
  296. [<InterfaceClass __main__.ISpecial>]
  297. External declarations
  298. ---------------------
  299. Normally, we make implementation declarations as part of a class
  300. definition. Sometimes, we may want to make declarations from outside
  301. the class definition. For example, we might want to declare interfaces
  302. for classes that we didn't write. The function `classImplements` can
  303. be used for this purpose::
  304. >>> class C:
  305. ... pass
  306. >>> zope.interface.classImplements(C, IFoo)
  307. >>> list(zope.interface.implementedBy(C))
  308. [<InterfaceClass __main__.IFoo>]
  309. We can use `classImplementsOnly` to exclude inherited interfaces::
  310. >>> class C(Foo):
  311. ... pass
  312. >>> zope.interface.classImplementsOnly(C, ISpecial)
  313. >>> list(zope.interface.implementedBy(C))
  314. [<InterfaceClass __main__.ISpecial>]
  315. Declaration Objects
  316. -------------------
  317. When we declare interfaces, we create *declaration* objects. When we
  318. query declarations, declaration objects are returned::
  319. >>> type(zope.interface.implementedBy(Special))
  320. <class 'zope.interface.declarations.Implements'>
  321. Declaration objects and interface objects are similar in many ways. In
  322. fact, they share a common base class. The important thing to realize
  323. about them is that they can be used where interfaces are expected in
  324. declarations. Here's a silly example::
  325. >>> class Special2(Foo):
  326. ... zope.interface.implementsOnly(
  327. ... zope.interface.implementedBy(Foo),
  328. ... ISpecial,
  329. ... )
  330. ... reason = 'I just am'
  331. ... def brag(self):
  332. ... return "I'm special because %s" % self.reason
  333. The declaration here is almost the same as
  334. ``zope.interface.implements(ISpecial)``, except that the order of
  335. interfaces in the resulting declaration is different::
  336. >>> list(zope.interface.implementedBy(Special2))
  337. [<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.ISpecial>]
  338. Interface Inheritance
  339. =====================
  340. Interfaces can extend other interfaces. They do this simply by listing
  341. the other interfaces as base interfaces::
  342. >>> class IBlat(zope.interface.Interface):
  343. ... """Blat blah blah"""
  344. ...
  345. ... y = zope.interface.Attribute("y blah blah")
  346. ... def eek():
  347. ... """eek blah blah"""
  348. >>> IBlat.__bases__
  349. (<InterfaceClass zope.interface.Interface>,)
  350. >>> class IBaz(IFoo, IBlat):
  351. ... """Baz blah"""
  352. ... def eek(a=1):
  353. ... """eek in baz blah"""
  354. ...
  355. >>> IBaz.__bases__
  356. (<InterfaceClass __main__.IFoo>, <InterfaceClass __main__.IBlat>)
  357. >>> names = list(IBaz)
  358. >>> names.sort()
  359. >>> names
  360. ['bar', 'eek', 'x', 'y']
  361. Note that `IBaz` overrides eek::
  362. >>> IBlat['eek'].__doc__
  363. 'eek blah blah'
  364. >>> IBaz['eek'].__doc__
  365. 'eek in baz blah'
  366. We were careful to override eek in a compatible way. When extending
  367. an interface, the extending interface should be compatible [#compat]_
  368. with the extended interfaces.
  369. We can ask whether one interface extends another::
  370. >>> IBaz.extends(IFoo)
  371. True
  372. >>> IBlat.extends(IFoo)
  373. False
  374. Note that interfaces don't extend themselves::
  375. >>> IBaz.extends(IBaz)
  376. False
  377. Sometimes we wish they did, but we can, instead use `isOrExtends`::
  378. >>> IBaz.isOrExtends(IBaz)
  379. True
  380. >>> IBaz.isOrExtends(IFoo)
  381. True
  382. >>> IFoo.isOrExtends(IBaz)
  383. False
  384. When we iterate over an interface, we get all of the names it defines,
  385. including names defined by base interfaces. Sometimes, we want *just*
  386. the names defined by the interface directly. We bane use the `names`
  387. method for that::
  388. >>> list(IBaz.names())
  389. ['eek']
  390. Inheritance of attribute specifications
  391. ---------------------------------------
  392. An interface may override attribute definitions from base interfaces.
  393. If two base interfaces define the same attribute, the attribute is
  394. inherited from the most specific interface. For example, with::
  395. >>> class IBase(zope.interface.Interface):
  396. ...
  397. ... def foo():
  398. ... "base foo doc"
  399. >>> class IBase1(IBase):
  400. ... pass
  401. >>> class IBase2(IBase):
  402. ...
  403. ... def foo():
  404. ... "base2 foo doc"
  405. >>> class ISub(IBase1, IBase2):
  406. ... pass
  407. ISub's definition of foo is the one from IBase2, since IBase2 is more
  408. specific that IBase::
  409. >>> ISub['foo'].__doc__
  410. 'base2 foo doc'
  411. Note that this differs from a depth-first search.
  412. Sometimes, it's useful to ask whether an interface defines an
  413. attribute directly. You can use the direct method to get a directly
  414. defined definitions::
  415. >>> IBase.direct('foo').__doc__
  416. 'base foo doc'
  417. >>> ISub.direct('foo')
  418. Specifications
  419. --------------
  420. Interfaces and declarations are both special cases of specifications.
  421. What we described above for interface inheritance applies to both
  422. declarations and specifications. Declarations actually extend the
  423. interfaces that they declare::
  424. >>> class Baz:
  425. ... zope.interface.implements(IBaz)
  426. >>> baz_implements = zope.interface.implementedBy(Baz)
  427. >>> baz_implements.__bases__
  428. (<InterfaceClass __main__.IBaz>,)
  429. >>> baz_implements.extends(IFoo)
  430. True
  431. >>> baz_implements.isOrExtends(IFoo)
  432. True
  433. >>> baz_implements.isOrExtends(baz_implements)
  434. True
  435. Specifications (interfaces and declarations) provide an `__sro__`
  436. that lists the specification and all of it's ancestors::
  437. >>> baz_implements.__sro__
  438. (<implementedBy __main__.Baz>,
  439. <InterfaceClass __main__.IBaz>,
  440. <InterfaceClass __main__.IFoo>,
  441. <InterfaceClass __main__.IBlat>,
  442. <InterfaceClass zope.interface.Interface>)
  443. Tagged Values
  444. =============
  445. Interfaces and attribute descriptions support an extension mechanism,
  446. borrowed from UML, called "tagged values" that lets us store extra
  447. data::
  448. >>> IFoo.setTaggedValue('date-modified', '2004-04-01')
  449. >>> IFoo.setTaggedValue('author', 'Jim Fulton')
  450. >>> IFoo.getTaggedValue('date-modified')
  451. '2004-04-01'
  452. >>> IFoo.queryTaggedValue('date-modified')
  453. '2004-04-01'
  454. >>> IFoo.queryTaggedValue('datemodified')
  455. >>> tags = list(IFoo.getTaggedValueTags())
  456. >>> tags.sort()
  457. >>> tags
  458. ['author', 'date-modified']
  459. Function attributes are converted to tagged values when method
  460. attribute definitions are created::
  461. >>> class IBazFactory(zope.interface.Interface):
  462. ... def __call__():
  463. ... "create one"
  464. ... __call__.return_type = IBaz
  465. >>> IBazFactory['__call__'].getTaggedValue('return_type')
  466. <InterfaceClass __main__.IBaz>
  467. Tagged values can also be defined from within an interface definition::
  468. >>> class IWithTaggedValues(zope.interface.Interface):
  469. ... zope.interface.taggedValue('squish', 'squash')
  470. >>> IWithTaggedValues.getTaggedValue('squish')
  471. 'squash'
  472. Invariants
  473. ==========
  474. Interfaces can express conditions that must hold for objects that
  475. provide them. These conditions are expressed using one or more
  476. invariants. Invariants are callable objects that will be called with
  477. an object that provides an interface. An invariant raises an `Invalid`
  478. exception if the condition doesn't hold. Here's an example::
  479. >>> class RangeError(zope.interface.Invalid):
  480. ... """A range has invalid limits"""
  481. ... def __repr__(self):
  482. ... return "RangeError(%r)" % self.args
  483. >>> def range_invariant(ob):
  484. ... if ob.max < ob.min:
  485. ... raise RangeError(ob)
  486. Given this invariant, we can use it in an interface definition::
  487. >>> class IRange(zope.interface.Interface):
  488. ... min = zope.interface.Attribute("Lower bound")
  489. ... max = zope.interface.Attribute("Upper bound")
  490. ...
  491. ... zope.interface.invariant(range_invariant)
  492. Interfaces have a method for checking their invariants::
  493. >>> class Range(object):
  494. ... zope.interface.implements(IRange)
  495. ...
  496. ... def __init__(self, min, max):
  497. ... self.min, self.max = min, max
  498. ...
  499. ... def __repr__(self):
  500. ... return "Range(%s, %s)" % (self.min, self.max)
  501. >>> IRange.validateInvariants(Range(1,2))
  502. >>> IRange.validateInvariants(Range(1,1))
  503. >>> IRange.validateInvariants(Range(2,1))
  504. Traceback (most recent call last):
  505. ...
  506. RangeError: Range(2, 1)
  507. If you have multiple invariants, you may not want to stop checking
  508. after the first error. If you pass a list to `validateInvariants`,
  509. then a single `Invalid` exception will be raised with the list of
  510. exceptions as it's argument::
  511. >>> errors = []
  512. >>> IRange.validateInvariants(Range(2,1), errors)
  513. Traceback (most recent call last):
  514. ...
  515. Invalid: [RangeError(Range(2, 1))]
  516. And the list will be filled with the individual exceptions::
  517. >>> errors
  518. [RangeError(Range(2, 1))]
  519. >>> del errors[:]
  520. Adaptation
  521. ==========
  522. Interfaces can be called to perform adaptation.
  523. The sematics based on those of the PEP 246 adapt function.
  524. If an object cannot be adapted, then a TypeError is raised::
  525. >>> class I(zope.interface.Interface):
  526. ... pass
  527. >>> I(0)
  528. Traceback (most recent call last):
  529. ...
  530. TypeError: ('Could not adapt', 0, <InterfaceClass __main__.I>)
  531. unless an alternate value is provided as a second positional argument::
  532. >>> I(0, 'bob')
  533. 'bob'
  534. If an object already implements the interface, then it will be returned::
  535. >>> class C(object):
  536. ... zope.interface.implements(I)
  537. >>> obj = C()
  538. >>> I(obj) is obj
  539. True
  540. If an object implements __conform__, then it will be used::
  541. >>> class C(object):
  542. ... zope.interface.implements(I)
  543. ... def __conform__(self, proto):
  544. ... return 0
  545. >>> I(C())
  546. 0
  547. Adapter hooks (see __adapt__) will also be used, if present::
  548. >>> from zope.interface.interface import adapter_hooks
  549. >>> def adapt_0_to_42(iface, obj):
  550. ... if obj == 0:
  551. ... return 42
  552. >>> adapter_hooks.append(adapt_0_to_42)
  553. >>> I(0)
  554. 42
  555. >>> adapter_hooks.remove(adapt_0_to_42)
  556. >>> I(0)
  557. Traceback (most recent call last):
  558. ...
  559. TypeError: ('Could not adapt', 0, <InterfaceClass __main__.I>)
  560. __adapt__
  561. ---------
  562. >>> class I(zope.interface.Interface):
  563. ... pass
  564. Interfaces implement the PEP 246 __adapt__ method.
  565. This method is normally not called directly. It is called by the PEP
  566. 246 adapt framework and by the interface __call__ operator.
  567. The adapt method is responsible for adapting an object to the
  568. reciever.
  569. The default version returns None::
  570. >>> I.__adapt__(0)
  571. unless the object given provides the interface::
  572. >>> class C(object):
  573. ... zope.interface.implements(I)
  574. >>> obj = C()
  575. >>> I.__adapt__(obj) is obj
  576. True
  577. Adapter hooks can be provided (or removed) to provide custom
  578. adaptation. We'll install a silly hook that adapts 0 to 42.
  579. We install a hook by simply adding it to the adapter_hooks
  580. list::
  581. >>> from zope.interface.interface import adapter_hooks
  582. >>> def adapt_0_to_42(iface, obj):
  583. ... if obj == 0:
  584. ... return 42
  585. >>> adapter_hooks.append(adapt_0_to_42)
  586. >>> I.__adapt__(0)
  587. 42
  588. Hooks must either return an adapter, or None if no adapter can
  589. be found.
  590. Hooks can be uninstalled by removing them from the list::
  591. >>> adapter_hooks.remove(adapt_0_to_42)
  592. >>> I.__adapt__(0)
  593. .. [#create] The main reason we subclass `Interface` is to cause the
  594. Python class statement to create an interface, rather
  595. than a class.
  596. It's possible to create interfaces by calling a special
  597. interface class directly. Doing this, it's possible
  598. (and, on rare occasions, useful) to create interfaces
  599. that don't descend from `Interface`. Using this
  600. technique is beyond the scope of this document.
  601. .. [#factory] Classes are factories. They can be called to create
  602. their instances. We expect that we will eventually
  603. extend the concept of implementation to other kinds of
  604. factories, so that we can declare the interfaces
  605. provided by the objects created.
  606. .. [#compat] The goal is substitutability. An object that provides an
  607. extending interface should be substitutable for an object
  608. that provides the extended interface. In our example, an
  609. object that provides IBaz should be usable whereever an
  610. object that provides IBlat is expected.
  611. The interface implementation doesn't enforce this.
  612. but maybe it should do some checks.
  613. ================
  614. Adapter Registry
  615. ================
  616. Adapter registries provide a way to register objects that depend on
  617. one or more interface specifications and provide (perhaps indirectly)
  618. some interface. In addition, the registrations have names. (You can
  619. think of the names as qualifiers of the provided interfaces.)
  620. The term "interface specification" refers both to interfaces and to
  621. interface declarations, such as declarations of interfaces implemented
  622. by a class.
  623. Single Adapters
  624. ===============
  625. Let's look at a simple example, using a single required specification::
  626. >>> from zope.interface.adapter import AdapterRegistry
  627. >>> import zope.interface
  628. >>> class IR1(zope.interface.Interface):
  629. ... pass
  630. >>> class IP1(zope.interface.Interface):
  631. ... pass
  632. >>> class IP2(IP1):
  633. ... pass
  634. >>> registry = AdapterRegistry()
  635. We'll register an object that depends on IR1 and "provides" IP2::
  636. >>> registry.register([IR1], IP2, '', 12)
  637. Given the registration, we can look it up again::
  638. >>> registry.lookup([IR1], IP2, '')
  639. 12
  640. Note that we used an integer in the example. In real applications,
  641. one would use some objects that actually depend on or provide
  642. interfaces. The registry doesn't care about what gets registered, so
  643. we'll use integers and strings to keep the examples simple. There is
  644. one exception. Registering a value of None unregisters any
  645. previously-registered value.
  646. If an object depends on a specification, it can be looked up with a
  647. specification that extends the specification that it depends on::
  648. >>> class IR2(IR1):
  649. ... pass
  650. >>> registry.lookup([IR2], IP2, '')
  651. 12
  652. We can use a class implementation specification to look up the object::
  653. >>> class C2:
  654. ... zope.interface.implements(IR2)
  655. >>> registry.lookup([zope.interface.implementedBy(C2)], IP2, '')
  656. 12
  657. and it can be looked up for interfaces that its provided interface
  658. extends::
  659. >>> registry.lookup([IR1], IP1, '')
  660. 12
  661. >>> registry.lookup([IR2], IP1, '')
  662. 12
  663. But if you require a specification that doesn't extend the specification the
  664. object depends on, you won't get anything::
  665. >>> registry.lookup([zope.interface.Interface], IP1, '')
  666. By the way, you can pass a default value to lookup::
  667. >>> registry.lookup([zope.interface.Interface], IP1, '', 42)
  668. 42
  669. If you try to get an interface the object doesn't provide, you also
  670. won't get anything::
  671. >>> class IP3(IP2):
  672. ... pass
  673. >>> registry.lookup([IR1], IP3, '')
  674. You also won't get anything if you use the wrong name::
  675. >>> registry.lookup([IR1], IP1, 'bob')
  676. >>> registry.register([IR1], IP2, 'bob', "Bob's 12")
  677. >>> registry.lookup([IR1], IP1, 'bob')
  678. "Bob's 12"
  679. You can leave the name off when doing a lookup::
  680. >>> registry.lookup([IR1], IP1)
  681. 12
  682. If we register an object that provides IP1::
  683. >>> registry.register([IR1], IP1, '', 11)
  684. then that object will be prefered over O(12)::
  685. >>> registry.lookup([IR1], IP1, '')
  686. 11
  687. Also, if we register an object for IR2, then that will be prefered
  688. when using IR2::
  689. >>> registry.register([IR2], IP1, '', 21)
  690. >>> registry.lookup([IR2], IP1, '')
  691. 21
  692. Finding out what, if anything, is registered
  693. --------------------------------------------
  694. We can ask if there is an adapter registered for a collection of
  695. interfaces. This is different than lookup, because it looks for an
  696. exact match.
  697. >>> print registry.registered([IR1], IP1)
  698. 11
  699. >>> print registry.registered([IR1], IP2)
  700. 12
  701. >>> print registry.registered([IR1], IP2, 'bob')
  702. Bob's 12
  703. >>> print registry.registered([IR2], IP1)
  704. 21
  705. >>> print registry.registered([IR2], IP2)
  706. None
  707. In the last example, None was returned because nothing was registered
  708. exactly for the given interfaces.
  709. lookup1
  710. -------
  711. Lookup of single adapters is common enough that there is a specialized
  712. version of lookup that takes a single required interface::
  713. >>> registry.lookup1(IR2, IP1, '')
  714. 21
  715. >>> registry.lookup1(IR2, IP1)
  716. 21
  717. Actual Adaptation
  718. -----------------
  719. The adapter registry is intended to support adaptation, where one
  720. object that implements an interface is adapted to another object that
  721. supports a different interface. The adapter registry supports the
  722. computation of adapters. In this case, we have to register adapter
  723. factories::
  724. >>> class IR(zope.interface.Interface):
  725. ... pass
  726. >>> class X:
  727. ... zope.interface.implements(IR)
  728. >>> class Y:
  729. ... zope.interface.implements(IP1)
  730. ... def __init__(self, context):
  731. ... self.context = context
  732. >>> registry.register([IR], IP1, '', Y)
  733. In this case, we registered a class as the factory. Now we can call
  734. `queryAdapter` to get the adapted object::
  735. >>> x = X()
  736. >>> y = registry.queryAdapter(x, IP1)
  737. >>> y.__class__.__name__
  738. 'Y'
  739. >>> y.context is x
  740. True
  741. We can register and lookup by name too::
  742. >>> class Y2(Y):
  743. ... pass
  744. >>> registry.register([IR], IP1, 'bob', Y2)
  745. >>> y = registry.queryAdapter(x, IP1, 'bob')
  746. >>> y.__class__.__name__
  747. 'Y2'
  748. >>> y.context is x
  749. True
  750. When the adapter factory produces `None`, then this is treated as if no
  751. adapter has been found. This allows us to prevent adaptation (when desired)
  752. and let the adapter factory determine whether adaptation is possible based on
  753. the state of the object being adapted.
  754. >>> def factory(context):
  755. ... if context.name == 'object':
  756. ... return 'adapter'
  757. ... return None
  758. >>> class Object(object):
  759. ... zope.interface.implements(IR)
  760. ... name = 'object'
  761. >>> registry.register([IR], IP1, 'conditional', factory)
  762. >>> obj = Object()
  763. >>> registry.queryAdapter(obj, IP1, 'conditional')
  764. 'adapter'
  765. >>> obj.name = 'no object'
  766. >>> registry.queryAdapter(obj, IP1, 'conditional') is None
  767. True
  768. >>> registry.queryAdapter(obj, IP1, 'conditional', 'default')
  769. 'default'
  770. An alternate method that provides the same function as `queryAdapter()` is
  771. `adapter_hook()`::
  772. >>> y = registry.adapter_hook(IP1, x)
  773. >>> y.__class__.__name__
  774. 'Y'
  775. >>> y.context is x
  776. True
  777. >>> y = registry.adapter_hook(IP1, x, 'bob')
  778. >>> y.__class__.__name__
  779. 'Y2'
  780. >>> y.context is x
  781. True
  782. The `adapter_hook()` simply switches the order of the object and
  783. interface arguments. It is used to hook into the interface call
  784. mechanism.
  785. Default Adapters
  786. ----------------
  787. Sometimes, you want to provide an adapter that will adapt anything.
  788. For that, provide None as the required interface::
  789. >>> registry.register([None], IP1, '', 1)
  790. then we can use that adapter for interfaces we don't have specific
  791. adapters for::
  792. >>> class IQ(zope.interface.Interface):
  793. ... pass
  794. >>> registry.lookup([IQ], IP1, '')
  795. 1
  796. Of course, specific adapters are still used when applicable::
  797. >>> registry.lookup([IR2], IP1, '')
  798. 21
  799. Class adapters
  800. --------------
  801. You can register adapters for class declarations, which is almost the
  802. same as registering them for a class::
  803. >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', 'C21')
  804. >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
  805. 'C21'
  806. Dict adapters
  807. -------------
  808. At some point it was impossible to register dictionary-based adapters due a
  809. bug. Let's make sure this works now:
  810. >>> adapter = {}
  811. >>> registry.register((), IQ, '', adapter)
  812. >>> registry.lookup((), IQ, '') is adapter
  813. True
  814. Unregistering
  815. -------------
  816. You can unregister by registering None, rather than an object::
  817. >>> registry.register([zope.interface.implementedBy(C2)], IP1, '', None)
  818. >>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
  819. 21
  820. Of course, this means that None can't be registered. This is an
  821. exception to the statement, made earlier, that the registry doesn't
  822. care what gets registered.
  823. Multi-adapters
  824. ==============
  825. You can adapt multiple specifications::
  826. >>> registry.register([IR1, IQ], IP2, '', '1q2')
  827. >>> registry.lookup([IR1, IQ], IP2, '')
  828. '1q2'
  829. >>> registry.lookup([IR2, IQ], IP1, '')
  830. '1q2'
  831. >>> class IS(zope.interface.Interface):
  832. ... pass
  833. >>> registry.lookup([IR2, IS], IP1, '')
  834. >>> class IQ2(IQ):
  835. ... pass
  836. >>> registry.lookup([IR2, IQ2], IP1, '')
  837. '1q2'
  838. >>> registry.register([IR1, IQ2], IP2, '', '1q22')
  839. >>> registry.lookup([IR2, IQ2], IP1, '')
  840. '1q22'
  841. Multi-adaptation
  842. ----------------
  843. You can adapt multiple objects::
  844. >>> class Q:
  845. ... zope.interface.implements(IQ)
  846. As with single adapters, we register a factory, which is often a class::
  847. >>> class IM(zope.interface.Interface):
  848. ... pass
  849. >>> class M:
  850. ... zope.interface.implements(IM)
  851. ... def __init__(self, x, q):
  852. ... self.x, self.q = x, q
  853. >>> registry.register([IR, IQ], IM, '', M)
  854. And then we can call `queryMultiAdapter` to compute an adapter::
  855. >>> q = Q()
  856. >>> m = registry.queryMultiAdapter((x, q), IM)
  857. >>> m.__class__.__name__
  858. 'M'
  859. >>> m.x is x and m.q is q
  860. True
  861. and, of course, we can use names::
  862. >>> class M2(M):
  863. ... pass
  864. >>> registry.register([IR, IQ], IM, 'bob', M2)
  865. >>> m = registry.queryMultiAdapter((x, q), IM, 'bob')
  866. >>> m.__class__.__name__
  867. 'M2'
  868. >>> m.x is x and m.q is q
  869. True
  870. Default Adapters
  871. ----------------
  872. As with single adapters, you can define default adapters by specifying
  873. None for the *first* specification::
  874. >>> registry.register([None, IQ], IP2, '', 'q2')
  875. >>> registry.lookup([IS, IQ], IP2, '')
  876. 'q2'
  877. Null Adapters
  878. =============
  879. You can also adapt no specification::
  880. >>> registry.register([], IP2, '', 2)
  881. >>> registry.lookup([], IP2, '')
  882. 2
  883. >>> registry.lookup([], IP1, '')
  884. 2
  885. Listing named adapters
  886. ----------------------
  887. Adapters are named. Sometimes, it's useful to get all of the named
  888. adapters for given interfaces::
  889. >>> adapters = list(registry.lookupAll([IR1], IP1))
  890. >>> adapters.sort()
  891. >>> adapters
  892. [(u'', 11), (u'bob', "Bob's 12")]
  893. This works for multi-adapters too::
  894. >>> registry.register([IR1, IQ2], IP2, 'bob', '1q2 for bob')
  895. >>> adapters = list(registry.lookupAll([IR2, IQ2], IP1))
  896. >>> adapters.sort()
  897. >>> adapters
  898. [(u'', '1q22'), (u'bob', '1q2 for bob')]
  899. And even null adapters::
  900. >>> registry.register([], IP2, 'bob', 3)
  901. >>> adapters = list(registry.lookupAll([], IP1))
  902. >>> adapters.sort()
  903. >>> adapters
  904. [(u'', 2), (u'bob', 3)]
  905. Subscriptions
  906. =============
  907. Normally, we want to look up an object that most-closely matches a
  908. specification. Sometimes, we want to get all of the objects that
  909. match some specification. We use subscriptions for this. We
  910. subscribe objects against specifications and then later find all of
  911. the subscribed objects::
  912. >>> registry.subscribe([IR1], IP2, 'sub12 1')
  913. >>> registry.subscriptions([IR1], IP2)
  914. ['sub12 1']
  915. Note that, unlike regular adapters, subscriptions are unnamed.
  916. You can have multiple subscribers for the same specification::
  917. >>> registry.subscribe([IR1], IP2, 'sub12 2')
  918. >>> registry.subscriptions([IR1], IP2)
  919. ['sub12 1', 'sub12 2']
  920. If subscribers are registered for the same required interfaces, they
  921. are returned in the order of definition.
  922. You can register subscribers for all specifications using None::
  923. >>> registry.subscribe([None], IP1, 'sub_1')
  924. >>> registry.subscriptions([IR2], IP1)
  925. ['sub_1', 'sub12 1', 'sub12 2']
  926. Note that the new subscriber is returned first. Subscribers defined
  927. for less general required interfaces are returned before subscribers
  928. for more general interfaces.
  929. Subscriptions may be combined over multiple compatible specifications::
  930. >>> registry.subscriptions([IR2], IP1)
  931. ['sub_1', 'sub12 1', 'sub12 2']
  932. >>> registry.subscribe([IR1], IP1, 'sub11')
  933. >>> registry.subscriptions([IR2], IP1)
  934. ['sub_1', 'sub12 1', 'sub12 2', 'sub11']
  935. >>> registry.subscribe([IR2], IP2, 'sub22')
  936. >>> registry.subscriptions([IR2], IP1)
  937. ['sub_1', 'sub12 1', 'sub12 2', 'sub11', 'sub22']
  938. >>> registry.subscriptions([IR2], IP2)
  939. ['sub12 1', 'sub12 2', 'sub22']
  940. Subscriptions can be on multiple specifications::
  941. >>> registry.subscribe([IR1, IQ], IP2, 'sub1q2')
  942. >>> registry.subscriptions([IR1, IQ], IP2)
  943. ['sub1q2']
  944. As with single subscriptions and non-subscription adapters, you can
  945. specify None for the first required interface, to specify a default::
  946. >>> registry.subscribe([None, IQ], IP2, 'sub_q2')
  947. >>> registry.subscriptions([IS, IQ], IP2)
  948. ['sub_q2']
  949. >>> registry.subscriptions([IR1, IQ], IP2)
  950. ['sub_q2', 'sub1q2']
  951. You can have subscriptions that are indepenent of any specifications::
  952. >>> list(registry.subscriptions([], IP1))
  953. []
  954. >>> registry.subscribe([], IP2, 'sub2')
  955. >>> registry.subscriptions([], IP1)
  956. ['sub2']
  957. >>> registry.subscribe([], IP1, 'sub1')
  958. >>> registry.subscriptions([], IP1)
  959. ['sub2', 'sub1']
  960. >>> registry.subscriptions([], IP2)
  961. ['sub2']
  962. Unregistering subscribers
  963. -------------------------
  964. We can unregister subscribers. When unregistering a subscriber, we
  965. can unregister a specific subscriber::
  966. >>> registry.unsubscribe([IR1], IP1, 'sub11')
  967. >>> registry.subscriptions([IR1], IP1)
  968. ['sub_1', 'sub12 1', 'sub12 2']
  969. If we don't specify a value, then all subscribers matching the given
  970. interfaces will be unsubscribed:
  971. >>> registry.unsubscribe([IR1], IP2)
  972. >>> registry.subscriptions([IR1], IP1)
  973. ['sub_1']
  974. Subscription adapters
  975. ---------------------
  976. We normally register adapter factories, which then allow us to compute
  977. adapters, but with subscriptions, we get multiple adapters. Here's an
  978. example of multiple-object subscribers::
  979. >>> registry.subscribe([IR, IQ], IM, M)
  980. >>> registry.subscribe([IR, IQ], IM, M2)
  981. >>> subscribers = registry.subscribers((x, q), IM)
  982. >>> len(subscribers)
  983. 2
  984. >>> class_names = [s.__class__.__name__ for s in subscribers]
  985. >>> class_names.sort()
  986. >>> class_names
  987. ['M', 'M2']
  988. >>> [(s.x is x and s.q is q) for s in subscribers]
  989. [True, True]
  990. adapter factory subcribers can't return None values::
  991. >>> def M3(x, y):
  992. ... return None
  993. >>> registry.subscribe([IR, IQ], IM, M3)
  994. >>> subscribers = registry.subscribers((x, q), IM)
  995. >>> len(subscribers)
  996. 2
  997. Handlers
  998. --------
  999. A handler is a subscriber factory that doesn't produce any normal
  1000. output. It returns None. A handler is unlike adapters in that it does
  1001. all of its work when the factory is called.
  1002. To register a handler, simply provide None as the provided interface::
  1003. >>> def handler(event):
  1004. ... print 'handler', event
  1005. >>> registry.subscribe([IR1], None, handler)
  1006. >>> registry.subscriptions([IR1], None) == [handler]
  1007. True
  1008. ==========================
  1009. Using the Adapter Registry
  1010. ==========================
  1011. This is a small demonstration of the ``zope.interface`` package including its
  1012. adapter registry. It is intended to provide a concrete but narrow example on
  1013. how to use interfaces and adapters outside of Zope 3.
  1014. First we have to import the interface package::
  1015. >>> import zope.interface
  1016. We now develop an interface for our object, which is a simple file in this
  1017. case. For now we simply support one attribute, the body, which contains the
  1018. actual file contents::
  1019. >>> class IFile(zope.interface.Interface):
  1020. ...
  1021. ... body = zope.interface.Attribute('Contents of the file.')
  1022. ...
  1023. For statistical reasons we often want to know the size of a file. However, it
  1024. would be clumsy to implement the size directly in the file object, since the
  1025. size really represents meta-data. Thus we create another interface that
  1026. provides the size of something::
  1027. >>> class ISize(zope.interface.Interface):
  1028. ...
  1029. ... def getSize():
  1030. ... 'Return the size of an object.'
  1031. ...
  1032. Now we need to implement the file. It is essential that the object states
  1033. that it implements the `IFile` interface. We also provide a default body
  1034. value (just to make things simpler for this example)::
  1035. >>> class File(object):
  1036. ...
  1037. ... zope.interface.implements(IFile)
  1038. ... body = 'foo bar'
  1039. ...
  1040. Next we implement an adapter that can provide the `ISize` interface given any
  1041. object providing `IFile`. By convention we use `__used_for__` to specify the
  1042. interface that we expect the adapted object to provide, in our case
  1043. `IFile`. However, this attribute is not used for anything. If you have
  1044. multiple interfaces for which an adapter is used, just specify the interfaces
  1045. via a tuple.
  1046. Again by convention, the constructor of an adapter takes one argument, the
  1047. context. The context in this case is an instance of `File` (providing `IFile`)
  1048. that is used to extract the size from. Also by convention the context is
  1049. stored in an attribute named `context` on the adapter. The twisted community
  1050. refers to the context as the `original` object. However, you may feel free to
  1051. use a specific argument name, such as `file`::
  1052. >>> class FileSize(object):
  1053. ...
  1054. ... zope.interface.implements(ISize)
  1055. ... __used_for__ = IFile
  1056. ...
  1057. ... def __init__(self, context):
  1058. ... self.context = context
  1059. ...
  1060. ... def getSize(self):
  1061. ... return len(self.context.body)
  1062. ...
  1063. Now that we have written our adapter, we have to register it with an adapter
  1064. registry, so that it can be looked up when needed. There is no such thing as a
  1065. global registry; thus we have to instantiate one for our example manually::
  1066. >>> from zope.interface.adapter import AdapterRegistry
  1067. >>> registry = AdapterRegistry()
  1068. The registry keeps a map of what adapters implement based on another
  1069. interface, the object already provides. Therefore, we next have to register an
  1070. adapter that adapts from `IFile` to `ISize`. The first argument to
  1071. the registry's `register()` method is a list of original interfaces.In our
  1072. cause we have only one original interface, `IFile`. A list makes sense, since
  1073. the interface package has the concept of multi-adapters, which are adapters
  1074. that require multiple objects to adapt to a new interface. In these
  1075. situations, your adapter constructor will require an argument for each
  1076. specified interface.
  1077. The second argument is the interface the adapter provides, in our case
  1078. `ISize`. The third argument is the name of the adapter. Since we do not care
  1079. about names, we simply leave it as an empty string. Names are commonly useful,
  1080. if you have adapters for the same set of interfaces, but they are useful in
  1081. different situations. The last argument is simply the adapter class::
  1082. >>> registry.register([IFile], ISize, '', FileSize)
  1083. You can now use the the registry to lookup the adapter::
  1084. >>> registry.lookup1(IFile, ISize, '')
  1085. <class '__main__.FileSize'>
  1086. Let's get a little bit more practical. Let's create a `File` instance and
  1087. create the adapter using a registry lookup. Then we see whether the adapter
  1088. returns the correct size by calling `getSize()`::
  1089. >>> file = File()
  1090. >>> size = registry.lookup1(IFile, ISize, '')(file)
  1091. >>> size.getSize()
  1092. 7
  1093. However, this is not very practical, since I have to manually pass in the
  1094. arguments to the lookup method. There is some syntactic candy that will allow
  1095. us to get an adapter instance by simply calling `ISize(file)`. To make use of
  1096. this functionality, we need to add our registry to the adapter_hooks list,
  1097. which is a member of the adapters module. This list stores a collection of
  1098. callables that are automatically invoked when IFoo(obj) is called; their
  1099. purpose is to locate adapters that implement an interface for a certain
  1100. context instance.
  1101. You are required to implement your own adapter hook; this example covers one
  1102. of the simplest hooks that use the registry, but you could implement one that
  1103. used an adapter cache or persistent adapters, for instance. The helper hook is
  1104. required to expect as first argument the desired output interface (for us
  1105. `ISize`) and as the second argument the context of the adapter (here
  1106. `file`). The function returns an adapter, i.e. a `FileSize` instance::
  1107. >>> def hook(provided, object):
  1108. ... adapter = registry.lookup1(zope.interface.providedBy(object),
  1109. ... provided, '')
  1110. ... return adapter(object)
  1111. ...
  1112. We now just add the hook to an `adapter_hooks` list::
  1113. >>> from zope.interface.interface import adapter_hooks
  1114. >>> adapter_hooks.append(hook)
  1115. Once the hook is registered, you can use the desired syntax::
  1116. >>> size = ISize(file)
  1117. >>> size.getSize()
  1118. 7
  1119. Now we have to cleanup after ourselves, so that others after us have a clean
  1120. `adapter_hooks` list::
  1121. >>> adapter_hooks.remove(hook)
  1122. That's it. I have intentionally left out a discussion of named adapters and
  1123. multi-adapters, since this text is intended as a practical and simple
  1124. introduction to Zope 3 interfaces and adapters. You might want to read the
  1125. `adapter.txt` in the `zope.interface` package for a more formal, referencial
  1126. and complete treatment of the package. Warning: People have reported that
  1127. `adapter.txt` makes their brain feel soft!
  1128. CHANGES
  1129. *******
  1130. ==================
  1131. 3.5.2 (2009-07-01)
  1132. ==================
  1133. - BaseAdapterRegistry.unregister, unsubscribe: Remove empty portions of
  1134. the data structures when something is removed. This avoids leaving
  1135. references to global objects (interfaces) that may be slated for
  1136. removal from the calling application.
  1137. ==================
  1138. 3.5.1 (2009-03-18)
  1139. ==================
  1140. - verifyObject: use getattr instead of hasattr to test for object attributes
  1141. in order to let exceptions other than AttributeError raised by properties
  1142. propagate to the caller
  1143. - Add Sphinx-based documentation building to the package buildout
  1144. configuration. Use the ``bin/docs`` command after buildout.
  1145. - Improve package description a bit. Unify changelog entries formatting.
  1146. - Change package's mailing list address to zope-dev at zope.org as
  1147. zope3-dev at zope.org is now retired.
  1148. ==================
  1149. 3.5.0 (2008-10-26)
  1150. ==================
  1151. - Fixed declaration of _zope_interface_coptimizations, it's not a top level
  1152. package.
  1153. - Add a DocTestSuite for odd.py module, so their tests are run.
  1154. - Allow to bootstrap on Jython.
  1155. - Fix https://bugs.launchpad.net/zope3/3.3/+bug/98388: ISpecification
  1156. was missing a declaration for __iro__.
  1157. - Added optional code optimizations support, which allows the building
  1158. of C code optimizations to fail (Jython).
  1159. - Replaced `_flatten` with a non-recursive implementation, effectively making
  1160. it 3x faster.
  1161. ==================
  1162. 3.4.1 (2007-10-02)
  1163. ==================
  1164. - Fixed a setup bug that prevented installation from source on systems
  1165. without setuptools.
  1166. ==================
  1167. 3.4.0 (2007-07-19)
  1168. ==================
  1169. - Final release for 3.4.0.
  1170. ====================
  1171. 3.4.0b3 (2007-05-22)
  1172. ====================
  1173. - Objects with picky custom comparison methods couldn't be added to
  1174. component registries. Now, when checking whether an object is
  1175. already registered, identity comparison is used.
  1176. ====================
  1177. 3.3.0.1 (2007-01-03)
  1178. ====================
  1179. - Made a reference to OverflowWarning, which disappeared in Python
  1180. 2.5, conditional.
  1181. ==================
  1182. 3.3.0 (2007/01/03)
  1183. ==================
  1184. New Features
  1185. ============
  1186. - The adapter-lookup algorithim was refactored to make it
  1187. much simpler and faster.
  1188. Also, more of the adapter-lookup logic is implemented in C, making
  1189. debugging of application code easier, since there is less
  1190. infrastructre code to step through.
  1191. - We now treat objects without interface declarations as if they
  1192. declared that they provide zope.interface.Interface.
  1193. - There are a number of richer new adapter-registration interfaces
  1194. that provide greater control and introspection.
  1195. - Added a new interface decorator to zope.interface that allows the
  1196. setting of tagged values on an interface at definition time (see
  1197. zope.interface.taggedValue).
  1198. Bug Fixes
  1199. =========
  1200. - A bug in multi-adapter lookup sometimes caused incorrect adapters to
  1201. be returned.
  1202. ====================
  1203. 3.2.0.2 (2006-04-15)
  1204. ====================
  1205. - Fix packaging bug: 'package_dir' must be a *relative* path.
  1206. ====================
  1207. 3.2.0.1 (2006-04-14)
  1208. ====================
  1209. - Packaging change: suppress inclusion of 'setup.cfg' in 'sdist' builds.
  1210. ==================
  1211. 3.2.0 (2006-01-05)
  1212. ==================
  1213. - Corresponds to the verison of the zope.interface package shipped as part of
  1214. the Zope 3.2.0 release.
  1215. ==================
  1216. 3.1.0 (2005-10-03)
  1217. ==================
  1218. - Corresponds to the verison of the zope.interface package shipped as part of
  1219. the Zope 3.1.0 release.
  1220. - Made attribute resolution order consistent with component lookup order,
  1221. i.e. new-style class MRO semantics.
  1222. - Deprecated 'isImplementedBy' and 'isImplementedByInstancesOf' APIs in
  1223. favor of 'implementedBy' and 'providedBy'.
  1224. ==================
  1225. 3.0.1 (2005-07-27)
  1226. ==================
  1227. - Corresponds to the verison of the zope.interface package shipped as part of
  1228. the Zope X3.0.1 release.
  1229. - Fixed a bug reported by James Knight, which caused adapter registries
  1230. to fail occasionally to reflect declaration changes.
  1231. ==================
  1232. 3.0.0 (2004-11-07)
  1233. ==================
  1234. - Corresponds to the verison of the zope.interface package shipped as part of
  1235. the Zope X3.0.0 release.
  1236. Download
  1237. ********
  1238. Platform: UNKNOWN