(Apologies if this has already been discussed. I tried to search and didn't find anything relevant.)
I was playing around with 3.12.0b4 this evening and noticed an odd (to me, at least) behavior with types.get_original_bases(). I hesitate to call it a bug because I think I understand *why* it's behaving this way—I'm just not sure it's desirable. >>> T = typing.TypeVar("T") >>> class FirstBase(typing.Generic[T]): ... pass ... >>> class SecondBase(typing.Generic[T]): ... pass ... >>> class First(FirstBase[int]): ... pass ... >>> class Second(SecondBase[int]): ... pass ... >>> class Example(First, Second): ... pass ... >>> types.get_original_bases(Example) (FirstBase[int],) >>> Example.__bases__ (First, Second) >>> types.get_original_bases(First) (FirstBase[int],) In other words, types.get_original_bases(Example) is returning the original base types for First, rather than its own. I believe this happens because __orig_bases__ is only set when one or more bases are not types. In this case both bases are types, so Example doesn't get its own __orig_bases__. Then when types.get_original_bases() tries to get __orig_bases__ with getattr(cls, "__orig_bases__") or something morally equivalent, it searches the MRO and finds __orig_bases__ on First. The same thing also happens if all the bases are "bare" generic types. >>> class First(typing.Generic[T]): ... pass ... >>> class Second(typing.Generic[T]): ... pass ... >>> class Example(First, Second): ... pass ... >>> types.get_original_bases(Example) (typing.Generic[~T],) As I said, I'm not clear if this is a bug, or just an unfortunate but intended behavior. I would personally expect types.get_original_bases() to check if the type has its *own* __orig_bases__ attribute, and to fall back to __bases__ otherwise. The way it works today makes it unnecessarily difficult to write a function that, for example, recurses down a type's inheritance tree inspecting the original bases—I currently have to work around this behavior via hacks like checking "__orig_bases__" in cls.__dict__ or any(types.get_original_bases(cls) == types.get_original_bases(base) for base in cls.__bases__). (Unless I'm missing some simpler solution.) Is this something that could (should?) be addressed before 3.12 lands? Thanks, Chris Bouchard -- https://mail.python.org/mailman/listinfo/python-list