Skip to content

Commit 576d371

Browse files
authored
Added special-case handling for __init_subclass__ checks for classes that have ABCMeta as a metaclass. Previously, these were exempted from __init_subclass__ because ABCMeta has a custom __new__ method, but we know that this metaclass calls through to type.__new__ which calls __init_subclass__. This addresses #7819. (#7871)
1 parent ecdea2c commit 576d371

File tree

1 file changed

+18
-6
lines changed

1 file changed

+18
-6
lines changed

packages/pyright-internal/src/analyzer/typeEvaluator.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17330,13 +17330,25 @@ export function createTypeEvaluator(
1733017330
const errorNode = argList.length > 0 ? argList[0].node?.name ?? node.name : node.name;
1733117331
let newMethodMember: ClassMember | undefined;
1733217332

17333+
// See if the class has a metaclass that overrides `__new__`. If so, we
17334+
// will validate the signature of the `__new__` method.
1733317335
if (classType.details.effectiveMetaclass && isClass(classType.details.effectiveMetaclass)) {
17334-
// See if the metaclass has a `__new__` method that accepts keyword parameters.
17335-
newMethodMember = lookUpClassMember(
17336-
classType.details.effectiveMetaclass,
17337-
'__new__',
17338-
MemberAccessFlags.SkipTypeBaseClass
17339-
);
17336+
// If the metaclass is 'type' or 'ABCMeta', we'll assume it will call through to
17337+
// __init_subclass__, so we'll skip the `__new__` method check. We need to exclude
17338+
// TypedDict classes here because _TypedDict uses ABCMeta as its metaclass, but its
17339+
// typeshed definition doesn't override __init_subclass__.
17340+
const metaclassCallsInitSubclass =
17341+
ClassType.isBuiltIn(classType.details.effectiveMetaclass, ['ABCMeta', 'type']) &&
17342+
!ClassType.isTypedDictClass(classType);
17343+
17344+
if (!metaclassCallsInitSubclass) {
17345+
// See if the metaclass has a `__new__` method that accepts keyword parameters.
17346+
newMethodMember = lookUpClassMember(
17347+
classType.details.effectiveMetaclass,
17348+
'__new__',
17349+
MemberAccessFlags.SkipTypeBaseClass
17350+
);
17351+
}
1734017352
}
1734117353

1734217354
if (newMethodMember) {

0 commit comments

Comments
 (0)