inspect feature

  • Thread starter Aaron \Castironpi\ Brady
  • Start date
A

Aaron \Castironpi\ Brady

Hello,

The 'inspect' module has this method:

inspect.getargvalues(frame)

It takes a frame and returns the parameters used to call it, including
the locals as defined in the frame, as shown.
.... import inspect
.... return inspect.getargvalues( inspect.currentframe() )
....(['a', 'b', 'd'], 'c', 'e', {'a': 0, 'c': ('def', (3, 2)), 'b': 1,
'e': {'h': 'g
hi'}, 'd': 'abc', 'inspect': <module 'inspect' from 'C:\Programs
\Python26\lib\in
spect.pyc'>})

However, if you wanted a decorator that examines the parameters to a
function, you're out of luck. By the time you have a frame, you're
already in the function.

Perhaps it would not be as common as something like 'join' for
example, or even the rest of the functions in 'inspect', but do you
think something similar to 'getargvalues' that accepted a function and
an argument list, and returned a dictionary mapping parameters to
values, could be useful?
 
B

Bruno Desthuilliers

Aaron "Castironpi" Brady a écrit :
Hello,

The 'inspect' module has this method:

inspect.getargvalues(frame)

It takes a frame and returns the parameters used to call it, including
the locals as defined in the frame, as shown.
... import inspect
... return inspect.getargvalues( inspect.currentframe() )
...(['a', 'b', 'd'], 'c', 'e', {'a': 0, 'c': ('def', (3, 2)), 'b': 1,
'e': {'h': 'g
hi'}, 'd': 'abc', 'inspect': <module 'inspect' from 'C:\Programs
\Python26\lib\in
spect.pyc'>})

However, if you wanted a decorator that examines the parameters to a
function, you're out of luck. By the time you have a frame, you're
already in the function.

Hem...

def decorator(func):
def _decorator(*args, *kw):
print "func args are ", *args, **kw
return func(*args, **kw)
return _decorator
 
A

Aaron \Castironpi\ Brady

Aaron "Castironpi" Brady a écrit :


The 'inspect' module has this method:
inspect.getargvalues(frame)

It takes a frame and returns the parameters used to call it, including
the locals as defined in the frame, as shown.
def f( a, b, d= None, *c, **e ):
...     import inspect
...     return inspect.getargvalues( inspect.currentframe() )
...
f( 0, 1, 'abc', 'def', ( 3, 2 ), h= 'ghi' )
(['a', 'b', 'd'], 'c', 'e', {'a': 0, 'c': ('def', (3, 2)), 'b': 1,
'e': {'h': 'g
hi'}, 'd': 'abc', 'inspect': <module 'inspect' from 'C:\Programs
\Python26\lib\in
spect.pyc'>})
However, if you wanted a decorator that examines the parameters to a
function, you're out of luck.  By the time you have a frame, you're
already in the function.

Hem...

def decorator(func):
     def _decorator(*args, *kw):
         print "func args are ", *args, **kw
         return func(*args, **kw)
     return _decorator

It is less of a problem without tuple unpacking, but you still have
code like:

if len( args )>= 2:
b= args[ 1 ]
else:
try:
b= (somehow check b's default val.)
except NoDefaultVal:
raise ArgumentError

Worse yet, you have it for each parameter. Unless I missed something,
this is the only way to mimic/recreate the signature of the decoratee.
 
B

Bruno Desthuilliers

Aaron "Castironpi" Brady a écrit :
Aaron "Castironpi" Brady a écrit :


Hello,
The 'inspect' module has this method:
inspect.getargvalues(frame)
It takes a frame and returns the parameters used to call it, including
the locals as defined in the frame, as shown.
def f( a, b, d= None, *c, **e ):
... import inspect
... return inspect.getargvalues( inspect.currentframe() )
...
f( 0, 1, 'abc', 'def', ( 3, 2 ), h= 'ghi' )
(['a', 'b', 'd'], 'c', 'e', {'a': 0, 'c': ('def', (3, 2)), 'b': 1,
'e': {'h': 'g
hi'}, 'd': 'abc', 'inspect': <module 'inspect' from 'C:\Programs
\Python26\lib\in
spect.pyc'>})
However, if you wanted a decorator that examines the parameters to a
function, you're out of luck. By the time you have a frame, you're
already in the function.
Hem...

def decorator(func):
def _decorator(*args, *kw):
print "func args are ", *args, **kw
return func(*args, **kw)
return _decorator

It is less of a problem without tuple unpacking, but you still have
code like:

if len( args )>= 2:
b= args[ 1 ]
else:
try:
b= (somehow check b's default val.)
except NoDefaultVal:
raise ArgumentError

Worse yet, you have it for each parameter. Unless I missed something,
this is the only way to mimic/recreate the signature of the decoratee.

I don't get what you're after ??? The decorator has full access to both
the actual params *and* the function's signature (via
inspect.getargspec). So your initial question "if you wanted a decorator
that examines the parameters to a function" seems fully answered. You
will indeed have to write a couple lines of code if you want the same
formating as the one you'd get with inspect.currentframe(), but what ?

FWIW, Michele Simionato's decorator module has some trick to allow for
signature-preserving decorators, so you may want to have a look - but
I'm not sure if this would solve your problem - at least in a sane way.
 
A

Aaron \Castironpi\ Brady

Aaron "Castironpi" Brady a écrit :


Aaron "Castironpi" Brady a écrit :
Hello,
The 'inspect' module has this method:
inspect.getargvalues(frame)
It takes a frame and returns the parameters used to call it, including
the locals as defined in the frame, as shown.
def f( a, b, d= None, *c, **e ):
...     import inspect
...     return inspect.getargvalues( inspect.currentframe() )
...
f( 0, 1, 'abc', 'def', ( 3, 2 ), h= 'ghi' )
(['a', 'b', 'd'], 'c', 'e', {'a': 0, 'c': ('def', (3, 2)), 'b': 1,
'e': {'h': 'g
hi'}, 'd': 'abc', 'inspect': <module 'inspect' from 'C:\Programs
\Python26\lib\in
spect.pyc'>})
However, if you wanted a decorator that examines the parameters to a
function, you're out of luck.  By the time you have a frame, you're
already in the function.
Hem...
def decorator(func):
     def _decorator(*args, *kw):
         print "func args are ", *args, **kw
         return func(*args, **kw)
     return _decorator
It is less of a problem without tuple unpacking, but you still have
code like:
if len( args )>= 2:
   b= args[ 1 ]
else:
   try:
      b= (somehow check b's default val.)
   except NoDefaultVal:
      raise ArgumentError
Worse yet, you have it for each parameter.  Unless I missed something,
this is the only way to mimic/recreate the signature of the decoratee.

I don't get what you're after ??? The decorator has full access to both
the actual params *and* the function's signature (via
inspect.getargspec). So your initial question "if you wanted a decorator
that examines the parameters to a function" seems fully answered. You
will indeed have to write a couple lines of code if you want the same
formating as the one you'd get with inspect.currentframe(), but what ?

FWIW, Michele Simionato's decorator module has some trick to allow for
signature-preserving decorators, so you may want to have a look - but
I'm not sure if this would solve your problem - at least in a sane way.

It's not exactly the next Millennium problem, but there are some
substantial checks you have to do on a per-parameter basis to see the
same thing that a function sees, when all you have is *args, **kwargs.

You are wrapping a function with this signature:

def f( a, b, c= None, *d, **e ):

You want to find out the values of 'a', 'b', and 'c' in a decorator.
You have these calls:

f( 0, 1, 'abc', 'def', h= 'ghi' )
f( 0, 1 )
f( 0, 1, h= 'abc' )
f( 0, 1, 'abc', c= 'def' ) #raise TypeError: multiple values

How do you determine 'a', 'b', and 'c'?
 
G

Gabriel Genellina

En Fri, 10 Oct 2008 14:18:53 -0300, Aaron "Castironpi" Brady
On Oct 10, 3:36 am, Bruno Desthuilliers <bruno.
(e-mail address removed)> wrote:

It's not exactly the next Millennium problem, but there are some
substantial checks you have to do on a per-parameter basis to see the
same thing that a function sees, when all you have is *args, **kwargs.

You are wrapping a function with this signature:

def f( a, b, c= None, *d, **e ):

You want to find out the values of 'a', 'b', and 'c' in a decorator.
You have these calls:

f( 0, 1, 'abc', 'def', h= 'ghi' )
f( 0, 1 )
f( 0, 1, h= 'abc' )
f( 0, 1, 'abc', c= 'def' ) #raise TypeError: multiple values

How do you determine 'a', 'b', and 'c'?

I'm afraid you'll have to duplicate the logic described here:
http://docs.python.org/reference/expressions.html#id9
To my knowledge, there is no available Python code (in the stdlib or
something) that already does that.
 
G

George Sakkis

En Fri, 10 Oct 2008 14:18:53 -0300, Aaron "Castironpi" Brady
<[email protected]> escribió:










I'm afraid you'll have to duplicate the logic described here: http://docs.python.org/reference/expressions.html#id9
To my knowledge, there is no available Python code (in the stdlib or
something) that already does that.

I wrote such a beast some time ago; it's hairy but to the best of my
knowledge it seems to reproduce the standard Python logic:
http://code.activestate.com/recipes/551779/

George
 
A

Aaron \Castironpi\ Brady

I wrote such a beast some time ago; it's hairy but to the best of my
knowledge it seems to reproduce the standard Python logic:http://code.activestate.com/recipes/551779/

George

I didn't see a 'got a duplicate argument for keyword "d"' error, but I
can add one if I need to.

Is there some reason why the built-in behavior should not be made
available, such as it's poorly defined outside the function? Or is it
just the fact that it's complicated that keeps it out of 'inspect'?
 
G

George Sakkis

I didn't see a 'got a duplicate argument for keyword "d"' error, but I
can add one if I need to.

Why don't you try it out:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "getcallargs.py", line 53, in getcallargs
"argument '%s'" % (f_name,arg))
TypeError: f() got multiple values for keyword argument 'c'

George
 
A

Aaron \Castironpi\ Brady

Why don't you try it out:


Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "getcallargs.py", line 53, in getcallargs
    "argument '%s'" % (f_name,arg))
TypeError: f() got multiple values for keyword argument 'c'

George

Excellent.

Here's some more info.

Ver 2.5:
Traceback (most recent call last):
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 64, in getcallargs
TypeError: f() takes at least 2 non-keyword arguments (0 given)

Just the wrong order to check errors in. Note the spacing '..keyword
arguments..'. Not a problem on 2.6:

Ver 2.6:
File "<stdin>", line 1
SyntaxError: keyword argument repeated

+1 standard library.
 
G

George Sakkis

Excellent.

Here's some more info.

Ver 2.5:


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() got multiple values for keyword argument 'c'>>> getcallargs( f, c= 0, c= 0 )

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 64, in getcallargs
TypeError: f() takes at least 2 non-keyword arguments (0 given)

Just the wrong order to check errors in.

The problem is getcallargs doesn't even see the double entry; if you
print (args, kwds) from within getcallargs you get ((), {'c': 0}). The
SyntaxError raised in 2.6 is more reasonable.

George
 
A

Aaron \Castironpi\ Brady

On Oct 14, 5:00 pm, "Aaron \"Castironpi\" Brady"









The problem is getcallargs doesn't even see the double entry; if you
print (args, kwds) from within getcallargs you get ((), {'c': 0}). The
SyntaxError raised in 2.6 is more reasonable.

George

There are some other bugs in inspect that put getcallargs on par with
the module as is, even without repairing it. And it covers a majority
of cases. Perhaps a lower-level C version could circumvent that, or
have access to the right information.
 

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

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top