
def attr_is_not_inherited(type_, attr):
    """
    returns True if type_'s attr is not inherited from any of its base classes
    """
    bases = type_.__mro__[1:]

    return getattr(type_, attr) not in (getattr(base, attr, None) for base in bases)


not_implementeds = []
for name, (typ, methods) in expected_methods.items():
    for method in methods:
        has_method = hasattr(typ, method)
        is_inherited = has_method and not attr_is_not_inherited(typ, method)
        if has_method and not is_inherited:
            continue
        not_implementeds.append((name, method, is_inherited))

for r in not_implementeds:
    print(r[0], ".", r[1], " (inherited)" if r[2] else "", sep="")
if not not_implementeds:
    print("Not much \\o/")

if platform.python_implementation() == "CPython":
    assert len(not_implementeds) == 0, "CPython should have all the methods"
