[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