mirror of
https://github.com/python/cpython.git
synced 2025-08-22 09:45:06 +00:00
bpo-32226: Implementation of PEP 560 (core components) (#4732)
This part of the PEP implementation adds support for __mro_entries__ and __class_getitem__ by updating __build_class__ and PyObject_GetItem.
This commit is contained in:
parent
15a8728415
commit
2b5fd1e9ca
7 changed files with 492 additions and 5 deletions
28
Lib/types.py
28
Lib/types.py
|
@ -60,10 +60,34 @@ del sys, _f, _g, _C, _c, # Not for export
|
|||
# Provide a PEP 3115 compliant mechanism for class creation
|
||||
def new_class(name, bases=(), kwds=None, exec_body=None):
|
||||
"""Create a class object dynamically using the appropriate metaclass."""
|
||||
meta, ns, kwds = prepare_class(name, bases, kwds)
|
||||
resolved_bases = resolve_bases(bases)
|
||||
meta, ns, kwds = prepare_class(name, resolved_bases, kwds)
|
||||
if exec_body is not None:
|
||||
exec_body(ns)
|
||||
return meta(name, bases, ns, **kwds)
|
||||
if resolved_bases is not bases:
|
||||
ns['__orig_bases__'] = bases
|
||||
return meta(name, resolved_bases, ns, **kwds)
|
||||
|
||||
def resolve_bases(bases):
|
||||
"""Resolve MRO entries dynamically as specified by PEP 560."""
|
||||
new_bases = list(bases)
|
||||
updated = False
|
||||
shift = 0
|
||||
for i, base in enumerate(bases):
|
||||
if isinstance(base, type):
|
||||
continue
|
||||
if not hasattr(base, "__mro_entries__"):
|
||||
continue
|
||||
new_base = base.__mro_entries__(bases)
|
||||
updated = True
|
||||
if not isinstance(new_base, tuple):
|
||||
raise TypeError("__mro_entries__ must return a tuple")
|
||||
else:
|
||||
new_bases[i+shift:i+shift+1] = new_base
|
||||
shift += len(new_base) - 1
|
||||
if not updated:
|
||||
return bases
|
||||
return tuple(new_bases)
|
||||
|
||||
def prepare_class(name, bases=(), kwds=None):
|
||||
"""Call the __prepare__ method of the appropriate metaclass.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue