From 890c69873cf22c6bf61b4d0f91515167fc158bff Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Sun, 13 Nov 2022 16:39:07 +0000 Subject: [PATCH 1/2] Allow class variable as implementation for read only attribute --- mypy/messages.py | 1 + mypy/subtypes.py | 5 ++++- test-data/unit/check-protocols.test | 13 +++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mypy/messages.py b/mypy/messages.py index e11ee9d0f7f29..ebe76509c1b65 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -2658,6 +2658,7 @@ def get_bad_protocol_flags( if ( IS_CLASSVAR in subflags and IS_CLASSVAR not in superflags + and IS_SETTABLE in superflags or IS_CLASSVAR in superflags and IS_CLASSVAR not in subflags or IS_SETTABLE in superflags diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 9a4982f5b8ecb..b4f948c6a9c1e 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -1027,7 +1027,10 @@ def named_type(fullname: str) -> Instance: if not is_subtype(supertype, subtype): return False if not class_obj: - if (IS_CLASSVAR in subflags) != (IS_CLASSVAR in superflags): + if IS_SETTABLE not in superflags: + if IS_CLASSVAR in superflags and IS_CLASSVAR not in subflags: + return False + elif (IS_CLASSVAR in subflags) != (IS_CLASSVAR in superflags): return False else: if IS_VAR in superflags and IS_CLASSVAR not in subflags: diff --git a/test-data/unit/check-protocols.test b/test-data/unit/check-protocols.test index 113b2000fc227..05766af7adf62 100644 --- a/test-data/unit/check-protocols.test +++ b/test-data/unit/check-protocols.test @@ -1153,6 +1153,19 @@ x2 = y2 # E: Incompatible types in assignment (expression has type "PP", variabl # N: Protocol member P.attr expected settable variable, got read-only attribute [builtins fixtures/property.pyi] +[case testClassVarProtocolImmutable] +from typing import Protocol, ClassVar + +class P(Protocol): + @property + def x(self) -> int: ... + +class C: + x: ClassVar[int] + +x: P = C() +[builtins fixtures/property.pyi] + [case testSettablePropertyInProtocols] from typing import Protocol From 28c6d09560fa5d95896dd2da5a55f1dccc4b82be Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Sun, 13 Nov 2022 16:43:00 +0000 Subject: [PATCH 2/2] Add a test with error --- test-data/unit/check-protocols.test | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test-data/unit/check-protocols.test b/test-data/unit/check-protocols.test index 05766af7adf62..ec7bf8816f341 100644 --- a/test-data/unit/check-protocols.test +++ b/test-data/unit/check-protocols.test @@ -1163,7 +1163,13 @@ class P(Protocol): class C: x: ClassVar[int] +class Bad: + x: ClassVar[str] + x: P = C() +y: P = Bad() # E: Incompatible types in assignment (expression has type "Bad", variable has type "P") \ + # N: Following member(s) of "Bad" have conflicts: \ + # N: x: expected "int", got "str" [builtins fixtures/property.pyi] [case testSettablePropertyInProtocols]