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

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to