Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use __signature__ and set __wrapped__ attribute even on signature-changing decorators. #86

Merged
merged 12 commits into from
Sep 7, 2022

Conversation

lucaswiman
Copy link
Contributor

Fixes #85 by using the __signature__ attribute specified by PEP 362 where appropriate, and setting the __wrapped__ attribute in all cases.

I think the fix for #66 introduced an issue with using forwardrefs in type annotations. Since typing uses __wrapped__ to dereference forward references, it's can lead to inconsistent behavior (https://github.com/python/cpython/blob/605e9c66ad367b54a847f9fc65447a071742f554/Lib/typing.py#L2314-L2315), not setting it seems inappropriate.
Always setting __wrapped__ and setting __signature__ when the signature changes seems to fix all the issues with typing and docs/etc.

Testing

I added a failing test for #85, asserting that typing.get_type_hints works correctly with signature-changing decorator on a method with a forward reference in its type annotations. It passes after my fix.

I am not sure the fix for smarie#66 was correct given that __wrapped__ is used by the
typing module in get_type_hints, and setting __signature__ seems to fix all other tests.
@smarie
Copy link
Owner

smarie commented Jun 25, 2022

Very nice proposal @lucaswiman !

It seems that your test code is not compliant with python 2, 3.5, and 3.6, mostly because you use dataclasses and type hints in the dataclass. I guess this is optional, since forward refs and type hints exist since 3.5

If you believe that this is not worth trying to pass on python 3.6 or 3.5, please move your test module contents in a new file named _test_py37. Otherwise if you can get rid of dataclasses and attribute-annotations (and replace the test class with a standard class with annotations in the init method), then you can move it to _test_py35.py. Once you've done this, please add an appropriate pytest skip mark on your test, and import the module inside the test - similar to

@pytest.mark.skipif(sys.version_info < (3, 5), reason="requires python 3.5 or higher (non-comment type hints)")
def test_type_hint_error():
""" Test for https://github.com/smarie/python-makefun/issues/32 """
from tests._test_py35 import make_ref_function
ref_f = make_ref_function()
@wraps(ref_f)
def foo(a):
return a
assert foo(10) == 10

This should make the build pass.

src/makefun/main.py Outdated Show resolved Hide resolved
tests/issue_85_module.py Outdated Show resolved Hide resolved
tests/test_issues.py Outdated Show resolved Hide resolved
src/makefun/main.py Outdated Show resolved Hide resolved
lucaswiman and others added 5 commits June 25, 2022 10:57
Co-authored-by: Sylvain Marié <sylvain.marie@schneider-electric.com>
Co-authored-by: Sylvain Marié <sylvain.marie@schneider-electric.com>
Co-authored-by: Sylvain Marié <sylvain.marie@schneider-electric.com>
1. Always setting __wrapped__ means we needed a slightly different assertion.
2. Support python <3.7 in the test suite.
@lucaswiman
Copy link
Contributor Author

This should be ready for another test suite run and final review. Thanks for the very speedy review!

@lucaswiman
Copy link
Contributor Author

Whoops, I missed the instructions in the README about how to actually run the full test suite. I'm working on fixing the test collection bug in 2.7.

@lucaswiman
Copy link
Contributor Author

Note: the test doesn't work on python <3.7.6, because the __wrapped__ dereferencing in get_type_hints was not added until then. See https://github.com/python/cpython/blob/v3.7.6/Lib/typing.py#L986-L987.

1. Rename issue_85_module so that it is not collected by pytest.
2. Use the signature polyfill rather than inspect.signature.
@lucaswiman
Copy link
Contributor Author

OK, should be passing on all supported versions of python. Thank you for your patience.

nox > Ran multiple sessions:
nox > * tests-3.9: success
nox > * tests-3.8: success
nox > * tests-2.7: success
nox > * tests-3.5: success
nox > * tests-3.6: success
nox > * tests-3.7: success
nox > * flake8: success

I noticed that 3.10 is now available on conda. The tests pass on 3.10 as well. You may want to add 3.10 to the build.

@smarie smarie mentioned this pull request Jun 29, 2022
src/makefun/main.py Outdated Show resolved Hide resolved
@smarie
Copy link
Owner

smarie commented Jun 29, 2022

Thanks @lucaswiman !

Sorry to be picky, but I just realized one important thing (see comment in code). Also could you please include in the PR an update to the doc/api_reference.md with the same docstring mod than the ones you did in the code ? Indeed this is not an automated operation at the moment. If I'm not mistaken you just modified the docstring from wraps, but you should probably also modify the docstring from create_function.

Thanks again, almost there :)

@lucaswiman
Copy link
Contributor Author

@smarie I believe I addressed your review comments. Please let me know if those changes were insufficient or if you need any other updates. Thanks very much!

Copy link
Owner

@smarie smarie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @lucaswiman for this nice PR! Sorry for the wait

@smarie smarie merged commit 9050569 into smarie:main Sep 7, 2022
@lucaswiman lucaswiman deleted the gh85-use-__signature__ branch September 7, 2022 19:30
@lucaswiman
Copy link
Contributor Author

No worries. Thanks very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Forward references in annotations with a signature changing decorator
2 participants