diff --git a/conformance/results/mypy/dataclasses_final.toml b/conformance/results/mypy/dataclasses_final.toml new file mode 100644 index 000000000..570bd3766 --- /dev/null +++ b/conformance/results/mypy/dataclasses_final.toml @@ -0,0 +1,22 @@ +conformant = "Partial" +notes = """ +Wrongly requires a Final dataclass field to be initialized at class level. +Doesn't support Final nested inside ClassVar. +""" +conformance_automated = "Fail" +errors_diff = """ +Line 16: Expected 1 errors +Line 6: Unexpected errors ['dataclasses_final.py:6: error: Final name must be initialized with a value [misc]'] +Line 8: Unexpected errors ['dataclasses_final.py:8: error: Final can be only used as an outermost qualifier in a variable annotation [valid-type]'] +Line 13: Unexpected errors ['dataclasses_final.py:13: error: Expression is of type "Any", not "int" [assert-type]'] +""" +output = """ +dataclasses_final.py:6: error: Final name must be initialized with a value [misc] +dataclasses_final.py:8: error: Final can be only used as an outermost qualifier in a variable annotation [valid-type] +dataclasses_final.py:13: error: Expression is of type "Any", not "int" [assert-type] +dataclasses_final.py:24: error: Cannot assign to final attribute "final_no_default" [misc] +dataclasses_final.py:25: error: Cannot assign to final attribute "final_with_default" [misc] +dataclasses_final.py:26: error: Cannot access final instance attribute "final_no_default" on class object [misc] +dataclasses_final.py:26: error: Cannot assign to final attribute "final_no_default" [misc] +dataclasses_final.py:27: error: Cannot assign to final attribute "final_with_default" [misc] +""" diff --git a/conformance/results/mypy/version.toml b/conformance/results/mypy/version.toml index 268bd31ac..2f1616c14 100644 --- a/conformance/results/mypy/version.toml +++ b/conformance/results/mypy/version.toml @@ -1,2 +1,2 @@ version = "mypy 1.10.0" -test_duration = 1.4 +test_duration = 1.0 diff --git a/conformance/results/pyre/dataclasses_final.toml b/conformance/results/pyre/dataclasses_final.toml new file mode 100644 index 000000000..5b8b20d92 --- /dev/null +++ b/conformance/results/pyre/dataclasses_final.toml @@ -0,0 +1,19 @@ +conformant = "Partial" +notes = """ +Mis-handles Final nested inside ClassVar. +""" +conformance_automated = "Fail" +errors_diff = """ +Line 8: Unexpected errors ['dataclasses_final.py:8:4 Incompatible attribute type [8]: Attribute `final_classvar` declared in class `D` has type `Final[int]` but is used as type `int`.', 'dataclasses_final.py:8:4 Invalid type [31]: Expression `Final[int]` is not a valid type. Final cannot be nested.'] +Line 13: Unexpected errors ['dataclasses_final.py:13:0 Incompatible parameter type [6]: In call `assert_type`, for 1st positional argument, expected `int` but got `Final[int]`.'] +""" +output = """ +dataclasses_final.py:8:4 Incompatible attribute type [8]: Attribute `final_classvar` declared in class `D` has type `Final[int]` but is used as type `int`. +dataclasses_final.py:8:4 Invalid type [31]: Expression `Final[int]` is not a valid type. Final cannot be nested. +dataclasses_final.py:13:0 Incompatible parameter type [6]: In call `assert_type`, for 1st positional argument, expected `int` but got `Final[int]`. +dataclasses_final.py:16:0 Incompatible attribute type [8]: Attribute `final_classvar` declared in class `D` has type `Final[int]` but is used as type `int`. +dataclasses_final.py:24:0 Invalid assignment [41]: Cannot reassign final attribute `d.final_no_default`. +dataclasses_final.py:25:0 Invalid assignment [41]: Cannot reassign final attribute `d.final_with_default`. +dataclasses_final.py:26:0 Invalid assignment [41]: Cannot reassign final attribute `D.final_no_default`. +dataclasses_final.py:27:0 Invalid assignment [41]: Cannot reassign final attribute `D.final_with_default`. +""" diff --git a/conformance/results/pyre/version.toml b/conformance/results/pyre/version.toml index 4e861da3b..2d37f23c3 100644 --- a/conformance/results/pyre/version.toml +++ b/conformance/results/pyre/version.toml @@ -1,2 +1,2 @@ version = "pyre 0.9.21" -test_duration = 3.2 +test_duration = 1.9 diff --git a/conformance/results/pyright/dataclasses_final.toml b/conformance/results/pyright/dataclasses_final.toml new file mode 100644 index 000000000..00d819e32 --- /dev/null +++ b/conformance/results/pyright/dataclasses_final.toml @@ -0,0 +1,29 @@ +conformant = "Partial" +notes = """ +Doesn't support Final nested inside ClassVar. +""" +conformance_automated = "Fail" +errors_diff = """ +Line 8: Unexpected errors ['dataclasses_final.py:8:30 - error: "Final" is not allowed in this context', 'dataclasses_final.py:8:44 - error: Expression of type "Literal[4]" is incompatible with declared type "Final"'] +Line 13: Unexpected errors ['dataclasses_final.py:13:13 - error: "assert_type" mismatch: expected "int" but received "Final" (reportAssertTypeFailure)'] +""" +output = """ +dataclasses_final.py:8:30 - error: "Final" is not allowed in this context +dataclasses_final.py:8:44 - error: Expression of type "Literal[4]" is incompatible with declared type "Final" +  "Literal[4]" is incompatible with "Final" (reportAssignmentType) +dataclasses_final.py:13:13 - error: "assert_type" mismatch: expected "int" but received "Final" (reportAssertTypeFailure) +dataclasses_final.py:16:20 - error: Cannot assign to attribute "final_classvar" for class "type[D]" +  "Literal[10]" is incompatible with "Final" (reportAttributeAccessIssue) +dataclasses_final.py:24:3 - error: Cannot assign to attribute "final_no_default" for class "D" +  "final_no_default" is declared as Final and cannot be reassigned +    Attribute "__set__" is unknown (reportAttributeAccessIssue) +dataclasses_final.py:25:3 - error: Cannot assign to attribute "final_with_default" for class "D" +  "final_with_default" is declared as Final and cannot be reassigned +    Attribute "__set__" is unknown (reportAttributeAccessIssue) +dataclasses_final.py:26:3 - error: Cannot assign to attribute "final_no_default" for class "type[D]" +  "final_no_default" is declared as Final and cannot be reassigned +    Attribute "__set__" is unknown (reportAttributeAccessIssue) +dataclasses_final.py:27:3 - error: Cannot assign to attribute "final_with_default" for class "type[D]" +  "final_with_default" is declared as Final and cannot be reassigned +    Attribute "__set__" is unknown (reportAttributeAccessIssue) +""" diff --git a/conformance/results/pyright/version.toml b/conformance/results/pyright/version.toml index aaff8bf7d..374e2a77a 100644 --- a/conformance/results/pyright/version.toml +++ b/conformance/results/pyright/version.toml @@ -1,2 +1,2 @@ version = "pyright 1.1.363" -test_duration = 1.4 +test_duration = 1.7 diff --git a/conformance/results/pytype/dataclasses_final.toml b/conformance/results/pytype/dataclasses_final.toml new file mode 100644 index 000000000..d44e92418 --- /dev/null +++ b/conformance/results/pytype/dataclasses_final.toml @@ -0,0 +1,17 @@ +conformant = "Partial" +notes = """ +Doesn't handle Final nested inside ClassVar. +""" +errors_diff = """ +Line 16: Expected 1 errors +Line 24: Expected 1 errors +Line 26: Expected 1 errors +Line 8: Unexpected errors ['File "dataclasses_final.py", line 8, in D: Invalid use of typing.Final [final-error]', 'File "dataclasses_final.py", line 8, in D: Invalid type annotation \\'ClassVar[Final[int]]\\' [invalid-annotation]'] +""" +output = """ +File "dataclasses_final.py", line 8, in D: Invalid use of typing.Final [final-error] +File "dataclasses_final.py", line 8, in D: Invalid type annotation 'ClassVar[Final[int]]' [invalid-annotation] +File "dataclasses_final.py", line 25, in : Assigning to attribute final_with_default, which was annotated with Final [final-error] +File "dataclasses_final.py", line 27, in : Assigning to attribute final_with_default, which was annotated with Final [final-error] +""" +conformance_automated = "Fail" diff --git a/conformance/results/pytype/version.toml b/conformance/results/pytype/version.toml index d161daf29..f2e061f2c 100644 --- a/conformance/results/pytype/version.toml +++ b/conformance/results/pytype/version.toml @@ -1,2 +1,2 @@ version = "pytype 2024.04.11" -test_duration = 30.6 +test_duration = 28.3 diff --git a/conformance/results/results.html b/conformance/results/results.html index 4bd78ee23..a41899762 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -159,16 +159,16 @@

Python Type System Conformance Test Results

+ + + + + + diff --git a/conformance/tests/dataclasses_final.py b/conformance/tests/dataclasses_final.py new file mode 100644 index 000000000..4c7f40277 --- /dev/null +++ b/conformance/tests/dataclasses_final.py @@ -0,0 +1,27 @@ +from dataclasses import dataclass +from typing import assert_type, ClassVar, Final + +@dataclass +class D: + final_no_default: Final[int] + final_with_default: Final[str] = "foo" + final_classvar: ClassVar[Final[int]] = 4 + # we don't require support for Final[ClassVar[...]] because the dataclasses + # runtime implementation won't recognize it as a ClassVar either + +# An explicitly marked ClassVar can be accessed on the class: +assert_type(D.final_classvar, int) + +# ...but not assigned to, because it's Final: +D.final_classvar = 10 # E: can't assign to final attribute + +# A non-ClassVar attribute (with or without default) is a dataclass field: +d = D(final_no_default=1, final_with_default="bar") +assert_type(d.final_no_default, int) +assert_type(d.final_with_default, str) + +# ... but can't be assigned to (on the class or on an instance): +d.final_no_default = 10 # E: can't assign to final attribute +d.final_with_default = "baz" # E: can't assign to final attribute +D.final_no_default = 10 # E: can't assign to final attribute / can't assign instance attr on class +D.final_with_default = "baz" # E: can't assign to final attribute / can't assign instance attr on class diff --git a/conformance/tests/qualifiers_final_annotation.py b/conformance/tests/qualifiers_final_annotation.py index d85382caf..c20a82528 100644 --- a/conformance/tests/qualifiers_final_annotation.py +++ b/conformance/tests/qualifiers_final_annotation.py @@ -98,7 +98,7 @@ class ClassCChild(ClassC): # > Type checkers should infer a final attribute that is initialized in a class # > body as being a class variable. Variables should not be annotated with both -# > ClassVar and Final. +# > ClassVar and Final. (Except in a dataclass; see dataclasses_final.py.) class ClassD:
 
mypy 1.10.0
-
1.4sec
+
1.0sec
pyright 1.1.363
-
1.4sec
+
1.7sec
pyre 0.9.21
-
3.2sec
+
1.9sec
pytype 2024.04.11
-
30.6sec
+
28.3sec
@@ -690,6 +690,12 @@

Python Type System Conformance Test Results

Partial

Incorrectly generates error when calling constructor of dataclass with descriptor.

Unsupported

Does not understand descriptor objects in dataclass.

     dataclasses_final
Partial

Wrongly requires a Final dataclass field to be initialized at class level.

Doesn't support Final nested inside ClassVar.

Partial

Doesn't support Final nested inside ClassVar.

Partial

Mis-handles Final nested inside ClassVar.

Partial

Doesn't handle Final nested inside ClassVar.

     dataclasses_frozen Pass Pass