Re: is decorator the right thing to use?



On Sep 25, 3:36 pm, "Dmitry S. Makovey" <dmi...@xxxxxxxxxxxxx> wrote:

Aaron "Castironpi" Brady wrote:
I kept this part of the problem out of this discussion as I'm pretty sure
I can fill those in once I figure out the basic problem of
auto-population of proxy methods since for each class/method those are
going to be nearly identical. If I can autogenerate those on-the-fly I'm
pretty sure I can add some extra-logic to them as well including
signature change where A::bmethod(self,c,x) would become
A::bmethod(self,x) etc.

Do you want to couple instances or classes together?

It would be nice to have objects of B, C and D classes not knowing that they
are proxied (as they are used on their own too, not only inside of A
objects).

I'm not sure if the approach below deals with all the issues, but one
thing it does is decouple completely the proxied objects from the
proxy:

#======== usage
================================================================

from proxies import Proxy

class B(object):
def __init__(self): self.val = 'bval'
def bmethod(self,n): print "B::bmethod",n
def bmethod2(self,n,m): print "B::bmethod2",n,m

class C(object):
def __init__(self): self.val = 'cval'
def cmethod(self,x): print "C::cmethod",x
def cmethod2(self,x,y): print "C::cmethod2",x,y
cattr = 4

class A(Proxy):
DelegateMap = {
'bmethod' : B,
'bmethod2': B,
'cmethod': C,
# do NOT delegate C.cmethod2
#'cmethod2': C,
'cattr' : C,
}

def __init__(self, b, c):
print "init A()"
# must call Proxy.__init__(*delegates)
super(A,self).__init__(b,c)

def amethod(self,a):
print "A::mymethod",a


if __name__ == '__main__':
a = A(B(), C())
a.amethod('foo')

# test bounded methods
a.bmethod('foo')
a.bmethod2('bar','baz')
a.cmethod('foo')
try: a.cmethod2('bar','baz')
except Exception, ex: print ex

# works for unbound methods too
A.bmethod(a,'foo')
A.bmethod2(a,'bar','baz')
A.cmethod(a, 'foo')
try: A.cmethod2(a,'bar','baz')
except Exception, ex: print ex

# non callable attributes
print A.cattr

#====== output ==================================
init A()
A::mymethod foo
B::bmethod foo
B::bmethod2 bar baz
C::cmethod foo
'A' object has no attribute 'cmethod2'
B::bmethod foo
B::bmethod2 bar baz
C::cmethod foo
type object 'A' has no attribute 'cmethod2'
4

#======== proxies.py =========================

class _ProxyMethod(object):
def __init__(self, name):
self._name = name
def unbound(proxy, *args, **kwds):
method = proxy._get_target_attr(name)
return method(*args, **kwds)
self._unbound = unbound

def __get__(self, proxy, proxytype):
if proxy is not None:
return proxy._get_target_attr(self._name)
else:
return self._unbound


class _ProxyMeta(type):
def __new__(meta, name, bases, namespace):
for attrname,cls in namespace.get('DelegateMap',
{}).iteritems():
if attrname not in namespace:
attr = getattr(cls, attrname)
if callable(attr):
namespace[attrname] = _ProxyMethod(attrname)
else:
namespace[attrname] = attr
return super(_ProxyMeta,meta).__new__(meta, name, bases,
namespace)


class Proxy(object):
__metaclass__ = _ProxyMeta

def __init__(self, *delegates):
self._cls2delegate = {}
for delegate in delegates:
cls = type(delegate)
if cls in self._cls2delegate:
raise ValueError('More than one %s delegates were
given' % cls)
self._cls2delegate[cls] = delegate

def _get_target_attr(self, name):
try:
cls = self.DelegateMap[name]
delegate = self._cls2delegate[cls]
return getattr(delegate, name)
except (KeyError, AttributeError):
raise AttributeError('%r object has no attribute %r' %
(self.__class__.__name__, name))

HTH,
George
.



Relevant Pages

  • Re: is decorator the right thing to use?
    ... from proxies import Proxy ... # Maps each delegate method to the proxy attribute that refers to ... B::bmethod 10 foo ...
    (comp.lang.python)
  • Re: smart pointer dangerous (no -> operator)
    ... So Ada provides only two ways to access the managed object? ... In Ada 95 I declare the proxy type tagged controlled. ... The implementation of Foo goes as follows: ... the target object is derived from Object.Entity. ...
    (comp.lang.ada)
  • Re: is decorator the right thing to use?
    ... ProxyMethod declarations instead of a dict; ... from proxies import Proxy, ProxyMethod ... bmethod = ProxyMethod ... B::bmethod 10 foo ...
    (comp.lang.python)
  • X11 forwarding over proxied connection.
    ... I can do "ssh -X foo" where foo is a local machine on the same network and ... I assume this has something to do with the proxy. ...
    (comp.security.ssh)