pythonpython-3.xrpyc

RPyC - inherit from exposed class


I have an RpyC server that imports a specific module, a class inside this module should be exposed so that this class can then be inherited from the client side.

For testing purposes I removed the module importing/exposing and created a simple class inside my RPyC service called exposed_TestClass.

server side: rpyc_server.py

import rpyc
from rpyc.utils.server import ThreadedServer

class MyService(rpyc.Service):
    class exposed_TestClass:
        def exposed_Exec(self):
            print("original print of class")

t = ThreadedServer(MyService, port=12345)
t.start()

client side: python3 shell

>>> import rpyc
>>> conn = rpyc.connect("localhost", 12345)
>>> conn.root.TestClass
<class 'exposed_TestClass'>
>>> conn.root.TestClass()
<exposed_TestClass object at 0x7f2dda642588>
>>> #calling the Exec function also works, prints at server side
>>> conn.root.TestClass().Exec()
>>>
>>>
>>> # test inheriting class
>>> class MyClass(conn.root.TestClass):
...     def NewMethod(self):
...         print("printing from new method")
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/rpyc/core/netref.py", line 220, in method
    return syncreq(_self, consts.HANDLE_CALLATTR, name, args, kwargs)
  File "/usr/lib/python3/dist-packages/rpyc/core/netref.py", line 74, in syncreq
    conn = object.__getattribute__(proxy, "____conn__")
AttributeError: 'str' object has no attribute '____conn__'

Solution

  • As per the documentation on: https://rpyc.readthedocs.io/en/latest/tutorial/tut2.html

    Voila, netrefs (network references, also known as transparent object proxies) are special objects that delegate everything done on them locally to the corresponding remote objects. Netrefs may not be real lists of functions or modules, but they “do their best” to look and feel like the objects they point to… in fact, they even fool python’s introspection mechanisms!

    on the client side, if you do:

    import rpyc
    conn = rpyc.connect("localhost", 12345)
    
    o=conn.root.TestClass()
    type_o = type(o)
    print(type_o)
    

    it will print out:

    <netref class 'rpyc.core.netref.__main__.exposed_TestClass'>
    

    So when trying to do:

    class MyClass(type_o):
        def NewMethod(self):
            print("printing from new method")
    

    You inherit from the proxy class definition but not from the remote class definition. So when documentation states

    they “do their best”

    , i think it exclude the possibility of doing inheritance from a remote class. I'll be more than glad if ever someone can find a way to met your requirment.

    Please note I made my tests by setting up the server using the following line:

    t = ThreadedServer(MyService, port=12345, protocol_config={ 'allow_all_attrs': True })