Skip to content

typing/Generic __orig_class__ availability during __init__ in 3.6 vs 3.7 #658

Description

@baltus-atomicrules

I observe that when executing __init__ in a Generic class, the value of __orig_class__ is available in version 3.6 but not in 3.7

(I am comparing 3.6.7 with 3.7.0)

I've attached a simple example that defines a Generic class and then accesses __orig_class__ in the associated __init__ method.

Simple.py.txt

N = TypeVar('N')
class ZZ(Generic[N]):
    def __init__(self):
        print("__orig_class__ is: ", self.__orig_class__)

In 3.6, this code runs fine:

In [42]: import Simple

In [51]: a = Simple.ZZ[int]

In [56]: b = a()
__orig_class__ is:  Simple.ZZ[int]

In 3.7 however, the value of __orig_class__ is not available:

In [4]: import Simple

In [5]: a = Simple.ZZ[int]

In [6]: b = a()

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-52a6c422c17e> in <module>
----> 1 b = a()
/tool/pandora64/.package/python-3.7.0/lib/python3.7/typing.py in __call__(self, *args, **kwargs)
    668             raise TypeError(f"Type {self._name} cannot be instantiated; "
    669                             f"use {self._name.lower()}() instead")
--> 670         result = self.__origin__(*args, **kwargs)
    671         try:
    672             result.__orig_class__ = self
/proj/emu_scratch4/users/dbaltus/python/experiment/Simple.py in __init__(self)
      4 class ZZ(Generic[N]):
      5     def __init__(self):
----> 6         print("__orig_class__ is: ", self.__orig_class__)
AttributeError: 'ZZ' object has no attribute '__orig_class__'

> /proj/emu_scratch4/users/dbaltus/python/experiment/Simple.py(6)__init__()
      2
      3 N = TypeVar('N')
      4 class ZZ(Generic[N]):
      5     def __init__(self):
----> 6         print("__orig_class__ is: ", self.__orig_class__)
ipdb> q

This occurs because in 3.7, the __call__ method of _GenericAlias does not set the value of __orig_class__ until after __init__ is called. (It is done differently in 3.6).

    def __call__(self, *args, **kwargs):
        if not self._inst:
            raise TypeError(f"Type {self._name} cannot be instantiated; "
                            f"use {self._name.lower()}() instead")
        result = self.__origin__(*args, **kwargs)
        try:
            result.__orig_class__ = self
        except AttributeError:
            pass
        return result

Activity

  1. ilevkivskyi commented on Jul 18, 2019

    @ilevkivskyi
    Member

    Yes, this is unfortunate, but as you know, this is undocumented internal attribute that you are using totally at your own risk. So unless you have a simple idea how to fix this, I don't think there is anything we can do here.

  2. Stewori commented on Oct 23, 2019

    @Stewori

    @baltus-atomicrules
    For the record, you can use pytypes.get_orig_class to solve this.
    Note: It's only available in master as of this writing. (I hope to make an new release soon.)

  3. mitar commented on Sep 30, 2021

    @mitar
    Contributor

    this is undocumented internal attribute that you are using totally at your own risk.

    Sure, but that makes also typing_inspect fail inside constructor: ilevkivskyi/typing_inspect#35

  4. JelleZijlstra commented on Sep 30, 2021

    @JelleZijlstra
    Member

    We can't change what typing looks like in 3.6 or 3.7, so I don't think there's anything actionable in this issue.

  5. mitar commented on Oct 18, 2021

    @mitar
    Contributor

    I mean, the same still holds true in 3.8, 3.9, 3.10. So the issue in all of those that inside __init__ you cannot access __orig_class__. The issue was only reported when 3.7 was out, but it is still valid.

  6. Gobot1234 commented on Jan 8, 2022

    @Gobot1234
    Contributor

    This has been annoying me as of late, couldn't we just have it not be available in __new__ but available in __init__?

  7. fzyzcjy commented on Dec 31, 2022

    @fzyzcjy

    Hi, is there any updates? Thanks

  8. LostInDarkMath commented on Oct 19, 2023

    @LostInDarkMath

    I still face this issue with Python 3.11. Are there any valid workarounds for this?

  9. srittau commented on Oct 19, 2023

    @srittau
    Collaborator

    Please report any issues related to issues with the typing module to CPython's issue tracker: https://github.com/python/cpython/issues, where the module is maintained nowadays.

  10. locked as off topic and limited conversation to collaborators on Oct 19, 2023
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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions