from types import prepare_class
def combine_meta(name, bases, namespace, **kwargs):
metaclasses = []
for base in bases:
meta, ns, _ = prepare_class(name, (base,), kwargs)
if meta is not type:
if type(ns) is not type(namespace):
if type(namespace) is not dict:
raise TypeError('metaclass conflict: '
'multiple custom namespaces defined.')
ns.update(namespace)
namespace = ns
elif ns:
namespace.update(ns)
metaclasses = [other for other in metaclasses if not issubclass(meta, other)]
if not any(issubclass(other, meta) for other in metaclasses):
metaclasses.append(meta)
if len(metaclasses) > 1:
meta_name = '_'.join(meta.__name__ for meta in metaclasses)
print(metaclasses)
metaclass = type(meta_name, tuple(metaclasses), {})
else:
metaclass, = metaclasses or (type,)
return metaclass(name, bases, namespace, **kwargs)
class M1(type):
pass
class M2(M1):
pass
class A(metaclass=M1):
pass
class B(metaclass=M2):
pass
class C(A, B, metaclass=combine_meta):
pass
assert type(C) is M2
class C(B, A, metaclass=combine_meta):
pass
assert type(C) is M2
ZnJvbSB0eXBlcyBpbXBvcnQgcHJlcGFyZV9jbGFzcwoKZGVmIGNvbWJpbmVfbWV0YShuYW1lLCBiYXNlcywgbmFtZXNwYWNlLCAqKmt3YXJncyk6CiAgICBtZXRhY2xhc3NlcyA9IFtdCiAgICBmb3IgYmFzZSBpbiBiYXNlczoKICAgICAgICBtZXRhLCBucywgXyA9IHByZXBhcmVfY2xhc3MobmFtZSwgKGJhc2UsKSwga3dhcmdzKQogICAgICAgIGlmIG1ldGEgaXMgbm90IHR5cGU6CiAgICAgICAgICAgIGlmIHR5cGUobnMpIGlzIG5vdCB0eXBlKG5hbWVzcGFjZSk6CiAgICAgICAgICAgICAgICBpZiB0eXBlKG5hbWVzcGFjZSkgaXMgbm90IGRpY3Q6CiAgICAgICAgICAgICAgICAgICAgcmFpc2UgVHlwZUVycm9yKCdtZXRhY2xhc3MgY29uZmxpY3Q6ICcKICAgICAgICAgICAgICAgICAgICAgICAgJ211bHRpcGxlIGN1c3RvbSBuYW1lc3BhY2VzIGRlZmluZWQuJykKICAgICAgICAgICAgICAgIG5zLnVwZGF0ZShuYW1lc3BhY2UpCiAgICAgICAgICAgICAgICBuYW1lc3BhY2UgPSBucwogICAgICAgICAgICBlbGlmIG5zOgogICAgICAgICAgICAgICAgbmFtZXNwYWNlLnVwZGF0ZShucykKICAgICAgICAgICAgbWV0YWNsYXNzZXMgPSBbb3RoZXIgZm9yIG90aGVyIGluIG1ldGFjbGFzc2VzIGlmIG5vdCBpc3N1YmNsYXNzKG1ldGEsIG90aGVyKV0KICAgICAgICAgICAgaWYgbm90IGFueShpc3N1YmNsYXNzKG90aGVyLCBtZXRhKSBmb3Igb3RoZXIgaW4gbWV0YWNsYXNzZXMpOgogICAgICAgICAgICAgICAgbWV0YWNsYXNzZXMuYXBwZW5kKG1ldGEpCiAgICBpZiBsZW4obWV0YWNsYXNzZXMpID4gMToKICAgICAgICBtZXRhX25hbWUgPSAnXycuam9pbihtZXRhLl9fbmFtZV9fIGZvciBtZXRhIGluIG1ldGFjbGFzc2VzKQogICAgICAgIHByaW50KG1ldGFjbGFzc2VzKQogICAgICAgIG1ldGFjbGFzcyA9IHR5cGUobWV0YV9uYW1lLCB0dXBsZShtZXRhY2xhc3NlcyksIHt9KQogICAgZWxzZToKICAgICAgICBtZXRhY2xhc3MsID0gbWV0YWNsYXNzZXMgb3IgKHR5cGUsKQogICAgcmV0dXJuIG1ldGFjbGFzcyhuYW1lLCBiYXNlcywgbmFtZXNwYWNlLCAqKmt3YXJncykKCmNsYXNzIE0xKHR5cGUpOgogICAgcGFzcwoKY2xhc3MgTTIoTTEpOgogICAgcGFzcwoKY2xhc3MgQShtZXRhY2xhc3M9TTEpOgogICAgcGFzcwoKY2xhc3MgQihtZXRhY2xhc3M9TTIpOgogICAgcGFzcwoKY2xhc3MgQyhBLCBCLCBtZXRhY2xhc3M9Y29tYmluZV9tZXRhKToKICAgIHBhc3MKCmFzc2VydCB0eXBlKEMpIGlzIE0yCgpjbGFzcyBDKEIsIEEsIG1ldGFjbGFzcz1jb21iaW5lX21ldGEpOgogICAgcGFzcwoKYXNzZXJ0IHR5cGUoQykgaXMgTTI=