Turning a signature-changing decorator into a signature-preservingone

G

Gustavo Narea

Hello, everybody.

I have this signature-changing decorator
<http://paste.chrisarndt.de/paste/15aac02a90094a41a13a1b9b85a14dd6>
which I
want to turn into a signature-preserving one. Here's my try
<http://paste.chrisarndt.de/paste/d0f835c00f824437bf4a0898f8020fc8>,
but I get
this error:
http://paste.chrisarndt.de/paste/33e06be6e6d74e49b05c45534dfcc9fe?wrap=no

What am I doing wrong? I think it looks like this example:
http://pypi.python.org/pypi/decorator#async

Thanks in advance.

- Gustavo.

PS: functols.wrap is not an option because my code has to work with
Python 2.4+.
 
M

Michele Simionato

Hello, everybody.

I have this signature-changing decorator
<http://paste.chrisarndt.de/paste/15aac02a90094a41a13a1b9b85a14dd6>
which I
want to turn into a signature-preserving one. Here's my try
<http://paste.chrisarndt.de/paste/d0f835c00f824437bf4a0898f8020fc8>,
but I get
this error:http://paste.chrisarndt.de/paste/33e06be6e6d74e49b05c45534dfcc9fe?wra...

What am I doing wrong? I think it looks like this example:http://pypi.python.org/pypi/decorator#async

Thanks in advance.

  - Gustavo.

PS: functols.wrap is not an option because my code has to work with
Python 2.4+.

Difficult to see what is happening, since you have so many
dependencies. However, from the traceback I would say that
you are passing to the decorator a function with a __name__
attribute which is None. I would insert a call to pdb here

def __call__(self, func):
import pdb; pdb.set_trace()
return decorator(self.call, func)

and I would inspect func.__name__.

HTH,

M.Simionato
 
G

Gustavo Narea

Difficult to see what is happening, since you have so many
dependencies. However, from the traceback I would say that
you are passing to the decorator a function with a __name__
attribute which is None. I would insert a call to pdb here

def __call__(self, func):
import pdb; pdb.set_trace()
return decorator(self.call, func)

and I would inspect func.__name__.

HTH,

M.Simionato

Thanks for your response, Michele.

This is what I get:
"""
(Pdb) func.__name__
'greetings'
(Pdb) func.__dict__
{}
(Pdb) func.__module__
'pylonsproject.controllers.root'
"""

Which seems correct to me.

By the way, I forgot to mention that what is decorated is an instance
method. I don't know if that would change something.

Thanks in advance.

- Gustavo.
 
M

Michele Simionato

This is what I get:
"""
(Pdb) func.__name__
'greetings'
(Pdb) func.__dict__
{}
(Pdb) func.__module__
'pylonsproject.controllers.root'
"""

Which seems correct to me.

By the way, I forgot to mention that what is decorated is an instance
method. I don't know if that would change something.

This is bad, func should be a function and not an instance
method (see line 49 of decorator.py). If the .signature
attribute of the FunctionMaker is missing, than that's the
reason for the AssertionError you see.
I should probably raise a clearer error message.
I lack the context to see how this could be fixed in your case, but
this a not a show stopper, you can just keep the original decorator
and forget about making it signature preserving.
 
M

Michele Simionato

I should probably raise a clearer error message.

Ok, I have uploaded version 3.0.1 of the decorator module,
which raises a more meaningful message in case you try to
decorate a method incorrectly. I have also added a
discussion of that case in the "caveats" session.
HTH,

M. Simionato
 
G

Gustavo Narea

I lack the context to see how this could be fixed in your case, but
this a not a show stopper, you can just keep the original decorator
and forget about making itsignature preserving.

I'm sorry for the possibly dumb question, but how can I do that?

Thanks for all the time you've spent on this, Michele.

- Gustavo.
 
M

Michele Simionato

I'm sorry for the possibly dumb question, but how can I do that?

Thanks for all the time you've spent on this, Michele.

  - Gustavo.

Let the original code as it is. If ain't broken, don't fix it.
 
G

Gustavo Narea

Let the original code as it is. If ain't broken, don't fix it.

But the problem is that it is broken.

That decorator is for controller actions in Pylons-powered web
applications (which are instance methods). Pylons inspects the
action's signature to find what parameters it's going to pass to its
instance method, which fails because my current decorator changes the
signature.
 
M

Michele Simionato

But the problem is that it is broken.

That decorator is for controller actions in Pylons-powered web
applications (which are instance methods). Pylons inspects the
action's signature to find what parameters it's going to pass to its
instance method, which fails because my current decorator changes the
signature.

Yes, I am saying don't mess with the internal mechanism of Pylons and
leave it as
it was. Or was it broken from the beginning? The only reason I see for
you
to touch those things is if you are a Pylons core developer.
 
G

Gustavo Narea

Yes, I am saying don't mess with the internal mechanism of Pylons and
leave it as
it was. Or was it broken from the beginning? The only reason I see for
you
to touch those things is if you are a Pylons core developer.

It was broken from the beginning on Pylons.

I'm a TurboGears 2 core developer, and TurboGears is powered by Pylons
as of version 2. The decorator has always worked in TurboGears because
of the way TG finds the action arguments, but now I'm working to make
it work in Pylons too, but this is the only problem that has stopped
me from making it work under Pylons.

Thanks.
 
M

Michele Simionato

It was broken from the beginning on Pylons.

I'm a TurboGears 2 core developer, and TurboGears is powered by Pylons
as of version 2. The decorator has always worked in TurboGears because
of the way TG finds the action arguments, but now I'm working to make
it work in Pylons too, but this is the only problem that has stopped
me from making it work under Pylons.

Thanks.

I see. I would ask on the Pylons list. I suspect a bound method is
passed and that you will
need to extract the corresponding function with .im_func, then making
sure that you pass
the self argument correctly. But this is wild guess since I have no
idea of how Pylons decorators
work internally as compared to TurboGears decorators.
 
G

Gustavo Narea

I see. I would ask on the Pylons list. I suspect a bound method is
passed and that you will
need to extract the corresponding function with .im_func, then making
sure that you pass
the self argument correctly. But this is wild guess since I have no
idea of how Pylons decorators
work internally as compared to TurboGears decorators.

I've not seen anything special in Pylons or TurboGears 2 decorators,
except that they are all functions that use the decorator package --
while my decorator is a class that doesn't use the decorator package
yet.

My attempt to turn that decorator into a signature preserving one
using the decorator packages fails even on TurboGears 2. As of
decorator 3.0.1, I get this error:
TypeError: You are decorating a non function: <unbound method
SecurePanel.__before__>

Isn't this caused by the fact that my decorator is a class, or the way
such a class is defined (whose code is in the first post of the
thread)? I can turn it into a function because I'm sure I'll work --
although I wanted a class to make it easier to customize.

Thanks.
 
G

Gustavo Narea

I've not seen anything special in Pylons or TurboGears 2 decorators,
except that they are all functions that use the decorator package --
while my decorator is a class that doesn't use the decorator package
yet.

My attempt to turn that decorator into a signature preserving one
using the decorator packages fails even on TurboGears 2. As of
decorator 3.0.1, I get this error:
TypeError: You are decorating a non function: <unbound method
SecurePanel.__before__>

Isn't this caused by the fact that my decorator is a class, or the way
such a class is defined (whose code is in the first post of the
thread)? I can turn it into a function because I'm sure I'll work --
although I wanted a class to make it easier to customize.

Thanks.


This is another attempt, where the decorator is a still a class but
uses an auxiliary function:
http://paste.chrisarndt.de/paste/38bf8a8443614464968d424e1f2d4182

However, that raises this exception:
http://paste.chrisarndt.de/paste/f90bc9a058254e2ca5660882011752a7?wrap=no
 
M

Michele Simionato

I've not seen anything special in Pylons or TurboGears 2 decorators,
except that they are all functions that use the decorator package --
while my decorator is a class that doesn't use the decorator package
yet.

My attempt to turn that decorator into a signature preserving one
using the decorator packages fails even on TurboGears 2. As of
decorator 3.0.1, I get this error:
    TypeError: You are decorating a non function: <unbound method
SecurePanel.__before__>

Isn't this caused by the fact that my decorator is a class, or the way
such a class is defined (whose code is in the first post of the
thread)? I can turn it into a function because I'm sure I'll work --
although I wanted a class to make it easier to customize.

Thanks.

The decorator class is fine, the error in clearly in what you pass to
the decorator.
You are trying to decorate an unbound method SecurePanel.__before__:
are you
sure this is really what you want to decorate? Are you decorating
automatically all methods
of SecurePanel? I have already mentioned it, but you can extract the
underlying function
from the method by using SecurePanel.__before__.im_func if you really
want.
 
G

Gustavo Narea

The decorator class is fine, the error in clearly in what you pass to
the decorator.
You are trying to decorate an unbound method SecurePanel.__before__:
are you
sure this is really what you want to decorate? Are you decorating
automatically all methods
of SecurePanel? I have already mentioned it, but you can extract the
underlying function
from the method by using SecurePanel.__before__.im_func if you really
want.

Thank you very much, it works with SecurePanel.__before__.im_func!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top