1
#Copyright ReportLab Europe Ltd. 2000-2004
2
#see license.txt for license details
3
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/lib/attrmap.py
4
__version__=''' $Id$ '''
5
from UserDict import UserDict
6
from reportlab.lib.validators import isAnything, _SequenceTypes
7
from reportlab import rl_config
10
'''a class to allow callable initial values'''
11
def __init__(self,func,*args,**kw):
12
#assert iscallable(func)
18
return apply(self.func,self.args,self.kw)
21
'''Simple multi-value holder for attribute maps'''
22
def __init__(self,validate=None,desc=None,initial=None, **kw):
23
self.validate = validate or isAnything
25
self.initial = initial
26
for k,v in kw.items():
29
def __getattr__(self,name):
30
#hack to allow callable initial values
32
if isinstance(self._initial,CallableValue): return self._initial()
36
raise AttributeError, name
38
class AttrMap(UserDict):
39
def __init__(self,BASE=None,UNWANTED=[],**kw):
42
if isinstance(BASE,AttrMap):
43
data = BASE.data #they used BASECLASS._attrMap
45
if type(BASE) not in (type(()),type([])): BASE = (BASE,)
47
if hasattr(B,'_attrMap'):
48
data.update(getattr(B._attrMap,'data',{}))
50
raise ValueError, 'BASE=%s has wrong kind of value' % str(B)
52
UserDict.__init__(self,data)
57
if isinstance(kw,AttrMap): kw = kw.data
60
def remove(self,unwanted):
67
def clone(self,UNWANTED=[],**kw):
68
c = AttrMap(BASE=self,UNWANTED=UNWANTED)
72
def validateSetattr(obj,name,value):
73
'''validate setattr(obj,name,value)'''
74
if rl_config.shapeChecking:
76
if map and name[0]!= '_':
78
validate = map[name].validate
79
if not validate(value):
80
raise AttributeError, "Illegal assignment of '%s' to '%s' in class %s" % (value, name, obj.__class__.__name__)
82
raise AttributeError, "Illegal attribute '%s' in class %s" % (name, obj.__class__.__name__)
83
obj.__dict__[name] = value
85
def _privateAttrMap(obj,ret=0):
86
'''clone obj._attrMap if required'''
88
oA = getattr(obj.__class__,'_attrMap',None)
96
obj._attrMap = A.clone()
98
def _findObjectAndAttr(src, P):
99
'''Locate the object src.P for P a string, return parent and name of attribute
101
P = string.split(P, '.')
106
src = getattr(src, p)
109
def hook__setattr__(obj):
110
if not hasattr(obj,'__attrproxy__'):
113
obj.__class__=new.classobj(C.__name__,(C,)+C.__bases__,
115
'__setattr__':lambda self,k,v,osa=getattr(obj,'__setattr__',None),hook=hook: hook(self,k,v,osa)})
117
def addProxyAttribute(src,name,validate=None,desc=None,initial=None,dst=None):
119
Add a proxy attribute 'name' to src with targets dst
122
assert hasattr(src,'_attrMap'), 'src object has no _attrMap'
123
A, oA = _privateAttrMap(src,1)
124
if type(dst) not in _SequenceTypes: dst = dst,
128
if type(d) in _SequenceTypes:
130
obj, attr = _findObjectAndAttr(src,d)
132
dA = getattr(obj,'_attrMap',None)