README.rst 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  1. ==========
  2. Interfaces
  3. ==========
  4. Interfaces are objects that specify (document) the external behavior
  5. of objects that "provide" them. An interface specifies behavior
  6. through:
  7. - Informal documentation in a doc string
  8. - Attribute definitions
  9. - Invariants, which are conditions that must hold for objects that
  10. provide the interface
  11. Attribute definitions specify specific attributes. They define the
  12. attribute name and provide documentation and constraints of attribute
  13. values. Attribute definitions can take a number of forms, as we'll
  14. see below.
  15. Defining interfaces
  16. ===================
  17. Interfaces are defined using Python ``class`` statements:
  18. .. doctest::
  19. >>> import zope.interface
  20. >>> class IFoo(zope.interface.Interface):
  21. ... """Foo blah blah"""
  22. ...
  23. ... x = zope.interface.Attribute("""X blah blah""")
  24. ...
  25. ... def bar(q, r=None):
  26. ... """bar blah blah"""
  27. In the example above, we've created an interface, :class:`IFoo`. We
  28. subclassed :class:`zope.interface.Interface`, which is an ancestor interface for
  29. all interfaces, much as ``object`` is an ancestor of all new-style
  30. classes [#create]_. The interface is not a class, it's an Interface,
  31. an instance of :class:`zope.interface.interface.InterfaceClass`:
  32. .. doctest::
  33. >>> type(IFoo)
  34. <class 'zope.interface.interface.InterfaceClass'>
  35. We can ask for the interface's documentation:
  36. .. doctest::
  37. >>> IFoo.__doc__
  38. 'Foo blah blah'
  39. and its name:
  40. .. doctest::
  41. >>> IFoo.__name__
  42. 'IFoo'
  43. and even its module:
  44. .. doctest::
  45. >>> IFoo.__module__
  46. '__builtin__'
  47. The interface defined two attributes:
  48. ``x``
  49. This is the simplest form of attribute definition. It has a name
  50. and a doc string. It doesn't formally specify anything else.
  51. ``bar``
  52. This is a method. A method is defined via a function definition. A
  53. method is simply an attribute constrained to be a callable with a
  54. particular signature, as provided by the function definition.
  55. Note that ``bar`` doesn't take a ``self`` argument. Interfaces document
  56. how an object is *used*. When calling instance methods, you don't
  57. pass a ``self`` argument, so a ``self`` argument isn't included in the
  58. interface signature. The ``self`` argument in instance methods is
  59. really an implementation detail of Python instances. Other objects,
  60. besides instances can provide interfaces and their methods might not
  61. be instance methods. For example, modules can provide interfaces and
  62. their methods are usually just functions. Even instances can have
  63. methods that are not instance methods.
  64. You can access the attributes defined by an interface using mapping
  65. syntax:
  66. .. doctest::
  67. >>> x = IFoo['x']
  68. >>> type(x)
  69. <class 'zope.interface.interface.Attribute'>
  70. >>> x.__name__
  71. 'x'
  72. >>> x.__doc__
  73. 'X blah blah'
  74. >>> IFoo.get('x').__name__
  75. 'x'
  76. >>> IFoo.get('y')
  77. You can use ``in`` to determine if an interface defines a name:
  78. .. doctest::
  79. >>> 'x' in IFoo
  80. True
  81. You can iterate over interfaces to get the names they define:
  82. .. doctest::
  83. >>> names = list(IFoo)
  84. >>> names.sort()
  85. >>> names
  86. ['bar', 'x']
  87. Remember that interfaces aren't classes. You can't access attribute
  88. definitions as attributes of interfaces:
  89. .. doctest::
  90. >>> IFoo.x
  91. Traceback (most recent call last):
  92. File "<stdin>", line 1, in ?
  93. AttributeError: 'InterfaceClass' object has no attribute 'x'
  94. Methods provide access to the method signature:
  95. .. doctest::
  96. >>> bar = IFoo['bar']
  97. >>> bar.getSignatureString()
  98. '(q, r=None)'
  99. TODO
  100. Methods really should have a better API. This is something that
  101. needs to be improved.
  102. Declaring interfaces
  103. ====================
  104. Having defined interfaces, we can *declare* that objects provide
  105. them. Before we describe the details, lets define some terms:
  106. *provide*
  107. We say that objects *provide* interfaces. If an object provides an
  108. interface, then the interface specifies the behavior of the
  109. object. In other words, interfaces specify the behavior of the
  110. objects that provide them.
  111. *implement*
  112. We normally say that classes *implement* interfaces. If a class
  113. implements an interface, then the instances of the class provide
  114. the interface. Objects provide interfaces that their classes
  115. implement [#factory]_. (Objects can provide interfaces directly,
  116. in addition to what their classes implement.)
  117. It is important to note that classes don't usually provide the
  118. interfaces that they implement.
  119. We can generalize this to factories. For any callable object we
  120. can declare that it produces objects that provide some interfaces
  121. by saying that the factory implements the interfaces.
  122. Now that we've defined these terms, we can talk about the API for
  123. declaring interfaces.
  124. Declaring implemented interfaces
  125. --------------------------------
  126. The most common way to declare interfaces is using the implements
  127. function in a class statement:
  128. .. doctest::
  129. >>> class Foo:
  130. ... zope.interface.implements(IFoo)
  131. ...
  132. ... def __init__(self, x=None):
  133. ... self.x = x
  134. ...
  135. ... def bar(self, q, r=None):
  136. ... return q, r, self.x
  137. ...
  138. ... def __repr__(self):
  139. ... return "Foo(%s)" % self.x
  140. In this example, we declared that ``Foo`` implements ``IFoo``. This means
  141. that instances of ``Foo`` provide ``IFoo``. Having made this declaration,
  142. there are several ways we can introspect the declarations. First, we
  143. can ask an interface whether it is implemented by a class:
  144. .. doctest::
  145. >>> IFoo.implementedBy(Foo)
  146. True
  147. And we can ask whether an interface is provided by an object:
  148. .. doctest::
  149. >>> foo = Foo()
  150. >>> IFoo.providedBy(foo)
  151. True
  152. Of course, ``Foo`` doesn't *provide* ``IFoo``, it *implements* it:
  153. .. doctest::
  154. >>> IFoo.providedBy(Foo)
  155. False
  156. We can also ask what interfaces are implemented by a class:
  157. .. doctest::
  158. >>> list(zope.interface.implementedBy(Foo))
  159. [<InterfaceClass __builtin__.IFoo>]
  160. It's an error to ask for interfaces implemented by a non-callable
  161. object:
  162. .. doctest::
  163. >>> IFoo.implementedBy(foo)
  164. Traceback (most recent call last):
  165. ...
  166. TypeError: ('ImplementedBy called for non-factory', Foo(None))
  167. >>> list(zope.interface.implementedBy(foo))
  168. Traceback (most recent call last):
  169. ...
  170. TypeError: ('ImplementedBy called for non-factory', Foo(None))
  171. Similarly, we can ask what interfaces are provided by an object:
  172. .. doctest::
  173. >>> list(zope.interface.providedBy(foo))
  174. [<InterfaceClass __builtin__.IFoo>]
  175. >>> list(zope.interface.providedBy(Foo))
  176. []
  177. We can declare interfaces implemented by other factories (besides
  178. classes). We do this using a Python-2.4-style decorator named
  179. `implementer`. In versions of Python before 2.4, this looks like:
  180. .. doctest::
  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 __builtin__.IFoo>]
  188. Note that the implementer decorator may modify its argument. Callers
  189. should not assume that a new object is created.
  190. Using implementer also works on callable objects. This is used by
  191. :py:mod:`zope.formlib`, as an example:
  192. .. doctest::
  193. >>> class yfactory:
  194. ... def __call__(self, y):
  195. ... foo = Foo()
  196. ... foo.y = y
  197. ... return foo
  198. >>> yfoo = yfactory()
  199. >>> yfoo = zope.interface.implementer(IFoo)(yfoo)
  200. >>> list(zope.interface.implementedBy(yfoo))
  201. [<InterfaceClass __builtin__.IFoo>]
  202. XXX: Double check and update these version numbers:
  203. In :py:mod:`zope.interface` 3.5.2 and lower, the implementer decorator can not
  204. be used for classes, but in 3.6.0 and higher it can:
  205. .. doctest::
  206. >>> Foo = zope.interface.implementer(IFoo)(Foo)
  207. >>> list(zope.interface.providedBy(Foo()))
  208. [<InterfaceClass __builtin__.IFoo>]
  209. Note that class decorators using the ``@implementer(IFoo)`` syntax are only
  210. supported in Python 2.6 and later.
  211. Declaring provided interfaces
  212. -----------------------------
  213. We can declare interfaces directly provided by objects. Suppose that
  214. we want to document what the ``__init__`` method of the ``Foo`` class
  215. does. It's not *really* part of ``IFoo``. You wouldn't normally call
  216. the ``__init__`` method on Foo instances. Rather, the ``__init__`` method
  217. is part of ``Foo``'s ``__call__`` method:
  218. .. doctest::
  219. >>> class IFooFactory(zope.interface.Interface):
  220. ... """Create foos"""
  221. ...
  222. ... def __call__(x=None):
  223. ... """Create a foo
  224. ...
  225. ... The argument provides the initial value for x ...
  226. ... """
  227. It's the class that provides this interface, so we declare the
  228. interface on the class:
  229. .. doctest::
  230. >>> zope.interface.directlyProvides(Foo, IFooFactory)
  231. And then, we'll see that Foo provides some interfaces:
  232. .. doctest::
  233. >>> list(zope.interface.providedBy(Foo))
  234. [<InterfaceClass __builtin__.IFooFactory>]
  235. >>> IFooFactory.providedBy(Foo)
  236. True
  237. Declaring class interfaces is common enough that there's a special
  238. declaration function for it, `classProvides`, that allows the
  239. declaration from within a class statement:
  240. .. doctest::
  241. >>> class Foo2:
  242. ... zope.interface.implements(IFoo)
  243. ... zope.interface.classProvides(IFooFactory)
  244. ...
  245. ... def __init__(self, x=None):
  246. ... self.x = x
  247. ...
  248. ... def bar(self, q, r=None):
  249. ... return q, r, self.x
  250. ...
  251. ... def __repr__(self):
  252. ... return "Foo(%s)" % self.x
  253. >>> list(zope.interface.providedBy(Foo2))
  254. [<InterfaceClass __builtin__.IFooFactory>]
  255. >>> IFooFactory.providedBy(Foo2)
  256. True
  257. There's a similar function, ``moduleProvides``, that supports interface
  258. declarations from within module definitions. For example, see the use
  259. of ``moduleProvides`` call in ``zope.interface.__init__``, which declares that
  260. the package ``zope.interface`` provides ``IInterfaceDeclaration``.
  261. Sometimes, we want to declare interfaces on instances, even though
  262. those instances get interfaces from their classes. Suppose we create
  263. a new interface, ``ISpecial``:
  264. .. doctest::
  265. >>> class ISpecial(zope.interface.Interface):
  266. ... reason = zope.interface.Attribute("Reason why we're special")
  267. ... def brag():
  268. ... "Brag about being special"
  269. We can make an existing foo instance special by providing ``reason``
  270. and ``brag`` attributes:
  271. .. doctest::
  272. >>> foo.reason = 'I just am'
  273. >>> def brag():
  274. ... return "I'm special!"
  275. >>> foo.brag = brag
  276. >>> foo.reason
  277. 'I just am'
  278. >>> foo.brag()
  279. "I'm special!"
  280. and by declaring the interface:
  281. .. doctest::
  282. >>> zope.interface.directlyProvides(foo, ISpecial)
  283. then the new interface is included in the provided interfaces:
  284. .. doctest::
  285. >>> ISpecial.providedBy(foo)
  286. True
  287. >>> list(zope.interface.providedBy(foo))
  288. [<InterfaceClass __builtin__.ISpecial>, <InterfaceClass __builtin__.IFoo>]
  289. We can find out what interfaces are directly provided by an object:
  290. .. doctest::
  291. >>> list(zope.interface.directlyProvidedBy(foo))
  292. [<InterfaceClass __builtin__.ISpecial>]
  293. >>> newfoo = Foo()
  294. >>> list(zope.interface.directlyProvidedBy(newfoo))
  295. []
  296. Inherited declarations
  297. ----------------------
  298. Normally, declarations are inherited:
  299. .. doctest::
  300. >>> class SpecialFoo(Foo):
  301. ... zope.interface.implements(ISpecial)
  302. ... reason = 'I just am'
  303. ... def brag(self):
  304. ... return "I'm special because %s" % self.reason
  305. >>> list(zope.interface.implementedBy(SpecialFoo))
  306. [<InterfaceClass __builtin__.ISpecial>, <InterfaceClass __builtin__.IFoo>]
  307. >>> list(zope.interface.providedBy(SpecialFoo()))
  308. [<InterfaceClass __builtin__.ISpecial>, <InterfaceClass __builtin__.IFoo>]
  309. Sometimes, you don't want to inherit declarations. In that case, you
  310. can use ``implementsOnly``, instead of ``implements``:
  311. .. doctest::
  312. >>> class Special(Foo):
  313. ... zope.interface.implementsOnly(ISpecial)
  314. ... reason = 'I just am'
  315. ... def brag(self):
  316. ... return "I'm special because %s" % self.reason
  317. >>> list(zope.interface.implementedBy(Special))
  318. [<InterfaceClass __builtin__.ISpecial>]
  319. >>> list(zope.interface.providedBy(Special()))
  320. [<InterfaceClass __builtin__.ISpecial>]
  321. External declarations
  322. ---------------------
  323. Normally, we make implementation declarations as part of a class
  324. definition. Sometimes, we may want to make declarations from outside
  325. the class definition. For example, we might want to declare interfaces
  326. for classes that we didn't write. The function ``classImplements`` can
  327. be used for this purpose:
  328. .. doctest::
  329. >>> class C:
  330. ... pass
  331. >>> zope.interface.classImplements(C, IFoo)
  332. >>> list(zope.interface.implementedBy(C))
  333. [<InterfaceClass __builtin__.IFoo>]
  334. We can use ``classImplementsOnly`` to exclude inherited interfaces:
  335. .. doctest::
  336. >>> class C(Foo):
  337. ... pass
  338. >>> zope.interface.classImplementsOnly(C, ISpecial)
  339. >>> list(zope.interface.implementedBy(C))
  340. [<InterfaceClass __builtin__.ISpecial>]
  341. Declaration Objects
  342. -------------------
  343. When we declare interfaces, we create *declaration* objects. When we
  344. query declarations, declaration objects are returned:
  345. .. doctest::
  346. >>> type(zope.interface.implementedBy(Special))
  347. <class 'zope.interface.declarations.Implements'>
  348. Declaration objects and interface objects are similar in many ways. In
  349. fact, they share a common base class. The important thing to realize
  350. about them is that they can be used where interfaces are expected in
  351. declarations. Here's a silly example:
  352. .. doctest::
  353. >>> class Special2(Foo):
  354. ... zope.interface.implementsOnly(
  355. ... zope.interface.implementedBy(Foo),
  356. ... ISpecial,
  357. ... )
  358. ... reason = 'I just am'
  359. ... def brag(self):
  360. ... return "I'm special because %s" % self.reason
  361. The declaration here is almost the same as
  362. ``zope.interface.implements(ISpecial)``, except that the order of
  363. interfaces in the resulting declaration is different:
  364. .. doctest::
  365. >>> list(zope.interface.implementedBy(Special2))
  366. [<InterfaceClass __builtin__.IFoo>, <InterfaceClass __builtin__.ISpecial>]
  367. Interface Inheritance
  368. =====================
  369. Interfaces can extend other interfaces. They do this simply by listing
  370. the other interfaces as base interfaces:
  371. .. doctest::
  372. >>> class IBlat(zope.interface.Interface):
  373. ... """Blat blah blah"""
  374. ...
  375. ... y = zope.interface.Attribute("y blah blah")
  376. ... def eek():
  377. ... """eek blah blah"""
  378. >>> IBlat.__bases__
  379. (<InterfaceClass zope.interface.Interface>,)
  380. >>> class IBaz(IFoo, IBlat):
  381. ... """Baz blah"""
  382. ... def eek(a=1):
  383. ... """eek in baz blah"""
  384. ...
  385. >>> IBaz.__bases__
  386. (<InterfaceClass __builtin__.IFoo>, <InterfaceClass __builtin__.IBlat>)
  387. >>> names = list(IBaz)
  388. >>> names.sort()
  389. >>> names
  390. ['bar', 'eek', 'x', 'y']
  391. Note that ``IBaz`` overrides ``eek``:
  392. .. doctest::
  393. >>> IBlat['eek'].__doc__
  394. 'eek blah blah'
  395. >>> IBaz['eek'].__doc__
  396. 'eek in baz blah'
  397. We were careful to override ``eek`` in a compatible way. When extending
  398. an interface, the extending interface should be compatible [#compat]_
  399. with the extended interfaces.
  400. We can ask whether one interface extends another:
  401. .. doctest::
  402. >>> IBaz.extends(IFoo)
  403. True
  404. >>> IBlat.extends(IFoo)
  405. False
  406. Note that interfaces don't extend themselves:
  407. .. doctest::
  408. >>> IBaz.extends(IBaz)
  409. False
  410. Sometimes we wish they did, but we can instead use ``isOrExtends``:
  411. .. doctest::
  412. >>> IBaz.isOrExtends(IBaz)
  413. True
  414. >>> IBaz.isOrExtends(IFoo)
  415. True
  416. >>> IFoo.isOrExtends(IBaz)
  417. False
  418. When we iterate over an interface, we get all of the names it defines,
  419. including names defined by base interfaces. Sometimes, we want *just*
  420. the names defined by the interface directly. We can use the ``names``
  421. method for that:
  422. .. doctest::
  423. >>> list(IBaz.names())
  424. ['eek']
  425. Inheritance of attribute specifications
  426. ---------------------------------------
  427. An interface may override attribute definitions from base interfaces.
  428. If two base interfaces define the same attribute, the attribute is
  429. inherited from the most specific interface. For example, with:
  430. .. doctest::
  431. >>> class IBase(zope.interface.Interface):
  432. ...
  433. ... def foo():
  434. ... "base foo doc"
  435. >>> class IBase1(IBase):
  436. ... pass
  437. >>> class IBase2(IBase):
  438. ...
  439. ... def foo():
  440. ... "base2 foo doc"
  441. >>> class ISub(IBase1, IBase2):
  442. ... pass
  443. ``ISub``'s definition of ``foo`` is the one from ``IBase2``, since ``IBase2`` is more
  444. specific than ``IBase``:
  445. .. doctest::
  446. >>> ISub['foo'].__doc__
  447. 'base2 foo doc'
  448. Note that this differs from a depth-first search.
  449. Sometimes, it's useful to ask whether an interface defines an
  450. attribute directly. You can use the direct method to get a directly
  451. defined definitions:
  452. .. doctest::
  453. >>> IBase.direct('foo').__doc__
  454. 'base foo doc'
  455. >>> ISub.direct('foo')
  456. Specifications
  457. --------------
  458. Interfaces and declarations are both special cases of specifications.
  459. What we described above for interface inheritance applies to both
  460. declarations and specifications. Declarations actually extend the
  461. interfaces that they declare:
  462. .. doctest::
  463. >>> class Baz(object):
  464. ... zope.interface.implements(IBaz)
  465. >>> baz_implements = zope.interface.implementedBy(Baz)
  466. >>> baz_implements.__bases__
  467. (<InterfaceClass __builtin__.IBaz>, <implementedBy ...object>)
  468. >>> baz_implements.extends(IFoo)
  469. True
  470. >>> baz_implements.isOrExtends(IFoo)
  471. True
  472. >>> baz_implements.isOrExtends(baz_implements)
  473. True
  474. Specifications (interfaces and declarations) provide an ``__sro__``
  475. that lists the specification and all of it's ancestors:
  476. .. doctest::
  477. >>> from pprint import pprint
  478. >>> pprint(baz_implements.__sro__)
  479. (<implementedBy __builtin__.Baz>,
  480. <InterfaceClass __builtin__.IBaz>,
  481. <InterfaceClass __builtin__.IFoo>,
  482. <InterfaceClass __builtin__.IBlat>,
  483. <InterfaceClass zope.interface.Interface>,
  484. <implementedBy ...object>)
  485. Tagged Values
  486. =============
  487. Interfaces and attribute descriptions support an extension mechanism,
  488. borrowed from UML, called "tagged values" that lets us store extra
  489. data:
  490. .. doctest::
  491. >>> IFoo.setTaggedValue('date-modified', '2004-04-01')
  492. >>> IFoo.setTaggedValue('author', 'Jim Fulton')
  493. >>> IFoo.getTaggedValue('date-modified')
  494. '2004-04-01'
  495. >>> IFoo.queryTaggedValue('date-modified')
  496. '2004-04-01'
  497. >>> IFoo.queryTaggedValue('datemodified')
  498. >>> tags = list(IFoo.getTaggedValueTags())
  499. >>> tags.sort()
  500. >>> tags
  501. ['author', 'date-modified']
  502. Function attributes are converted to tagged values when method
  503. attribute definitions are created:
  504. .. doctest::
  505. >>> class IBazFactory(zope.interface.Interface):
  506. ... def __call__():
  507. ... "create one"
  508. ... __call__.return_type = IBaz
  509. >>> IBazFactory['__call__'].getTaggedValue('return_type')
  510. <InterfaceClass __builtin__.IBaz>
  511. Tagged values can also be defined from within an interface definition:
  512. .. doctest::
  513. >>> class IWithTaggedValues(zope.interface.Interface):
  514. ... zope.interface.taggedValue('squish', 'squash')
  515. >>> IWithTaggedValues.getTaggedValue('squish')
  516. 'squash'
  517. Invariants
  518. ==========
  519. Interfaces can express conditions that must hold for objects that
  520. provide them. These conditions are expressed using one or more
  521. invariants. Invariants are callable objects that will be called with
  522. an object that provides an interface. An invariant raises an ``Invalid``
  523. exception if the condition doesn't hold. Here's an example:
  524. .. doctest::
  525. >>> class RangeError(zope.interface.Invalid):
  526. ... """A range has invalid limits"""
  527. ... def __repr__(self):
  528. ... return "RangeError(%r)" % self.args
  529. >>> def range_invariant(ob):
  530. ... if ob.max < ob.min:
  531. ... raise RangeError(ob)
  532. Given this invariant, we can use it in an interface definition:
  533. .. doctest::
  534. >>> class IRange(zope.interface.Interface):
  535. ... min = zope.interface.Attribute("Lower bound")
  536. ... max = zope.interface.Attribute("Upper bound")
  537. ...
  538. ... zope.interface.invariant(range_invariant)
  539. Interfaces have a method for checking their invariants:
  540. .. doctest::
  541. >>> class Range(object):
  542. ... zope.interface.implements(IRange)
  543. ...
  544. ... def __init__(self, min, max):
  545. ... self.min, self.max = min, max
  546. ...
  547. ... def __repr__(self):
  548. ... return "Range(%s, %s)" % (self.min, self.max)
  549. >>> IRange.validateInvariants(Range(1,2))
  550. >>> IRange.validateInvariants(Range(1,1))
  551. >>> IRange.validateInvariants(Range(2,1))
  552. Traceback (most recent call last):
  553. ...
  554. RangeError: Range(2, 1)
  555. If you have multiple invariants, you may not want to stop checking
  556. after the first error. If you pass a list to ``validateInvariants``,
  557. then a single ``Invalid`` exception will be raised with the list of
  558. exceptions as its argument:
  559. .. doctest::
  560. >>> from zope.interface.exceptions import Invalid
  561. >>> errors = []
  562. >>> try:
  563. ... IRange.validateInvariants(Range(2,1), errors)
  564. ... except Invalid, e:
  565. ... str(e)
  566. '[RangeError(Range(2, 1))]'
  567. And the list will be filled with the individual exceptions:
  568. .. doctest::
  569. >>> errors
  570. [RangeError(Range(2, 1))]
  571. >>> del errors[:]
  572. Adaptation
  573. ==========
  574. Interfaces can be called to perform adaptation.
  575. The semantics are based on those of the PEP 246 ``adapt`` function.
  576. If an object cannot be adapted, then a ``TypeError`` is raised:
  577. .. doctest::
  578. >>> class I(zope.interface.Interface):
  579. ... pass
  580. >>> I(0)
  581. Traceback (most recent call last):
  582. ...
  583. TypeError: ('Could not adapt', 0, <InterfaceClass __builtin__.I>)
  584. unless an alternate value is provided as a second positional argument:
  585. .. doctest::
  586. >>> I(0, 'bob')
  587. 'bob'
  588. If an object already implements the interface, then it will be returned:
  589. .. doctest::
  590. >>> class C(object):
  591. ... zope.interface.implements(I)
  592. >>> obj = C()
  593. >>> I(obj) is obj
  594. True
  595. If an object implements ``__conform__``, then it will be used:
  596. .. doctest::
  597. >>> class C(object):
  598. ... zope.interface.implements(I)
  599. ... def __conform__(self, proto):
  600. ... return 0
  601. >>> I(C())
  602. 0
  603. Adapter hooks (see ``__adapt__``) will also be used, if present:
  604. .. doctest::
  605. >>> from zope.interface.interface import adapter_hooks
  606. >>> def adapt_0_to_42(iface, obj):
  607. ... if obj == 0:
  608. ... return 42
  609. >>> adapter_hooks.append(adapt_0_to_42)
  610. >>> I(0)
  611. 42
  612. >>> adapter_hooks.remove(adapt_0_to_42)
  613. >>> I(0)
  614. Traceback (most recent call last):
  615. ...
  616. TypeError: ('Could not adapt', 0, <InterfaceClass __builtin__.I>)
  617. ``__adapt__``
  618. -------------
  619. .. doctest::
  620. >>> class I(zope.interface.Interface):
  621. ... pass
  622. Interfaces implement the PEP 246 ``__adapt__`` method.
  623. This method is normally not called directly. It is called by the PEP
  624. 246 adapt framework and by the interface ``__call__`` operator.
  625. The ``adapt`` method is responsible for adapting an object to the
  626. reciever.
  627. The default version returns ``None``:
  628. .. doctest::
  629. >>> I.__adapt__(0)
  630. unless the object given provides the interface:
  631. .. doctest::
  632. >>> class C(object):
  633. ... zope.interface.implements(I)
  634. >>> obj = C()
  635. >>> I.__adapt__(obj) is obj
  636. True
  637. Adapter hooks can be provided (or removed) to provide custom
  638. adaptation. We'll install a silly hook that adapts 0 to 42.
  639. We install a hook by simply adding it to the ``adapter_hooks``
  640. list:
  641. .. doctest::
  642. >>> from zope.interface.interface import adapter_hooks
  643. >>> def adapt_0_to_42(iface, obj):
  644. ... if obj == 0:
  645. ... return 42
  646. >>> adapter_hooks.append(adapt_0_to_42)
  647. >>> I.__adapt__(0)
  648. 42
  649. Hooks must either return an adapter, or ``None`` if no adapter can
  650. be found.
  651. Hooks can be uninstalled by removing them from the list:
  652. .. doctest::
  653. >>> adapter_hooks.remove(adapt_0_to_42)
  654. >>> I.__adapt__(0)
  655. .. [#create] The main reason we subclass ``Interface`` is to cause the
  656. Python class statement to create an interface, rather
  657. than a class.
  658. It's possible to create interfaces by calling a special
  659. interface class directly. Doing this, it's possible
  660. (and, on rare occasions, useful) to create interfaces
  661. that don't descend from ``Interface``. Using this
  662. technique is beyond the scope of this document.
  663. .. [#factory] Classes are factories. They can be called to create
  664. their instances. We expect that we will eventually
  665. extend the concept of implementation to other kinds of
  666. factories, so that we can declare the interfaces
  667. provided by the objects created.
  668. .. [#compat] The goal is substitutability. An object that provides an
  669. extending interface should be substitutable for an object
  670. that provides the extended interface. In our example, an
  671. object that provides ``IBaz`` should be usable wherever an
  672. object that provides ``IBlat`` is expected.
  673. The interface implementation doesn't enforce this,
  674. but maybe it should do some checks.