Skip to content

Merge typing.Union and types.UnionType #105499

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
JelleZijlstra opened this issue Jun 8, 2023 · 5 comments
Closed

Merge typing.Union and types.UnionType #105499

JelleZijlstra opened this issue Jun 8, 2023 · 5 comments
Assignees
Labels
3.13 bugs and security fixes topic-typing type-feature A feature request or enhancement

Comments

@JelleZijlstra
Copy link
Member

JelleZijlstra commented Jun 8, 2023

Currently, unions created through typing.Union[A, B] and through the PEP-604 syntax A | B are at runtime instances of completely different types, and they differ in exactly what elements they accept. This is confusing and makes it harder for users to detect unions at runtime.

I propose to proceed in two steps:

  1. Make typing.Union an alias for types.UnionType and make it so types.UnionType[A, B] works, accepting the same types Union accepts now.
  2. Loosen the rules for what the | operator accepts to accept more types that are commonly used in unions.

Linked PRs

@JelleZijlstra
Copy link
Member Author

I put up a first implementation at #105511. Some thoughts on the details:

  • I implemented it by making typing.Union just a re-export of types.UnionType, but I feel it might actually be more intuitive if typing.Union was the canonical name of the object, and types.UnionType was an alias. We could change the implementation to set the module and name differently.
  • The repr() of all unions changes to use the | syntax.
  • I added dummy __name__, __qualname__, and __origin__ fields to types.UnionType to satisfy some test_typing tests.
  • We no longer support writing to a union's __args__ attribute. A test relied on this, but nobody should have been assigning to __args__ anyway, so I'm fine with this change.
  • There's a couple of behavior changes around issubclass() and subclassing because types.UnionType is (unlike typing.Union) an actual type.

@tibbe
Copy link

tibbe commented Jun 14, 2023

This broken an AST walker I had written for Python 3.9, after I upgraded all my Union[X, Y] to X | Y, something is expected to be purely syntactical change.

@MarsCapone
Copy link

Will this also fix the issue of unsupported operand type(s) for |: 'str' and ... when using a string reference of a type?

i.e.

class Foo:
    def get_self(self) -> "Foo" | None:
        pass

# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
#   File "<stdin>", line 2, in Foo
# TypeError: unsupported operand type(s) for |: 'str' and 'NoneType'

from typing import Union
class Foo:
    def get_self(self) -> Union["Foo", None]:
        pass

# no issues

@JelleZijlstra
Copy link
Member Author

@MarsCapone, no, but other changes in Python 3.14 (PEP-649) will fix that case.

@hauntsaninja
Copy link
Contributor

hauntsaninja commented Sep 28, 2024

See also https://mypy.readthedocs.io/en/stable/runtime_troubles.html and from __future__ import annotations, for mostly solutions in Python 3.7 onwards

JelleZijlstra added a commit that referenced this issue Mar 4, 2025
Co-authored-by: Alex Waygood <[email protected]>
Co-authored-by: Ken Jin <[email protected]>
Co-authored-by: Carl Meyer <[email protected]>
kepler added a commit to kepler/agno that referenced this issue Mar 12, 2025
The main issue: newish syntax for unions with `|` supported by Python 3.10 are of [type](https://docs.python.org/3.10/library/types.html#types.UnionType) `types.UnionType`, and didn't match `type(Union)`. There's a very recently [completed issue on CPython](python/cpython#105499) that will unify both (apparently for 3.14). See also this [MyPy warning](https://mypy.readthedocs.io/en/stable/runtime_troubles.html#future-annotations-import-pep-563) about evaluating type hints.

Other issues:
- Only unions of two values were properly handled for optional values;
- Unions with more than two values and an optional one would only parse one of the values, dropping the others;
- Some code lines were never true (like `isinstance(arg_json_schema["type"], list)`);

The code is now simplified while handling new type annotation syntax and null/optional values.
kepler added a commit to kepler/agno that referenced this issue Mar 13, 2025
The main issue: newish syntax for unions with `|` supported by Python 3.10 are of [type](https://docs.python.org/3.10/library/types.html#types.UnionType) `types.UnionType`, and didn't match `type(Union)`. There's a very recently [completed issue on CPython](python/cpython#105499) that will unify both (apparently for 3.14). See also this [MyPy warning](https://mypy.readthedocs.io/en/stable/runtime_troubles.html#future-annotations-import-pep-563) about evaluating type hints.

Other issues:
- Only unions of two values were properly handled for optional values;
- Unions with more than two values and an optional one would only parse one of the values, dropping the others;
- Some code lines were never true (like `isinstance(arg_json_schema["type"], list)`);

The code is now simplified while handling new type annotation syntax and null/optional values.
kepler added a commit to kepler/agno that referenced this issue Mar 15, 2025
The main issue: newish syntax for unions with `|` supported by Python 3.10 are of [type](https://docs.python.org/3.10/library/types.html#types.UnionType) `types.UnionType`, and didn't match `type(Union)`. There's a very recently [completed issue on CPython](python/cpython#105499) that will unify both (apparently for 3.14). See also this [MyPy warning](https://mypy.readthedocs.io/en/stable/runtime_troubles.html#future-annotations-import-pep-563) about evaluating type hints.

Other issues:
- Only unions of two values were properly handled for optional values;
- Unions with more than two values and an optional one would only parse one of the values, dropping the others;
- Some code lines were never true (like `isinstance(arg_json_schema["type"], list)`);

The code is now simplified while handling new type annotation syntax and null/optional values.
dirkbrnd added a commit to agno-agi/agno that referenced this issue Mar 19, 2025
## Description

**Summary of changes**:

The main problem: newish syntax for unions with `|` supported by Python
3.10 are of
[type](https://docs.python.org/3.10/library/types.html#types.UnionType)
`types.UnionType`, and didn't match `Union`. There's a very recently
[completed issue on
CPython](python/cpython#105499) that will
unify both (apparently for 3.14). See also this [MyPy
warning](https://mypy.readthedocs.io/en/stable/runtime_troubles.html#future-annotations-import-pep-563)
about evaluating type hints.

Other problems:
- Only unions of two values were properly handled for optional values;
- Unions with more than two values and an optional one would only parse
one of the values, dropping the others;
- Some code lines were never true (like
`isinstance(arg_json_schema["type"], list)`);

The code is now simplified while handling new type annotation syntax and
null/optional values.

Fixes #2441.

- **Related issues**: I didn't find any.
- **Motivation and context**: I was getting errors with a custom toolkit
that uses the new type hinting syntax.
- **Environment or dependencies**: None.
- **Impact on metrics**: N/A.

---

## Type of change

Please check the options that are relevant:

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- [ ] Model update (Addition or modification of models)
- [ ] Other (please describe):

---

## Checklist

- [x] Adherence to standards: Code complies with Agno’s style guidelines
and best practices.
- [x] Formatting and validation: You have run `./scripts/format.sh` and
`./scripts/validate.sh` to ensure code is formatted and linted.
- [x] Self-review completed: A thorough review has been performed by the
contributor(s).
- [x] Documentation: Docstrings and comments have been added or updated
for any complex logic.
- [ ] Examples and guides: Relevant cookbook examples have been included
or updated (if applicable).
- [x] Tested in a clean environment: Changes have been tested in a clean
environment to confirm expected behavior.
- [ ] Tests (optional): Tests have been added or updated to cover any
new or changed functionality.

---

## Additional Notes

Linked in the description.

---------

Co-authored-by: Dirk Brand <[email protected]>
layday added a commit to layday/cattrs that referenced this issue Mar 29, 2025
`_UnionGenericAlias` is no longer used to construct unions, see
python/cpython#105499.
layday added a commit to layday/cattrs that referenced this issue Mar 29, 2025
`_UnionGenericAlias` is no longer used to construct unions
and `UnionType` is an alias of `Union`, see
python/cpython#105499.
JelleZijlstra added a commit that referenced this issue Mar 31, 2025
Leftover from #105511 I believe. GitHub code search found no usages other
than copies of typing.py and lists of stdlib functions.
JelleZijlstra added a commit to JelleZijlstra/cpython that referenced this issue Apr 4, 2025
A bunch of other warnings in typing.py were already deferred, but
I added a few non-lazy ones.
JelleZijlstra added a commit that referenced this issue Apr 4, 2025
A bunch of other warnings in typing.py were already deferred, but
I added a few non-lazy ones.
seehwan pushed a commit to seehwan/cpython that referenced this issue Apr 16, 2025
seehwan pushed a commit to seehwan/cpython that referenced this issue Apr 16, 2025
Leftover from python#105511 I believe. GitHub code search found no usages other
than copies of typing.py and lists of stdlib functions.
seehwan pushed a commit to seehwan/cpython that referenced this issue Apr 16, 2025
A bunch of other warnings in typing.py were already deferred, but
I added a few non-lazy ones.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.13 bugs and security fixes topic-typing type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

4 participants