Skip to content

Commit

Permalink
Exempted __slots__ symbol when determining whether a class is a cal…
Browse files Browse the repository at this point in the history
…lback protocol. This addresses #9878. (#9879)
  • Loading branch information
erictraut authored Feb 11, 2025
1 parent 0006588 commit 8abc3ff
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 9 deletions.
30 changes: 21 additions & 9 deletions packages/pyright-internal/src/analyzer/typeEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25928,19 +25928,31 @@ export function createTypeEvaluator(
for (const mroClass of objType.shared.mro) {
if (isClass(mroClass) && ClassType.isProtocolClass(mroClass)) {
for (const field of ClassType.getSymbolTable(mroClass)) {
if (field[0] !== '__call__' && !field[1].isIgnoredForProtocolMatch()) {
let fieldIsPartOfFunction = false;
const fieldName = field[0];
const fieldSymbol = field[1];

if (prefetched?.functionClass && isClass(prefetched.functionClass)) {
if (ClassType.getSymbolTable(prefetched.functionClass).has(field[0])) {
fieldIsPartOfFunction = true;
}
}
// We're expecting a __call__ method. We will also ignore a
// __slots__ definition, which is (by convention) ignored for
// protocol matching.
if (fieldName === '__call__' || fieldName === '__slots__') {
continue;
}

if (!fieldIsPartOfFunction) {
return undefined;
if (fieldSymbol.isIgnoredForProtocolMatch()) {
continue;
}

let fieldIsPartOfFunction = false;

if (prefetched?.functionClass && isClass(prefetched.functionClass)) {
if (ClassType.getSymbolTable(prefetched.functionClass).has(field[0])) {
fieldIsPartOfFunction = true;
}
}

if (!fieldIsPartOfFunction) {
return undefined;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class CallbackProto2(Protocol):
__module__: str
__qualname__: str
__annotations__: dict[str, Any]
__slots__ = ()

def __call__(self) -> None:
...
Expand Down

0 comments on commit 8abc3ff

Please sign in to comment.