1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """
20 Family, a specialized C{L{Model}} for networks of C{L{Model}}s.
21
22 @var DEBUG: Turns on debugging messages for the cellattr module.
23 """
24
25 DEBUG = False
26
27 import cells
28 from model import Model, ModelMetatype
29 from cellattr import CellAttr
30 from cell import ListCell
31
33 """
34 debug() -> None
35
36 Prints debug messages.
37 """
38 msgs = list(msgs)
39 msgs.insert(0, "family".rjust(cells._DECO_OFFSET) + " > ")
40 if DEBUG or cells.DEBUG:
41 print " ".join(msgs)
42
44 """
45 Family
46
47 A specialized C{L{Model}} which has C{kids}, C{kid_slots}, and a
48 number of convenience functions for traversing the parent/child
49 graph.
50
51 @ivar kids: A list of Models which are guaranteed to have the
52 attribute overrides defined in C{L{kid_slots}}
53
54 @ivar kid_slots: An override definition for the Cells inserted
55 into the C{L{kids}} list. The attributes overridden are every
56 attribute defined in the class in C{kid_slots} minus the
57 attributes defined in every Model.
58 """
59 kids = cells.makecell(celltype=ListCell, kid_overrides=False)
60 kid_slots = cells.makecell(value=Model, kid_overrides=False)
61
64
66 """
67 _kid_instance(self, klass) -> Cell
68
69 Creates a new instance of a Cell based on the passed class (in
70 C{klass}) and the overrides defined in C{kid_slots}.
71
72 @param klass: The base type for the new kid instance
73 """
74 if not klass:
75 klass = self.kid_slots
76 _debug("making an instance of", str(klass))
77
78
79 override_attrnames = []
80 for attrname in dir(self.kid_slots):
81 cvar = getattr(self.kid_slots, attrname)
82
83
84 if isinstance(cvar, CellAttr):
85 if cvar.kid_overrides:
86
87 override_attrnames.append(attrname)
88
89
90 else:
91 if attrname not in dir(cells.Family):
92 override_attrnames.append(attrname)
93
94
95 for attrib_name in override_attrnames:
96 _debug("overriding", attrib_name, "in", str(klass))
97 setattr(klass, attrib_name, self.kid_slots.__dict__[attrib_name])
98
99
100 klass._observernames.update(self.kid_slots._observernames)
101
102
103
104
105
106 i = klass(parent=self)
107 return i
108
110 """
111 make_kid(self, klass) -> None
112
113 Adds a new instance of a Cell based on the passed class (in
114 C{klass}) and the overrides defined in C{kid_slots} into the
115 C{kids} list
116
117 @param klass: the base type for the new kid instance
118 """
119 _debug("make_kid called with", str(klass))
120 self._add_kid(self._kid_instance(klass))
121
123 """
124 _add_kid(self, kid) -> None
125
126 Inserts the kid into this Family's C{kids} list
127
128 @param kid: the Model instance to insert
129 """
130 kid.parent = self
131 self.kids.append(kid)
132
134 """
135 position(self) -> int
136
137 Returns this instance's position in the enclosing Family's
138 C{kids} list. Returns -1 if there is no enclosing Family.
139
140 @raise FamilyTraversalError: Raises if there is no enclosing Family
141 """
142 if self.parent:
143 return self.parent.kids.index(self)
144 raise FamilyTraversalError("No enclosing Family")
145
147 """
148 previous_sib(self) -> Model
149
150 Returns the Model previous to this Model in the enclosing
151 Family's C{kids} list
152
153 @raise FamilyTraversalError: Raises if there is no enclosing Family
154 """
155 if self.parent and self.position() > 0:
156 return self.parent.kids[self.position() - 1]
157 raise FamilyTraversalError("No enclosing Family")
158
160 """
161 previous_sib(self) -> Model
162
163 Returns the Model subsequent to this Model in the enclosing
164 Family's C{kids} list
165
166 @raise FamilyTraversalError: Raises if there is no enclosing Family
167 """
168 if self.parent and self.position() < len(self.parent.kids) - 1:
169 return self.parent.kids[self.position() + 1]
170 raise FamilyTraversalError("No enclosing Family")
171
173 """
174 grandparent(self) -> Model
175
176 Returns enclosing Family instance's enclosing Family instance,
177 or None if no such object exists.
178 """
179
180 if self.parent:
181 if self.parent.parent:
182 return self.parent.parent
183 return None
184
186 """
187 Raised when there's some sort of error in C{L{Family}}'s traversal
188 methods.
189 """
191 self.value = value
193 return repr(self.value)
194