[issue23764] functools.wraps should be able to change function argspec as well

2015-03-25 Thread Nick Coghlan

Nick Coghlan added the comment:

Correctly processing a function's signature involves following the __wrapped__ 
chains to get to the underlying callable (or to a callable that defines an 
explicitly modified __signature__ value).

inspect.signature follows these chains automatically, and in 3.4+ 
inspect.getargspec and inspect.getfullargspec have been updated to use 
inspect.signature internally.

Using these functions will also allow introspection of builtin and extension 
module functions that have been processed through Argument Clinic to produce 
appropriate signature information in their docstrings.

If an IDE or other tool is still producing incorrect signature information for 
functions wrapped with functools.wraps in 3.4+ then that's either a bug in the 
affected tool, or else a bug report against the inspect module.

--
resolution:  - not a bug
stage:  - resolved
status: open - closed

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23764
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue23764] functools.wraps should be able to change function argspec as well

2015-03-25 Thread R. David Murray

R. David Murray added the comment:

I think you need to explain exactly what it is you are looking for, because it 
doesn't seem to me that you can change the argspec of a function.  What is it 
that decorator is doing that is helpful?

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23764
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue23764] functools.wraps should be able to change function argspec as well

2015-03-25 Thread Nick Coghlan

Nick Coghlan added the comment:

Backport proposal: https://github.com/aliles/funcsigs/issues/12

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23764
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue23764] functools.wraps should be able to change function argspec as well

2015-03-25 Thread Nick Coghlan

Nick Coghlan added the comment:

Regarding the PyPI decorator module, the difference there is between using a 
def f(*args, **kwargs) wrapper (which requires following wrapper chains to 
read the signature correctly) and using functools.partial (which reports the 
correct surface signature directly).

You can define your own wrapper decorators like this to reproduce that 
behaviour with standard library components:

  def wrapper(func):
return functools.wraps(func)(functools.partial(func))

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23764
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue23764] functools.wraps should be able to change function argspec as well

2015-03-25 Thread productivememberofsociety666

productivememberofsociety666 added the comment:

def wrapper(func):
return functools.wraps(func)(functools.partial(func))

^ doesn't that just return something that is completely equivalent to func 
itself? Where do I put the actual wrapper functionality, i.e. code that is 
executed with each call to the new (wrapped) function?

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23764
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue23764] functools.wraps should be able to change function argspec as well

2015-03-25 Thread Nick Coghlan

Nick Coghlan added the comment:

Full example showing the functools.partial based implementation:

 def wrapper(func):
... return functools.wraps(func)(functools.partial(func))
... 
 def to_be_wrapped(x):
... pass
... 
 import inspect
 inspect.getargspec(wrapper(to_be_wrapped))
ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)

Th usage of functools.partial is also what gives the PyPI decorator module 
eager validation of the argument structure, even if the original function is 
never actually called.

When you use the pass-through *args, **kwds signature on a wrapper function 
it really is just a pass-through - even setting __signature__ won't get the 
*interpreter* to change the way it processes the arguments, as that's baked 
directly into the compiled code object:

 def f(*args, **kwds):
... pass
... 
 import dis
 dis.show_code(f)
Name:  f
Filename:  stdin
Argument count:0
Kw-only arguments: 0
Number of locals:  2
Stack size:1
Flags: OPTIMIZED, NEWLOCALS, VARARGS, VARKEYWORDS, NOFREE
Constants:
   0: None
Variable names:
   0: args
   1: kwds

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23764
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue23764] functools.wraps should be able to change function argspec as well

2015-03-25 Thread productivememberofsociety666

productivememberofsociety666 added the comment:

You're probably right and it's next to impossible to implement what I want in a 
clean manner. I'll get back to that at the end, but first for completeness's 
sake two examples to illustrate what this issue is even about.



import functools

def wrapper(func):
  @functools.wraps(func)
  def new_func(*args, **kwargs):
pass
  return new_func

def to_be_wrapped(a):
  pass

wrapped = wrapper(to_be_wrapped)

wrapped(1) # Ok
wrapped(1, 2, 3) # Also ok, but shouldn't be! Should raise TypeError


The second call to wrapped() should fail because it's supposed to be a wrapper 
around to_be_wrapped(), which only takes 1 argument. But it succeeds because 
functools.wraps only changes superficial function attributes such as its 
signature or docstring. This creates a mismatch between expected and actual 
behaviour of wrapped().

Contrast this with how it works when using the decorator package I mentioned:


import decorator

def to_be_wrapped(x):
  print(f(x) called)
  pass

def _wrapper(func, *args, **kwargs):
  # Put actual functionality of your decorator here
  pass

def wrapper(func):
  return decorator.decorator(_wrapper, func)

wrapped = wrapper(to_be_wrapped)

wrapped(1) # Ok, because to_be_wrapped takes exactly 1 argument
wrapped(1, 2, 3) # raises TypeError for too many arguments, as it should


Like I said, the details of how it is used are different from those of 
functools.wraps. But the important thing is that, at the end, wrapped()'s 
argspec matches that of to_be_wrapped() and an appropriate error is raised by 
the second call.
Note that this does NOT work via propagation from a call to to_be_wrapped() or 
anything of the sort, as can be verified by the lack of output to stdout.


Now, the only problem is: I had a look at how this is achieved in the decorator 
package's source code and if I understand it correctly, they are doing some 
nasty nasty things with exec() to create a function with an argspec of their 
choosing at runtime. If this is in fact the only way to do it, I agree that it 
has no place in the standard library and should only be available via 3rd party 
libraries. Sorry for wasting your time then.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23764
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue23764] functools.wraps should be able to change function argspec as well

2015-03-25 Thread Nick Coghlan

Nick Coghlan added the comment:

I double checked the current behaviour, and rediscovered something I had 
forgotten: when inspect.getargspec and inspect.getfullargspec were converted to 
be based on the inspect.signature machinery, we had to decide whether or not to 
follow wrapper chains to report the underlying signature or not.

We opted to continue reporting the surface signature for compatibility with 
the behaviour of these APIs in previous versions of Python (including 
introspection tools that handle wrapper chains themselves), while encouraging 
introspection tools to migrate to using the more capable inspect.signature API 
instead: https://docs.python.org/3/library/inspect.html#inspect.getfullargspec

If a particular introspection tool reports incorrect signatures in 3.4+, then 
that's an issue with that particular tool needing to be made wrapper chain 
aware.

I'll also ping Aaron Iles about potentially bringing 
https://funcsigs.readthedocs.org/ up to date with the features in the Python 
3.4 version of the library, including the helper to traverse wrapper chains 
correctly: https://docs.python.org/3/library/inspect.html#inspect.unwrap

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23764
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue23764] functools.wraps should be able to change function argspec as well

2015-03-24 Thread productivememberofsociety666

productivememberofsociety666 added the comment:

I'm not sure if I understand issue 15731 correctly, but isn't that one just 
about docstrings and signatures? These are both purely cosmetic and don't 
have an effect on calling behaviour, do they?
This issue wouldn't be a duplicate then.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23764
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue23764] functools.wraps should be able to change function argspec as well

2015-03-24 Thread SilentGhost

Changes by SilentGhost ghost@gmail.com:


--
nosy: +ncoghlan, rhettinger
versions:  -Python 3.2, Python 3.3, Python 3.4, Python 3.6

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23764
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue23764] functools.wraps should be able to change function argspec as well

2015-03-24 Thread R. David Murray

R. David Murray added the comment:

See also issue 15731 (this might be effectively a duplicate of that one, I'm 
not sure).  I believe the idea of incorporating decorator into the stdlib has 
been brought up in the past.

--
nosy: +r.david.murray

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23764
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue23764] functools.wraps should be able to change function argspec as well

2015-03-24 Thread productivememberofsociety666

New submission from productivememberofsociety666:

functools.wraps currently only changes the wrapped function's superficial 
attributes such as docstring or annotations.

But it would be useful to be able to change the function's actual argspec as 
well so it matches up with the changed annotations (e.g. to get proper error 
messages when the wrapped and wrapper functions' argspecs don't match up).

To avoid breaking existing code, this could be achieved by adding another 
argument change_argspec (defaulting to False) to functools.wraps. Of course, 
the way functools.wraps is implemented now as well as its current documentation 
would have to be thrown out of the window in order for this to work (at least 
for the case of change_argspec==True).


There is an existing 3rd party package ( https://pypi.python.org/pypi/decorator 
) which has a decorator called decorator that does kind of what I'd want 
functools.wraps to do, but the details of how it is called are different and 
either way it's embarassing that you have to fall back on a 3rd party library 
to get functionality that is present but incomplete in Python's standard 
library.

--
components: Library (Lib)
messages: 239165
nosy: productivememberofsociety666
priority: normal
severity: normal
status: open
title: functools.wraps should be able to change function argspec as well
type: enhancement
versions: Python 3.2, Python 3.3, Python 3.4, Python 3.5, Python 3.6

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue23764
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com