Skip to content

More differences in instance and subclass checks between typing.Union and types.Union #88834

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
serhiy-storchaka opened this issue Jul 18, 2021 · 6 comments
Labels
3.10 only security fixes 3.11 only security fixes stdlib Python modules in the Lib dir topic-typing type-bug An unexpected behavior, bug, or error

Comments

@serhiy-storchaka
Copy link
Member

serhiy-storchaka commented Jul 18, 2021

BPO 44668
Nosy @gvanrossum, @serhiy-storchaka, @Fidget-Spinner

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2021-07-18.17:21:30.520>
labels = ['type-bug', 'library', '3.10', '3.11']
title = 'More differences in instance and subclass checks between typing.Union and types.Union'
updated_at = <Date 2021-07-19.17:57:02.931>
user = 'https://github.com/serhiy-storchaka'

bugs.python.org fields:

activity = <Date 2021-07-19.17:57:02.931>
actor = 'gvanrossum'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation = <Date 2021-07-18.17:21:30.520>
creator = 'serhiy.storchaka'
dependencies = []
files = []
hgrepos = []
issue_num = 44668
keywords = []
message_count = 4.0
messages = ['397757', '397775', '397778', '397823']
nosy_count = 3.0
nosy_names = ['gvanrossum', 'serhiy.storchaka', 'kj']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue44668'
versions = ['Python 3.10', 'Python 3.11']

Linked PRs

@serhiy-storchaka
Copy link
Member Author

  1. Checks for types.Union ignore any non-type args. Checks for typing.Union require fail on first checked non-type (but it can short circuit).
>>> import typing
>>> T = typing.TypeVar('T')
>>> issubclass(int, int | T | str)
True
>>> issubclass(int, str | T | int)
True
>>> issubclass(int, typing.Union[int, T, str])
True
>>> issubclass(int, typing.Union[str, T, int])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/serhiy/py/cpython/Lib/typing.py", line 1208, in __subclasscheck__
    if issubclass(cls, arg):
       ^^^^^^^^^^^^^^^^^^^^
TypeError: issubclass() arg 2 must be a class, a tuple of classes, or a union.
>>> isinstance(1, int | T | str)
True
>>> isinstance(1, str | T | int)
True
>>> isinstance(1, typing.Union[int, T, str])
True
>>> isinstance(1, typing.Union[str, T, int])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/serhiy/py/cpython/Lib/typing.py", line 1204, in __instancecheck__
    return self.__subclasscheck__(type(obj))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/serhiy/py/cpython/Lib/typing.py", line 1208, in __subclasscheck__
    if issubclass(cls, arg):
       ^^^^^^^^^^^^^^^^^^^^
TypeError: issubclass() arg 2 must be a class, a tuple of classes, or a union.
  1. __instancecheck__ of typing.Union uses __subclasscheck__ of args instead of __instancecheck__. In normal cases the result should be the same, but there should be a reason of having two different special methods.

@serhiy-storchaka serhiy-storchaka added stdlib Python modules in the Lib dir 3.10 only security fixes 3.11 only security fixes type-bug An unexpected behavior, bug, or error labels Jul 18, 2021
@gvanrossum
Copy link
Member

This seems a low-priority issue to me. The code is invalid, but I don't think it's very important to raise an exception (typing.Union is also inconsistent). Static type checkers will flag all these as errors. (Or perhaps none of them? It may depend on the meaning of T in the current scope.)

@serhiy-storchaka
Copy link
Member Author

It is easy to fix once we define the correct behavior in corner cases.

@gvanrossum
Copy link
Member

Sure.

@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
@AlexWaygood
Copy link
Member

AlexWaygood commented Apr 10, 2023

This looks to have been fixed at some point, though I don't know when. types.UnionType and typing.Union are now consistent: they will both succeed if they hit a "success case" before they hit an "invalid case", but they will both error out if they hit an invalid case before a success case. On main (and the behaviour is the same on 3.11.2):

>>> import typing
>>> T = typing.TypeVar("T")
>>> issubclass(int, int | T | str)
True
>>> issubclass(int, str | T | int)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 1698, in __subclasscheck__
    if issubclass(cls, arg):
       ^^^^^^^^^^^^^^^^^^^^
TypeError: issubclass() arg 2 must be a class, a tuple of classes, or a union
>>> issubclass(int, typing.Union[int, T, str])
True
>>> issubclass(int, typing.Union[str, T, int])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 1698, in __subclasscheck__
    if issubclass(cls, arg):
       ^^^^^^^^^^^^^^^^^^^^
TypeError: issubclass() arg 2 must be a class, a tuple of classes, or a union
>>> isinstance(1, int | T | str)
True
>>> isinstance(1, str | T | int)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 1694, in __instancecheck__
    return self.__subclasscheck__(type(obj))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 1698, in __subclasscheck__
    if issubclass(cls, arg):
       ^^^^^^^^^^^^^^^^^^^^
TypeError: issubclass() arg 2 must be a class, a tuple of classes, or a union
>>> isinstance(1, typing.Union[int, T, str])
True
>>> isinstance(1, typing.Union[str, T, int])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 1694, in __instancecheck__
    return self.__subclasscheck__(type(obj))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\alexw\coding\cpython\Lib\typing.py", line 1698, in __subclasscheck__
    if issubclass(cls, arg):
       ^^^^^^^^^^^^^^^^^^^^
TypeError: issubclass() arg 2 must be a class, a tuple of classes, or a union

Depending on whether it was fixed "on purpose" or "by accident", we may need to add regression tests.

serhiy-storchaka added a commit to serhiy-storchaka/cpython that referenced this issue Dec 30, 2024
…nionType

Union now uses the instance checks against its parameters instead of
the subclass checks.
@serhiy-storchaka
Copy link
Member Author

Indeed, the first part was fixed in #91603.

#128363 fixes the second part.

serhiy-storchaka added a commit that referenced this issue Dec 31, 2024
…pe (GH-128363)

Union now uses the instance checks against its parameters instead of
the subclass checks.
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Dec 31, 2024
…nionType (pythonGH-128363)

Union now uses the instance checks against its parameters instead of
the subclass checks.
(cherry picked from commit b2ac70a)

Co-authored-by: Serhiy Storchaka <[email protected]>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Dec 31, 2024
…nionType (pythonGH-128363)

Union now uses the instance checks against its parameters instead of
the subclass checks.
(cherry picked from commit b2ac70a)

Co-authored-by: Serhiy Storchaka <[email protected]>
serhiy-storchaka added a commit that referenced this issue Dec 31, 2024
…UnionType (GH-128363) (GH-128371)

Union now uses the instance checks against its parameters instead of
the subclass checks.
(cherry picked from commit b2ac70a)

Co-authored-by: Serhiy Storchaka <[email protected]>
serhiy-storchaka added a commit that referenced this issue Dec 31, 2024
…UnionType (GH-128363) (GH-128370)

Union now uses the instance checks against its parameters instead of
the subclass checks.
(cherry picked from commit b2ac70a)

Co-authored-by: Serhiy Storchaka <[email protected]>
srinivasreddy pushed a commit to srinivasreddy/cpython that referenced this issue Jan 8, 2025
…nionType (pythonGH-128363)

Union now uses the instance checks against its parameters instead of
the subclass checks.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.10 only security fixes 3.11 only security fixes stdlib Python modules in the Lib dir topic-typing type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

3 participants