[Zope-Perl] Calling python functions with keyword arguments from perl
Gisle Aas
gisle@ActiveState.com
15 Aug 2000 11:50:22 +0200
Currently there is no way to call a python function with keyword
arguments from perl. I think we need some nice/easy way of doing just
that.
Yesterday, I tried to translate a DTML method that contained the
following call:
<dtml-call expr="photoArchive.manage_addImage(id='',
file=file,
title=photo_title)">
It would have been nice if this could simply have been turned into:
$self->{photoArchive}->manage_addImage(id => '',
file => $file,
title => $photo_title);
I ended up greping the source to find the signature of
manage_addImage() and wrote it using positional arguments only:
$self->{f1}->manage_addImage("", $file, $photo_title);
The main problem is that it is not possible to know if "=>" or "," is
used in the argument lists inside the called function. At least not
until perl6 comes along and make => a pair operator or something :-)
The basic support for keyword arguments can be added by implementing:
Python::apply($CALLABLE, \@POSITIONAL_ARGUMENTS, \%KEYWORD_ARGUMENTS)
Currently we only support PyObject_CallObject() interface.
But it is not very nice to always have to say:
apply(getattr($self->{photoArchive}, "manage_addImage"), [],
{ id => '', file => $file, title => $photo_title });
One suggestion could be to introduce a rule which says that if the
last argument to a python function is a hash, then that hash contains
the keyword arguments. Then we could say:
$self->{photoArchive}->manage_addImage({id => '',
file => $file,
title => $photo_title});
or in general:
$obj->foo($pos1, $pos2, { key1 => $val1, key2 => $val2 });
It is not too cluttered, but you might get surprises in cases where
you did not intend to pass any keyword arguments and the last
positional argument just happened to be a hash reference. You can
protect yourself by appending an empty hash to the argument list in
this case:
$obj->foo(@args, {})
Other potential interfaces I could think of include:
* Use some specific object to wrap the keyword arguments. It looks
uglier than the plain hash, will be slower, but will be safe from
surprises.
$obj->foo($pos1, $pos2, KW( key1 => $val1, key2 => $val2 ));
* Use some special marker object inside the argument list to signal
where the keywords begin:
$obj->foo($pos1, $pos2, $KW, key1 => $val1, key2 => $val2);
We would then have to scan the argument to locate this marker.
It is also kind of ugly.
* Use leading dashes on keywords:
$obj->foo($pos1, $pos2, -key1 => $val1, -key2 => $val2);
Not too bad, but what if you want to pass plain strings with
leading dashes as positional arguments?
* Tell people to use apply() :-)
apply(getattr($obj, "foo"), [$pos1, $pos2], { key1 => $val1, key2 => $val2 });
Any other ideas or preferences for what interface to choose?
Regards,
Gisle