python / cpython

The Python programming language
https://www.python.org
Other
63.51k stars 30.42k forks source link

functools.partial objects should set __signature__ and _annotations__ #91002

Open larryhastings opened 2 years ago

larryhastings commented 2 years ago
BPO 46846
Nosy @rhettinger, @larryhastings, @merwok, @AlexWaygood

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields: ```python assignee = None closed_at = None created_at = labels = ['type-feature', 'library', '3.11'] title = 'functools.partial objects should set __signature__ and _annotations__' updated_at = user = 'https://github.com/larryhastings' ``` bugs.python.org fields: ```python activity = actor = 'grahamd' assignee = 'none' closed = False closed_date = None closer = None components = ['Library (Lib)'] creation = creator = 'larry' dependencies = [] files = [] hgrepos = [] issue_num = 46846 keywords = [] message_count = 1.0 messages = ['413897'] nosy_count = 5.0 nosy_names = ['rhettinger', 'larry', 'eric.araujo', 'grahamd', 'AlexWaygood'] pr_nums = [] priority = 'normal' resolution = None stage = 'test needed' status = 'open' superseder = None type = 'enhancement' url = 'https://bugs.python.org/issue46846' versions = ['Python 3.11'] ```

larryhastings commented 2 years ago

I ran across an interesting bug in issue bpo-46761. If you call functools.update_wrapper on a functools.partial object, inspect.signature will return the wrong (original) signature for the partial object.

We're still figuring that one out. And, of course, it's telling that the bug has been there for a long time. I suspect this isn't something that has inconvenienced a lot of people.

But: I suggest that it's time functools.partial participated in signature stuff. Specifically, I think functools.partial should generate a new and correct __signature for the partial object. And I propose it should also generate a new and correct __annotations for the partial, by removing all entries for parameters that are filled in by the partial object.

Right now inspect.signature has special support for functools.partial objects. It finds the underlying function, and . Which means there's code in both modules that has to understand the internals of partial objects. Just from a code hygiene perspective, it'd be better if all that logic lived under functools.

I wonder if functools.partial objects should generally do a better job of impersonating the original function. Should they adopt the same __name? __file? __qualname__? My intuition is, it'd be nice if it did. But I might be forgetting something important.

(I suspect everything I said about functools.partial also applies to functools.partialmethod.)

pekkaklarck commented 2 years ago

I just noticed that inspect.isroutine returns false for partial functions and methods. That's rather strange considering that inspect.isroutine docs say this:

Return true if the object is a user-defined or built-in function or method.

While looking for possible existing issues, this one was the first related one I found and I do agree "partial objects should generally do a better job of impersonating the original function". I also found #74315 that proposes exactly this as well as related #90878. With all these issues around, I decided not to submit a new one.

bharel commented 2 years ago

An example use is for libraries that process annotated arguments to provide a certain functionality. These include FastAPI (using function annotations for processing requests), Discord.py and others. Dependency injection using those libraries is almost impossible under current conditions.

stevendaprano commented 2 years ago

I wonder if functools.partial objects should generally do a better job of impersonating the original function. Should they adopt the same __name__? __file__? __qualname__? My intuition is, it'd be nice if it did. But I might be forgetting something important.

Please add those dunders. See the discussion on Python-Ideas.

casperdcl commented 1 year ago

Just ran into this as well when trying to implement https://github.com/tqdm/tqdm/pull/1491.

See also: #79644, #74315, #56363

ostrowr commented 7 months ago

At least one decent sized library (dd-trace-py) assumed that __name__ would always exist, (fix here) which caused a crash when trying to trace a functools.partial. I'd expect that people are making this assumption in lots of other places as well.