Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32.3k
gh-101688: Implement types.get_original_bases#101827
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes from32 commits
50707ba
4fef9f8
4cb193d
44d3ae9
59e9ac2
20024e9
769fdbd
7194d3e
eeb4475
198dc08
695cf93
cc11033
a66282b
d3768ba
581a91a
fb15427
96b9536
6c38e4d
372bd6b
a6fe8ac
2b71b74
e7635c6
42e1668
1040478
8085258
b9bf4fd
ee59cbd
e5a91a5
7bad429
2a39055
1ea82be
1cb14c2
6f06c52
689267a
1ae16ea
3a8619a
e1d55d6
bab8cb3
fb9ef70
dc433c4
4268b74
9f54ac1
c122b23
2134053
cb21a65
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -86,6 +86,34 @@ Dynamic Type Creation | ||||||
:pep:`560` - Core support for typing module and generic types | ||||||
.. function:: get_original_bases(cls, /) | ||||||
Return the objects in the bases list of the class's definition as they | ||||||
existed prior to any modification by :meth:`~object.__mro_entries__`. This | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. What does "modification by But I'm probably missing another subtle distinction. :-) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. It doesn't modify anything itself I guess, but it does cause the Suggested change
Does this reflect the nature of the internals here better do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. I still don't follow. Can you point me to the code where FWIW In general it's better not to describe things in terms of "internals", but instead refer to the specification of an object or operation in the documentation. (And once something is documented it's no longer internal, even if it has a dunder name.) Member
| ||||||
is useful for introspecting :ref:`Generics <user-defined-generics>`. | ||||||
Gobot1234 marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||||||
Examples:: | ||||||
from typing import TypeVar, Generic | ||||||
T = TypeVar("T") | ||||||
class Foo(Generic[T]): ... | ||||||
class Bar(Foo[int], float): ... | ||||||
class Baz(list[str]): ... | ||||||
Foo.__bases__ == (Generic,) | ||||||
get_original_bases(Foo) == (Generic[T],) | ||||||
Bar.__bases__ == (Foo, float) | ||||||
AlexWaygood marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||||||
get_original_bases(Bar) == (Foo[int], float) | ||||||
Baz.__bases__ == (list,) | ||||||
get_original_bases(Baz) == (list[str],) | ||||||
get_original_bases(int) == None | ||||||
.. versionadded:: 3.12 | ||||||
Standard Interpreter Types | ||||||
-------------------------- | ||||||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1360,6 +1360,29 @@ class C: pass | ||
D = types.new_class('D', (A(), C, B()), {}) | ||
self.assertEqual(D.__bases__, (A1, A2, A3, C, B1, B2)) | ||
def test_get_original_bases(self): | ||
T = typing.TypeVar('T') | ||
class A: pass | ||
class B(typing.Generic[T]): pass | ||
class C(B[int]): pass | ||
class D(B[str], float): pass | ||
self.assertIsNone(types.get_original_bases(A)) | ||
self.assertEqual(types.get_original_bases(B), (typing.Generic[T],)) | ||
self.assertEqual(types.get_original_bases(C), (B[int],)) | ||
self.assertIsNone(types.get_original_bases(int)) | ||
self.assertEqual(types.get_original_bases(D), (B[str], float)) | ||
class E(list[T]): pass | ||
class F(list[int]): pass | ||
self.assertEqual(types.get_original_bases(E), (list[T],)) | ||
self.assertEqual(types.get_original_bases(F), (list[int],)) | ||
Gobot1234 marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
class G(typing.NamedTuple): | ||
x: int | ||
self.assertIs(types.get_original_bases(G)[0], typing.NamedTuple) | ||
# Many of the following tests are derived from test_descr.py | ||
def test_prepare_class(self): | ||
# Basic test of metaclass derivation | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -143,6 +143,34 @@ def _calculate_meta(meta, bases): | ||
"of the metaclasses of all its bases") | ||
return winner | ||
def get_original_bases(cls, /): | ||
"""Return the class's "original" bases prior to modification by `__mro_entries__`. | ||
This is useful for introspecting Generics. | ||
Gobot1234 marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
Examples:: | ||
from typing import TypeVar, Generic | ||
T = TypeVar("T") | ||
class Foo(Generic[T]): ... | ||
class Bar(Foo[int], float): ... | ||
class Baz(list[str]): ... | ||
get_original_bases(Foo) == (Generic[T],) | ||
get_original_bases(Bar) == (Foo[int], float) | ||
get_original_bases(Baz) == (list[str],) | ||
get_original_bases(int) == None | ||
""" | ||
if isinstance(cls, type): | ||
try: | ||
return cls.__orig_bases__ | ||
except AttributeError: | ||
pass | ||
return None | ||
Gobot1234 marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page.
Gobot1234 marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
class DynamicClassAttribute: | ||
"""Route attribute access on a class to __getattr__. | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Implement :func:`types.get_original_bases` to provide further introspection | ||
for types. |