Search code examples
pythonpyropyro4

Pyro4: Call method on remote sub-object without it trying to return the sub-object


Let's say I have an object that is a property of another object.

import Pyro4

@Pyro4.expose
class ClassB:
    def foo(self):
        return 'Hello from ClassB::foo()'

@Pyro4.expose
class ClassA:
    def __init__(self):
        self._b = ClassB()

    def foo(self):
        return 'Hello from ClassA::foo()'

    @property
    def b(self):
        return self._b

if __name__ == '__main__':
    daemon = Pyro4.Daemon(host='localhost')

    ns = Pyro4.locateNS(host='localhost', port=9090)
    ns.register('ClassA', daemon.register(ClassA))

    daemon.requestLoop()

And on the local machine, I run this

import Pyro4

if __name__ == '__main__':
    ns = Pyro4.locateNS(host='localhost', port=9090)
    uri = ns.lookup('ClassA')
    a = Pyro4.Proxy(uri)

    print(a.foo())
    print(a.b.foo()) # Fails here

When I try to invoke a.b.foo, it's trying to serialize a.b and invoke foo on it locally, but I want to invoke foo on the instance of ClassB that already exists on the remote ClassA instance.

Of course, I could add a method to ClassA that delegates to b.foo(), e.g.

def classA:
    # ...
    def foo_on_b(self):
        return self._b.foo()

But I'd rather not do that.


Solution

  • This is not possible, by design. It's a security vulnerability. https://pyro4.readthedocs.io/en/stable/security.html#dotted-names-object-traversal