class Test_SSL(unittest.TestCase): ''' created key like that http://www.akadia.com/services/ssh_test_certificate.html openssl req -newkey rsa:1024 -nodes -keyout mycert.pem -out mycert.pem ''' def setUp(self): self.key = os.path.join( os.path.dirname(__file__) , "server.key") self.cert = os.path.join( os.path.dirname(__file__) , "server.crt") print( self.cert, self.key ) authenticator = SSLAuthenticator(self.key, self.cert) self.server = ThreadedServer(SlaveService, port = 18812, auto_register=False, authenticator = authenticator) self.server.logger.quiet = False self.server._start_in_thread() def tearDown(self): self.server.close() def test_ssl_conenction(self): c = rpyc.classic.ssl_connect("localhost", port = 18812, keyfile=self.key, certfile=self.cert) print( repr(c) ) print( c.modules.sys ) print( c.modules["xml.dom.minidom"].parseString("<a/>") ) c.execute("x = 5") self.assertEqual(c.namespace["x"], 5) self.assertEqual(c.eval("1+x"), 6) c.close()
class Test_ThreadedServer(unittest.TestCase): def setUp(self): self.server = ThreadedServer(SlaveService, port=18878, auto_register=False) self.server.logger.quiet = False self.server._start_in_thread() def tearDown(self): self.server.close() def test_connection(self): conn = rpyc.classic.connect("localhost", port=18878) print(conn.modules.sys) print(conn.modules["xml.dom.minidom"].parseString("<a/>")) conn.execute("x = 5") self.assertEqual(conn.namespace["x"], 5) self.assertEqual(conn.eval("1+x"), 6) conn.close() def test_instancecheck_across_connections(self): conn = rpyc.classic.connect("localhost", port=18878) conn2 = rpyc.classic.connect("localhost", port=18878) conn.execute("import test_magic") conn2.execute("import test_magic") foo = conn.modules.test_magic.Foo() bar = conn.modules.test_magic.Bar() self.assertTrue(isinstance(foo, conn.modules.test_magic.Foo)) self.assertTrue(isinstance(bar, conn2.modules.test_magic.Bar)) self.assertFalse(isinstance(bar, conn.modules.test_magic.Foo)) with self.assertRaises(TypeError): isinstance(conn.modules.test_magic.Foo, bar) conn.close() conn2.close()
class Test_SSL(unittest.TestCase): ''' created key like that http://www.akadia.com/services/ssh_test_certificate.html openssl req -newkey rsa:1024 -nodes -keyout mycert.pem -out mycert.pem ''' def setUp(self): self.key = os.path.join( os.path.dirname(__file__) , "server.key") self.cert = os.path.join( os.path.dirname(__file__) , "server.crt") print( self.cert, self.key ) authenticator = SSLAuthenticator(self.key, self.cert) self.server = ThreadedServer(SlaveService, port = 18812, auto_register=False, authenticator = authenticator) self.server.logger.quiet = False self.server._start_in_thread() def tearDown(self): self.server.close() def test_ssl_conenction(self): c = rpyc.classic.ssl_connect("localhost", port = 18812, keyfile=self.key, certfile=self.cert) print( repr(c) ) print( c.modules.sys ) print( c.modules["xml.dom.minidom"].parseString("<a/>") ) c.execute("x = 5") self.assertEqual(c.namespace["x"], 5) self.assertEqual(c.eval("1+x"), 6) c.close()
class Test_GDB(unittest.TestCase): def setUp(self): self.dtemp = tempfile.mkdtemp() self.a_out = pathlib.Path(self.dtemp, 'a.out') compile_cmd = ['g++', '-g', '-o', str(self.a_out), '-x', 'c++', '-'] proc = subprocess.Popen(compile_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) proc_input = b'int func(int a, int b){return a + b;}int main(){return func(1, 2);}' stdout, stderr = proc.communicate(input=proc_input) if stdout or stderr: raise ValueError( "stdout and stderr should have be empty for a.out creation") self.server = ThreadedServer(ParentGDB, port=18878, auto_register=False, protocol_config={'allow_all_attrs': True}) self.server._start_in_thread() def tearDown(self): self.server.close() while not self.server._closed: pass def test_gdb(self): parent_gdb_conn = rpyc.connect(host='localhost', port=18878) gdb = parent_gdb_conn.root.get_gdb() gdb.execute('file {}'.format(self.a_out)) disasm = gdb.execute('disassemble main', to_string=True) self.assertIn('End of assembler dump', disasm) parent_gdb_conn.close()
class RemoteTests(unittest.TestCase): def setUp(self): self.server = ThreadedServer(SlaveService, port=18812, auto_register=False) self.server.logger.quiet = False self.server._start_in_thread() def tearDown(self): while self.server.clients: pass self.server.close() def testConnection(self): conn = rpyc.classic.connect("localhost", port=18812) #print(conn.modules.sys) #print(conn.modules["xml.dom.minidom"].parseString("<a/>")) conn.execute("x = 5") self.assertEqual(conn.namespace["x"], 5) self.assertEqual(conn.eval("1+x"), 6) conn.close() def testHalConnect(self): conn = remote.RPyCModules('localhost') conn.Disconnect() def testHalFind(self): conn = remote.RPyCModules('localhost') try: hal = conn.LoadModule('halc.hal') conn.LoadModule('halc.iproute2') print("") hal.showTree() loInterface = hal.Devices.find('localhost') self.assertIsNotNone(loInterface,'lo Interface expected') finally: conn.Disconnect()
class Test_Ssh(unittest.TestCase): def setUp(self): if sys.platform == "win32": self.server = None os.environ["HOME"] = os.path.expanduser("~") self.remote_machine = SshMachine("localhost") else: # assume "ssh localhost" is configured to run without asking for password self.server = ThreadedServer(SlaveService, hostname = "localhost", ipv6 = False, port = 18888, auto_register=False) self.server._start_in_thread() self.remote_machine = SshMachine("localhost") def tearDown(self): if self.server: self.server.close() def test_simple(self): conn = rpyc.classic.ssh_connect(self.remote_machine, 18888) print( "server's pid =", conn.modules.os.getpid()) conn.modules.sys.stdout.write("hello over ssh\n") conn.modules.sys.stdout.flush() def test_connect(self): conn2 = rpyc.ssh_connect(self.remote_machine, 18888, service=MasterService) conn2.modules.sys.stdout.write("hello through rpyc.ssh_connect()\n") conn2.modules.sys.stdout.flush()
class Test_Ssh(unittest.TestCase): def setUp(self): if sys.platform == "win32": self.server = None os.environ["HOME"] = os.path.expanduser("~") self.remote_machine = SshMachine("localhost") else: # assume "ssh localhost" is configured to run without asking for password self.server = ThreadedServer(SlaveService, hostname="localhost", ipv6=False, port=18888, auto_register=False) self.server._start_in_thread() self.remote_machine = SshMachine("localhost") def tearDown(self): if self.server: self.server.close() def test_simple(self): conn = rpyc.classic.ssh_connect(self.remote_machine, 18888) print("server's pid =", conn.modules.os.getpid()) conn.modules.sys.stdout.write("hello over ssh\n") conn.modules.sys.stdout.flush() def test_connect(self): conn2 = rpyc.ssh_connect(self.remote_machine, 18888, service=MasterService) conn2.modules.sys.stdout.write("hello through rpyc.ssh_connect()\n") conn2.modules.sys.stdout.flush()
class Test_get_id_pack(unittest.TestCase): def setUp(self): self.port = 18878 self.port2 = 18879 self.server = ThreadedServer(SlaveService, port=self.port, auto_register=False) self.server2 = ThreadedServer(SlaveService, port=self.port2, auto_register=False) self.server._start_in_thread() self.server2._start_in_thread() self.conn = rpyc.classic.connect("localhost", port=self.port) self.conn_rpyc = self.conn.root.getmodule('rpyc') self.chained_conn = self.conn_rpyc.connect('localhost', self.port2) def tearDown(self): self.chained_conn.close() self.conn.close() self.server.close() self.server2.close() def test_netref(self): self.assertEquals(self.conn.root.____id_pack__, rpyc.lib.get_id_pack(self.conn.root)) def test_chained_connect(self): self.chained_conn.root.getmodule('os') def test_class_instance_wo_name(self): ss = rpyc.SlaveService() id_pack = rpyc.lib.get_id_pack(ss) self.assertEqual('rpyc.core.service.SlaveService', id_pack[0]) def test_class_wo_name(self): ss = rpyc.SlaveService id_pack = rpyc.lib.get_id_pack(ss) self.assertEqual('rpyc.core.service.SlaveService', id_pack[0])
class Test_rpyc_over_rpyc(unittest.TestCase): """Issue #346 shows that exceptions are being raised when an RPyC service method calls another RPyC service, forwarding a non-trivial (and thus given as a proxy) argument. """ def setUp(self): self.server = ThreadedServer(Service, port=Service.PORT, auto_register=False) self.i_server = ThreadedServer(Intermediate, port=Intermediate.PORT, auto_register=False, protocol_config=CONNECT_CONFIG) self.server._start_in_thread() self.i_server._start_in_thread() self.conn = rpyc.connect("localhost", port=Intermediate.PORT, config=CONNECT_CONFIG) def tearDown(self): self.conn.close() while self.server.clients or self.i_server.clients: pass self.server.close() self.i_server.close() def test_immutable_object_return(self): """Tests using rpyc over rpyc---issue #346 reported traceback for this use case""" obj = Fee() result = self.conn.root.fee_str(obj) self.assertEqual( str(obj), "Fee", "String representation of obj should not have changed") self.assertEqual( str(result), "Fee", "String representation of result should be the same as obj") def test_return_of_unmodified_parameter(self): obj = Fee() original_obj_id = id(obj) result = self.conn.root.fee(obj) self.assertEqual( str(obj), "Fee", "String representation of obj should not have changed") self.assertEqual( id(result), original_obj_id, "Unboxing of result should be bound to the same object as obj") def test_return_of_modified_parameter(self): obj = Fee() original_obj_id = id(obj) result = self.conn.root.fie_update(obj) self.assertEqual(str(obj), "Fee fie foe foo bar", "String representation of obj should have changed") self.assertEqual( id(result), original_obj_id, "Unboxing of result should be bound to the same object as obj")
class Test_Netref_Hierarchy(unittest.TestCase): def setUp(self): self.server = ThreadedServer(SlaveService, port=18878, auto_register=False) self.server.logger.quiet = False self.server._start_in_thread() def tearDown(self): self.server.close() def test_instancecheck_across_connections(self): conn = rpyc.classic.connect('localhost', port=18878) conn2 = rpyc.classic.connect('localhost', port=18878) conn.execute('import test_magic') conn2.execute('import test_magic') foo = conn.modules.test_magic.Foo() bar = conn.modules.test_magic.Bar() self.assertTrue(isinstance(foo, conn.modules.test_magic.Foo)) self.assertTrue(isinstance(bar, conn2.modules.test_magic.Bar)) self.assertFalse(isinstance(bar, conn.modules.test_magic.Foo)) with self.assertRaises(TypeError): isinstance(conn.modules.test_magic.Foo, bar) conn.close() conn2.close() def test_classic(self): conn = rpyc.classic.connect_thread() x = conn.builtin.list((1, 2, 3, 4)) print(conn.builtin.list, type(conn.builtin.list)) print(x, type(x)) print(x.__class__, type(x.__class__)) self.assertTrue(isinstance(x, list)) self.assertTrue(isinstance(x, rpyc.BaseNetref)) with self.assertRaises(TypeError): isinstance([], x) i = 0 self.assertTrue(type(x).__getitem__(x, i) == x.__getitem__(i)) _builtins = conn.modules.builtins if rpyc.lib.compat.is_py3k else conn.modules.__builtin__ self.assertEqual(repr(_builtins.float.__class__), repr(type)) self.assertEqual(repr(type(_builtins.float)), repr(type(_builtins.type))) def test_instancecheck_list(self): service = MyService() conn = rpyc.connect_thread(remote_service=service) conn.root remote_list = conn.root.getlist() self.assertTrue(conn.root.instance(remote_list, list)) conn.close()
class TestRestricted(unittest.TestCase): def setUp(self): self.server = ThreadedServer(MyService) self.thd = self.server._start_in_thread() self.conn = rpyc.connect("localhost", self.server.port) def tearDown(self): self.conn.close() self.server.close() self.thd.join() def test_restricted(self): obj = self.conn.root.get_one() self.assertEqual(obj.foo(), "foo") self.assertEqual(obj.bar(), "bar") self.assertEqual(obj.__add__("bar"), "foobar") self.assertEqual(obj._privy(), "privy") self.assertEqual(obj.exposed_foobar(), "Fee Fie Foe Foo") self.assertRaises(AttributeError, lambda: obj.spam) def test_restricted2(self): self.server.protocol_config = {'allow_public_attrs': False} obj = self.conn.root.get_one() self.assertEqual(obj.foo(), "foo") self.assertEqual(obj.bar(), "bar") self.assertEqual(obj.__add__("bar"), "foobar") self.assertEqual(obj._privy(), "privy") self.assertRaises(AttributeError, lambda: obj.spam)
class Test_ThreadedServer(unittest.TestCase): def setUp(self): self.server = ThreadedServer(SlaveService, port=18878, auto_register=False) self.server.logger.quiet = False self.server._start_in_thread() def tearDown(self): self.server.close() def test_connection(self): c = rpyc.classic.connect("localhost", port=18878) print( c.modules.sys ) print( c.modules["xml.dom.minidom"].parseString("<a/>") ) c.execute("x = 5") self.assertEqual(c.namespace["x"], 5) self.assertEqual(c.eval("1+x"), 6) c.close()
class Test_ThreadedServer(unittest.TestCase): def setUp(self): self.server = ThreadedServer(SlaveService, port=18878, auto_register=False) self.server.logger.quiet = False self.server._start_in_thread() def tearDown(self): self.server.close() def test_connection(self): c = rpyc.classic.connect("localhost", port=18878) print( c.modules.sys ) print( c.modules["xml.dom.minidom"].parseString("<a/>") ) c.execute("x = 5") self.assertEqual(c.namespace["x"], 5) self.assertEqual(c.eval("1+x"), 6) c.close()
class Test_ThreadedServerOverUnixSocket(unittest.TestCase): def setUp(self): self.socket_path = tempfile.mktemp() self.server = ThreadedServer(SlaveService, socket_path=self.socket_path, auto_register=False) self.server.logger.quiet = False self.server._start_in_thread() def tearDown(self): self.server.close() os.remove(self.socket_path) def test_connection(self): c = rpyc.classic.unix_connect(self.socket_path) print( c.modules.sys ) print( c.modules["xml.dom.minidom"].parseString("<a/>") ) c.execute("x = 5") self.assertEqual(c.namespace["x"], 5) self.assertEqual(c.eval("1+x"), 6) c.close()
class Test_ThreadedServerOverUnixSocket(unittest.TestCase): def setUp(self): self.socket_path = tempfile.mktemp() self.server = ThreadedServer(SlaveService, socket_path=self.socket_path, auto_register=False) self.server.logger.quiet = False self.server._start_in_thread() def tearDown(self): self.server.close() os.remove(self.socket_path) def test_connection(self): c = rpyc.classic.unix_connect(self.socket_path) print( c.modules.sys ) print( c.modules["xml.dom.minidom"].parseString("<a/>") ) c.execute("x = 5") self.assertEqual(c.namespace["x"], 5) self.assertEqual(c.eval("1+x"), 6) c.close()
class Test_rpyc_over_rpyc(unittest.TestCase): """Issue #346 shows that exceptions are being raised when an RPyC service method calls another RPyC service, forwarding a non-trivial (and thus given as a proxy) argument. """ def setUp(self): self.server = ThreadedServer(Service, port=Service.PORT, auto_register=False) self.i_server = ThreadedServer(Intermediate, port=Intermediate.PORT, auto_register=False) self.server._start_in_thread() self.i_server._start_in_thread() self.conn = rpyc.connect("localhost", port=Intermediate.PORT) def tearDown(self): self.conn.close() self.server.close() self.i_server.close() def test_rpyc_over_rpyc(self): """Tests using rpyc over rpyc throws an exception as described in #346""" obj = Foo() result = self.conn.root.foo(obj) self.assertEqual(result, str(obj))
class TestRestricted(unittest.TestCase): def setUp(self): self.server = ThreadedServer(MyService, port = 0) self.thd = self.server._start_in_thread() self.conn = rpyc.connect("localhost", self.server.port) def tearDown(self): self.conn.close() self.server.close() self.thd.join() def test_restricted(self): obj = self.conn.root.get_one() self.assertEqual(obj.foo(), "foo") self.assertEqual(obj.bar(), "bar") self.assertRaises(AttributeError, lambda: obj.spam)
class TestRestricted(unittest.TestCase): def setUp(self): self.server = ThreadedServer(MyService, port=0) self.thd = self.server._start_in_thread() self.conn = rpyc.connect("localhost", self.server.port) def tearDown(self): self.conn.close() self.server.close() self.thd.join() def test_restricted(self): obj = self.conn.root.get_one() self.assertEqual(obj.foo(), "foo") self.assertEqual(obj.bar(), "bar") self.assertRaises(AttributeError, lambda: obj.spam)
class Test_IPv6(unittest.TestCase): def setUp(self): self.server = ThreadedServer(SlaveService, port=0, ipv6=True) self.server.logger.quiet = True self.thd = self.server._start_in_thread() def tearDown(self): self.server.close() self.thd.join() def test_ipv6_conenction(self): c = rpyc.classic.connect("::1", port=self.server.port, ipv6=True) print(repr(c)) print(c.modules.sys) print(c.modules["xml.dom.minidom"].parseString("<a/>")) c.execute("x = 5") self.assertEqual(c.namespace["x"], 5) self.assertEqual(c.eval("1+x"), 6) c.close()
class Test_IPv6(unittest.TestCase): def setUp(self): self.server = ThreadedServer(SlaveService, port = 0, ipv6 = True) self.server.logger.quiet = True self.thd = self.server._start_in_thread() def tearDown(self): self.server.close() self.thd.join() def test_ipv6_conenction(self): c = rpyc.classic.connect("::1", port = self.server.port, ipv6 = True) print( repr(c) ) print( c.modules.sys ) print( c.modules["xml.dom.minidom"].parseString("<a/>") ) c.execute("x = 5") self.assertEqual(c.namespace["x"], 5) self.assertEqual(c.eval("1+x"), 6) c.close()
class TestConfigAllows(unittest.TestCase): def setUp(self): self.cfg = self._reset_cfg() self.server = ThreadedServer(MyService, port=0) self.thd = self.server._start_in_thread() self.conn = rpyc.connect("localhost", self.server.port) def tearDown(self): self.conn.close() self.server.close() self.thd.join() def _reset_cfg(self): self.cfg = copy.copy(rpyc.core.protocol.DEFAULT_CONFIG) return self.cfg def _get_myclass(self, proto_config): self.conn.close() self.server.protocol_config.update(proto_config) self.conn = rpyc.connect("localhost", self.server.port) return self.conn.root.MyClass() def test_default_config(self): obj = self._get_myclass(self.cfg) self.assertEqual(obj + 'bar', "foobar") self.assertEqual(obj.foobar(), "Fee Fie Foe Foo") self.assertEqual(obj.exposed_foobar(), "Fee Fie Foe Foo") self.assertRaises(AttributeError, lambda: obj._privy) self.assertRaises(AttributeError, lambda: obj.foo) self.assertRaises(AttributeError, lambda: obj.bar) self.assertRaises(AttributeError, lambda: obj.spam) def test_allow_all(self): self._reset_cfg() self.cfg['allow_all_attrs'] = True obj = self._get_myclass(self.cfg) self.assertEqual(obj + 'bar', "foobar") self.assertEqual(obj.__add__("bar"), "foobar") self.assertEqual(obj._privy(), "privy") self.assertEqual(obj.foobar(), "Fee Fie Foe Foo") self.assertEqual(obj.exposed_foobar(), "Fee Fie Foe Foo") def test_allow_exposed(self): self._reset_cfg() self.cfg['allow_exposed_attrs'] = False try: self._get_myclass(self.cfg) # returns obj, but ignored passed = False except Exception: passed = True self.assertEqual(passed, True) def test_allow_safe_attrs(self): self._reset_cfg() self.cfg['allow_safe_attrs'] = False obj = self._get_myclass(self.cfg) self.assertEqual(obj.foobar(), "Fee Fie Foe Foo") self.assertEqual(obj.exposed_foobar(), "Fee Fie Foe Foo") self.assertRaises(AttributeError, lambda: obj._privy) self.assertRaises(AttributeError, lambda: obj + 'bar') self.assertRaises(AttributeError, lambda: obj.foo) self.assertRaises(AttributeError, lambda: obj.bar) self.assertRaises(AttributeError, lambda: obj.spam) def test_allow_public_attrs(self): self._reset_cfg() self.cfg['allow_public_attrs'] = True obj = self._get_myclass(self.cfg) self.assertEqual(obj + 'bar', "foobar") self.assertEqual(obj.foo(), "foo") self.assertEqual(obj.bar(), "bar") self.assertEqual(obj.foobar(), "Fee Fie Foe Foo") self.assertEqual(obj.exposed_foobar(), "Fee Fie Foe Foo") self.assertRaises(AttributeError, lambda: obj._privy)
'cpu': info[3], 'mem': info[4], 'net': info[5], 'gpu': info[6] }) print("Host " + str(info[0]) + ":" + str(info[1]) + " subscribed") def exposed_unsubscribe(self, info): remove_reg(db, {'ip': info[0], 'port': info[1]}) print("Host " + str(info[0]) + ":" + str(info[1]) + " unsubscribed") if __name__ == "__main__": rpyc.core.protocol.DEFAULT_CONFIG['allow_pickle'] = True db = create_db() print("Starting chain receiver at port " + str(port_chain)) server_chain = Server(ReceiveChain, port=port_chain, backlog=10, protocol_config=rpyc.core.protocol.DEFAULT_CONFIG) server_chain._start_in_thread() print("Starting client receiver at port " + str(port_cli)) server_cli = Server(ReceiveClient, port=port_cli, backlog=10, protocol_config=rpyc.core.protocol.DEFAULT_CONFIG) server_cli.start()
class Test_Netref_Hierarchy(unittest.TestCase): def setUp(self): self.server = ThreadedServer(SlaveService, port=18878, auto_register=False) self.server.logger.quiet = False self.server._start_in_thread() def tearDown(self): self.server.close() def test_instancecheck_across_connections(self): conn = rpyc.classic.connect('localhost', port=18878) conn2 = rpyc.classic.connect('localhost', port=18878) conn.execute('import test_magic') conn2.execute('import test_magic') foo = conn.modules.test_magic.Foo() bar = conn.modules.test_magic.Bar() self.assertTrue(isinstance(foo, conn.modules.test_magic.Foo)) self.assertTrue(isinstance(bar, conn2.modules.test_magic.Bar)) self.assertFalse(isinstance(bar, conn.modules.test_magic.Foo)) with self.assertRaises(TypeError): isinstance(conn.modules.test_magic.Foo, bar) conn.close() conn2.close() def test_classic(self): conn = rpyc.classic.connect_thread() x = conn.builtin.list((1, 2, 3, 4)) self.assertTrue(isinstance(x, list)) self.assertTrue(isinstance(x, rpyc.BaseNetref)) with self.assertRaises(TypeError): isinstance([], x) i = 0 self.assertTrue(type(x).__getitem__(x, i) == x.__getitem__(i)) _builtins = conn.modules.builtins if rpyc.lib.compat.is_py_3k else conn.modules.__builtin__ self.assertEqual(repr(_builtins.float.__class__), repr(type)) self.assertEqual(repr(type(_builtins.float)), repr(type(_builtins.type))) def test_instancecheck_list(self): service = MyService() conn = rpyc.connect_thread(remote_service=service) conn.root remote_list = conn.root.getlist() self.assertTrue(conn.root.instance(remote_list, list)) conn.close() def test_StandardError(self): conn = rpyc.classic.connect_thread() _builtins = conn.modules.builtins if rpyc.lib.compat.is_py_3k else conn.modules.__builtin__ self.assertTrue(isinstance(_builtins.Exception(), _builtins.BaseException)) self.assertTrue(isinstance(_builtins.Exception(), _builtins.Exception)) self.assertTrue(isinstance(_builtins.Exception(), BaseException)) self.assertTrue(isinstance(_builtins.Exception(), Exception)) def test_modules(self): """ >>> type(sys) <type 'module'> # base case >>> type(conn.modules.sys) <netref class 'rpyc.core.netref.__builtin__.module'> # matches base case >>> sys.__class__ <type 'module'> # base case >>> conn.modules.sys.__class__ <type 'module'> # matches base case >>> type(sys.__class__) <type 'type'> # base case >>> type(conn.modules.sys.__class__) <netref class 'rpyc.core.netref.__builtin__.module'> # doesn't match. Should be a netref class of "type" (or maybe just <type 'type'> itself?) """ import sys conn = rpyc.classic.connect_thread() self.assertEqual(repr(sys.__class__), repr(conn.modules.sys.__class__))