[PEAK] dispatch -- chaining decorators

Phillip J. Eby pje at telecommunity.com
Fri Dec 9 15:29:22 EST 2005

At 08:31 PM 12/9/2005 +0100, Simon Belak wrote:
>I have a decorator I would like to use along-side generic functions but I 
>am having some trouble getting it to play along:
>def unpickle(arg_name):
>         def __entangle(func):
>                 pickle_pos = list(func.func_code.co_varnames).index(arg_name)
>                 assert pickle_pos < func.func_code.co_argcount
>                 def __func(*args, **kwargs):
>                         return func(*args[:pickle_pos] + 
> (load(args[pickle_pos]),)
>                                                 + args[pickle_pos+1:], 
> **kwargs)
>                 return __func
>         return __entangle
>When I apply this decorator on an "around" function:
>def unpickle_form(next_method, form, context):
>         next_method(form, context)
>one of two things happen depending on order in which decorators were 
>applied. Either  argument position gets wrongly calculated (around, 
>unpickle) or my decorator does not get called at all (unpickle, around).
>I am guessing that in the first case next_method the causing me troubles, 
>but what about the second case? Any good wraparounds?

You want to use around+unpickle, because you want the unpickling to apply 
to the individual method, in the individual case.  The problem you're 
having is that __func doesn't have a 'next_method' argument, so the generic 
function doesn't pass it one, throwing off the argument order.

A trivial fix would be for __entangle to check 'func' for a next_method 
argument, and to define a variant def __func(next_method, *args, ...) in 
that case.

(Meanwhile, note that if you have a bunch of 
around("something(some_param)") cases, you're likely going to end up with 
method ambiguities.)

>On a not-so-related note, can generic functions be overused?

Maybe.  I haven't encountered such a situation yet, myself.  In my 
experience they mainly save me from writing a bunch *more* stuff, or 
replace a bunch of stuff I already had, with *less*.  So, it seems like 
overuse of generic functions would mean you'd have no code at all left, and 
so it's hard to see how that would be a *bad* thing, actually.  :)

>  I am currently writing a framework and just realised that nearly all 
> exposed functions have become generic. To me it seems that this allows 
> perfect flexibility and modularity as the user can plug in his code 
> almost anywhere. But still I cannot completely silent a voice in the back 
> of my mind screaming "Danger of cool things!".

I can't know without understanding your framework if that's the case.  But 
if generic functions aren't reducing the *number* of operations you have, 
then I would be concerned.  Note that peak.security.rules uses two generic 
functions and three classes in order to implement a fairly sophisticated 
ACL framework.  If your framework isn't dissolving into a surprisingly 
small number of simple generic functions, I'd say you're right to worry, 
because it means you haven't assimilated them yet, and therefore might well 
be "overusing" them.  But if they're *dissolving* the framework, then you 
have assimilated them (or they've assimilated you), and everything's fine.

(I say "dissolving" because peak.security.rules is technically a framework, 
and yet it's so lightweight there doesn't seem to be any "framework" left; 
it looks and smells more like a library than a framework, and that's 
definitely the place you want to get to.)

More information about the PEAK mailing list