It's been a long time since I poked at Zope with XML-RPC. I was hoping to start using it for a very public set of tools, but the only things I can do right now are very clumsy. I have a Python Script, "test", in Zope with parameters "first=None, second=None". The Script just "prints" and returns the values. Trying what would seem to be an elegant way of calling it, Zope_server.test(first='foo', second='bar') yields an error. TypeError: __call__() got an unexpected keyword argument 'second' O.k., so I fall back to an old script I wrote that uses Meerkat (which still works!) and see that I can pass it a dictionary. Try again. Zope_server.test({'first': 'foo', 'second': 'bar'}) "first={'second': 'bar', 'first': 'foo'}\nsecond=None\n" That still doesn't give me access to "second". I've been looking in the obvious places for examples with multiple parameters but I've found none. Any pointers? (I think I originally worked from an article by Jon Udell at Byte but it seems to have disappeared.) The obvious alternative is to ditch XML-RPC and just use plain HTTP. Zope knows how to handle HTTP well enough and I'm quite comfortable with it, so it's almost my preference. I just thought that XML-RPC seemed like a cleaner way to handle this (and I'd recommended it for some other uses so I thought I should get some real experience with it). Thank you. --kyler
Kyler, xml-rpc doesn't accept named parameters, only positional ones. Once you know this then the behaviour you see makes perfect sense. Phil Kyler Laird wrote:
It's been a long time since I poked at Zope with XML-RPC. I was hoping to start using it for a very public set of tools, but the only things I can do right now are very clumsy.
I have a Python Script, "test", in Zope with parameters "first=None, second=None". The Script just "prints" and returns the values.
Trying what would seem to be an elegant way of calling it, Zope_server.test(first='foo', second='bar') yields an error. TypeError: __call__() got an unexpected keyword argument 'second'
O.k., so I fall back to an old script I wrote that uses Meerkat (which still works!) and see that I can pass it a dictionary. Try again. Zope_server.test({'first': 'foo', 'second': 'bar'}) "first={'second': 'bar', 'first': 'foo'}\nsecond=None\n" That still doesn't give me access to "second".
I've been looking in the obvious places for examples with multiple parameters but I've found none. Any pointers? (I think I originally worked from an article by Jon Udell at Byte but it seems to have disappeared.)
The obvious alternative is to ditch XML-RPC and just use plain HTTP. Zope knows how to handle HTTP well enough and I'm quite comfortable with it, so it's almost my preference. I just thought that XML-RPC seemed like a cleaner way to handle this (and I'd recommended it for some other uses so I thought I should get some real experience with it).
Thank you.
--kyler
_______________________________________________ Zope maillist - Zope@zope.org http://mail.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope-dev )
From kyler@lairds.com Thu Dec 25 09:14:58 2003 . . . It's been a long time since I poked at Zope with XML-RPC. I was hoping to start using it for a very public set of tools, but the only things I can do right now are very clumsy.
I have a Python Script, "test", in Zope with parameters "first=None, second=None". The Script just "prints" and returns the values.
Trying what would seem to be an elegant way of calling it, Zope_server.test(first='foo', second='bar') yields an error. TypeError: __call__() got an unexpected keyword argument 'second'
O.k., so I fall back to an old script I wrote that uses Meerkat (which still works!) and see that I can pass it a dictionary. Try again. Zope_server.test({'first': 'foo', 'second': 'bar'}) "first={'second': 'bar', 'first': 'foo'}\nsecond=None\n" That still doesn't give me access to "second".
I've been looking in the obvious places for examples with multiple parameters but I've found none. Any pointers? (I think I originally worked from an article by Jon Udell at Byte but it seems to have disappeared.)
The obvious alternative is to ditch XML-RPC and just use plain HTTP. Zope knows how to handle HTTP well enough and I'm quite comfortable with it, so it's almost my preference. I just thought that XML-RPC seemed like a cleaner way to handle this (and I'd recommended it for some other uses so I thought I should get some real experience with it). . . . Short answer: don't hesitate to use straight HTTP for communications. RPC, and XML-RPC in particular, is *supposed* to be about clean and easy programma- bility, but it just doesn't live up to the promise. At this point, I see little motivation in being a pioneer at doing what's necessary to make it useful in, for example, Zope.
xml-rpc doesn't accept named parameters, only positional ones. Once you know this then the behaviour you see makes perfect sense.
I gathered that much. That's why I switched to sending a dictionary as the first parameter. It's not the behavior of XML-RPC that bothered me. I was hoping that Zope would do something smart with the dictionary instead of just passing it as the first parameter. (Meerkat appears to handle this reasonably.) As it is, users must change their (non-trivial) scripts to work with XML-RPC. Zope is (otherwise) too elegant for me to suggest that. For now it appears that straight HTTP is the right approach to take. I can imagine that I'll run in to problems with this and someday I might want to modify the XML-RPC interface to Zope. --kyler
On Fri, Dec 26, 2003 at 08:51:28AM -0500, Cameron Laird wrote:
Short answer: don't hesitate to use straight HTTP for communications. RPC, and XML-RPC in particular, is *supposed* to be about clean and easy programma- bility, but it just doesn't live up to the promise. At this point, I see little motivation in being a pioneer at doing what's necessary to make it useful in, for example, Zope.
I took your advice...for awhile. There are a lot of things I've been planning to do with XML-RPC and rethinking those with only plain HTTP interfaces was frustrating me so I started poking around in Zope. It only took a few minutes to modify HTTPRequest.py to parse the arguments just as it does for plain HTTP requests. I let it simmer while I took a walk and I still like the idea. I think it'll be worth using a fork to be able to use a much cleaner interface. --kyler
O.k., I decided to attack it again this evening. It's starting to feel good. Before I forget what I did, I want to get my notes recorded. Maybe someone else will need to do this someday. The first step I took was to modify HTTPRequest.py so that if the request is just a single arg that's a dictionary, it stuffs the name/value pairs (with types) into fslist and then parses them just as if they'd been passed it by HTTP. [code too ugly to post - You'd do better on your own.] This is good. It lets me use named parameters *almost* like plain Python. Zope_server.test({'first': 'une', 'second': 'deux'}) I can use integers, floats, strings, lists, and dictionaries. They all slip right into place. I liked it...but not enough. With the server working better, I felt like seeing if I could make the calls from the client even simpler. Here's the terribly simple kludge I developed. class _Method(xmlrpclib._Method): def __call__(self, *args, **kw): if kw: return self.__send(self.__name, tuple(list(args) + [kw])) else: return self.__send(self.__name, args) xmlrpclib._Method = _Method O.k., besides screwing up a standard library, what does that do? Well, it lets me make calls like this. Zope_server.test(first='une', second='deux') Ah...much better. With that in place, I started playing. I quickly discovered that Zope XML-RPC still doesn't handle binary data well. I ran into this about a year ago, trying to send data to Zope. Now I just wanted to get an image *from* Zope. The xmlrpclib call would choke on illegal characters in the returned "<string>" element. My solution is to modify Zope's xmlrpc.py so that setBody converts body to a Binary object before marshalling it. body = xmlrpclib.dumps((xmlrpclib.Binary(body),), methodresponse=1) Now I can do real stuff. toolbox = xmlrpclib.Server("https://aviationtoolbox.org/Members/kyler/tools/") chunk = toolbox.chunk_create( ul_lon=-87.0, ul_lat=40.5, lr_lon=-86.8, lr_lat=40.4 ) chunk_file = open('/tmp/chunk.tif', 'w') chunk_file.write(str(chunk)) chunk_file.close() Oh, that feels good. I know this is all riding on a bunch of kludges, but it does show that XML-RPC *can* be a slick way to work with Zope. I'm going to play with it for awhile. --kyler
On 25 Dec 2003 at 9:10, Kyler Laird wrote:
Trying what would seem to be an elegant way of calling it, Zope_server.test(first='foo', second='bar') yields an error. TypeError: __call__() got an unexpected keyword argument 'second'
You can not use keyword arguments with xml-rpc. Only positional arguments are allowed. Also, Zope's mapply() doesn't like passing a variable number of arguments to PythonScript objects that try to use *args or **kw. So, I've always just declared my exposed functions as taking one argument, a dictionary. All xml-rpc clients just pass one dictionary, and that dict serves as keywords. So your server function could be params: d={} and the client could call
Zope_server.test({'first': 'foo', 'second': 'bar'})
That still doesn't give me access to "second".
Back on the server side, you'd use something like this: first = d.get('first', None) second = d.get('second', None) -- Brad Clements, bkc@murkworks.com (315)268-1000 http://www.murkworks.com (315)268-9812 Fax http://www.wecanstopspam.org/ AOL-IM: BKClements
participants (4)
-
Brad Clements -
Cameron Laird -
Kyler Laird -
Phil Harris