Skip to content

Commit 52aad76

Browse files
committed
Add conformance test for @final-decorated @Property
The language of the typing spec indicates that the @Final decorator may be used with properties: > The method decorator version may be used with all of instance methods, class methods, static methods, and properties. I noticed this case while working on Pyre. I observed that Mypy and Pyright also differ in behavior, so it seemed like a good conformance test to add. See discussion here: https://discuss.python.org/t/proposal-allow-chaining-final-decorator-when-previous-decorators-return-a-non-function/78918
1 parent b76a853 commit 52aad76

18 files changed

+198
-98
lines changed

conformance/results/mypy/qualifiers_final_decorator.toml

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
conformant = "Pass"
22
output = """
33
qualifiers_final_decorator.py:21: error: Cannot inherit from final class "Base1" [misc]
4-
qualifiers_final_decorator.py:56: error: Cannot override final attribute "method1" (previously declared in base class "Base2") [misc]
5-
qualifiers_final_decorator.py:59: error: Cannot override final attribute "method2" (previously declared in base class "Base2") [misc]
6-
qualifiers_final_decorator.py:63: error: Cannot override final attribute "method3" (previously declared in base class "Base2") [misc]
7-
qualifiers_final_decorator.py:67: error: Cannot override final attribute "method4" (previously declared in base class "Base2") [misc]
8-
qualifiers_final_decorator.py:80: error: Cannot override final attribute "method" (previously declared in base class "Base3") [misc]
9-
qualifiers_final_decorator.py:84: error: @final should be applied only to overload implementation [misc]
10-
qualifiers_final_decorator.py:94: error: Cannot override final attribute "method" (previously declared in base class "Base4") [misc]
11-
qualifiers_final_decorator.py:118: error: Cannot override final attribute "method" (previously declared in base class "Base5_2") [misc]
12-
qualifiers_final_decorator.py:118: error: Signature of "method" incompatible with supertype "Base5_2" [override]
13-
qualifiers_final_decorator.py:118: note: Superclass:
14-
qualifiers_final_decorator.py:118: note: def method(self, v: int) -> None
15-
qualifiers_final_decorator.py:118: note: Subclass:
16-
qualifiers_final_decorator.py:118: note: def method(self) -> None
17-
qualifiers_final_decorator.py:125: error: @final cannot be used with non-method functions [misc]
4+
qualifiers_final_decorator.py:64: error: Cannot override final attribute "method1" (previously declared in base class "Base2") [misc]
5+
qualifiers_final_decorator.py:67: error: Cannot override final attribute "method2" (previously declared in base class "Base2") [misc]
6+
qualifiers_final_decorator.py:71: error: Cannot override final attribute "method3" (previously declared in base class "Base2") [misc]
7+
qualifiers_final_decorator.py:75: error: Cannot override final attribute "method4" (previously declared in base class "Base2") [misc]
8+
qualifiers_final_decorator.py:86: error: Cannot override final attribute "method5" (previously declared in base class "Base2") [misc]
9+
qualifiers_final_decorator.py:92: error: Cannot override final attribute "method" (previously declared in base class "Base3") [misc]
10+
qualifiers_final_decorator.py:96: error: @final should be applied only to overload implementation [misc]
11+
qualifiers_final_decorator.py:106: error: Cannot override final attribute "method" (previously declared in base class "Base4") [misc]
12+
qualifiers_final_decorator.py:130: error: Cannot override final attribute "method" (previously declared in base class "Base5_2") [misc]
13+
qualifiers_final_decorator.py:130: error: Signature of "method" incompatible with supertype "Base5_2" [override]
14+
qualifiers_final_decorator.py:130: note: Superclass:
15+
qualifiers_final_decorator.py:130: note: def method(self, v: int) -> None
16+
qualifiers_final_decorator.py:130: note: Subclass:
17+
qualifiers_final_decorator.py:130: note: def method(self) -> None
18+
qualifiers_final_decorator.py:137: error: @final cannot be used with non-method functions [misc]
1819
"""
1920
conformance_automated = "Pass"
2021
errors_diff = """

conformance/results/mypy/version.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
version = "mypy 1.14.0"
2-
test_duration = 1.6
1+
version = "mypy 1.14.1"
2+
test_duration = 3.3

conformance/results/pyre/qualifiers_final_decorator.toml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,19 @@ Reports misleading error when overload is marked @final but implementation is no
77
output = """
88
qualifiers_final_decorator.py:21:0 Invalid inheritance [39]: Cannot inherit from final class `Base1`.
99
qualifiers_final_decorator.py:51:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
10-
qualifiers_final_decorator.py:56:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method1` cannot override final method defined in `Base2`.
11-
qualifiers_final_decorator.py:60:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method2` cannot override final method defined in `Base2`.
12-
qualifiers_final_decorator.py:64:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method3` cannot override final method defined in `Base2`.
13-
qualifiers_final_decorator.py:75:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method4` cannot override final method defined in `Base2`.
14-
qualifiers_final_decorator.py:86:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
15-
qualifiers_final_decorator.py:118:4 Inconsistent override [14]: `qualifiers_final_decorator.Derived5.method` overrides method defined in `Base5_2` inconsistently. Could not find parameter `v` in overriding signature.
16-
qualifiers_final_decorator.py:118:4 Invalid override [40]: `qualifiers_final_decorator.Derived5.method` cannot override final method defined in `Base5_2`.
17-
qualifiers_final_decorator.py:126:0 Invalid inheritance [39]: `final` cannot be used with non-method functions.
10+
qualifiers_final_decorator.py:64:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method1` cannot override final method defined in `Base2`.
11+
qualifiers_final_decorator.py:68:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method2` cannot override final method defined in `Base2`.
12+
qualifiers_final_decorator.py:72:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method3` cannot override final method defined in `Base2`.
13+
qualifiers_final_decorator.py:83:4 Invalid override [40]: `qualifiers_final_decorator.Derived2.method4` cannot override final method defined in `Base2`.
14+
qualifiers_final_decorator.py:98:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).
15+
qualifiers_final_decorator.py:130:4 Inconsistent override [14]: `qualifiers_final_decorator.Derived5.method` overrides method defined in `Base5_2` inconsistently. Could not find parameter `v` in overriding signature.
16+
qualifiers_final_decorator.py:130:4 Invalid override [40]: `qualifiers_final_decorator.Derived5.method` cannot override final method defined in `Base5_2`.
17+
qualifiers_final_decorator.py:138:0 Invalid inheritance [39]: `final` cannot be used with non-method functions.
1818
"""
1919
conformance_automated = "Fail"
2020
errors_diff = """
21-
Lines 80, 89: Expected error (tag 'Derived3')
22-
Lines 94, 102: Expected error (tag 'Derived4')
21+
Lines 86, 87: Expected error (tag 'method5')
22+
Lines 92, 101: Expected error (tag 'Derived3')
23+
Lines 106, 114: Expected error (tag 'Derived4')
2324
Line 51: Unexpected errors ['qualifiers_final_decorator.py:51:4 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s).']
2425
"""

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 = 7.3
2+
test_duration = 10.0

conformance/results/pyright/aliases_explicit.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,25 @@ aliases_explicit.py:79:21 - error: Invalid expression form for type alias defini
1010
aliases_explicit.py:79:21 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
1111
aliases_explicit.py:80:21 - error: Invalid expression form for type alias definition (reportInvalidTypeForm)
1212
aliases_explicit.py:80:21 - error: List expression not allowed in type expression
13-
  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
13+
  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
1414
aliases_explicit.py:80:21 - error: Expected class but received "list[Unknown]" (reportGeneralTypeIssues)
1515
aliases_explicit.py:81:21 - error: Invalid expression form for type alias definition (reportInvalidTypeForm)
1616
aliases_explicit.py:81:21 - error: Tuple expression not allowed in type expression
17-
  Use tuple[T1, ..., Tn] to indicate a tuple type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
17+
  Use tuple[T1, ..., Tn] to indicate a tuple type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
1818
aliases_explicit.py:82:21 - error: Invalid expression form for type alias definition (reportInvalidTypeForm)
1919
aliases_explicit.py:82:21 - error: List expression not allowed in type expression
20-
  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
20+
  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
2121
aliases_explicit.py:82:21 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
2222
aliases_explicit.py:83:21 - error: Invalid expression form for type alias definition (reportInvalidTypeForm)
2323
aliases_explicit.py:83:21 - error: Dictionary expression not allowed in type expression
24-
  Use Dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
24+
  Use dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
2525
aliases_explicit.py:83:21 - error: Expected class but received "dict[str, Unknown]" (reportGeneralTypeIssues)
2626
aliases_explicit.py:83:28 - error: "b" is not defined (reportUndefinedVariable)
2727
aliases_explicit.py:84:21 - error: Invalid expression form for type alias definition (reportInvalidTypeForm)
2828
aliases_explicit.py:84:21 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
2929
aliases_explicit.py:85:21 - error: Invalid expression form for type alias definition (reportInvalidTypeForm)
3030
aliases_explicit.py:85:21 - error: List expression not allowed in type expression
31-
  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
31+
  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
3232
aliases_explicit.py:85:21 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
3333
aliases_explicit.py:85:27 - error: Expected class but received "Literal[0]" (reportGeneralTypeIssues)
3434
aliases_explicit.py:86:21 - error: Invalid expression form for type alias definition (reportInvalidTypeForm)

conformance/results/pyright/aliases_type_statement.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,20 @@ aliases_type_statement.py:31:22 - error: Argument of type "TypeAliasType" cannot
1414
    "TypeAliasType" is not assignable to "tuple[_ClassInfo, ...]" (reportArgumentType)
1515
aliases_type_statement.py:37:22 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
1616
aliases_type_statement.py:38:22 - error: List expression not allowed in type expression
17-
  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
17+
  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
1818
aliases_type_statement.py:38:22 - error: Expected class but received "list[Unknown]" (reportGeneralTypeIssues)
1919
aliases_type_statement.py:39:22 - error: Tuple expression not allowed in type expression
20-
  Use tuple[T1, ..., Tn] to indicate a tuple type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
20+
  Use tuple[T1, ..., Tn] to indicate a tuple type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
2121
aliases_type_statement.py:40:22 - error: List expression not allowed in type expression
22-
  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
22+
  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
2323
aliases_type_statement.py:40:22 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
2424
aliases_type_statement.py:41:22 - error: Dictionary expression not allowed in type expression
25-
  Use Dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
25+
  Use dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
2626
aliases_type_statement.py:41:22 - error: Expected class but received "dict[str, Unknown]" (reportGeneralTypeIssues)
2727
aliases_type_statement.py:41:29 - error: "b" is not defined (reportUndefinedVariable)
2828
aliases_type_statement.py:42:22 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
2929
aliases_type_statement.py:43:22 - error: List expression not allowed in type expression
30-
  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
30+
  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
3131
aliases_type_statement.py:43:22 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
3232
aliases_type_statement.py:43:28 - error: Expected class but received "Literal[0]" (reportGeneralTypeIssues)
3333
aliases_type_statement.py:44:22 - error: Ternary expression not allowed in type expression (reportInvalidTypeForm)

conformance/results/pyright/aliases_typealiastype.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ aliases_typealiastype.py:56:42 - error: Expected class but received "dict[str, U
1919
aliases_typealiastype.py:56:49 - error: "b" is not defined (reportUndefinedVariable)
2020
aliases_typealiastype.py:57:42 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
2121
aliases_typealiastype.py:58:42 - error: List expression not allowed in type expression
22-
  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
22+
  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
2323
aliases_typealiastype.py:58:42 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
2424
aliases_typealiastype.py:58:48 - error: Expected class but received "Literal[0]" (reportGeneralTypeIssues)
2525
aliases_typealiastype.py:59:42 - error: Ternary expression not allowed in type expression (reportInvalidTypeForm)

conformance/results/pyright/annotations_forward_refs.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ annotations_forward_refs.py:24:7 - error: Union syntax cannot be used with strin
66
annotations_forward_refs.py:25:13 - error: Union syntax cannot be used with string operand; use quotes around entire expression (reportGeneralTypeIssues)
77
annotations_forward_refs.py:41:10 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
88
annotations_forward_refs.py:42:10 - error: List expression not allowed in type expression
9-
  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
9+
  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
1010
annotations_forward_refs.py:42:10 - error: Expected class but received "list[Unknown]" (reportGeneralTypeIssues)
1111
annotations_forward_refs.py:43:10 - error: Tuple expression not allowed in type expression
12-
  Use tuple[T1, ..., Tn] to indicate a tuple type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
12+
  Use tuple[T1, ..., Tn] to indicate a tuple type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
1313
annotations_forward_refs.py:44:10 - error: List expression not allowed in type expression
14-
  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
14+
  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
1515
annotations_forward_refs.py:44:10 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
1616
annotations_forward_refs.py:45:10 - error: Dictionary expression not allowed in type expression
17-
  Use Dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
17+
  Use dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
1818
annotations_forward_refs.py:45:10 - error: Expected class but received "dict[Unknown, Unknown]" (reportGeneralTypeIssues)
1919
annotations_forward_refs.py:46:10 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
2020
annotations_forward_refs.py:47:10 - error: List expression not allowed in type expression
21-
  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
21+
  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
2222
annotations_forward_refs.py:47:10 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
2323
annotations_forward_refs.py:47:16 - error: Expected class but received "Literal[0]" (reportGeneralTypeIssues)
2424
annotations_forward_refs.py:48:10 - error: Ternary expression not allowed in type expression (reportInvalidTypeForm)

conformance/results/pyright/annotations_typeexpr.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@ conformant = "Pass"
22
output = """
33
annotations_typeexpr.py:88:9 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
44
annotations_typeexpr.py:89:9 - error: List expression not allowed in type expression
5-
  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
5+
  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
66
annotations_typeexpr.py:89:9 - error: Expected class but received "list[Unknown]" (reportGeneralTypeIssues)
77
annotations_typeexpr.py:90:9 - error: Tuple expression not allowed in type expression
8-
  Use tuple[T1, ..., Tn] to indicate a tuple type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
8+
  Use tuple[T1, ..., Tn] to indicate a tuple type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
99
annotations_typeexpr.py:91:9 - error: List expression not allowed in type expression
10-
  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
10+
  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
1111
annotations_typeexpr.py:91:9 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
1212
annotations_typeexpr.py:92:9 - error: Dictionary expression not allowed in type expression
13-
  Use Dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
13+
  Use dict[T1, T2] to indicate a dictionary type (reportInvalidTypeForm)
1414
annotations_typeexpr.py:92:9 - error: Expected class but received "dict[Unknown, Unknown]" (reportGeneralTypeIssues)
1515
annotations_typeexpr.py:93:9 - error: Call expression not allowed in type expression (reportInvalidTypeForm)
1616
annotations_typeexpr.py:94:9 - error: List expression not allowed in type expression
17-
  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
17+
  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
1818
annotations_typeexpr.py:94:9 - error: Expected class but received "list[type[int]]" (reportGeneralTypeIssues)
1919
annotations_typeexpr.py:94:15 - error: Expected class but received "Literal[0]" (reportGeneralTypeIssues)
2020
annotations_typeexpr.py:95:9 - error: Ternary expression not allowed in type expression (reportInvalidTypeForm)

conformance/results/pyright/generics_syntax_declarations.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ generics_syntax_declarations.py:32:11 - error: Cannot access attribute "is_integ
66
  Attribute "is_integer" is unknown (reportAttributeAccessIssue)
77
generics_syntax_declarations.py:44:21 - error: TypeVar constraint type cannot be generic (reportGeneralTypeIssues)
88
generics_syntax_declarations.py:48:17 - error: List expression not allowed in type expression
9-
  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportInvalidTypeForm)
9+
  Use list[T] to indicate a list type or T1 | T2 to indicate a union type (reportInvalidTypeForm)
1010
generics_syntax_declarations.py:48:17 - error: Expected class but received "list[Unknown]" (reportGeneralTypeIssues)
1111
generics_syntax_declarations.py:60:17 - error: TypeVar must have at least two constrained types (reportGeneralTypeIssues)
1212
generics_syntax_declarations.py:64:17 - error: TypeVar must have at least two constrained types (reportGeneralTypeIssues)

0 commit comments

Comments
 (0)