cpython icon indicating copy to clipboard operation
cpython copied to clipboard

`functools.update_wrapper` does not work with `type`

Open nikola-benes opened this issue 1 year ago • 5 comments

Bug report

Bug description:

from functools import update_wrapper

def my_type(*args): pass

t = update_wrapper(my_type, type)

This works on Python ≤ 3.11, and I think this is expected because the docs for update_wrapper claim that it may be used with callables other than functions.

However, with 3.12, I get

TypeError: __type_params__ must be set to a tuple

(Similarly for functools.wraps.)

The problem is that update_wrapper includes __type_params__ by default (which is undocumented, see related issue) and type.__type_params__ is a descriptor.

CPython versions tested on:

3.12

Operating systems tested on:

Linux

nikola-benes avatar May 13 '24 19:05 nikola-benes

3.11:

Python 3.11.5 (main, Sep  5 2023, 10:34:31) [Clang 14.0.3 (clang-1403.0.22.14.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from functools import update_wrapper
>>> 
>>> def my_type(*args): pass
... 
>>> t = update_wrapper(my_type, type)
>>> 
>>> t
<function type at 0x104963060>

3.12+:

>>> from functools import update_wrapper
... 
... def my_type(*args): pass
... 
... t = update_wrapper(my_type, type)
Traceback (most recent call last):
  File "<python-input-8>", line 5, in <module>
    t = update_wrapper(my_type, type)
  File "/Users/sobolev/Desktop/cpython2/Lib/functools.py", line 57, in update_wrapper
    setattr(wrapper, attr, value)
    ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
TypeError: __type_params__ must be set to a tuple

sobolevn avatar May 13 '24 19:05 sobolevn

This was reported to me at dwt/fluent#14

I'm seeing this when wrapping type() to make it useable in a fluent way.

Is there something I need to do differently for python 3.12, or is this a bug in the python stdlib?

dwt avatar May 16 '24 20:05 dwt

Is there something I need to do differently for python 3.12, or is this a bug in the python stdlib?

This is a CPython bug

AlexWaygood avatar May 16 '24 20:05 AlexWaygood

hi @AlexWaygood, I'm trying to figure out what is happening here; what CPython should do with __type_params__? Should it be skipped?

@encukou is also helping me to understand it :)

mdkcore0 avatar May 20 '24 20:05 mdkcore0

Some notes from in-person conversation:

The problem is this:

>>> type.__type_params__
<attribute '__type_params__' of 'type' objects>

We would instead want this to be an empty tuple, because that's the normal behavior for classes that are not PEP 695 generics.

The way to achieve this would be to use a special case for &PyType_Type in the type_get_type_params getter. There is a similar check in the __abstractmethods__ getter.

JelleZijlstra avatar May 20 '24 21:05 JelleZijlstra

Is there more to do here?

encukou avatar May 30 '24 11:05 encukou

Sorry if this is daft, but could someone help me understand how I can find out what python release this fix will be part of?

dwt avatar Jun 05 '24 13:06 dwt

The fix will be included in 3.13.0b2 and 3.12.4. I think both should be coming pretty soon.

AlexWaygood avatar Jun 05 '24 13:06 AlexWaygood