1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """
20 CellAttr, a wrapper for C{L{Cell}} objects within C{L{Models}}
21
22 @var DEBUG: Turns on debugging messages for the cellattr module.
23 """
24
25 import cells
26 from cell import Cell, RuleCell, InputCell
27
28 DEBUG = False
29
31 """
32 debug() -> None
33
34 Prints debug messages.
35 """
36 msgs = list(msgs)
37 msgs.insert(0, "cell attr".rjust(cells._DECO_OFFSET) + " > ")
38 if DEBUG or cells.DEBUG:
39 print " ".join(msgs)
40
41
43 """
44 CellAttr
45
46 A descriptor which auto-vivifies a new Cell in each instance of a
47 Model, and which does the hiding of C{Cell.L{get}()} and
48 C{Cell.L{set}()}.
49 """
50
51
52 - def __init__(self, kid_overrides=True, *args, **kwargs):
53 """
54 __init__(self, rule=None, value=None, unchanged_if=None, celltype=None)
55
56 Sets the parameters which will be used as defaults to build a
57 Cell when the time comes.
58
59 @param rule: Define a rule which backs this cell. You must
60 only define one of C{rule} or C{value}. Lacking C{celltype},
61 this creates a L{RuleCell}. This must be passed a
62 callable with the signature C{f(self, prev) -> value},
63 where C{self} is the model instance the cell is in and
64 C{prev} is the cell's out-of-date value.
65
66 @param value: Define a value for this cell. You must only
67 define one of C{rule} or C{value}. Lacking C{celltype}, this
68 creates an L{InputCell}.
69
70 @param unchanged_if: Sets a function to determine if a cell's
71 value has changed. The signature for the passed function
72 is C{f(old, new) -> bool}.
73
74 @param celltype: Set the cell type to generate. You must pass
75 C{rule} or C{value} correctly. Refer to L{cells.cell} for
76 available types.
77 """
78 self.kid_overrides = kid_overrides
79 self.args = args
80 self.kwargs = kwargs
81
83 """
84 __set__(self, owner, value) -> None
85
86 Runs C{L{set}(value)} on the Cell in C{owner}.
87
88 @param owner: The Model instance in which to look for the Cell
89 to run C{L{set}()} on.
90
91 @param value: The value to set
92 """
93 self.getcell(owner).set(value)
94
95 - def __get__(self, owner, ownertype):
96 """
97 __get__(self, owner, ownertype) -> value
98
99 Runs C{L{get}()} on the Cell in C{owner}, if C{owner} is
100 passed. Otherwise, return C{self}.
101
102 @param owner: The Model instance in which to look for the Cell
103 to run C{L{get}()} on .
104
105 @param ownertype: (unused)
106 """
107 if not owner: return self
108
109 cell = self.getcell(owner)
110 if isinstance(cell, (cells.cell.ListCell, cells.cell.DictCell)):
111 return cell
112 else:
113
114 return cell.getvalue()
115
117 """
118 getcell(owner) -> Cell
119
120 Return the instance of this CellAttr's Cell in C{owner}. If an
121 instance of the CellAttr's Cell doesn't exist in C{owner},
122 first insert an instance into C{owner}, then return it. To
123 build it, first examine the C{owner} for runtime overrides of
124 this cell, and use those (if they exist) as parameters to
125 C{L{buildcell}}.
126
127 @param owner: The Model instance in which to look for the Cell.
128 """
129
130 debug("got request for cell in", self.name)
131 if self.name not in owner.__dict__.keys():
132 debug(self.name, "not in owner. Building a new cell in it.")
133
134 override = owner._initregistry.get(self.name)
135 if override:
136 newkwargs = self.kwargs.copy()
137 newkwargs.update(override)
138 newcell = self.buildcell(owner, *self.args, **newkwargs)
139 else:
140 newcell = self.buildcell(owner, *self.args, **self.kwargs)
141
142 owner.__dict__[self.name] = newcell
143
144
145
146 owner._run_observers(newcell)
147
148
149 debug("finished getting", self.name)
150 return owner.__dict__[self.name]
151
152 - def buildcell(self, owner, *args, **kwargs):
153 """
154 buildcell(self, owner, rule=None, value=None, celltype=None,
155 unchanged_if=None) -> Cell
156
157 Builds an instance of a Cell into C{owner}. Will automatically
158 create the right type of Cell given the keyword arguments if
159 C{celltype} is not passed
160
161 @param owner: The Model instance in which to build the Cell.
162
163 @param rule: Define a rule which backs this cell. You must
164 only define one of C{rule} or C{value}. Lacking C{celltype},
165 this creates a L{RuleCell}. This must be passed a
166 callable with the signature C{f(self, prev) -> value},
167 where C{self} is the model instance the cell is in and
168 C{prev} is the cell's out-of-date value.
169
170 @param value: Define a value for this cell. You must only
171 define one of C{rule} or C{value}. Lacking C{celltype}, this
172 creates an L{InputCell}.
173
174 @param unchanged_if: Sets a function to determine if a cell's
175 value has changed. The signature for the passed function
176 is C{f(old, new) -> bool}.
177
178 @param celltype: Set the cell type to generate. You must pass
179 C{rule} or C{value} correctly. Refer to L{cells.cell} for
180 available types.
181 """
182
183 """Creates a new cell of the appropriate type"""
184 debug("Building cell: owner:", str(owner))
185 debug(" name:", self.name)
186 debug(" args:", str(args))
187 debug(" kwargs:", str(kwargs))
188
189 if kwargs.has_key('celltype'):
190 celltype = kwargs["celltype"]
191 elif kwargs.has_key('rule'):
192 celltype = RuleCell
193 elif kwargs.has_key('value'):
194 celltype = InputCell
195 else:
196 raise Exception("Could not determine target type for cell " +
197 "given owner: " + str(owner) +
198 ", name: " + self.name +
199 ", args:" + str(args) +
200 ", kwargs:" + str(kwargs))
201
202 kwargs['name'] = self.name
203
204 return celltype(owner, *args, **kwargs)
205