Package cells
[hide private]
[frames] | no frames]

Source Code for Package cells

  1  # PyCells: Automatic dataflow management for Python 
  2  # Copyright (C) 2006, Ryan Forsythe 
  3   
  4  # This library is free software; you can redistribute it and/or 
  5  # modify it under the terms of the GNU Lesser General Public 
  6  # License as published by the Free Software Foundation; either 
  7  # version 2.1 of the License, or (at your option) any later version. 
  8  # See LICENSE for the full license text. 
  9   
 10  # This library is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 13  # Lesser General Public License for more details. 
 14   
 15  # You should have received a copy of the GNU Lesser General Public 
 16  # License along with this library; if not, write to the Free Software 
 17  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 
 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                 #: for the debug '  module > ' messages 
 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   
68 -def makecell(*args, **kwargs):
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
122 -def fun2cell(*args, **kwargs):
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 """
160 - def fun2cell_decorator(func):
161 return CellAttr(rule=func, *args, **kwargs)
162 return fun2cell_decorator
163 164 from cell import Cell, InputCell, RuleCell, RuleThenInputCell 165 from cell import UntilAskedLazyCell, AlwaysLazyCell, DictCell, ListCell 166 from cell import _CellException, RuleCellSetError 167 from cell import InputCellRunError, SetDuringNotificationError 168 169 from model import Model, NonCellSetError 170 from family import Family, FamilyTraversalError 171 from synapse import ChangeSynapse 172
173 -def _debug(*msgs):
174 """ 175 debug() -> None 176 177 Prints debug messages. 178 """ 179 if DEBUG: 180 print " ".join(msgs)
181
182 -def reset():
183 """ 184 reset() -> None 185 186 Resets all of PyCells' globals back to their on-package-import 187 values. This is a pretty dangerous thing to do if you care about 188 the currently-instantiated cells' state, but quite useful while 189 fooling around in an ipython session. 190 """ 191 global cellenv 192 193 cellenv.dp = 1 194 cellenv.curr = None 195 cellenv.curr_propogator = None 196 cellenv.queued_updates = [] 197 cellenv.deferred_sets = []
198 199 reset() 200