boolean (@NotNull PyClass subClass, @NotNull String superClassName, boolean inherited, @Nullable TypeEvalContext context) { if (PyNames.CALLABLE.equals(superClassName)) { return hasMethod(subClass, PyNames.CALL, inherited, context); } if (PyNames.HASHABLE.equals(superClassName)) { return hasMethod(subClass, PyNames.HASH, inherited, context); } final boolean hasIter = hasMethod(subClass, PyNames.ITER, inherited, context); final boolean hasGetItem = hasMethod(subClass, PyNames.GETITEM, inherited, context); if (PyNames.ITERABLE.equals(superClassName)) { return hasIter || hasGetItem; } if (PyNames.ITERATOR.equals(superClassName)) { return (hasIter && (hasMethod(subClass, PyNames.NEXT, inherited, context) || hasMethod(subClass, PyNames.DUNDER_NEXT, inherited, context))) || hasGetItem; } final boolean isSized = hasMethod(subClass, PyNames.LEN, inherited, context); if (PyNames.SIZED.equals(superClassName)) { return isSized; } final boolean isContainer = hasMethod(subClass, PyNames.CONTAINS, inherited, context); if (PyNames.CONTAINER.equals(superClassName)) { return isContainer; } if (PyNames.SEQUENCE.equals(superClassName)) { return isSized && hasIter && isContainer && hasGetItem; } if (PyNames.MAPPING.equals(superClassName)) { return isSized && hasIter && isContainer && hasGetItem && hasMethod(subClass, PyNames.KEYS, inherited, context); } if (PyNames.MUTABLE_MAPPING.equals(superClassName)) { final boolean hasSetItem = hasMethod(subClass, PyNames.SETITEM, inherited, context); final boolean hasUpdate = hasMethod(subClass, PyNames.UPDATE, inherited, context); return isSized && hasIter && isContainer && hasGetItem && hasSetItem && hasUpdate; } if (PyNames.ABC_SET.equals(superClassName)) { return isSized && hasIter && isContainer; } if (PyNames.ABC_MUTABLE_SET.equals(superClassName)) { return isSized && hasIter && isContainer && hasMethod(subClass, "discard", inherited, context) && hasMethod(subClass, "add", inherited, context); } if (PyNames.ABC_COMPLEX.equals(superClassName)) { return hasMethod(subClass, PyNames.COMPLEX, inherited, context); } if (PyNames.ABC_REAL.equals(superClassName)) { return hasMethod(subClass, PyNames.FLOAT, inherited, context); } if (PyNames.ABC_INTEGRAL.equals(superClassName)) { return hasMethod(subClass, PyNames.INT, inherited, context); } if (PyNames.ABC_NUMBER.equals(superClassName) && "Decimal".equals(subClass.getName())) { return true; } if (PyNames.ASYNC_ITERABLE.equals(superClassName)) { return hasMethod(subClass, PyNames.AITER, inherited, context); } if (PyNames.AWAITABLE.equals(superClassName)) { return hasMethod(subClass, PyNames.DUNDER_AWAIT, inherited, context); } return false; }