'Base','App','Service','Specialist','DynamicBinding','StaticBinding', |
'Base','App','Service','Specialist','DynamicBinding','StaticBinding', |
'StructuralFeature', 'Field', 'Collection', 'Reference', 'Sequence', |
'StructuralFeature', 'Field', 'Collection', 'Reference', 'Sequence', |
'Classifier','PrimitiveType','Enumeration','DataType','Element', |
'Classifier','PrimitiveType','Enumeration','DataType','Element', |
'bindTo', 'requireBinding', 'bindToNames', 'bindToParent', 'Specialist' |
'bindTo', 'requireBinding', 'bindToNames', 'bindToParent', 'bindToSelf', |
|
'Specialist' |
] |
] |
|
|
|
|
|
|
|
|
|
|
|
|
class bindTo(Once): |
class bindTo(Once): |
|
|
"""Automatically look up and cache a relevant service |
"""Automatically look up and cache a relevant service |
'someClass' can then refer to 'self.grandPa' instead of calling |
'someClass' can then refer to 'self.grandPa' instead of calling |
'self.getSEFparent().getSEFparent()'. |
'self.getSEFparent().getSEFparent()'. |
|
|
Note that this binding creates a circular reference as soon as it |
This binding descriptor saves a weak reference to its target in |
is retrieved from an instance. The circular reference can be |
the object's instance dictionary, and dereferences it on each access. |
broken by deleting the attribute (e.g. 'del self.grandPa'), but of |
It therefore supports '__set__' and '__delete__' as well as '__get__' |
course it will come back the next time you use the attribute. |
methods, and retrieval is slower than for other 'Once' attributes. But |
|
it avoids creating circular reference garbage. |
""" |
""" |
|
|
def __init__(self,level=1): |
def __init__(self,level=1): |
self.level = level |
self.level = level |
|
|
def computeValue(self, obj, instDict, attrName): |
def __get__(self, obj, typ=None): |
|
|
for step in range(self.level): |
if obj is None: return self |
newObj = obj.getSEFparent() |
|
if newObj is None: break |
|
obj = newObj |
|
|
|
return obj |
d = obj.__dict__ |
|
n = self.attrName |
|
|
|
if not n or getattr(obj.__class__,n) is not self: |
|
self.usageError() |
|
|
|
ref = d.get(n) |
|
|
|
if ref is None: |
|
d[n] = ref = self.computeValue(obj, d, n) |
|
|
|
return ref() |
|
|
|
|
|
def __set__(self, obj, val): |
|
|
|
n = self.attrName |
|
|
|
if not n or getattr(obj.__class__,n) is not self: |
|
self.usageError() |
|
|
|
from weakref import ref |
|
obj.__dict__[n] = ref(val) |
|
|
|
|
class requireBinding(Once): |
def __delete__(self, obj): |
|
|
|
n = self.attrName |
|
|
|
if not n or getattr(obj.__class__,n) is not self: |
|
self.usageError() |
|
|
|
del obj.__dict__[n] |
|
|
|
|
|
def computeValue(self, obj, instDict, attrName): |
|
|
|
for step in range(self.level): |
|
newObj = obj.getSEFparent() |
|
if newObj is None: break |
|
obj = newObj |
|
|
|
from weakref import ref |
|
return ref(obj) |
|
|
|
|
"""Placeholder for a binding that should be (re)defined by a subclass""" |
|
|
|
def __init__(self,description=""): |
|
self.description = description |
|
|
|
def computeValue(self, obj, instanceDict, attrName): |
|
|
|
raise NameError("Class %s must define %s; %s" |
|
% (obj.__class__.__name__, attrName, self.description) |
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def bindToSelf(): |
|
|
|
"""Weak reference to the 'self' object |
|
|
|
This is just a shortcut for 'bindToParent(0)', and does pretty much what |
|
you'd expect. It's handy for objects that provide default support for |
|
various interfaces in the absence of an object to delegate to. The object |
|
can refer to 'self.delegateForInterfaceX.someMethod()', and have |
|
'delegateForInterfaceX' be a 'bindToSelf()' by default. |
|
""" |
|
|
|
return bindToParent(0) |
|
|
|
|
|
class requireBinding(Once): |
|
|
|
"""Placeholder for a binding that should be (re)defined by a subclass""" |
|
|
|
def __init__(self,description=""): |
|
self.description = description |
|
|
|
def computeValue(self, obj, instanceDict, attrName): |
|
|
|
raise NameError("Class %s must define %s; %s" |
|
% (obj.__class__.__name__, attrName, self.description) |
|
) |
|
|
|
|
|
|