[issue46761] functools.update_wrapper breaks the signature of functools.partial objects
Ofey Chan added the comment: Hello, I am new to cpython project and want to help. I dig into `follow_wrapper_chains` feature and found it really interesting. In `inspect.signature()`, the conversion of `functools.partial` object's signature is made when going down the unwrap chain. Relevant code: https://github.com/python/cpython/blob/288af845a32fd2a92e3b49738faf8f2de6a7bf7c/Lib/inspect.py#L2467 So, there is an inconsistent assumption which cause the problem: - `inspect.signature()` handle `functools.partial` object it met specially. - `functools.update_wrapper()` just treat `functools.partial` object as a normal decorator and ignore it. After calling `functools.update_wrapper()`, a new (wrong) signature is constructed, and it covers the original (right) process. That's why `inspect.signature()` returns the *original* function's signature, not the *wrapped* function's signature. In my humble opinion, A sane solution might be that: let the `functools.update_wrapper` respect the `functools.partial` object in the similar way of `inspect.signature()`. I'm working on a pull request to express my idea more clearly, any help is welcome! -- nosy: +ofey404 ___ Python tracker <https://bugs.python.org/issue46761> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46761] functools.update_wrapper breaks the signature of functools.partial objects
Change by Ofey Chan : -- keywords: +patch pull_requests: +29653 stage: test needed -> patch review pull_request: https://github.com/python/cpython/pull/31529 ___ Python tracker <https://bugs.python.org/issue46761> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46761] functools.update_wrapper breaks the signature of functools.partial objects
Ofey Chan added the comment: I fix the problem. But sorry for my last message, because it totally miss the point ;) In `inspect.signature()`, the order of handle `follow_wrapper_chains` and `functools.partial` cause the problem. Relevant code: https://github.com/python/cpython/blob/288af845a32fd2a92e3b49738faf8f2de6a7bf7c/Lib/inspect.py#L2408 The original order is: 1. `follow_wrapper_chains` unwrap decorators. - It would check `__wrapped__` attribute in `unwrap()`. - `functools.update_wrapper()` would set `__wrapped__`. 2. Then handle `functools.partial`, construct new signature with `_signature_get_partial()` So the original `functools.partial` object would skip (1), goto (2) and would be correctly processed. But after calling `functools.update_wrapper()`, the `functools.partial` object has a `__wrapped__` attribute, so it directly handled by (1) and will never reach (2). That's why `inspect.signature()` return the original function's signature. `update_wrapper.breaks.partial.signature.check.__wrapped__.py` shows the `__wrapped__` attribute. My solution is simple: swap the order of (1) and (2). `functools.partial` is a special type of wrapper, handle it before going down the wrapper chain is sane. And I have written test case to ensure it's correct, hope it works. -- ___ Python tracker <https://bugs.python.org/issue46761> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46761] functools.update_wrapper breaks the signature of functools.partial objects
Change by Ofey Chan : Added file: https://bugs.python.org/file50639/update_wrapper.breaks.partial.signature.check.__wrapped__.py ___ Python tracker <https://bugs.python.org/issue46761> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46761] functools.update_wrapper breaks the signature of functools.partial objects
Ofey Chan added the comment: Thank you Larry. It can never be too careful to deal with language issues! > why the code behaves like this--is this behavior a genuine bug, or is it > actually a bugfix for some worse behavior? In my view, there's rather an concept needing clarify, than a genuine bug. I look into the file blame, and it shows the processing order around `follow_wrapper_chains` might be carefully arranged... - The `follow_wrapper_chains` functionality is added in issue 13266: https://bugs.python.org/issue13266 - When `signature()` first implemented, `__wrapped__` is handled then `partial`, this order never changed. - Issue #15008: Implement PEP 362 "Signature Objects": https://github.com/python/cpython/commit/7c7cbfc00fc8d655fc267ff57f8084357858b1db > will fixing the bug cause problems for Python users? and if so, can we still > fix the bug while mitigating the damage to people who are unfortunately > depending on the bug? It's really a heavy responsibility! Slow down is right... A clear explaination and plan should be constructed before any action is taken. So I may study PEP 362 to get some context, about why the code is this way. And I'm wondering what else can I do? -- ___ Python tracker <https://bugs.python.org/issue46761> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46761] functools.update_wrapper breaks the signature of functools.partial objects
Ofey Chan added the comment: > Maybe we can loop in someone who works on a popular runtime function > introspection library (FastAPI, Pydantic) to see if they have any take on it. I've checked issues of FastAPI and Pydantic. There is only one issue about `update_wrapper()`, and it's about documentation generation: https://github.com/samuelcolvin/pydantic/issues/1032 Would it be proper to open an issue under FastAPI and Pydantic, to describe the situation, and collect their feedbacks? -- ___ Python tracker <https://bugs.python.org/issue46761> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue46761] functools.update_wrapper breaks the signature of functools.partial objects
Ofey Chan added the comment: I updated NEWS and all checks have passed! -- ___ Python tracker <https://bugs.python.org/issue46761> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com