1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """
20 PyCells
21
22 PyCells is a port of Ken Tilton's Cells extenstion to Common
23 Lisp. Cells are objects which automatically discover the cells which
24 call them, and notify those cells of changes.
25
26 A short example:
27
28 >>> import cells
29 >>> class Rectangle(cells.Model):
30 ... width = cells.makecell(value=1)
31 ... ratio = cells.makecell(value=1.618)
32 ... @cells.fun2cell()
33 ... def length(self, prev):
34 ... print "Length updating..."
35 ... return float(self.width) * float(self.ratio)
36 ...
37 >>> r = Rectangle()
38 Length updating...
39 >>> r.length
40 1.6180000000000001
41 >>> r.width = 5
42 Length updating...
43 >>> r.length
44 8.0899999999999999
45
46
47 @var DEBUG: Turns on debugging messages for *all* submodules. This is
48 a whole lot of text, so you'll probably want to use the
49 submodules' C{DEBUG} flags instead
50
51 @var cellenv: Thread-local cell environment variables.
52 """
53 DEBUG = False
54
55 _DECO_OFFSET = 9
56
57 import threading
58
59 cellenv = threading.local()
60 cellenv.dp = 0
61 cellenv.curr = None
62 cellenv.curr_propogator = None
63 cellenv.queued_updates = []
64 cellenv.deferred_sets = []
65
66 from cellattr import CellAttr
67
69 """
70 makecell(rule=None, value=None, unchanged_if=None,
71 celltype=None) -> CellAttr
72
73 Creates a new cell attribute in a L{Model}. This attribute may be
74 accessed as one would access a non-cell attribute, and
75 autovivifies itself in the instance upon first access (in
76 L{Model.__init__}).
77
78 @param rule: Define a rule which backs this cell. You must only
79 define one of C{rule} or C{value}. Lacking C{celltype}, this
80 creates a L{RuleCell}. This must be passed a callable with
81 the signature C{f(self, prev) -> value}, where C{self} is the
82 model instance the cell is in and C{prev} is the cell's
83 out-of-date value.
84
85 @param value: Define a value for this cell. You must only define
86 one of C{rule} or C{value}. Lacking C{celltype}, this creates an
87 L{InputCell}.
88
89 @param unchanged_if: Sets a function to determine if a cell's
90 value has changed. For example,
91
92 >>> class A(cells.Model):
93 ... x = cells.makecell(value=1,
94 ... unchanged_if=lambda n,o: abs(n - o) > 5)
95 ... y = cells.makecell(rule=lambda s,p: s.x * 2)
96 ...
97 >>> a = A()
98 >>> a.x
99 1
100 >>> a.y
101 2
102 >>> a.x = 3
103 >>> a.x
104 3
105 >>> a.y
106 6
107 >>> a.x = 90
108 >>> a.x
109 3
110 >>> a.y
111 6
112
113 The signature for the passed function is C{f(old, new) ->
114 bool}.
115
116 @param celltype: Set the cell type to generate. You must pass C{rule}
117 or C{value} correctly. Refer to L{cells.cell} for available
118 types.
119 """
120 return CellAttr(*args, **kwargs)
121
123 """
124 fun2cell(unchanged_if=None, celltype=None) -> decorator
125
126 A decorator which creates a new RuleCell using the decorated
127 function as the C{rule} parameter.
128
129 @param unchanged_if: Sets a function to determine if a cell's
130 value has changed. For example,
131
132 >>> class A(cells.Model):
133 ... x = cells.makecell(value=1,
134 ... unchanged_if=lambda n,o: abs(n - o) > 5)
135 ... y = cells.makecell(rule=lambda s,p: s.x * 2)
136 ...
137 >>> a = A()
138 >>> a.x
139 1
140 >>> a.y
141 2
142 >>> a.x = 3
143 >>> a.x
144 3
145 >>> a.y
146 6
147 >>> a.x = 90
148 >>> a.x
149 3
150 >>> a.y
151 6
152
153 The signature for the passed function is C{f(old, new) ->
154 bool}.
155
156 @param celltype: Set the cell type to generate. You must pass C{rule}
157 or C{value} correctly. Refer to L{cells.cell} for available
158 types.
159 """
161 return CellAttr(rule=func, *args, **kwargs)
162 return fun2cell_decorator