I'm going to make everyone's life miserable again. ;)
In r1279 I added support for "alternative" decorator syntax as used by
PEAK to lessen the anguish of people still on Python 2.3. This
unfortunately requires a bit different application of decorator() function.
Before:
def foo(a):
def entagle(func)
def caller(func, *args, **kw):
func(*args, **kw)
return decorator(caller)(func)
return entagle
after:
def foo(a):
def entagle(func)
def caller(func, *args, **kw):
func(*args, **kw)
return caller
return decorator(entagle)
As an added bonus it is also marginally more concise.
While I was at it, I made another change. Until now decorator() added
*args and **kw to the resulting function signature unless optional
argument "argsink" was false.
Well, "argsink" is no more. Instead we have a much more powerful (still
optional) argument "signature" similar in composition to what
inspect.getargspec() returns, allowing us to define an arbitrary
signatures (mind, the function being decorated still needs to be able to
digest this new parameter specification).
To get the beloved care-free will-eat-anything signatures back a helper
named weak_signature_decorator() is available.
I invite all interested to take a look at decorator.py and
test_decorator.py. The use of signature in anger can be observed in
util.bind_args().
Knowing myself I suggest we keep it in trunk for a while (maybe until
after the sprint and than send it into the wild with nice and shiny
documentation by it's side).
Cheers,
Simon
This change needs to be in a5. I don't want to do another alpha
release, and I don't want to see this wait until 1.1. Do we have any
other code that is impacted that needs changing? Is there any way to
provide backwards compatibility?
Kevin
I am trying to make old code work with this... I'm sending another message
describing my problems.
Maybe I had wrong code before -- it worked perfectly before, though -- and now
I have it fixed, but...
--
Jorge Godoy <jgo...@gmail.com>
I had, before:
@decorator
def my_decorator(func, *args, **kwords):
...
How should I translate it to the new syntax? I'm not worried with supporting
Python 2.3 here, so the easiness of the old syntax was very nice to me.
> While I was at it, I made another change. Until now decorator() added
> *args and **kw to the resulting function signature unless optional
> argument "argsink" was false.
> Well, "argsink" is no more. Instead we have a much more powerful (still
> optional) argument "signature" similar in composition to what
> inspect.getargspec() returns, allowing us to define an arbitrary
> signatures (mind, the function being decorated still needs to be able to
> digest this new parameter specification).
> To get the beloved care-free will-eat-anything signatures back a helper
> named weak_signature_decorator() is available.
I tried it as well, but it won't work with the above (mine) syntax. I had to
convert to your syntax to have it working... But then, I started having
other problems, specially with @turbogears.validate, which is failing always.
> I invite all interested to take a look at decorator.py and
> test_decorator.py. The use of signature in anger can be observed in
> util.bind_args().
>
> Knowing myself I suggest we keep it in trunk for a while (maybe until
> after the sprint and than send it into the wild with nice and shiny
> documentation by it's side).
Here are my "attempts":
===============================================================================
def mensagem_json():
def entangle(func):
def caller(func, *args, **kwords):
print "#################"
return caller
return decorator(entangle)
===============================================================================
What results in:
===============================================================================
Traceback (most recent call last):
File "./start-siteamostras.py", line 26, in ?
from siteamostras.controllers import Root
File
"/home/godoy/empresa/clientes/latam/Site-Amostras/siteamostras/controllers/__init__.py",
line 18, in ?
from siteamostras.controllers.toxicologia import Toxicologia
File
"/home/godoy/empresa/clientes/latam/Site-Amostras/siteamostras/controllers/toxicologia.py",
line 24, in ?
from siteamostras.controllers import analises
File
"/home/godoy/empresa/clientes/latam/Site-Amostras/siteamostras/controllers/analises.py",
line 29, in ?
class Analises(controllers.Controller):
File
"/home/godoy/empresa/clientes/latam/Site-Amostras/siteamostras/controllers/analises.py",
line 213, in Analises
@turbogears.expose()
TypeError: mensagem_json() takes no arguments (1 given)
===============================================================================
When I change it to:
===============================================================================
def mensagem_json(something):
def entangle(func):
def caller(func, *args, **kwords):
print "#################"
return caller
return decorator(entangle)
===============================================================================
it runs, but @turbogears.validate fails.
Changing it to:
===============================================================================
def mensagem_json(func):
def entangle(func):
def caller(func, *args, **kwords):
print "#################"
return caller
return decorator(entangle)
===============================================================================
Using weak_signature_decorator doesn't help and yields the same results.
In my code I have:
===============================================================================
@turbogears.expose()
@turbogears.error_handler(turbogears.util.bind_args(add = True)(analises))
@turbogears.validate(form = formulario_analises)
@identity.require(identity.conditions.in_group("latam_novo"))
@mensagem_json
def save(self, **kword):
...
===============================================================================
I hope I'm doing something wrong and that is easy to solve.
--
Jorge Godoy <jgo...@gmail.com>
Sorry if my message last night sounded terse. I didn't have much time
just then...
I have one other question about this: is there any perceptible
difference in startup time? startup time is actually somewhat
important, because the user has to sit through that startup time every
time they make a change to their code during development. I'd rather
not dramatically slow down use for Py2.4 users. If there isn't a big
startup cost, then this is a really nice change for 2.3 users (and
those of use working on TG itself!)
Kevin
> I have one other question about this: is there any perceptible
> difference in startup time? startup time is actually somewhat
> important, because the user has to sit through that startup time every
> time they make a change to their code during development. I'd rather
> not dramatically slow down use for Py2.4 users. If there isn't a big
> startup cost, then this is a really nice change for 2.3 users (and
> those of use working on TG itself!)
Penalty is a couple of function calls per decorator. Nothing wild.
I intend to make some changes to not burden people who do not need 2.3
compatibility (see Jorge's example) and than merge with a5.
Cheers
Simon
That's not too bad. I was worried about the whole "debug hook" thing
slowing things down.
> I intend to make some changes to not burden people who do not need 2.3
> compatibility (see Jorge's example) and than merge with a5.
That's great! Thanks!
Kevin
def mensagem_json():
def entangle(func):
def caller(func, *args, **kwords):
print "#################"
return caller
return weak_signature_decorator(entangle)
....
@mensagem_json()
def ...
should do the trick.
As of 1285 two new decorator factories are available:
simple_decorator()
simple_simple_weak_signature_decorator()
which work as before (apply to caller, no Py2.3 compatibility).
I would however very much appreciate if you could also try to make the
new weak_signature_decorator() work with your code, just to make sure
before I apply these changes to a5. Thanks!
Cheers,
Simon
It didn't.
> As of 1285 two new decorator factories are available:
>
> simple_decorator()
> simple_simple_weak_signature_decorator()
>
> which work as before (apply to caller, no Py2.3 compatibility).
They still give me errors. Second is with simple_weak_signature_decorator.
godoy@jupiter ~/empresa/clientes/latam/Site-Amostras % ./start-siteamostras.py
Traceback (most recent call last):
File "./start-siteamostras.py", line 26, in ?
from siteamostras.controllers import Root
File
"/home/godoy/empresa/clientes/latam/Site-Amostras/siteamostras/controllers/__init__.py",
line 18, in ?
from siteamostras.controllers.toxicologia import Toxicologia
File
"/home/godoy/empresa/clientes/latam/Site-Amostras/siteamostras/controllers/toxicologia.py",
line 24, in ?
from siteamostras.controllers import analises
File
"/home/godoy/empresa/clientes/latam/Site-Amostras/siteamostras/controllers/analises.py",
line 24, in ?
from siteamostras.decorador import mensagem_json
File
"/home/godoy/empresa/clientes/latam/Site-Amostras/siteamostras/decorador.py",
line 18, in ?
@decorator()
TypeError: simple_decorator() takes at least 1 argument (0 given)
godoy@jupiter ~/empresa/clientes/latam/Site-Amostras % ./start-siteamostras.py
Traceback (most recent call last):
File "./start-siteamostras.py", line 26, in ?
from siteamostras.controllers import Root
File
"/home/godoy/empresa/clientes/latam/Site-Amostras/siteamostras/controllers/__init__.py",
line 18, in ?
from siteamostras.controllers.toxicologia import Toxicologia
File
"/home/godoy/empresa/clientes/latam/Site-Amostras/siteamostras/controllers/toxicologia.py",
line 24, in ?
from siteamostras.controllers import analises
File
"/home/godoy/empresa/clientes/latam/Site-Amostras/siteamostras/controllers/analises.py",
line 29, in ?
class Analises(controllers.Controller):
File
"/home/godoy/empresa/clientes/latam/Site-Amostras/siteamostras/controllers/analises.py",
line 213, in Analises
@turbogears.expose()
TypeError: entangle() takes exactly 1 argument (0 given)
godoy@jupiter ~/empresa/clientes/latam/Site-Amostras %
> I would however very much appreciate if you could also try to make the
> new weak_signature_decorator() work with your code, just to make sure
> before I apply these changes to a5. Thanks!
I'm trying that for hours :-)
May I send you my decorator off list so that you take a look and see what I'm
doing wrong? :-)
--
Jorge Godoy <jgo...@gmail.com>
Please do.
Cheers,
Simon
Done. Thanks! :-)
--
Jorge Godoy <jgo...@gmail.com>
Commited into 1.0 branch as 1290.
Cheers,
Simon
And works with "legacy" decorators ;-) One just has to
from turbogears.decorator import simple_decorator as decorator
and he can keep using the old syntax.
Simon did a great job with this compatibility layer! Really good!
--
Jorge Godoy <jgo...@gmail.com>
Just to clarify, simple_decorator and family are not intended solely for
backward compatibility, my main motivation was reducing boilerplate and
not have the user adjust to the framework but vice versa.
Cheers,
Simon