Package suds :: Module properties
[hide private]
[frames] | no frames]

Source Code for Module suds.properties

  1  # This program is free software; you can redistribute it and/or modify 
  2  # it under the terms of the (LGPL) GNU Lesser General Public License as 
  3  # published by the Free Software Foundation; either version 3 of the  
  4  # License, or (at your option) any later version. 
  5  # 
  6  # This program is distributed in the hope that it will be useful, 
  7  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
  8  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  9  # GNU Library Lesser General Public License for more details at 
 10  # ( http://www.gnu.org/licenses/lgpl.html ). 
 11  # 
 12  # You should have received a copy of the GNU Lesser General Public License 
 13  # along with this program; if not, write to the Free Software 
 14  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 15  # written by: Jeff Ortel ( jortel@redhat.com ) 
 16   
 17  """ 
 18  Properties classes. 
 19  """ 
 20   
 21  from logging import getLogger 
 22   
 23  log = getLogger(__name__) 
 24   
 25   
26 -class AutoLinker(object):
27 """ 28 Base class, provides interface for I{automatic} link 29 management between a L{Properties} object and the L{Properties} 30 contained within I{values}. 31 """
32 - def updated(self, properties, prev, next):
33 """ 34 Notification that a values was updated and the linkage 35 between the I{properties} contained with I{prev} need to 36 be relinked to the L{Properties} contained within the 37 I{next} value. 38 """ 39 pass
40 41 106 107
108 -class Endpoint(object):
109 """ 110 Link endpoint (wrapper). 111 @ivar link: The associated link. 112 @type link: L{Link} 113 @ivar target: The properties object. 114 @type target: L{Property} 115 """
116 - def __init__(self, link, target):
117 self.link = link 118 self.target = target
119
120 - def teardown(self):
121 return self.link.teardown()
122
123 - def __eq__(self, rhs):
124 return ( self.target == rhs )
125
126 - def __hash__(self):
127 return hash(self.target)
128
129 - def __getattr__(self, name):
130 return getattr(self.target, name)
131 132
133 -class Definition:
134 """ 135 Property definition. 136 @ivar name: The property name. 137 @type name: str 138 @ivar classes: The (class) list of permitted values 139 @type classes: tuple 140 @ivar default: The default value. 141 @ivar type: any 142 """
143 - def __init__(self, name, classes, default, linker=AutoLinker()):
144 """ 145 @param name: The property name. 146 @type name: str 147 @param classes: The (class) list of permitted values 148 @type classes: tuple 149 @param default: The default value. 150 @type default: any 151 """ 152 if not isinstance(classes, (list, tuple)): 153 classes = (classes,) 154 self.name = name 155 self.classes = classes 156 self.default = default 157 self.linker = linker
158
159 - def nvl(self, value=None):
160 """ 161 Convert the I{value} into the default when I{None}. 162 @param value: The proposed value. 163 @type value: any 164 @return: The I{default} when I{value} is I{None}, else I{value}. 165 @rtype: any 166 """ 167 if value is None: 168 return self.default 169 else: 170 return value
171
172 - def validate(self, value):
173 """ 174 Validate the I{value} is of the correct class. 175 @param value: The value to validate. 176 @type value: any 177 @raise AttributeError: When I{value} is invalid. 178 """ 179 if value is None: 180 return 181 if len(self.classes) and \ 182 not isinstance(value, self.classes): 183 msg = '"%s" must be: %s' % (self.name, self.classes) 184 raise AttributeError,msg
185 186
187 - def __repr__(self):
188 return '%s: %s' % (self.name, str(self))
189
190 - def __str__(self):
191 s = [] 192 if len(self.classes): 193 s.append('classes=%s' % str(self.classes)) 194 else: 195 s.append('classes=*') 196 s.append("default=%s" % str(self.default)) 197 return ', '.join(s)
198 199
200 -class Properties:
201 """ 202 Represents basic application properties. 203 Provides basic type validation, default values and 204 link/synchronization behavior. 205 @ivar domain: The domain name. 206 @type domain: str 207 @ivar definitions: A table of property definitions. 208 @type definitions: {name: L{Definition}} 209 @ivar links: A list of linked property objects used to create 210 a network of properties. 211 @type links: [L{Property},..] 212 @ivar defined: A dict of property values. 213 @type defined: dict 214 """
215 - def __init__(self, domain, definitions, kwargs):
216 """ 217 @param domain: The property domain name. 218 @type domain: str 219 @param definitions: A table of property definitions. 220 @type definitions: {name: L{Definition}} 221 @param kwargs: A list of property name/values to set. 222 @type kwargs: dict 223 """ 224 self.definitions = {} 225 for d in definitions: 226 self.definitions[d.name] = d 227 self.domain = domain 228 self.links = [] 229 self.defined = {} 230 self.modified = set() 231 self.prime() 232 self.update(kwargs)
233
234 - def definition(self, name):
235 """ 236 Get the definition for the property I{name}. 237 @param name: The property I{name} to find the definition for. 238 @type name: str 239 @return: The property definition 240 @rtype: L{Definition} 241 @raise AttributeError: On not found. 242 """ 243 d = self.definitions.get(name) 244 if d is None: 245 raise AttributeError(name) 246 return d
247
248 - def update(self, other):
249 """ 250 Update the property values as specified by keyword/value. 251 @param other: An object to update from. 252 @type other: (dict|L{Properties}) 253 @return: self 254 @rtype: L{Properties} 255 """ 256 if isinstance(other, Properties): 257 other = other.defined 258 for n,v in other.items(): 259 self.set(n, v) 260 return self
261
262 - def notset(self, name):
263 """ 264 Get whether a property has never been set by I{name}. 265 @param name: A property name. 266 @type name: str 267 @return: True if never been set. 268 @rtype: bool 269 """ 270 self.provider(name).__notset(name)
271
272 - def set(self, name, value):
273 """ 274 Set the I{value} of a property by I{name}. 275 The value is validated against the definition and set 276 to the default when I{value} is None. 277 @param name: The property name. 278 @type name: str 279 @param value: The new property value. 280 @type value: any 281 @return: self 282 @rtype: L{Properties} 283 """ 284 self.provider(name).__set(name, value) 285 return self
286
287 - def unset(self, name):
288 """ 289 Unset a property by I{name}. 290 @param name: A property name. 291 @type name: str 292 @return: self 293 @rtype: L{Properties} 294 """ 295 self.provider(name).__set(name, None) 296 return self
297
298 - def get(self, name, *df):
299 """ 300 Get the value of a property by I{name}. 301 @param name: The property name. 302 @type name: str 303 @param df: An optional value to be returned when the value 304 is not set 305 @type df: [1]. 306 @return: The stored value, or I{df[0]} if not set. 307 @rtype: any 308 """ 309 return self.provider(name).__get(name, *df)
310 322 337
338 - def provider(self, name, history=None):
339 """ 340 Find the provider of the property by I{name}. 341 @param name: The property name. 342 @type name: str 343 @param history: A history of nodes checked to prevent 344 circular hunting. 345 @type history: [L{Properties},..] 346 @return: The provider when found. Otherwise, None (when nested) 347 and I{self} when not nested. 348 @rtype: L{Properties} 349 """ 350 if history is None: 351 history = [] 352 history.append(self) 353 if name in self.definitions: 354 return self 355 for x in self.links: 356 if x in history: 357 continue 358 provider = x.provider(name, history) 359 if provider is not None: 360 return provider 361 history.remove(self) 362 if len(history): 363 return None 364 return self
365
366 - def keys(self, history=None):
367 """ 368 Get the set of I{all} property names. 369 @param history: A history of nodes checked to prevent 370 circular hunting. 371 @type history: [L{Properties},..] 372 @return: A set of property names. 373 @rtype: list 374 """ 375 if history is None: 376 history = [] 377 history.append(self) 378 keys = set() 379 keys.update(self.definitions.keys()) 380 for x in self.links: 381 if x in history: 382 continue 383 keys.update(x.keys(history)) 384 history.remove(self) 385 return keys
386
387 - def domains(self, history=None):
388 """ 389 Get the set of I{all} domain names. 390 @param history: A history of nodes checked to prevent 391 circular hunting. 392 @type history: [L{Properties},..] 393 @return: A set of domain names. 394 @rtype: list 395 """ 396 if history is None: 397 history = [] 398 history.append(self) 399 domains = set() 400 domains.add(self.domain) 401 for x in self.links: 402 if x in history: 403 continue 404 domains.update(x.domains(history)) 405 history.remove(self) 406 return domains
407
408 - def prime(self):
409 """ 410 Prime the stored values based on default values 411 found in property definitions. 412 @return: self 413 @rtype: L{Properties} 414 """ 415 for d in self.definitions.values(): 416 self.defined[d.name] = d.default 417 return self
418
419 - def __notset(self, name):
420 return not (name in self.modified)
421
422 - def __set(self, name, value):
423 d = self.definition(name) 424 d.validate(value) 425 value = d.nvl(value) 426 prev = self.defined[name] 427 self.defined[name] = value 428 self.modified.add(name) 429 d.linker.updated(self, prev, value)
430
431 - def __get(self, name, *df):
432 d = self.definition(name) 433 value = self.defined.get(name) 434 if value == d.default and len(df): 435 value = df[0] 436 return value
437
438 - def str(self, history):
439 s = [] 440 s.append('Definitions:') 441 for d in self.definitions.values(): 442 s.append('\t%s' % repr(d)) 443 s.append('Content:') 444 for d in self.defined.items(): 445 s.append('\t%s' % str(d)) 446 if self not in history: 447 history.append(self) 448 s.append('Linked:') 449 for x in self.links: 450 s.append(x.str(history)) 451 history.remove(self) 452 return '\n'.join(s)
453
454 - def __repr__(self):
455 return str(self)
456
457 - def __str__(self):
458 return self.str([])
459 460
461 -class Skin(object):
462 """ 463 The meta-programming I{skin} around the L{Properties} object. 464 @ivar __pts__: The wrapped object. 465 @type __pts__: L{Properties}. 466 """
467 - def __init__(self, domain, definitions, kwargs):
468 self.__pts__ = Properties(domain, definitions, kwargs)
469
470 - def __setattr__(self, name, value):
471 builtin = name.startswith('__') and name.endswith('__') 472 if builtin: 473 self.__dict__[name] = value 474 return 475 self.__pts__.set(name, value)
476
477 - def __getattr__(self, name):
478 return self.__pts__.get(name)
479
480 - def __repr__(self):
481 return str(self)
482
483 - def __str__(self):
484 return str(self.__pts__)
485 486
487 -class Unskin(object):
488 - def __new__(self, *args, **kwargs):
489 return args[0].__pts__
490 491
492 -class Inspector:
493 """ 494 Wrapper inspector. 495 """
496 - def __init__(self, options):
497 self.properties = options.__pts__
498
499 - def get(self, name, *df):
500 """ 501 Get the value of a property by I{name}. 502 @param name: The property name. 503 @type name: str 504 @param df: An optional value to be returned when the value 505 is not set 506 @type df: [1]. 507 @return: The stored value, or I{df[0]} if not set. 508 @rtype: any 509 """ 510 return self.properties.get(name, *df)
511
512 - def update(self, **kwargs):
513 """ 514 Update the property values as specified by keyword/value. 515 @param kwargs: A list of property name/values to set. 516 @type kwargs: dict 517 @return: self 518 @rtype: L{Properties} 519 """ 520 return self.properties.update(**kwargs)
521 533
544