Slave to master auto linking.
Богун Дмитрий
vugluskr at vugluskr.org.ua
Sun Nov 13 19:58:44 EST 2011
Hello.
I try make some weird thing. I want to get from code like this:
class master:
...
class slave:
...
m = master()
s = m.slave()
s.master is m
Last expression must be true. I want link "master" to be set
automatically by master object while creating slave object. Additional
requirement - "master" link must be available for constructor of slave
object.
Best what I can get is:
import functools
from weakref import WeakKeyDictionary
from threading import RLock
class meth_wrap(object):
def __init__(self, func):
object.__init__(self)
self.func = func
functools.update_wrapper(self, func, updated=())
class lazy_attr(meth_wrap):
def __get__(self, obj, type=None):
if obj is None:
return self
val = self.func(obj)
setattr(obj, self.__name__, val)
return val
class slave_mixin(object):
@lazy_attr
def master(self):
m = slave_gen._unbound_master
assert m is not None, '"Slave" object can\'t find master link.
Is it was correctly created? obj:%s' % repr(self)
return m
class slave_gen(meth_wrap):
_storage = WeakKeyDictionary()
# Используется глобально
_unbound_master = None
_lock = RLock()
def __get__(self, mobj, type=None):
if mobj is None:
return self.func
d = {
'm': mobj,
'w': self}
obj = self.delay_init()
self._storage[obj] = d
functools.update_wrapper(obj, self.func, updated=())
return obj
class delay_init(object):
def __call__(self, *args, **kw_args):
d = slave_gen._storage[self]
slave_gen._lock.acquire()
try:
slave_gen._unbound_master = d['m']
obj = d['w'].func(*args, **kw_args)
obj.master = d['m']
slave_gen._unbound_master = None
finally:
slave_gen._lock.release()
return obj
def __getattr__(self, attr):
d = slave_gen._storage[self]
return getattr(d['m'], attr)
def __setattr__(self, attr, val):
d = slave_gen._storage[self]
return setattr(d['m'], attr, val)
class Master(object):
@slave_gen
class Slave(slave_mixin):
def __init__(self):
slave_mixin.__init__(self)
print 'Slave.__init__: self.master: ', self.master
if __name__ == '__main__':
m = Master()
s = m.Slave()
print 's.master: ', s.master
It works, by looking little weird... and I can't find way to escape from
using lock at object creation phase. It can be done by adding mandatory
attribute to slave class constructor, but this is even worse(for me)
than using lock.
Please show me more clear way to make this slave to master link.
PS Sorry for my English.
--
Богун Дмитрий aka vugluskr
More information about the Python-list
mailing list