5 This module defines utilities for the jet config.
6 These are mainly to allow to "lock" the standard, reference definitions so
7 they are not accidentally changed by some user scripts.
11 """Build on the standard property to allow a property to be locked if the holding class has its _locked attribute set to True """
13 def lockedfunc(self, v):
15 raise Exception(
"Error "+func.__name__+
" is locked. Either clone or unlock",self)
18 return self.setter(lockedfunc)
21 """creates a property from a class method (or a str) which can be locked if the holding class has its _locked attribute set to True
25 # simple locked property
26 x = make_lproperty('x')
28 # same but using decorator
32 # same but now with customized setter :
37 print("setting z to ",v)
41 if isinstance(func, str):
48 return getattr(self,pname_i,
None)
51 raise AttributeError(
"Error property '"+pname+
"' is locked. Either clone or unlock",self)
52 setattr(self, pname_i, v)
56 """Returns a property which act as a read-only alias to existing prop """
58 return getattr(self,prop,
None)
60 raise AttributeError(
"Cannot set alias "+prop+
" from "+
str(self) )
61 return property(_getter, _setter)
65 lprops = getattr(cls,
'_allowedattributes', [])
67 lprops += [k
for (k,v)
in cls.__dict__.
items()
if isinstance(v,lproperty) ]
69 lprops +=[
'_'+k
for k
in lprops]
71 for base
in cls.__bases__:
76 """Transforms the input class cls so the only attributes which can be set are the lproperty of the class.
77 Best used as a decorator. Ex :
78 @onlyAttributesAreProperties
80 myprop0 = make_lproperty('myprop0')
84 a.mypropO = 3 # impossible
90 cls._allowedattributes += [
'_locked']
93 cls._nomoreattributes=
False
96 cls.__init__origin = cls.__init__
100 def initwraper(self, *l,finalinit=True, **args):
101 cls.__init__origin(self, *l,**args)
102 self._nomoreattributes = finalinit
103 cls.__init__ = initwraper
106 def setattr(self, k, v):
107 if self._nomoreattributes
and k
not in self._allowedattributes:
108 raise AttributeError(
"Setting attribute "+k+
" on "+
str(self)+
" not allowed")
110 cls.__setattr__ = setattr
115 """Transforms the input class cls by adding a clone() method.
116 This clone() method returns a clone instance with a _locked attribute set to False by default (so the clone is modifiable) """
120 def recc_lock(o, lock):
121 if hasattr(
type(o),
'isClonable')
and type(o).isClonable
and hasattr(o,
"_locked"):
123 for k,v
in o.__dict__.items():
126 def clone(self, lock=False, **args):
127 from copy
import deepcopy
130 for k,v
in args.items():
135 cls.isClonable =
True
140 """A dictionnary which items can not be modified once set.
142 Also implements 2 additional features :
143 - a clone method to conveniently create a new version with only some items changed
144 - all items are also attributes (i.e. d['a'] can be accessed by d.a : this is mostly for easier interactive inspection)
149 for k,v
in args.items():
155 raise KeyError(f
"Can't override self[{k}] == {self[k]} with new value {v}")
161 for k,v
in args.items():
165 from copy
import deepcopy
167 for k,v
in args.items():
169 dict.__setitem__(o,k,v)
170 dict.__setattr__(o,k,v)
174 """returns a copy of the inD dictionnary with no nested directories. Instead the content of nested dict inside inD are indexed by keys constructed from nested keys :
175 {'A' : 3 , 'B' : { 'C':5, 'D': 6} } --> {'A' : 3 , 'B.C':5, 'B.D': 6}
176 This works only if nested dic have str keys.
178 This function is used mainly in trigger config
181 for k,v
in inD.items():
182 if isinstance(v,dict):
184 for subk, subv
in subD.items():
185 outD[f
'{k}.{subk}']=subv