~ztk-steering-group/zope.container/trunk

« back to all changes in this revision

Viewing changes to src/zope/container/constraints.txt

  • Committer: alga
  • Date: 2013-02-14 14:20:19 UTC
  • Revision ID: svn-v4:62d5b8a3-27da-0310-9561-8e5933582275:zope.container/trunk:129409
Move to GitHub under https://github.com/zopefoundation/zope.container

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
=========================
2
 
 Containment constraints
3
 
=========================
4
 
 
5
 
Containment constraints allow us to express restrictions on the types
6
 
of items that can be placed in containers or on the types of
7
 
containers an item can be placed in.  We express these constraints in
8
 
interfaces.  Let's define some container and item interfaces:
9
 
 
10
 
    >>> from zope.container.interfaces import IContainer
11
 
    >>> from zope.location.interfaces import IContained
12
 
    >>> from zope.container.constraints import containers, contains
13
 
 
14
 
    >>> class IBuddyFolder(IContainer):
15
 
    ...     contains('.IBuddy')
16
 
 
17
 
 
18
 
In this example, we used the contains function to declare that objects
19
 
that provide IBuddyFolder can only contain items that provide IBuddy.
20
 
Note that we used a string containing a dotted name for the IBuddy
21
 
interface. This is because IBuddy hasn't been defined yet.  When we
22
 
define IBuddy, we can use IBuddyFolder directly:
23
 
 
24
 
    >>> class IBuddy(IContained):
25
 
    ...     containers(IBuddyFolder)
26
 
 
27
 
 
28
 
Now, with these interfaces in place, we can define Buddy and
29
 
BuddyFolder classes and verify that we can put buddies in buddy
30
 
folders:
31
 
 
32
 
    >>> from zope import interface
33
 
 
34
 
    >>> @interface.implementer(IBuddy)
35
 
    ... class Buddy:
36
 
    ...     pass
37
 
 
38
 
    >>> @interface.implementer(IBuddyFolder)
39
 
    ... class BuddyFolder:
40
 
    ...     pass
41
 
 
42
 
    >>> from zope.container.constraints import checkObject, checkFactory
43
 
    >>> from zope.component.factory import Factory
44
 
 
45
 
    >>> checkObject(BuddyFolder(), 'x', Buddy())
46
 
    >>> checkFactory(BuddyFolder(), 'x', Factory(Buddy))
47
 
    True
48
 
 
49
 
If we try to use other containers or folders, we'll get errors:
50
 
 
51
 
    >>> @interface.implementer(IContainer)
52
 
    ... class Container:
53
 
    ...     pass
54
 
 
55
 
    >>> @interface.implementer(IContained)
56
 
    ... class Contained:
57
 
    ...     pass
58
 
 
59
 
    >>> checkObject(Container(), 'x', Buddy())
60
 
    ... # doctest: +ELLIPSIS
61
 
    Traceback (most recent call last):
62
 
    InvalidContainerType: ...
63
 
 
64
 
    >>> checkFactory(Container(), 'x', Factory(Buddy))
65
 
    False
66
 
 
67
 
    >>> checkObject(BuddyFolder(), 'x', Contained())
68
 
    ... # doctest: +ELLIPSIS
69
 
    Traceback (most recent call last):
70
 
    InvalidItemType: ...
71
 
 
72
 
    >>> checkFactory(BuddyFolder(), 'x', Factory(Contained))
73
 
    False
74
 
 
75
 
In the example, we defined the container first and then the items.  We
76
 
could have defined these in the opposite order:
77
 
 
78
 
    >>> class IContact(IContained):
79
 
    ...     containers('.IContacts')
80
 
 
81
 
    >>> class IContacts(IContainer):
82
 
    ...     contains(IContact)
83
 
 
84
 
    >>> @interface.implementer(IContact)
85
 
    ... class Contact:
86
 
    ...     pass
87
 
 
88
 
    >>> @interface.implementer(IContacts)
89
 
    ... class Contacts:
90
 
    ...     pass
91
 
 
92
 
    >>> checkObject(Contacts(), 'x', Contact())
93
 
 
94
 
    >>> checkFactory(Contacts(), 'x', Factory(Contact))
95
 
    True
96
 
 
97
 
    >>> checkObject(Contacts(), 'x', Buddy())
98
 
    ... # doctest: +ELLIPSIS
99
 
    Traceback (most recent call last):
100
 
    InvalidItemType: ...
101
 
 
102
 
    >>> checkFactory(Contacts(), 'x', Factory(Buddy))
103
 
    False
104
 
 
105
 
The constraints prevent us from moving a container beneath itself (either into
106
 
itself or another folder beneath it):
107
 
 
108
 
    >>> container = Container()
109
 
    >>> checkObject(container, 'x', container)
110
 
    Traceback (most recent call last):
111
 
    TypeError: Cannot add an object to itself or its children.
112
 
 
113
 
    >>> import zope.location.interfaces
114
 
    >>> import zope.interface
115
 
    >>> subcontainer = Container()
116
 
    >>> zope.interface.directlyProvides(subcontainer,
117
 
    ...     zope.location.interfaces.ILocation)
118
 
    >>> subcontainer.__parent__ = container
119
 
    >>> checkObject(subcontainer, 'x', container)
120
 
    Traceback (most recent call last):
121
 
    TypeError: Cannot add an object to itself or its children.