summaryrefslogtreecommitdiff
path: root/Lib/types.py
diff options
context:
space:
mode:
authorIvan Levkivskyi <levkivskyi@gmail.com>2017-12-14 23:32:56 +0100
committerGitHub <noreply@github.com>2017-12-14 23:32:56 +0100
commit2b5fd1e9ca9318673989e6ccac2c8acadc3809cd (patch)
tree5aa372f821be82c0d17265700364a5c4643d1cd4 /Lib/types.py
parent15a8728415e765f57e37f431f09e5c5821a04063 (diff)
downloadcpython-git-2b5fd1e9ca9318673989e6ccac2c8acadc3809cd.tar.gz
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.
Diffstat (limited to 'Lib/types.py')
-rw-r--r--Lib/types.py28
1 files changed, 26 insertions, 2 deletions
diff --git a/Lib/types.py b/Lib/types.py
index 336918fea0..c5976f3057 100644
--- a/Lib/types.py
+++ b/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.