Skip to content

Commit 97334a2

Browse files
committed
Feedback, add conformance test
1 parent d2d8036 commit 97334a2

File tree

11 files changed

+71
-72
lines changed

11 files changed

+71
-72
lines changed

conformance/results/mypy/classes_classvar.toml

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ Internal error if TypeVarTuple is used in ClassVar.
44
Does not reject use of ParamSpec in ClassVar.
55
Rejects ClassVar nested in Annotated.
66
Does not reject use of ClassVar in TypeAlias definition.
7-
Does not infer type of ClassVar from assignment if no type is provided.
87
"""
98
output = """
109
classes_classvar.py:38: error: ClassVar[...] must have at most one type argument [valid-type]
@@ -15,24 +14,22 @@ classes_classvar.py:46: error: ClassVar cannot contain type variables [misc]
1514
classes_classvar.py:52: error: Incompatible types in assignment (expression has type "dict[Never, Never]", variable has type "list[str]") [assignment]
1615
classes_classvar.py:54: error: Variable should not be annotated with both ClassVar and Final [misc]
1716
classes_classvar.py:55: error: Invalid type: ClassVar nested inside other type [valid-type]
18-
classes_classvar.py:61: error: Invalid type: ClassVar nested inside other type [valid-type]
19-
classes_classvar.py:63: error: ClassVar can only be used for assignments in class body [misc]
20-
classes_classvar.py:64: error: ClassVar can only be used for assignments in class body [misc]
21-
classes_classvar.py:65: error: ClassVar can only be used for assignments in class body [misc]
22-
classes_classvar.py:67: error: ClassVar can only be used for assignments in class body [misc]
17+
classes_classvar.py:67: error: Invalid type: ClassVar nested inside other type [valid-type]
18+
classes_classvar.py:69: error: ClassVar can only be used for assignments in class body [misc]
19+
classes_classvar.py:70: error: ClassVar can only be used for assignments in class body [misc]
2320
classes_classvar.py:71: error: ClassVar can only be used for assignments in class body [misc]
24-
classes_classvar.py:78: error: Expression is of type "Any", not "float" [assert-type]
25-
classes_classvar.py:105: error: Cannot assign to class variable "stats" via instance [misc]
26-
classes_classvar.py:134: error: Incompatible types in assignment (expression has type "ProtoAImpl", variable has type "ProtoA") [assignment]
27-
classes_classvar.py:134: note: "ProtoAImpl" is missing following "ProtoA" protocol member:
28-
classes_classvar.py:134: note: z
29-
classes_classvar.py:134: note: Protocol member ProtoA.x expected class variable, got instance variable
30-
classes_classvar.py:134: note: Protocol member ProtoA.y expected class variable, got instance variable
21+
classes_classvar.py:73: error: ClassVar can only be used for assignments in class body [misc]
22+
classes_classvar.py:77: error: ClassVar can only be used for assignments in class body [misc]
23+
classes_classvar.py:111: error: Cannot assign to class variable "stats" via instance [misc]
24+
classes_classvar.py:140: error: Incompatible types in assignment (expression has type "ProtoAImpl", variable has type "ProtoA") [assignment]
25+
classes_classvar.py:140: note: "ProtoAImpl" is missing following "ProtoA" protocol member:
26+
classes_classvar.py:140: note: z
27+
classes_classvar.py:140: note: Protocol member ProtoA.x expected class variable, got instance variable
28+
classes_classvar.py:140: note: Protocol member ProtoA.y expected class variable, got instance variable
3129
"""
3230
conformance_automated = "Fail"
3331
errors_diff = """
3432
Line 47: Expected 1 errors
35-
Line 72: Expected 1 errors
36-
Line 61: Unexpected errors ['classes_classvar.py:61: error: Invalid type: ClassVar nested inside other type [valid-type]']
37-
Line 78: Unexpected errors ['classes_classvar.py:78: error: Expression is of type "Any", not "float" [assert-type]']
33+
Line 78: Expected 1 errors
34+
Line 67: Unexpected errors ['classes_classvar.py:67: error: Invalid type: ClassVar nested inside other type [valid-type]']
3835
"""

conformance/results/mypy/version.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
version = "mypy 1.15.0"
2-
test_duration = 1.8
2+
test_duration = 2.1

conformance/results/pyre/classes_classvar.toml

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ notes = """
33
Does not reject use of TypeVar in ClassVar.
44
Does not reject use of ParamSpec in ClassVar.
55
Does not reject use of ClassVar as a generic type argument.
6+
Does not allow ClassVar to be used without an assigned value.
67
Does not reject use of ClassVar in parameter type annotation.
78
Does not reject use of ClassVar in local variable annotation.
89
Does not reject use of ClassVar in instance variable annotation.
@@ -15,11 +16,11 @@ classes_classvar.py:38:10 Invalid type parameters [24]: Generic type `CV` expect
1516
classes_classvar.py:39:10 Invalid type [31]: Expression `typing.ClassVar[3]` is not a valid type.
1617
classes_classvar.py:40:13 Unbound name [10]: Name `var` is used but not defined in the current scope.
1718
classes_classvar.py:52:4 Incompatible attribute type [8]: Attribute `bad8` declared in class `ClassA` has type `List[str]` but is used as type `Dict[Variable[_KT], Variable[_VT]]`.
18-
classes_classvar.py:65:8 Undefined attribute [16]: `ClassA` has no attribute `xx`.
19-
classes_classvar.py:68:8 Incompatible return type [7]: Expected `CV[int]` but got `int`.
20-
classes_classvar.py:78:0 Assert type [70]: Expected `float` but got `typing.Any`.
21-
classes_classvar.py:105:0 Invalid assignment [41]: Assigning to class variable through instance, did you mean to assign to `Starship.stats` instead?
22-
classes_classvar.py:134:0 Incompatible variable type [9]: a is declared to have type `ProtoA` but is used as type `ProtoAImpl`.
19+
classes_classvar.py:66:4 Uninitialized attribute [13]: Attribute `good5` is declared in class `ClassA` to have type `typing.Any` but is never initialized.
20+
classes_classvar.py:71:8 Undefined attribute [16]: `ClassA` has no attribute `xx`.
21+
classes_classvar.py:74:8 Incompatible return type [7]: Expected `CV[int]` but got `int`.
22+
classes_classvar.py:111:0 Invalid assignment [41]: Assigning to class variable through instance, did you mean to assign to `Starship.stats` instead?
23+
classes_classvar.py:140:0 Incompatible variable type [9]: a is declared to have type `ProtoA` but is used as type `ProtoAImpl`.
2324
"""
2425
conformance_automated = "Fail"
2526
errors_diff = """
@@ -28,11 +29,11 @@ Line 46: Expected 1 errors
2829
Line 47: Expected 1 errors
2930
Line 54: Expected 1 errors
3031
Line 55: Expected 1 errors
31-
Line 63: Expected 1 errors
32-
Line 64: Expected 1 errors
33-
Line 67: Expected 1 errors
34-
Line 71: Expected 1 errors
35-
Line 72: Expected 1 errors
36-
Line 68: Unexpected errors ['classes_classvar.py:68:8 Incompatible return type [7]: Expected `CV[int]` but got `int`.']
37-
Line 78: Unexpected errors ['classes_classvar.py:78:0 Assert type [70]: Expected `float` but got `typing.Any`.']
32+
Line 69: Expected 1 errors
33+
Line 70: Expected 1 errors
34+
Line 73: Expected 1 errors
35+
Line 77: Expected 1 errors
36+
Line 78: Expected 1 errors
37+
Line 66: Unexpected errors ['classes_classvar.py:66:4 Uninitialized attribute [13]: Attribute `good5` is declared in class `ClassA` to have type `typing.Any` but is never initialized.']
38+
Line 74: Unexpected errors ['classes_classvar.py:74:8 Incompatible return type [7]: Expected `CV[int]` but got `int`.']
3839
"""

conformance/results/pyre/version.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
version = "pyre 0.9.23"
2-
test_duration = 6.5
2+
test_duration = 3.9

conformance/results/pyright/classes_classvar.toml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ classes_classvar.py:47:20 - error: "ClassVar" type cannot include type variables
99
classes_classvar.py:52:33 - error: Type "dict[Any, Any]" is not assignable to declared type "list[str]" (reportAssignmentType)
1010
classes_classvar.py:54:17 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm)
1111
classes_classvar.py:55:17 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm)
12-
classes_classvar.py:63:26 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm)
13-
classes_classvar.py:64:12 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm)
14-
classes_classvar.py:65:18 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm)
15-
classes_classvar.py:67:26 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm)
16-
classes_classvar.py:71:8 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm)
17-
classes_classvar.py:72:20 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm)
18-
classes_classvar.py:105:14 - error: Cannot assign to attribute "stats" for class "Starship"
12+
classes_classvar.py:69:26 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm)
13+
classes_classvar.py:70:12 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm)
14+
classes_classvar.py:71:18 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm)
15+
classes_classvar.py:73:26 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm)
16+
classes_classvar.py:77:8 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm)
17+
classes_classvar.py:78:20 - error: "ClassVar" is not allowed in this context (reportInvalidTypeForm)
18+
classes_classvar.py:111:14 - error: Cannot assign to attribute "stats" for class "Starship"
1919
  Attribute "stats" cannot be assigned through a class instance because it is a ClassVar (reportAttributeAccessIssue)
20-
classes_classvar.py:134:13 - error: Type "ProtoAImpl" is not assignable to declared type "ProtoA"
20+
classes_classvar.py:140:13 - error: Type "ProtoAImpl" is not assignable to declared type "ProtoA"
2121
  "ProtoAImpl" is incompatible with protocol "ProtoA"
2222
    "x" is defined as a ClassVar in protocol
2323
    "y" is defined as a ClassVar in protocol (reportAssignmentType)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
version = "pyright 1.1.394"
2-
test_duration = 1.3
2+
test_duration = 2.3

conformance/results/pytype/classes_classvar.toml

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Does not reject use of TypeVar in ClassVar.
44
Does not reject use of ParamSpec in ClassVar.
55
Does not reject use of ClassVar as a generic type argument.
66
Rejects initialization of ClassVar if no type argument is provided.
7+
Does not infer ClassVar with no type argument and no assigned value as Any.
78
Does not reject use of ClassVar in parameter type annotation.
89
Does not reject use of ClassVar in local variable annotation.
910
Does not reject use of ClassVar in instance variable annotation.
@@ -85,27 +86,27 @@ classes_classvar.py:52:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in ClassA
8586
bad8: ClassVar[list[str]] = {} # E: type violation in initialization
8687
\u001b[1m\u001b[31m~~~~\u001b[39m\u001b[0m
8788
88-
classes_classvar.py:60:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in ClassA: Type annotation for good4 does not match type of assignment [annotation-type-mismatch]
89+
classes_classvar.py:63:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in ClassA: Type annotation for good4 does not match type of assignment [annotation-type-mismatch]
8990
9091
good4: ClassVar = 3.1
9192
\u001b[1m\u001b[31m~~~~~\u001b[39m\u001b[0m
9293
93-
classes_classvar.py:68:16: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in method2: bad return type [bad-return-type]
94+
classes_classvar.py:74:16: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in method2: bad return type [bad-return-type]
9495
9596
return 3
9697
\u001b[1m\u001b[31m~\u001b[39m\u001b[0m
9798
98-
classes_classvar.py:78:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: ClassVar [assert-type]
99+
classes_classvar.py:84:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: ClassVar [assert-type]
99100
100-
assert_type(ClassA.good4, float)
101-
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
101+
assert_type(ClassA.good5, Any)
102+
\u001b[1m\u001b[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\u001b[39m\u001b[0m
102103
103-
classes_classvar.py:124:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in ProtoA: Type annotation for z does not match type of assignment [annotation-type-mismatch]
104+
classes_classvar.py:130:5: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in ProtoA: Type annotation for z does not match type of assignment [annotation-type-mismatch]
104105
105106
z: CV = [""]
106107
\u001b[1m\u001b[31m~\u001b[39m\u001b[0m
107108
108-
classes_classvar.py:134:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Type annotation for a does not match type of assignment [annotation-type-mismatch]
109+
classes_classvar.py:140:1: \u001b[1m\u001b[31merror\u001b[39m\u001b[0m: in <module>: Type annotation for a does not match type of assignment [annotation-type-mismatch]
109110
110111
a: ProtoA = ProtoAImpl() # E: y is not a ClassVar
111112
\u001b[1m\u001b[31m~\u001b[39m\u001b[0m
@@ -118,17 +119,17 @@ Line 46: Expected 1 errors
118119
Line 47: Expected 1 errors
119120
Line 54: Expected 1 errors
120121
Line 55: Expected 1 errors
121-
Line 63: Expected 1 errors
122-
Line 64: Expected 1 errors
123-
Line 65: Expected 1 errors
124-
Line 67: Expected 1 errors
122+
Line 69: Expected 1 errors
123+
Line 70: Expected 1 errors
125124
Line 71: Expected 1 errors
126-
Line 72: Expected 1 errors
127-
Line 105: Expected 1 errors
125+
Line 73: Expected 1 errors
126+
Line 77: Expected 1 errors
127+
Line 78: Expected 1 errors
128+
Line 111: Expected 1 errors
128129
Line 7: Unexpected errors ['classes_classvar.py:7:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: typing.TypeVarTuple not supported yet [not-supported-yet]']
129130
Line 29: Unexpected errors ['classes_classvar.py:29:6: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: Function TypeVarTuple.__init__ expects 1 arg(s), got 2 [wrong-arg-count]']
130-
Line 60: Unexpected errors ['classes_classvar.py:60:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in ClassA: Type annotation for good4 does not match type of assignment [annotation-type-mismatch]']
131-
Line 68: Unexpected errors ['classes_classvar.py:68:16: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in method2: bad return type [bad-return-type]']
132-
Line 78: Unexpected errors ['classes_classvar.py:78:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: ClassVar [assert-type]']
133-
Line 124: Unexpected errors ['classes_classvar.py:124:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in ProtoA: Type annotation for z does not match type of assignment [annotation-type-mismatch]']
131+
Line 63: Unexpected errors ['classes_classvar.py:63:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in ClassA: Type annotation for good4 does not match type of assignment [annotation-type-mismatch]']
132+
Line 74: Unexpected errors ['classes_classvar.py:74:16: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in method2: bad return type [bad-return-type]']
133+
Line 84: Unexpected errors ['classes_classvar.py:84:1: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in <module>: ClassVar [assert-type]']
134+
Line 130: Unexpected errors ['classes_classvar.py:130:5: \\x1b[1m\\x1b[31merror\\x1b[39m\\x1b[0m: in ProtoA: Type annotation for z does not match type of assignment [annotation-type-mismatch]']
134135
"""
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
version = "pytype 2024.10.11"
2-
test_duration = 34.9
2+
test_duration = 43.3

conformance/results/results.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,16 +159,16 @@ <h3>Python Type System Conformance Test Results</h3>
159159
<div class="table_container"><table><tbody>
160160
<tr><th class="col1">&nbsp;</th>
161161
<th class='tc-header'><div class='tc-name'>mypy 1.15.0</div>
162-
<div class='tc-time'>1.8sec</div>
162+
<div class='tc-time'>2.1sec</div>
163163
</th>
164164
<th class='tc-header'><div class='tc-name'>pyright 1.1.394</div>
165-
<div class='tc-time'>1.3sec</div>
165+
<div class='tc-time'>2.3sec</div>
166166
</th>
167167
<th class='tc-header'><div class='tc-name'>pyre 0.9.23</div>
168-
<div class='tc-time'>6.5sec</div>
168+
<div class='tc-time'>3.9sec</div>
169169
</th>
170170
<th class='tc-header'><div class='tc-name'>pytype 2024.10.11</div>
171-
<div class='tc-time'>34.9sec</div>
171+
<div class='tc-time'>43.3sec</div>
172172
</th>
173173
</tr>
174174
<tr><th class="column" colspan="5">

conformance/tests/classes_classvar.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,14 @@ class ClassA(Generic[T, P]):
5757
good1: CV[int] = 1
5858
good2: ClassVar[list[str]] = []
5959
good3: ClassVar[Any] = 1
60+
# > If an assigned value is available, the type should be inferred as some type
61+
# > to which this value is assignable.
62+
# Here, type checkers could infer good4 as `float` or `Any`, for example.
6063
good4: ClassVar = 3.1
61-
good5: Annotated[ClassVar[list[int]], ""] = []
64+
# > If the `ClassVar` qualifier is used without any assigned value, the type
65+
# > should be inferred as `Any`:
66+
good5: ClassVar
67+
good6: Annotated[ClassVar[list[int]], ""] = []
6268

6369
def method1(self, a: ClassVar[int]): # E: ClassVar not allowed here
6470
x: ClassVar[str] = "" # E: ClassVar not allowed here
@@ -75,7 +81,7 @@ def method2(self) -> ClassVar[int]: # E: ClassVar not allowed here
7581
assert_type(ClassA.good1, int)
7682
assert_type(ClassA.good2, list[str])
7783
assert_type(ClassA.good3, Any)
78-
assert_type(ClassA.good4, float)
84+
assert_type(ClassA.good5, Any)
7985

8086

8187
class BasicStarship:

docs/spec/class-compat.rst

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ The :py:data:`typing.ClassVar` :term:`type qualifier` is used to annotate
1414
class variables that should not be set on class instances. This restriction
1515
is enforced by static checkers, but not at runtime.
1616

17-
Syntax
18-
^^^^^^
19-
2017
:py:data:`~typing.ClassVar` may be used in one of several forms:
2118

2219
* With an explicit type, using the syntax ``ClassVar[<type>]``. Example::
@@ -31,14 +28,11 @@ Syntax
3128
z: ClassVar
3229

3330
If an assigned value is available (e.g. with ``y``), the type should be
34-
inferred as some type to which this value is :term:`assignable` (in this
35-
case, either ``int``, ``Literal[2]``, or ``Any``).
31+
inferred as some type to which this value is :term:`assignable` (for example,
32+
``int``, ``Literal[2]``, or ``Any``).
3633

3734
If the ``ClassVar`` qualifier is used without any assigned value, the type
38-
should be inferred to an unknown static type (such as :ref:`Any`).
39-
40-
Semantics and examples
41-
^^^^^^^^^^^^^^^^^^^^^^
35+
should be inferred as :ref:`any`.
4236

4337
Type annotations can be used to annotate class and instance variables
4438
in class bodies and methods. In particular, the value-less notation ``a: int``

0 commit comments

Comments
 (0)