@@ -11,6 +11,85 @@ def BYTES_LITERAL(text):
1111
1212 rpyc .lib .compat .BYTES_LITERAL = BYTES_LITERAL
1313
14+ # TODO: This will not be found in Rhino 5!
15+ # TODO: This will not work if in IronPython outside Rhino!
16+ # TODO: This loads the gh components early?? not needed if not accessing them??
17+ # TODO: Remove that when ghpythonlib.components.__namedtuple.__getattr__ is fixed
18+ import ghpythonlib .components
19+
20+ def get_id_pack (obj ):
21+ """introspects the given "local" object, returns id_pack as expected by BaseNetref
22+
23+ The given object is "local" in the sense that it is from the local cache. Any object in the local cache exists
24+ in the current address space or is a netref. A netref in the local cache could be from a chained-connection.
25+ To handle type related behavior properly, the attribute `__class__` is a descriptor for netrefs.
26+
27+ So, check thy assumptions regarding the given object when creating `id_pack`.
28+ """
29+
30+ # TODO: Remove that when ghpythonlib.components.__namedtuple.__getattr__ is fixed
31+ if hasattr (obj , "____id_pack__" ) and not isinstance (
32+ obj , ghpythonlib .components .__namedtuple
33+ ):
34+ # netrefs are handled first since __class__ is a descriptor
35+ return obj .____id_pack__
36+ elif inspect .ismodule (obj ) or getattr (obj , "__name__" , None ) == "module" :
37+ # TODO: not sure about this, need to enumerate cases in units
38+ if isinstance (obj , type ): # module
39+ obj_cls = type (obj )
40+ name_pack = "{0}.{1}" .format (obj_cls .__module__ , obj_cls .__name__ )
41+ return (name_pack , id (type (obj )), id (obj ))
42+ else :
43+ if inspect .ismodule (obj ) and obj .__name__ != "module" :
44+ if obj .__name__ in sys .modules :
45+ name_pack = obj .__name__
46+ else :
47+ name_pack = "{0}.{1}" .format (
48+ obj .__class__ .__module__ , obj .__name__
49+ )
50+ elif inspect .ismodule (obj ):
51+ name_pack = "{0}.{1}" .format (obj__module__ , obj .__name__ )
52+ print (name_pack )
53+ elif hasattr (obj , "__module__" ):
54+ name_pack = "{0}.{1}" .format (obj .__module__ , obj .__name__ )
55+ else :
56+ obj_cls = type (obj )
57+ name_pack = "{0}" .format (obj .__name__ )
58+ return (name_pack , id (type (obj )), id (obj ))
59+ elif not inspect .isclass (obj ):
60+ name_pack = "{0}.{1}" .format (
61+ obj .__class__ .__module__ , obj .__class__ .__name__
62+ )
63+ return (name_pack , id (type (obj )), id (obj ))
64+ else :
65+ name_pack = "{0}.{1}" .format (obj .__module__ , obj .__name__ )
66+ return (name_pack , id (obj ), 0 )
67+
68+ rpyc .lib .get_id_pack = get_id_pack
69+ rpyc .core .netref .get_id_pack = get_id_pack
70+ rpyc .core .protocol .get_id_pack = get_id_pack
71+
72+ # TODO: Remove that when ghpythonlib.components.__namedtuple.__getattr__ is fixed
73+ def _handle_inspect (self , id_pack ): # request handler
74+ obj = self ._local_objects [id_pack ]
75+ if hasattr (obj , "____conn__" ) and not isinstance (
76+ obj , ghpythonlib .components .__namedtuple
77+ ):
78+ # When RPyC is chained (RPyC over RPyC), id_pack is cached in local objects as a netref
79+ # since __mro__ is not a safe attribute the request is forwarded using the proxy connection
80+ # see issue #346 or tests.test_rpyc_over_rpyc.Test_rpyc_over_rpyc
81+ conn = self ._local_objects [id_pack ].____conn__
82+ return conn .sync_request (rpyc .core .consts .HANDLE_INSPECT , id_pack )
83+ else :
84+ return tuple (
85+ rpyc .lib .get_methods (
86+ rpyc .core .netref .LOCAL_ATTRS , self ._local_objects [id_pack ]
87+ )
88+ )
89+
90+ # TODO: Remove that when ghpythonlib.componentns.__namedtuple.__getattr__ is fixed
91+ rpyc .core .protocol .Connection ._handle_inspect = _handle_inspect
92+
1493 if sys .version_info < (2 , 7 , 5 ):
1594
1695 def dump (obj ):
0 commit comments