summaryrefslogtreecommitdiff
path: root/docs/verify.rst
blob: 0ae7fdf5c232558753d0412a5c87eae754070b24 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
===================================
Verifying interface implementations
===================================

The ``zope.interface.verify`` module provides functions that test whether a
given interface is implemented by a class or provided by an object, resp.


Verifying classes
=================

This is covered by unit tests defined in ``zope.interface.tests.test_verify``.


Verifying objects
=================

An object provides an interface if

- either its class declares that it implements the interfaces, or the object
  declares that it directly provides the interface;

- the object defines all the methods required by the interface;

- all the methods have the correct signature;

- the object defines all non-method attributes required by the interface.

This doctest currently covers only the latter item.

Testing for attributes
----------------------

Attributes of the object, be they defined by its class or added by its
``__init__`` method, will be recognized:

.. doctest::

   >>> from zope.interface import Interface, Attribute, implements
   >>> from zope.interface.exceptions import BrokenImplementation
   >>> class IFoo(Interface):
   ...     x = Attribute("The X attribute")
   ...     y = Attribute("The Y attribute")

   >>> class Foo(object):
   ...     implements(IFoo)
   ...     x = 1
   ...     def __init__(self):
   ...         self.y = 2

   >>> from zope.interface.verify import verifyObject
   >>> verifyObject(IFoo, Foo())
   True

If either attribute is missing, verification will fail:

.. doctest::

   >>> class Foo(object):
   ...     implements(IFoo)
   ...     x = 1
   >>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
   ...     verifyObject(IFoo, Foo())
   ... except BrokenImplementation, e:
   ...     print str(e)
   An object has failed to implement interface <InterfaceClass ...IFoo>
   <BLANKLINE>
           The y attribute was not provided.
   <BLANKLINE>
   >>> class Foo(object):
   ...     implements(IFoo)
   ...     def __init__(self):
   ...         self.y = 2
   >>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
   ...     verifyObject(IFoo, Foo())
   ... except BrokenImplementation, e:
   ...     print str(e)
   An object has failed to implement interface <InterfaceClass ...IFoo>
   <BLANKLINE>
           The x attribute was not provided.
   <BLANKLINE>

If an attribute is implemented as a property that raises an ``AttributeError``
when trying to get its value, the attribute is considered missing:

.. doctest::

   >>> class IFoo(Interface):
   ...     x = Attribute('The X attribute')
   >>> class Foo(object):
   ...     implements(IFoo)
   ...     @property
   ...     def x(self):
   ...         raise AttributeError
   >>> try: #doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
   ...     verifyObject(IFoo, Foo())
   ... except BrokenImplementation, e:
   ...     print str(e)
   An object has failed to implement interface <InterfaceClass ...IFoo>
   <BLANKLINE>
           The x attribute was not provided.
   <BLANKLINE>

Any other exception raised by a property will propagate to the caller of
``verifyObject``:

.. doctest::

   >>> class Foo(object):
   ...     implements(IFoo)
   ...     @property
   ...     def x(self):
   ...         raise Exception
   >>> verifyObject(IFoo, Foo())
   Traceback (most recent call last):
   Exception

Of course, broken properties that are not required by the interface don't do
any harm:

.. doctest::

   >>> class Foo(object):
   ...     implements(IFoo)
   ...     x = 1
   ...     @property
   ...     def y(self):
   ...         raise Exception
   >>> verifyObject(IFoo, Foo())
   True