Closed
Description
Bug report
Bug description:
Before #105511, typing.Union
is implemented in Python, and custom attributes can be assigned to a Union
variable.
ta = Union[int, str]
ta.__some_attribute__ = (int, str)
However, after #105511, typing.Union
is now implemented in C, and no attributes can be assigned to it. The UnionType
does not allow subclassing; users cannot bypass this using subclassing.
$ ipython
Python 3.14.0a6+ experimental free-threading build (heads/main:1755157207c, Apr 6 2025, 02:21:10) [Clang 17.0.0 (clang-1700.0.13.3)]
Type 'copyright', 'credits' or 'license' for more information
IPython 9.0.2 -- An enhanced Interactive Python. Type '?' for help.
Tip: Use `object?` to see the help on `object`, `object??` to view it's source
In [1]: import optree
In [2]: optree.PyTree[int]
/Users/PanXuehai/Projects/optree/env/lib/python3.14t/site-packages/IPython/core/interactiveshell.py:3111: SyntaxWarning: 'return' in a 'finally' block
return result
╭────────────────────────────────────────────────────────────────────── Traceback (most recent call last) ───────────────────────────────────────────────────────────────────────╮
│ in <module>:1 │
│ │
│ /Users/PanXuehai/Projects/cpython/.pydev/lib/python3.14t/typing.py:398 in inner │
│ │
│ 395 │ │ @functools.wraps(func) │
│ 396 │ │ def inner(*args, **kwds): │
│ 397 │ │ │ try: │
│ ❱ 398 │ │ │ │ return _caches[func](*args, **kwds) │
│ 399 │ │ │ except TypeError: │
│ 400 │ │ │ │ pass # All real errors (not unhashable args) are raised below. │
│ 401 │ │ │ return func(*args, **kwds) │
│ │
│ /Users/PanXuehai/Projects/optree/optree/typing.py:254 in __class_getitem__ │
│ │
│ 251 │ │ │ Deque[recurse_ref], # type: ignore[valid-type] │
│ 252 │ │ │ CustomTreeNode[recurse_ref], # type: ignore[valid-type] │
│ 253 │ │ ] │
│ ❱ 254 │ │ pytree_alias.__pytree_args__ = item # type: ignore[attr-defined] │
│ 255 │ │ │
│ 256 │ │ # pylint: disable-next=no-member │
│ 257 │ │ original_copy_with = pytree_alias.copy_with # type: ignore[attr-defined] │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'typing.Union' object has no attribute '__pytree_args__' and no __dict__ for setting new attributes
In [3]: class Foo(type(int | str)):
...: pass
...:
╭────────────────────────────────────────────────────────────────────── Traceback (most recent call last) ───────────────────────────────────────────────────────────────────────╮
│ in <module>:1 │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
TypeError: type 'typing.Union' is not an acceptable base type
Repro:
./python -m pip install -v optree
./python -c 'import optree; optree.PyTree[int]'
Source: https://github.com/metaopt/optree/blob/v0.15.0/optree/typing.py#L246-L254
CPython versions tested on:
CPython main branch
Operating systems tested on:
macOS