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 — typing: tested TypeVar instance subclass TypeError is incidental · Issue #90800 · python/cpython

typing: tested TypeVar instance subclass TypeError is incidental #90800

New issue
Copy link
New issue
Copy link
Closed
#31148
Closed
typing: tested TypeVar instance subclass TypeError is incidental#90800
#31148
Copy link
Assignees
JelleZijlstra
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-typingtype-featureA feature request or enhancementA feature request or enhancement

Description

GBeauregard
mannequin
opened on Feb 4, 2022
Issue body actions
BPO 46642
Nosy @serhiy-storchaka, @JelleZijlstra, @sobolevn, @Fidget-Spinner, @AlexWaygood, @GBeauregard
PRs
  • bpo-46642: explicitly disallow typing.TypeVar instance subclassing #31148
  • 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 2022-02-04.21:59:21.151>
    labels = ['type-feature', 'library']
    title = 'typing: tested TypeVar instance subclass TypeError is incidental'
    updated_at = <Date 2022-03-12.03:39:46.337>
    user = 'https://github.com/GBeauregard'

    bugs.python.org fields:

    activity = <Date 2022-03-12.03:39:46.337>
    actor = 'JelleZijlstra'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Library (Lib)']
    creation = <Date 2022-02-04.21:59:21.151>
    creator = 'GBeauregard'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 46642
    keywords = ['patch']
    message_count = 7.0
    messages = ['412544', '412589', '412591', '412627', '412646', '412661', '414970']
    nosy_count = 6.0
    nosy_names = ['serhiy.storchaka', 'JelleZijlstra', 'sobolevn', 'kj', 'AlexWaygood', 'GBeauregard']
    pr_nums = ['31148']
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue46642'
    versions = []

    Activity

    1. GBeauregard commented on Feb 4, 2022

      @GBeauregard
      GBeauregardmannequin
      on Feb 4, 2022
      MannequinAuthor
      More actions

      cpython/Lib/test/test_typing.py

      Lines 227 to 230 in bf95ff9

      def test_cannot_subclass_vars(self):
      with self.assertRaises(TypeError):
      class V(TypeVar('T')):
      pass

      typing's testcases contain the following test to ensure instances of TypeVar cannot be subclassed:

      def test_cannot_subclass_vars(self):
          with self.assertRaises(TypeError):
              class V(TypeVar('T')):
                  pass

      The reason this raises a TypeError is incidental and subject to behavior change, not because doing so is prohibited per se; what's happening is the class creation does the equivalent of type(TypeVar('T')(name, bases, namespace), but this calls TypeVar's __init__ function with these items as the TypeVar constraints. TypeVar runs typing._type_check on the type constraints passed to it, and the literals for the namespace/name do not pass the callable() check in typing._type_check, causing it to raise a TypeError. I find it dubious this is the behavior the testcase is intending to test and the error it gives is confusing

      I propose we add __mro_entries__ to the TypeVar class that only contains a raise of TypeError to properly handle this case

      I can write this patch

    2. GBeauregard
      added
      stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
      type-featureA feature request or enhancementA feature request or enhancement
      on Feb 4, 2022
    3. GBeauregard commented on Feb 5, 2022

      @GBeauregard
      GBeauregardmannequin
      on Feb 5, 2022
      MannequinAuthor
      More actions

      The reason this test passed before is a bit confusing. Run the following code standalone to see where the type(TypeVar('T'))(name, bases, namespace) check is coming from.

      class TypeVar:
          def __init__(self, name, *constraints):
              # in actual TypeVar, each constraint is run through
              # typing._type_check, casuing TypeError via not callable() 
              print(repr(constraints))
      
      class V(TypeVar("T")):
          pass
      
    4. GBeauregard commented on Feb 5, 2022

      @GBeauregard
      GBeauregardmannequin
      on Feb 5, 2022
      MannequinAuthor
      More actions

      Fixing this test unblocks bpo-46644

    5. serhiy-storchaka commented on Feb 6, 2022

      @serhiy-storchaka
      serhiy-storchaka
      on Feb 6, 2022
      Member
      More actions

      Note that instances of most other types are non-subclassable "by accident".

      >>> class A(42): pass
      ... 
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      TypeError: int() takes at most 2 arguments (3 given)
      
      >>> class B:
      ...     def __init__(self, *args): pass
      ... 
      >>> class C(B()): pass
      ... 
      >>> C
      <__main__.B object at 0x7fdcfb49aae0>

      It is okay until we decide that there is a problem, and it that case it would require more general solution.

      Are there any issues with this in real code?

    6. GBeauregard commented on Feb 6, 2022

      @GBeauregard
      GBeauregardmannequin
      on Feb 6, 2022
      MannequinAuthor
      More actions

      The issue in real code I had in mind was internal to cpython: if we remove the callable() check from _type_check naively, this test starts to fail. Both of our proposed changes happen to not fail this check. Given your second example, would you prefer if we remove this testcase if the issue comes up in the final proposed patches? On the other hand, there is precedent for giving this a nice error message other places in typing.py.

    7. serhiy-storchaka commented on Feb 6, 2022

      @serhiy-storchaka
      serhiy-storchaka
      on Feb 6, 2022
      Member
      More actions

      The test is good. If we accidentally make a TypeVar instance subclassable, it will catch such error.

    8. JelleZijlstra commented on Mar 12, 2022

      @JelleZijlstra
      JelleZijlstra
      on Mar 12, 2022
      Member
      More actions

      This still behaves similarly after the bpo-46642 fix:

      >>> class V(TypeVar("T")): pass
      ... 
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "/Users/jelle/py/cpython/Lib/typing.py", line 906, in __init__
          self.__constraints__ = tuple(_type_check(t, msg) for t in constraints)
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/Users/jelle/py/cpython/Lib/typing.py", line 906, in <genexpr>
          self.__constraints__ = tuple(_type_check(t, msg) for t in constraints)
                                       ^^^^^^^^^^^^^^^^^^^
        File "/Users/jelle/py/cpython/Lib/typing.py", line 189, in _type_check
          raise TypeError(f"{msg} Got {arg!r:.100}.")
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      TypeError: TypeVar(name, constraint, ...): constraints must be types. Got (~T,).
    9. ezio-melotti
      transferred this issue fromon Apr 10, 2022
    10. JelleZijlstra
      self-assigned this
      on Apr 10, 2022
    11. AlexWaygood
      added
      topic-typing
      on Apr 13, 2022
    12. serhiy-storchaka
      closed this as completedon Jun 25, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    • @JelleZijlstra
      JelleZijlstra

    Labels

    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-typingtype-featureA feature request or enhancementA feature request or enhancement

    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.