diff options
author | Ivan Levkivskyi <levkivskyi@gmail.com> | 2017-12-14 23:32:56 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-12-14 23:32:56 +0100 |
commit | 2b5fd1e9ca9318673989e6ccac2c8acadc3809cd (patch) | |
tree | 5aa372f821be82c0d17265700364a5c4643d1cd4 /Lib/types.py | |
parent | 15a8728415e765f57e37f431f09e5c5821a04063 (diff) | |
download | cpython-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.py | 28 |
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. |