[issue41231] Type annotations lost when using wraps by default

2020-07-10 Thread Terry J. Reedy


Terry J. Reedy  added the comment:

Only 3.8+ for bug fixes.

--
nosy: +terry.reedy
versions:  -Python 3.5, Python 3.6, Python 3.7

___
Python tracker 

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



[issue41231] Type annotations lost when using wraps by default

2020-07-08 Thread David Caro


David Caro  added the comment:

Elaborating on the last message, given the following code:
```
  1 #!/usr/bin/env python3
  2 
  3 from functools import wraps
  4 
  5 
  6 def return_string(wrapped):
  7 @wraps(wrapped)
  8 def wrapper(an_int: int) -> str:
  9 return str(wrapped(an_int))
 10 
 11 return wrapper
 12 
 13 
 14 @return_string
 15 def identity(an_int: int) -> int:
 16 return an_int
 17 
 18 def print_bool(a_bool: bool) -> None:
 19 print(a_bool)
 20 
 21 def identity_nonwrapped(an_int: int) -> int:
 22 return an_int
 23 
 24 
 25 print_bool(a_bool=identity(7))
 26 print_bool(a_bool=identity_nonwrapped(7))
```

mypy will complain only on the last line, being unable to check properly the 
line 25.

I'll investigate a bit more on why mypy skips that.

--

___
Python tracker 

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



[issue41231] Type annotations lost when using wraps by default

2020-07-08 Thread David Caro


David Caro  added the comment:

As a note, mypy does not tpyecheck the wrapper functions, probably because it 
would not be possible with the current code (as the typing hints get lost):

https://mypy.readthedocs.io/en/latest/generics.html?highlight=wrapper#declaring-decorators

--

___
Python tracker 

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



[issue41231] Type annotations lost when using wraps by default

2020-07-08 Thread David Caro


Change by David Caro :


--
keywords: +patch
pull_requests: +20538
stage:  -> patch review
pull_request: https://github.com/python/cpython/pull/21392

___
Python tracker 

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



[issue41231] Type annotations lost when using wraps by default

2020-07-07 Thread David Caro


David Caro  added the comment:

Hi Terry,

That would not work in this case, as I'd want to override all annotations with 
the wrapper function ones if there's any, instead of merging them.

The specific use case, is a type checker (part of TestSlide testing framework), 
to verify that if there's any type annotations, the parameters mocked and 
passed to it are the expected types.

For example, the contextmanager decorator returns an actual ContextManager, 
wrapping whatever the wrapped function returned, so if the wrapped function 
annotations prevail, then there's no way if verifying that the returned type is 
correct.

Thanks for the ChainMap pointer though, I'll use it for sure somewhere else.

--

___
Python tracker 

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



[issue41231] Type annotations lost when using wraps by default

2020-07-07 Thread Terry Davis


Terry Davis  added the comment:

I don't understand this use-case, but would it make sense to `ChainMap` the 
wrapper's __annotations__ on top of the wrapped __annotations__?

--
nosy: +Terry Davis

___
Python tracker 

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



[issue41231] Type annotations lost when using wraps by default

2020-07-07 Thread David Caro


New submission from David Caro :

In version 3.2, bpo-8814 introduced copying the __annotations__ property from 
the wrapped function to the wrapper by default.

That would be the desired behavior when your wrapper function has the same 
signature than the function it wraps, but in some cases (for example, with the 
contextlib.asynccontextmanager function) the return value is different, and 
then the __annotations__ property will have invalid information:

In [2]: from contextlib import asynccontextmanager  
  

In [3]: @asynccontextmanager 
   ...: async def mytest() -> int: 
   ...: return 1 
   ...: 
  

In [4]: mytest.__annotations__  
  
Out[4]: {'return': int}


I propose changing the behavior of wraps, to only assign the __annotations__ by 
default if there's no __annotations__ already in the wrapper function, that 
would fit most default cases, but would allow to preserve the __annotations__ 
of the wrapper function when the types are explicitly specified, allowing now 
to change the contextlib.asynccontextmanager function with the proper types 
(returning now an AsyncContextManager) and keep the __annotation__ valid.

I'll try to get a POC and attach to the issue, but please comment with your 
ideas too.

--
components: Library (Lib)
messages: 373233
nosy: David Caro
priority: normal
severity: normal
status: open
title: Type annotations lost when using wraps by default
type: behavior
versions: Python 3.10, Python 3.5, Python 3.6, Python 3.7, Python 3.8, Python 
3.9

___
Python tracker 

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