Package cells :: Module cellattr
[hide private]
[frames] | no frames]

Source Code for Module cells.cellattr

  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  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   
30 -def debug(*msgs):
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
42 -class CellAttr(object):
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 # kid_overrides is essentially internal, so it's hidden from the 51 # documentation
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
82 - def __set__(self, owner, value):
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 # return the value in owner.myname 114 return cell.getvalue()
115
116 - def getcell(self, owner):
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 # if there isn't a value in owner.myname, make it a cell 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 # first, find out if this object has overrides on this cell's init 134 override = owner._initregistry.get(self.name) 135 if override: # it does, use the override 136 newkwargs = self.kwargs.copy() 137 newkwargs.update(override) 138 newcell = self.buildcell(owner, *self.args, **newkwargs) 139 else: # it doesn't, use class's default 140 newcell = self.buildcell(owner, *self.args, **self.kwargs) 141 142 owner.__dict__[self.name] = newcell 143 144 # observers have to be run *after* the cell is embedded in the 145 # instance! 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 # figure out what type the user wants: 189 if kwargs.has_key('celltype'): # user-specified cell 190 celltype = kwargs["celltype"] 191 elif kwargs.has_key('rule'): # it's a rule-cell. 192 celltype = RuleCell 193 elif kwargs.has_key('value'): # it's a value-cell 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