Is it possible to create a class object in a Python client and pass it as an argument to in a service function

10 views
Skip to first unread message

Josh D

unread,
Jun 18, 2012, 2:37:17 PM6/18/12
to ag...@googlegroups.com
I'm trying to implement the observer pattern using Agnos and am running into some difficulty.  Here is a small snippet from my IDL:

  <record name="LogRecord">
    <doc>Stores all of the information for a log message.</doc>
    <attr name="timestamp" type="date" />
    <attr name="type" type="LogType" />
    <attr name="message" type="str" />
  </record>
 
  <class name="LogListener">
    <doc>Stores all of the information for a log update</doc>
    <method name="logUpdate" type="void">
      <arg name="record" type="LogRecord"/>
    </method>
  </class>

  <func name="registerLogUpdate" type="void">
    <doc>Register to be notified of log messages</doc>
    <arg name="listener" type="LogListener" />
  </func>


Basically, I want to register a callback with the server.  My server is implemented in Java and the client is Python.  My naive approach was to simply create a class on the client side and pass it in, but I was met with the following error:

  File "C:\TEMP\wspace2\SimService\build\gen_src\GroundService_bindings.py", line 523, in sync_900023
    LogListenerObjRef.pack(listener, _self.utils.transport)
  File "c:\Python26\lib\contextlib.py", line 34, in __exit__
    self.gen.throw(type, value, traceback)
  File "c:\Python26\lib\site-packages\agnos-1.0.2-py2.6.egg\agnos\protocol.py", line 381, in invocation
    yield seq
  File "C:\TEMP\wspace2\SimService\build\gen_src\GroundService_bindings.py", line 523, in sync_900023
    LogListenerObjRef.pack(listener, _self.utils.transport)
  File "c:\Python26\lib\site-packages\agnos-1.0.2-py2.6.egg\agnos\packers.py", line 90, in pack
    Int64.pack(self.storer(obj), stream)
  File "C:\TEMP\wspace2\SimService\build\gen_src\GroundService_bindings.py", line 488, in <lambda>
    storer = lambda proxy: -1 if proxy is None else proxy._objref
AttributeError: 'LogListener' object has no attribute '_objref'

Clearly, it's expecting me to do something special to create this object.  In my generated bindings module, I see the classes for the Proxy objects, but not abstract class for me to implement.  Is what I'm trying to do even possible?

Tomer Filiba

unread,
Jun 18, 2012, 4:11:41 PM6/18/12
to ag...@googlegroups.com
yes, well, agnos, unlike rpyc (http://rpyc.sf.net) is not a symmetric protocol.
this means only the server can create proxy objects -- you cannot pass an object (by ref) from the client to the server, only the other way around.
also, the server can't "invoke" callbacks on the client. it's a technical limitation of the design.

you can create a workaround, maybe, by passing an enum of options, or a url that the server could ping, etc.
also, it's a bit more complicated, but the client can act as both a client and a server. 
for instance, on one thread run an agnos server, and use the other to make requests from the server.
this way, the server could connect to the client's server thread and invoke callbacks, etc.

it would require two separate IDLs. here's a sketch:

client.py
======
create_server_on_bg_thread(port = 12345)
root = agnos.Client.connect("myserver", 23456)
root.connect_to_me("myhostname", 12345)

where the client's server (a funny term, but still) would expose a service with all the "callbacks" for the server.
so once the server connects to the client, it would be able to invoke code in the client's server thread.

as i said, it's a bit complicated, but agnos wasn't design for this kind of interaction :)


-----------------------------------------------------------------
    
Tomer Filiba 
tomerfiliba.com        
Reply all
Reply to author
Forward
0 new messages