PY-84461 Don't consider attributes assigned in protocol functions for protocol matching

(cherry picked from commit 5e540caf9f11b78036785cb94d189c91d1899c97)

IJ-MR-174248

GitOrigin-RevId: 53c1179c86cda95a72e57cbf08075c6e1b20aa2c
This commit is contained in:
evgeny.bovykin
2025-11-19 13:05:44 +00:00
committed by intellij-monorepo-bot
parent d1cb10773b
commit 59d7739bd6
2 changed files with 32 additions and 0 deletions
@@ -1,6 +1,7 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.jetbrains.python.codeInsight.typing
import com.intellij.psi.util.contextOfType
import com.jetbrains.python.PyNames
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider.PROTOCOL
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider.PROTOCOL_EXT
@@ -41,6 +42,10 @@ fun inspectProtocolSubclass(protocol: PyClassType, subclass: PyClassType, contex
return@visitMembers true
}
if (e.contextOfType<PyFunction>()?.containingClass == protocol.pyClass) {
return@visitMembers true
}
val name = e.name ?: return@visitMembers true
when (name) {
PyNames.SLOTS -> return@visitMembers true // __slots__ in a protocol definition are not considered to be a part of the protocol
@@ -3098,4 +3098,31 @@ def foo(param: str | int) -> TypeGuard[str]:
public void testStrictUnionImplicitProtocolMatching() {
doTest();
}
// PY-76822
public void testProtocolWithAssignedPropertyInMethod() {
doTestByText("""
from typing import Protocol
class Template(Protocol):
name: str
value: int = 0
def method(self) -> None:
self.name = "name"
self.temp: list[int] = []
class Concrete:
def __init__(self, name: str, value: int) -> None:
self.name = name
self.value = value
def method(self) -> None:
return
var: Template = Concrete("value", 42)
""");
}
}