[capi-sig] Constructing variable arg tuples

Hrvoje Niksic hniksic at xemacs.org
Mon Jun 10 23:09:34 CEST 2013


Todd Lyons <tlyons at ivenue.com> writes:

>> Obviously the scripts and your embedding module need to agree on an API;
>
> Yes.  I've set the following limitations:
> 1. All args passed to a python function are converted to strings.  It
> is up to the function to include an implicit cast
> 2. No dicts, tuples, etc are passed.  Just simple strings or numbers
> (which are converted to strings).
> 3. Return from a function is always cast back to a string, which is
> what exim prefers.
>
> This is subject to changes and additions.

Such an interface makes sense in Perl, where you can always treat
numbers and strings in vice-versa, but might be somewhat inconvenient in
Python, which is much more "strongly" typed (you can query for an
object's type, and things like 1+"2" fail).

If my understanding is correct, you want exim configuration to define
which Python functions will be called by exim, without an API defined
upfront.

>> interface of the function is regulated by you, and it is you who
>> prescribe how many and what kind of arguments it will accept.
>
> I had to do a little work to figure out how many arguments the
> function is written to accept, and then double check that the call
> from the exim ACL's is using the correct number, and only then convert
> the variables and make the function call.

Why would you need to do that -- can't you just call the function and
leave it to raise an exception if called with an incorrect argument
count?  Not only for EAFP, but because inspecting how many argument a
function can fail.  After all, the function could be imported from a
module written in C or Boost.Python, or accept *args, which will likely
confuse count detection.

> The perl function count_headers() gets passed one variable: "from",
> stored in a variable named $header.  The perl function is written to
> load the headers from the message (a big text blob), convert it to an
> array, then loop through the array looking for /^$header:/, counting
> how many it finds.  Then it returns the number.
>
> The "condition" line simply compares the returned value to 1, and if
> it's greater than one, it will set the fakereject and quarantine
> settings.

This will work and is easy to implement, but it does feel a bit more
Perlish than Pythonic.  If you want to go for a solution with a more
native Python accent, I'd recommend passing the Python function some
sort of context argument.  Instead of a string, this would be an object
with some methods that retrieve the message information, such as
headers, and others to affect the response.  This needn't be a complex
framework -- if designed carefully, excellent functionality can be
achieved with a very small number of methods.


More information about the capi-sig mailing list