Skip to content

typing.Union does not support attribute assignment post gh-105511 #132139

Closed
@XuehaiPan

Description

@XuehaiPan

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

cc @JelleZijlstra

CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.14bugs and security fixesextension-modulesC modules in the Modules dirstdlibPython modules in the Lib dirtopic-typingtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions