2008-12-04 7 views
1

J'essaie de créer un objet proxy dans IronPython, qui devrait présenter dynamiquement la structure sous-jacente. Le proxy lui-même ne devrait pas avoir de fonctions et de propriétés, j'essaie d'attraper tous les appels dans l'exécution. Attraper les appels de fonction est facile, je dois juste définir getattr() fonction pour mon objet, et vérifie que la fonction appropriée existe dans le calque sous-jacent, et retourne un objet semblable à la fonction.Objets proxy dans IronPython

J'ai des problèmes avec des propriétés - Je ne sais pas comment distinguer le contexte d'appel, est ma propriété appelée comme lvalue ou rvalue:

o = myproxy.myproperty # Je dois appeler underlying.myproperty_get()

ou

myproxy.myproperty = o # Je dois appeler underlying.myproperty_set (o)

J'ai regardé la liste des fonctions spéciales en Python, mais je n'ai rien trouvé de convenable.

J'ai également essayé de faire la propriété dans l'objet à la volée, avec la combinaison de la fonction d'exec() et de propriété intégrée, mais j'ai trouvé que IronPython 1.1.2 manque du module 'nouveau' entier (qui est présent dans IronPython 2.x beta, mais je vais plutôt utiliser IP 1.x, à cause du framework .NET 2.0).

Des idées?

+0

Les gars, je vous remercie beaucoup! – apetrovic

Répondre

2

La mise en œuvre habituelle de ce que vous voulez en python serait ceci:

class CallProxy(object): 
    'this class wraps a callable in an object' 
    def __init__(self, fun): 
     self.fun = fun 

    def __call__(self, *args, **kwargs): 
     return self.fun(*args, **kwargs) 

class ObjProxy(object): 
    ''' a proxy object intercepting attribute access 
    ''' 
    def __init__(self, obj): 
     self.__dict__['_ObjProxy__obj'] = obj 

    def __getattr__(self, name): 
     attr = getattr(self.__obj, name) 
     if callable(attr): 
      return CallProxy(attr) 
     else: 
      return attr 

    def __setattr__(self, name, value): 
     setattr(self.__obj, name, value) 

j'ai écrit un test pour prouver que ce comportement comme prévu:

#keep a list of calls to the TestObj for verification 
call_log = list() 
class TestObj(object): 
    ''' test object on which to prove 
     that the proxy implementation is correct 
    ''' 
    def __init__(self): 
     #example attribute 
     self.a = 1 
     self._c = 3 

    def b(self): 
     'example method' 
     call_log.append('b') 
     return 2 

    def get_c(self): 
     call_log.append('get_c') 
     return self._c 
    def set_c(self, value): 
     call_log.append('set_c') 
     self._c = value 
    c = property(get_c, set_c, 'example property') 

def verify(obj, a_val, b_val, c_val): 
    'testing of the usual object semantics' 
    assert obj.a == a_val 
    obj.a = a_val + 1 
    assert obj.a == a_val + 1 
    assert obj.b() == b_val 
    assert call_log[-1] == 'b' 
    assert obj.c == c_val 
    assert call_log[-1] == 'get_c' 
    obj.c = c_val + 1 
    assert call_log[-1] == 'set_c' 
    assert obj.c == c_val + 1 

def test(): 
    test = TestObj() 
    proxy = ObjProxy(test) 
    #check validity of the test 
    verify(test, 1, 2, 3) 
    #check proxy equivalent behavior 
    verify(proxy, 2, 2, 4) 
    #check that change is in the original object 
    verify(test, 3, 2, 5) 

if __name__ == '__main__': 
    test() 

Cette exécute sur CPython sans assert jeter une exception. IronPython devrait être équivalent, sinon il est cassé et ce test devrait être ajouté à sa suite de tests unitaires.

2

Essayez ceci:

class Test(object): 
    _test = 0 

    def test(): 
     def fget(self): 
      return self._test 
     def fset(self, value): 
      self._test = value 
     return locals() 
    test = property(**test()) 

    def greet(self, name): 
     print "hello", name 


class Proxy(object): 
    def __init__(self, obj): 
     self._obj = obj 

    def __getattribute__(self, key): 
     obj = object.__getattribute__(self, "_obj") 
     return getattr(obj, key) 

    def __setattr__(self, name, value): 
     if name == "_obj": 
      object.__setattr__(self, name, value) 
     else: 
      obj = object.__getattribute__(self, "_obj") 
      setattr(obj, name, value) 


t = Test() 
p = Proxy(t) 
p.test = 1 
assert t.test == p.test 
p.greet("world") 
Questions connexes