GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — PEP 585 breaks inspect.isclass · Issue #88459 · python/cpython

PEP 585 breaks inspect.isclass #88459

New issue
Copy link
New issue
Copy link
Closed
Closed
PEP 585 breaks inspect.isclass#88459
Copy link
Labels
3.9 (EOL)end of lifeend of lifetopic-typing

Description

wyfo
mannequin
opened on Jun 2, 2021
Issue body actions
BPO 44293
Nosy @gvanrossum, @ilevkivskyi, @JelleZijlstra, @wyfo, @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-06-02.22:26:01.666>
labels = ['3.9']
title = 'PEP 585 breaks inspect.isclass'
updated_at = <Date 2021-06-05.22:35:28.114>
user = 'https://github.com/wyfo'

bugs.python.org fields:

activity = <Date 2021-06-05.22:35:28.114>
actor = 'levkivskyi'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = []
creation = <Date 2021-06-02.22:26:01.666>
creator = 'joperez'
dependencies = []
files = []
hgrepos = []
issue_num = 44293
keywords = []
message_count = 8.0
messages = ['394950', '394963', '394966', '394988', '395001', '395006', '395008', '395185']
nosy_count = 5.0
nosy_names = ['gvanrossum', 'levkivskyi', 'JelleZijlstra', 'joperez', 'kj']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = None
url = 'https://bugs.python.org/issue44293'
versions = ['Python 3.9']

Activity

  1. wyfo commented on Jun 2, 2021

    @wyfo
    wyfomannequin
    on Jun 2, 2021
    MannequinAuthor
    More actions

    PEP-585 has the side-effect of making list[int] an instance of type. This is not the case for other generic aliases.

    It also implies that inspect.isclass(list[int]) is True, while list[int] is not a class; as a proof of this statement issubclass(list[int], collections.abc.Collection) raises TypeError: issubclass() arg 1 must be a class.

    By the way, there is the awkward thing of having isinstance(list[int], type) is True while issubclass(type(list[int]), type) is False.

  2. wyfo
    added
    3.9 (EOL)end of lifeend of life
    on Jun 2, 2021
  3. JelleZijlstra commented on Jun 3, 2021

    @JelleZijlstra
    JelleZijlstra
    on Jun 3, 2021
    Member
    More actions

    The reason for this is that types.GenericAlias.getattribute delegates to the alias's origin (in the ga_getattro function). As a result, list[int].__class__ calls list.__class__ and returns type. And the implementation of isinstance(obj, type) ultimately calls issubclass(obj.__class__, type). (That's in object_isinstance() in abstract.c. It's news to me; I didn't know you could customize isinstance() behavior on the object side.)

    To fix this, we could make ga_getattro not delegate for __class__, so that list[int].__class__ would return GenericAlias instead of type. The current implementation of GenericAlias has been around for a few releases by now, though, so that change might break some use cases.

    This is not the case for other generic aliases.

    This is not true; it is the same for e.g. set[int]. Unless you meant something else here.

  4. gvanrossum commented on Jun 3, 2021

    @gvanrossum
    gvanrossum
    on Jun 3, 2021
    Member
    More actions

    Since these are new forms (list[int] previously was an error), does it actually matter? Especially since these are primarily used in annotations.

    @joseph Perez, is there a specific library or pattern that is broken by this?

    FWIW I did think rather carefully about which attributes to delegate or not, and delegating __class__ was intentional.

  5. wyfo commented on Jun 3, 2021

    @wyfo
    wyfomannequin
    on Jun 3, 2021
    MannequinAuthor
    More actions

    @jelle Zijlstra Thank you for the explanation.

    The current implementation of GenericAlias has been around for a few releases by now, though, so that change might break some use cases.

    I agree that a "fix" could have unexpected side-effect, my issue comes quite late indeed. By the way, Python typing is so much unstable (every version breaks the previous one), it's very complicated to write code that support multiple versions, so whatever the typing internal implementation, we must adapt.

    This is not true; it is the same for e.g. set[int]. Unless you meant something else here.

    I have chosen list[int] as an example of types.GenericAlias introduced by PEP-585 (i could have chosen set[int] or collections.abc.Collection[int]). But other generic aliases, e.g. typing.List[int] or MyClass[int] (where MyClass inherits Generic[T]), are not instances of type.

    @joseph Perez, is there a specific library or pattern that is broken by this?

    Because issubclass requires a "class" as arg 1, I use the pattern if isinstance(tp, type) and issubclass(tp, SomeClass) (isinstance check being equivalent to inspect.isclass). With PEP-585, it breaks for list[int] and other builtin generic aliases.

    FWIW I did think rather carefully about which attributes to delegate or not, and delegating __class__ was intentional.

    I don't have the context of the decision, so I can quite understand that delegating __class__ was the right thing to do, especially when __mro__ and other type attributes are also delegated.
    I mainly wanted to highlight this side effect, especially on the pattern mentioned above. (My issue title is a little bit excessive in this regard)

    But as I've written, I've already so many wrappers to maintain compatibility between Python versions of typing that I can write a new one to handle this particularity of PEP-585. So this issue is not critical to me.

  6. Fidget-Spinner commented on Jun 3, 2021

    @Fidget-Spinner
    Fidget-Spinner
    on Jun 3, 2021
    Member
    More actions

    @jelle thanks for nosy-ing me too and the thorough investigation.

    @joseph

    Thanks for taking the time to raise this inconvenience on the bug tracker.

    By the way, Python typing is so much unstable (every version breaks the previous one), it's very complicated to write code that support multiple versions, so whatever the typing internal implementation, we must adapt.

    Compared to some of the more mature modules in Python, I have to agree that typing.py is mildly unstable. However, you're not supposed to be using/importing from the internal constructs - those have no guarantee of stability. If you feel some common use cases aren't met by the current introspection helpers, please please please create a new issue for that and we'll consider it. How we use typing may differ from how you use it and so there's a lot we don't see. User bug reports and feedback have helped to surface such issues and improved typing for everyone :).

    I have chosen list[int] as an example of types.GenericAlias introduced by PEP-585 (i could have chosen set[int] or collections.abc.Collection[int]). But other generic aliases, e.g. typing.List[int] or MyClass[int] (where MyClass inherits Generic[T]), are not instances of type.

    This is an implementation detail. Most typing PEPs don't usually specify the runtime behavior in detail because most of them focus on static analysis. The implementation is usually up to the contributor's judgement. FWIW, to accommodate the new 3.9 GenericAlias, typing.py just added additional checks for isinstance(tp, types.GenericAlias) instead of checking only for isinstance(tp, type) and friends.

  7. gvanrossum commented on Jun 3, 2021

    @gvanrossum
    gvanrossum
    on Jun 3, 2021
    Member
    More actions

    Instead of introspecting types, use this library:
    https://github.com/ilevkivskyi/typing_inspect

  8. ilevkivskyi commented on Jun 3, 2021

    @ilevkivskyi
    ilevkivskyi
    on Jun 3, 2021
    Member
    More actions

    Btw this reminds me I should make a PyPI release of typing_inspect (last release was May 2020), hopefully will make a release on this weekend.

  9. ilevkivskyi commented on Jun 5, 2021

    @ilevkivskyi
    ilevkivskyi
    on Jun 5, 2021
    Member
    More actions

    Uploaded typing_inspect 0.7.0 to PyPI (it should work with Python 3.9 hopefully)

  10. ezio-melotti
    transferred this issue fromon Apr 10, 2022
  11. AlexWaygood
    added
    topic-typing
    on Apr 13, 2022
  12. JacobHayes commented on Nov 28, 2022

    @JacobHayes
    JacobHayes
    on Nov 28, 2022
    Contributor
    More actions

    I think this can be closed after #93754 (though I don't see it in the 3.11 changelog):

    Python 3.9.14 (main, Nov 28 2022, 13:10:52)
    [Clang 13.1.6 (clang-1316.0.21.2.5)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from types import GenericAlias
    >>> isinstance(list[int], type)
    True
    >>> isinstance(list[int], GenericAlias)
    True
    Python 3.11.0 (main, Nov 28 2022, 13:26:47)
    [Clang 13.1.6 (clang-1316.0.21.2.5)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from types import GenericAlias
    >>> isinstance(list[int], type)
    False
    >>> isinstance(list[int], GenericAlias)
    True

    Anyone relying on isinstance(list[int], type) to be True can instead use isinstance(list[int], (type, GenericAlias)).

  13. gvanrossum
    closed this as completedon Nov 29, 2022
  14. masenf
    added 2 commits that reference this issue on Mar 26, 2024

    Workaround python/cpython#88459

    cea4cd8

    [REF-2302] When a Var points to a model, prefer access to model field…

    b23859a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.9 (EOL)end of lifeend of lifetopic-typing

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.