Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: 'Proxy' object is not callable #95

Open
quajak opened this issue Aug 10, 2024 · 4 comments
Open

TypeError: 'Proxy' object is not callable #95

quajak opened this issue Aug 10, 2024 · 4 comments

Comments

@quajak
Copy link

quajak commented Aug 10, 2024

I want to Proxy an object using Pyro5, which has a __call__ method defined. Therefore, I can do object() but when I then use Pyro5 and have

proxy_object = Pyro5.api.Proxy(uri_from_ns)
proxy_object._pryoBind()
proxy_object()

the code crashes with the error message TypeError: 'Proxy' object is not callable

Is it possible to use Pyro5 with callable objects?

@irmen
Copy link
Owner

irmen commented Aug 18, 2024

Not entirely sure. What happens if you try proxy_object.__call__() ?

@quajak
Copy link
Author

quajak commented Aug 18, 2024

Unfortunately I am using a library, which uses __call__ internally and I don't want to change their code. For now, I followed https://stackoverflow.com/questions/38541015/how-to-monkey-patch-a-call-method to fix the issue in the one case I need it.

@michael-a-schmidt
Copy link

michael-a-schmidt commented Sep 5, 2024

I've also ran into this issue, and I made a minimal example that shows the problem. I'm running python 3.11.3 and Pyro5 version 5.15.

server.py:

import Pyro5.api

@Pyro5.api.expose
class DemoClass:

    def __len__(self):
        print("you called len")
        return 1

    def __dunder__(self):
        return "you called dunder"

    def __call__(self, x):
        return f"you called Demo with x={x}"

    def call_it(self, x):
        return self.__call__(x)


demo_object = DemoClass()
daemon = Pyro5.api.Daemon()
uri = daemon.register(demo_object)

print("Ready. Object uri = ", uri)
daemon.requestLoop()

client.py:

import Pyro5.api

demo_proxy = Pyro5.api.Proxy(uri_goes_here)
demo_proxy.call_it("foo") # this works fine
assert len(demo_proxy) == 1 # this works as expected
demo_proxy.__dunder__() # returns a string as needed

demo_proxy() # this fails with the error message above
demo_proxy.__call__() # this fails with an Attribute error

If I do demo_proxy.__call__() I get the following error:

AttributeError: remote object '<the url>' has no exposed attribute or method '__call__'. Did you mean: '__bool__'?

I've tried to explicitly wrap the __call__ method in the server code with @Pyro5.api.expose but then I get an error when I try to start the server:

AttributeError: exposing private names (starting with _) is not allowed

The documentation indicates that __dunder__ methods are generally exposed:
https://pyro5.readthedocs.io/en/latest/servercode.html

However, there is a comment on that same page that "There is a short list of dunder methods that will never be remoted though (because they are essential to let the Pyro proxy function correctly)."

It would be very helpful in my use case to be able to expose the __call__ method for remote objects - is there a list of the dunder methods that will never be remoted? Hopefully __call__ is not one of them, and this can be exposed...somehow.

@michael-a-schmidt
Copy link

following up on this, I looked through code in https://github.com/irmen/Pyro5/blob/master/Pyro5/server.py to find the source of the AttributeError: exposing private names (starting with _) is not allowed above when I attempted to decorate the __call__ method, and I can see that it checks to see if the method is a private attribute. If the method name is in the list of _private_dunder_methods then it will raise this exception, and indeed __call__ is in this list. See screenshot below

I think __call__ is marked as one of the special never-to-be-remoted method because the batch proxies use this method to start execution. In my use case this is unfortunate, but I can work around this limitation - just documenting here in case anyone runs into the same issue.

Screenshot 2024-10-07 at 10 55 19 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants