`functools.update_wrapper` does not work with `type`
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
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
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?
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
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 :)
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.
Is there more to do here?
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?
The fix will be included in 3.13.0b2 and 3.12.4. I think both should be coming pretty soon.