From 925b8dde0b73a849f447660f7404ddffa5b3f240 Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Fri, 17 Apr 2026 15:27:40 -0700 Subject: [PATCH 1/3] support conditional fields on TypedDict and NamedTuple --- .../mypy/namedtuples_define_class.toml | 41 +++++++++++-------- .../results/mypy/typeddicts_class_syntax.toml | 21 ++++++---- .../pyrefly/namedtuples_define_class.toml | 28 ++++++------- .../pyrefly/typeddicts_class_syntax.toml | 10 ++--- .../pyright/namedtuples_define_class.toml | 26 ++++++------ .../pyright/typeddicts_class_syntax.toml | 19 +++++---- conformance/results/results.html | 12 +++--- .../results/ty/namedtuples_define_class.toml | 26 ++++++------ .../results/ty/typeddicts_class_syntax.toml | 18 +++++--- .../zuban/namedtuples_define_class.toml | 32 +++++++++------ .../zuban/typeddicts_class_syntax.toml | 20 ++++++--- conformance/tests/namedtuples_define_class.py | 12 ++++++ conformance/tests/typeddicts_class_syntax.py | 12 ++++++ docs/spec/namedtuples.rst | 8 ++++ docs/spec/typeddict.rst | 7 +++- 15 files changed, 182 insertions(+), 110 deletions(-) diff --git a/conformance/results/mypy/namedtuples_define_class.toml b/conformance/results/mypy/namedtuples_define_class.toml index 575c5c0c8..72785e42f 100644 --- a/conformance/results/mypy/namedtuples_define_class.toml +++ b/conformance/results/mypy/namedtuples_define_class.toml @@ -1,29 +1,34 @@ conformant = "Partial" notes = """ Does not reject override of named tuple attribute in child class. +Does not support version-conditional fields. """ output = """ -namedtuples_define_class.py:32: error: Tuple index out of range [misc] namedtuples_define_class.py:33: error: Tuple index out of range [misc] -namedtuples_define_class.py:44: error: Missing positional argument "y" in call to "Point" [call-arg] +namedtuples_define_class.py:34: error: Tuple index out of range [misc] namedtuples_define_class.py:45: error: Missing positional argument "y" in call to "Point" [call-arg] -namedtuples_define_class.py:46: error: Argument 2 to "Point" has incompatible type "str"; expected "int" [arg-type] -namedtuples_define_class.py:47: error: Argument "units" to "Point" has incompatible type "int"; expected "str" [arg-type] -namedtuples_define_class.py:48: error: Too many arguments for "Point" [call-arg] -namedtuples_define_class.py:49: error: Unexpected keyword argument "other" for "Point" [call-arg] -namedtuples_define_class.py:59: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc] -namedtuples_define_class.py:65: error: Missing positional argument "units" in call to "Point2" [call-arg] -namedtuples_define_class.py:67: error: Too many values to unpack (2 expected, 3 provided) [misc] -namedtuples_define_class.py:76: error: NamedTuple field name cannot start with an underscore: _y [misc] -namedtuples_define_class.py:86: error: Non-default NamedTuple fields cannot follow default fields [misc] -namedtuples_define_class.py:125: error: Argument 2 to "Property" has incompatible type "float"; expected "str" [arg-type] -namedtuples_define_class.py:132: error: NamedTuple should be a single base [misc] +namedtuples_define_class.py:46: error: Missing positional argument "y" in call to "Point" [call-arg] +namedtuples_define_class.py:47: error: Argument 2 to "Point" has incompatible type "str"; expected "int" [arg-type] +namedtuples_define_class.py:48: error: Argument "units" to "Point" has incompatible type "int"; expected "str" [arg-type] +namedtuples_define_class.py:49: error: Too many arguments for "Point" [call-arg] +namedtuples_define_class.py:50: error: Unexpected keyword argument "other" for "Point" [call-arg] +namedtuples_define_class.py:60: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc] +namedtuples_define_class.py:66: error: Missing positional argument "units" in call to "Point2" [call-arg] +namedtuples_define_class.py:68: error: Too many values to unpack (2 expected, 3 provided) [misc] +namedtuples_define_class.py:77: error: NamedTuple field name cannot start with an underscore: _y [misc] +namedtuples_define_class.py:87: error: Non-default NamedTuple fields cannot follow default fields [misc] +namedtuples_define_class.py:114: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc] +namedtuples_define_class.py:118: error: Too many arguments for "ConditionalField" [call-arg] +namedtuples_define_class.py:137: error: Argument 2 to "Property" has incompatible type "float"; expected "str" [arg-type] +namedtuples_define_class.py:144: error: NamedTuple should be a single base [misc] """ conformance_automated = "Fail" errors_diff = """ -Line 69: Expected 1 errors -Line 106: Expected 1 errors -Line 59: Unexpected errors ['namedtuples_define_class.py:59: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc]'] -Line 65: Unexpected errors ['namedtuples_define_class.py:65: error: Missing positional argument "units" in call to "Point2" [call-arg]'] -Line 67: Unexpected errors ['namedtuples_define_class.py:67: error: Too many values to unpack (2 expected, 3 provided) [misc]'] +Line 70: Expected 1 errors +Line 107: Expected 1 errors +Line 60: Unexpected errors ['namedtuples_define_class.py:60: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc]'] +Line 66: Unexpected errors ['namedtuples_define_class.py:66: error: Missing positional argument "units" in call to "Point2" [call-arg]'] +Line 68: Unexpected errors ['namedtuples_define_class.py:68: error: Too many values to unpack (2 expected, 3 provided) [misc]'] +Line 114: Unexpected errors ['namedtuples_define_class.py:114: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc]'] +Line 118: Unexpected errors ['namedtuples_define_class.py:118: error: Too many arguments for "ConditionalField" [call-arg]'] """ diff --git a/conformance/results/mypy/typeddicts_class_syntax.toml b/conformance/results/mypy/typeddicts_class_syntax.toml index 76e44ef9b..573c04e3e 100644 --- a/conformance/results/mypy/typeddicts_class_syntax.toml +++ b/conformance/results/mypy/typeddicts_class_syntax.toml @@ -1,11 +1,18 @@ -conformant = "Pass" +conformant = "Partial" +notes = """ +Does not support version-conditional items in TypedDict definitions. +""" output = """ -typeddicts_class_syntax.py:29: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] -typeddicts_class_syntax.py:33: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] -typeddicts_class_syntax.py:38: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] -typeddicts_class_syntax.py:44: error: Unexpected keyword argument "metaclass" for "__init_subclass__" of "TypedDict" [call-arg] -typeddicts_class_syntax.py:49: error: Unexpected keyword argument "other" for "__init_subclass__" of "TypedDict" [call-arg] +typeddicts_class_syntax.py:30: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] +typeddicts_class_syntax.py:34: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] +typeddicts_class_syntax.py:39: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] +typeddicts_class_syntax.py:45: error: Unexpected keyword argument "metaclass" for "__init_subclass__" of "TypedDict" [call-arg] +typeddicts_class_syntax.py:50: error: Unexpected keyword argument "other" for "__init_subclass__" of "TypedDict" [call-arg] +typeddicts_class_syntax.py:58: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] +typeddicts_class_syntax.py:62: error: Extra key "y" for TypedDict "ConditionalField" [typeddict-unknown-key] """ -conformance_automated = "Pass" +conformance_automated = "Fail" errors_diff = """ +Line 58: Unexpected errors ['typeddicts_class_syntax.py:58: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc]'] +Line 62: Unexpected errors ['typeddicts_class_syntax.py:62: error: Extra key "y" for TypedDict "ConditionalField" [typeddict-unknown-key]'] """ diff --git a/conformance/results/pyrefly/namedtuples_define_class.toml b/conformance/results/pyrefly/namedtuples_define_class.toml index 706bce8fe..67af61d9e 100644 --- a/conformance/results/pyrefly/namedtuples_define_class.toml +++ b/conformance/results/pyrefly/namedtuples_define_class.toml @@ -3,18 +3,18 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ -ERROR namedtuples_define_class.py:32:10-11: Index 3 out of range for tuple with 3 elements [bad-index] -ERROR namedtuples_define_class.py:33:10-12: Index -4 out of range for tuple with 3 elements [bad-index] -ERROR namedtuples_define_class.py:44:11-14: Missing argument `y` in function `Point.__new__` [missing-argument] -ERROR namedtuples_define_class.py:45:11-16: Missing argument `y` in function `Point.__new__` [missing-argument] -ERROR namedtuples_define_class.py:46:15-17: Argument `Literal['']` is not assignable to parameter `y` with type `int` in function `Point.__new__` [bad-argument-type] -ERROR namedtuples_define_class.py:47:24-25: Argument `Literal[3]` is not assignable to parameter `units` with type `str` in function `Point.__new__` [bad-argument-type] -ERROR namedtuples_define_class.py:48:22-24: Expected 3 positional arguments, got 4 in function `Point.__new__` [bad-argument-count] -ERROR namedtuples_define_class.py:49:23-28: Unexpected keyword argument `other` in function `Point.__new__` [unexpected-keyword] -ERROR namedtuples_define_class.py:69:20-22: Expected 2 positional arguments, got 3 in function `Point2.__new__` [bad-argument-count] -ERROR namedtuples_define_class.py:76:5-7: NamedTuple field name may not start with an underscore: `_y` [bad-class-definition] -ERROR namedtuples_define_class.py:86:5-13: NamedTuple field 'latitude' without a default may not follow NamedTuple field with a default [bad-class-definition] -ERROR namedtuples_define_class.py:106:5-6: Cannot override named tuple element `x` [bad-override] -ERROR namedtuples_define_class.py:125:19-22: Argument `float` is not assignable to parameter `value` with type `str` in function `Property.__new__` [bad-argument-type] -ERROR namedtuples_define_class.py:132:7-11: Named tuples do not support multiple inheritance [invalid-inheritance] +ERROR namedtuples_define_class.py:33:10-11: Index 3 out of range for tuple with 3 elements [bad-index] +ERROR namedtuples_define_class.py:34:10-12: Index -4 out of range for tuple with 3 elements [bad-index] +ERROR namedtuples_define_class.py:45:11-14: Missing argument `y` in function `Point.__new__` [missing-argument] +ERROR namedtuples_define_class.py:46:11-16: Missing argument `y` in function `Point.__new__` [missing-argument] +ERROR namedtuples_define_class.py:47:15-17: Argument `Literal['']` is not assignable to parameter `y` with type `int` in function `Point.__new__` [bad-argument-type] +ERROR namedtuples_define_class.py:48:24-25: Argument `Literal[3]` is not assignable to parameter `units` with type `str` in function `Point.__new__` [bad-argument-type] +ERROR namedtuples_define_class.py:49:22-24: Expected 3 positional arguments, got 4 in function `Point.__new__` [bad-argument-count] +ERROR namedtuples_define_class.py:50:23-28: Unexpected keyword argument `other` in function `Point.__new__` [unexpected-keyword] +ERROR namedtuples_define_class.py:70:20-22: Expected 2 positional arguments, got 3 in function `Point2.__new__` [bad-argument-count] +ERROR namedtuples_define_class.py:77:5-7: NamedTuple field name may not start with an underscore: `_y` [bad-class-definition] +ERROR namedtuples_define_class.py:87:5-13: NamedTuple field 'latitude' without a default may not follow NamedTuple field with a default [bad-class-definition] +ERROR namedtuples_define_class.py:107:5-6: Cannot override named tuple element `x` [bad-override] +ERROR namedtuples_define_class.py:137:19-22: Argument `float` is not assignable to parameter `value` with type `str` in function `Property.__new__` [bad-argument-type] +ERROR namedtuples_define_class.py:144:7-11: Named tuples do not support multiple inheritance [invalid-inheritance] """ diff --git a/conformance/results/pyrefly/typeddicts_class_syntax.toml b/conformance/results/pyrefly/typeddicts_class_syntax.toml index 6e367e6d2..58e3bff54 100644 --- a/conformance/results/pyrefly/typeddicts_class_syntax.toml +++ b/conformance/results/pyrefly/typeddicts_class_syntax.toml @@ -3,9 +3,9 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ -ERROR typeddicts_class_syntax.py:29:9-16: TypedDict members must be declared in the form `field: Annotation` with no assignment [bad-class-definition] -ERROR typeddicts_class_syntax.py:34:9-16: TypedDict members must be declared in the form `field: Annotation` with no assignment [bad-class-definition] -ERROR typeddicts_class_syntax.py:39:9-16: TypedDict members must be declared in the form `field: Annotation` with no assignment [bad-class-definition] -ERROR typeddicts_class_syntax.py:44:7-20: Metaclass of `BadTypedDict2` has type `type[Any]` that is not a simple class type [invalid-inheritance] -ERROR typeddicts_class_syntax.py:49:7-20: TypedDict does not support keyword argument `other` [bad-typed-dict] +ERROR typeddicts_class_syntax.py:30:9-16: TypedDict members must be declared in the form `field: Annotation` with no assignment [bad-class-definition] +ERROR typeddicts_class_syntax.py:35:9-16: TypedDict members must be declared in the form `field: Annotation` with no assignment [bad-class-definition] +ERROR typeddicts_class_syntax.py:40:9-16: TypedDict members must be declared in the form `field: Annotation` with no assignment [bad-class-definition] +ERROR typeddicts_class_syntax.py:45:7-20: Metaclass of `BadTypedDict2` has type `type[Any]` that is not a simple class type [invalid-inheritance] +ERROR typeddicts_class_syntax.py:50:7-20: TypedDict does not support keyword argument `other` [bad-typed-dict] """ diff --git a/conformance/results/pyright/namedtuples_define_class.toml b/conformance/results/pyright/namedtuples_define_class.toml index e04b26fce..b4cc632cd 100644 --- a/conformance/results/pyright/namedtuples_define_class.toml +++ b/conformance/results/pyright/namedtuples_define_class.toml @@ -1,22 +1,22 @@ conformant = "Pass" output = """ -namedtuples_define_class.py:32:7 - error: Index 3 is out of range for type Point (reportGeneralTypeIssues) -namedtuples_define_class.py:33:7 - error: Index -4 is out of range for type Point (reportGeneralTypeIssues) -namedtuples_define_class.py:44:6 - error: Argument missing for parameter "y" (reportCallIssue) +namedtuples_define_class.py:33:7 - error: Index 3 is out of range for type Point (reportGeneralTypeIssues) +namedtuples_define_class.py:34:7 - error: Index -4 is out of range for type Point (reportGeneralTypeIssues) namedtuples_define_class.py:45:6 - error: Argument missing for parameter "y" (reportCallIssue) -namedtuples_define_class.py:46:15 - error: Argument of type "Literal['']" cannot be assigned to parameter "y" of type "int" in function "__new__" +namedtuples_define_class.py:46:6 - error: Argument missing for parameter "y" (reportCallIssue) +namedtuples_define_class.py:47:15 - error: Argument of type "Literal['']" cannot be assigned to parameter "y" of type "int" in function "__new__"   "Literal['']" is not assignable to "int" (reportArgumentType) -namedtuples_define_class.py:47:24 - error: Argument of type "Literal[3]" cannot be assigned to parameter "units" of type "str" in function "__new__" +namedtuples_define_class.py:48:24 - error: Argument of type "Literal[3]" cannot be assigned to parameter "units" of type "str" in function "__new__"   "Literal[3]" is not assignable to "str" (reportArgumentType) -namedtuples_define_class.py:48:22 - error: Expected 3 positional arguments (reportCallIssue) -namedtuples_define_class.py:49:23 - error: No parameter named "other" (reportCallIssue) -namedtuples_define_class.py:69:20 - error: Expected 2 positional arguments (reportCallIssue) -namedtuples_define_class.py:76:5 - error: Named tuple field names cannot start with an underscore (reportGeneralTypeIssues) -namedtuples_define_class.py:86:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues) -namedtuples_define_class.py:106:5 - error: Cannot override "x" because parent class "Point" is a named tuple (reportIncompatibleVariableOverride) -namedtuples_define_class.py:125:19 - error: Argument of type "float" cannot be assigned to parameter "value" of type "str" in function "__new__" +namedtuples_define_class.py:49:22 - error: Expected 3 positional arguments (reportCallIssue) +namedtuples_define_class.py:50:23 - error: No parameter named "other" (reportCallIssue) +namedtuples_define_class.py:70:20 - error: Expected 2 positional arguments (reportCallIssue) +namedtuples_define_class.py:77:5 - error: Named tuple field names cannot start with an underscore (reportGeneralTypeIssues) +namedtuples_define_class.py:87:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues) +namedtuples_define_class.py:107:5 - error: Cannot override "x" because parent class "Point" is a named tuple (reportIncompatibleVariableOverride) +namedtuples_define_class.py:137:19 - error: Argument of type "float" cannot be assigned to parameter "value" of type "str" in function "__new__"   "float" is not assignable to "str" (reportArgumentType) -namedtuples_define_class.py:132:7 - error: Multiple inheritance with NamedTuple is not supported (reportGeneralTypeIssues) +namedtuples_define_class.py:144:7 - error: Multiple inheritance with NamedTuple is not supported (reportGeneralTypeIssues) """ conformance_automated = "Pass" errors_diff = """ diff --git a/conformance/results/pyright/typeddicts_class_syntax.toml b/conformance/results/pyright/typeddicts_class_syntax.toml index b518cd64a..5558eb7cc 100644 --- a/conformance/results/pyright/typeddicts_class_syntax.toml +++ b/conformance/results/pyright/typeddicts_class_syntax.toml @@ -1,11 +1,16 @@ -conformant = "Pass" +conformant = "Partial" +notes = """ +Does not support version-conditional items in TypedDict definitions. +""" output = """ -typeddicts_class_syntax.py:29:5 - error: TypedDict classes can contain only type annotations (reportGeneralTypeIssues) -typeddicts_class_syntax.py:33:5 - error: TypedDict classes can contain only type annotations (reportGeneralTypeIssues) -typeddicts_class_syntax.py:38:5 - error: TypedDict classes can contain only type annotations (reportGeneralTypeIssues) -typeddicts_class_syntax.py:44:32 - error: TypedDict does not support __init_subclass__ parameter "metaclass" (reportGeneralTypeIssues) -typeddicts_class_syntax.py:49:32 - error: TypedDict does not support __init_subclass__ parameter "other" (reportGeneralTypeIssues) +typeddicts_class_syntax.py:30:5 - error: TypedDict classes can contain only type annotations (reportGeneralTypeIssues) +typeddicts_class_syntax.py:34:5 - error: TypedDict classes can contain only type annotations (reportGeneralTypeIssues) +typeddicts_class_syntax.py:39:5 - error: TypedDict classes can contain only type annotations (reportGeneralTypeIssues) +typeddicts_class_syntax.py:45:32 - error: TypedDict does not support __init_subclass__ parameter "metaclass" (reportGeneralTypeIssues) +typeddicts_class_syntax.py:50:32 - error: TypedDict does not support __init_subclass__ parameter "other" (reportGeneralTypeIssues) +typeddicts_class_syntax.py:58:5 - error: TypedDict classes can contain only type annotations (reportGeneralTypeIssues) """ -conformance_automated = "Pass" +conformance_automated = "Fail" errors_diff = """ +Line 58: Unexpected errors ['typeddicts_class_syntax.py:58:5 - error: TypedDict classes can contain only type annotations (reportGeneralTypeIssues)'] """ diff --git a/conformance/results/results.html b/conformance/results/results.html index b94b97b29..a7aee5b05 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -936,11 +936,11 @@

Python Type System Conformance Test Results

Pass      typeddicts_class_syntax +
Partial

Does not support version-conditional items in TypedDict definitions.

+
Partial

Does not support version-conditional items in TypedDict definitions.

+
Partial

Does not support version-conditional items in TypedDict definitions.

Pass -Pass -Pass -Pass -Pass +
Partial

Errors on version-conditional items in TypedDict definitions.

     typeddicts_extra_items
Unsupported

Not supported.

@@ -1054,9 +1054,9 @@

Python Type System Conformance Test Results

Named tuples      namedtuples_define_class -
Partial

Does not reject override of named tuple attribute in child class.

-Pass +
Partial

Does not reject override of named tuple attribute in child class.

Does not support version-conditional fields.

Pass +
Partial

Does not support version-conditional fields in NamedTuple definitions.

Pass Pass diff --git a/conformance/results/ty/namedtuples_define_class.toml b/conformance/results/ty/namedtuples_define_class.toml index fdf613b7d..d42221707 100644 --- a/conformance/results/ty/namedtuples_define_class.toml +++ b/conformance/results/ty/namedtuples_define_class.toml @@ -2,18 +2,18 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ -namedtuples_define_class.py:32:7: error[index-out-of-bounds] Index 3 is out of bounds for tuple `Point` with length 3 -namedtuples_define_class.py:33:7: error[index-out-of-bounds] Index -4 is out of bounds for tuple `Point` with length 3 -namedtuples_define_class.py:44:6: error[missing-argument] No argument provided for required parameter `y` +namedtuples_define_class.py:33:7: error[index-out-of-bounds] Index 3 is out of bounds for tuple `Point` with length 3 +namedtuples_define_class.py:34:7: error[index-out-of-bounds] Index -4 is out of bounds for tuple `Point` with length 3 namedtuples_define_class.py:45:6: error[missing-argument] No argument provided for required parameter `y` -namedtuples_define_class.py:46:15: error[invalid-argument-type] Argument is incorrect: Expected `int`, found `Literal[""]` -namedtuples_define_class.py:47:18: error[invalid-argument-type] Argument is incorrect: Expected `str`, found `Literal[3]` -namedtuples_define_class.py:48:22: error[too-many-positional-arguments] Too many positional arguments: expected 4, got 5 -namedtuples_define_class.py:49:23: error[unknown-argument] Argument `other` does not match any known parameter -namedtuples_define_class.py:69:20: error[too-many-positional-arguments] Too many positional arguments: expected 3, got 4 -namedtuples_define_class.py:76:5: error[invalid-named-tuple] NamedTuple field `_y` cannot start with an underscore -namedtuples_define_class.py:86:5: error[invalid-named-tuple] NamedTuple field without default value cannot follow field(s) with default value(s): Field `latitude` defined here without a default value -namedtuples_define_class.py:106:5: error[invalid-named-tuple-override] Cannot override NamedTuple field `x` inherited from `Point` -namedtuples_define_class.py:125:19: error[invalid-argument-type] Argument is incorrect: Expected `str`, found `float` -namedtuples_define_class.py:132:24: error[invalid-named-tuple] NamedTuple class `Unit` cannot use multiple inheritance except with `Generic[]` +namedtuples_define_class.py:46:6: error[missing-argument] No argument provided for required parameter `y` +namedtuples_define_class.py:47:15: error[invalid-argument-type] Argument is incorrect: Expected `int`, found `Literal[""]` +namedtuples_define_class.py:48:18: error[invalid-argument-type] Argument is incorrect: Expected `str`, found `Literal[3]` +namedtuples_define_class.py:49:22: error[too-many-positional-arguments] Too many positional arguments: expected 4, got 5 +namedtuples_define_class.py:50:23: error[unknown-argument] Argument `other` does not match any known parameter +namedtuples_define_class.py:70:20: error[too-many-positional-arguments] Too many positional arguments: expected 3, got 4 +namedtuples_define_class.py:77:5: error[invalid-named-tuple] NamedTuple field `_y` cannot start with an underscore +namedtuples_define_class.py:87:5: error[invalid-named-tuple] NamedTuple field without default value cannot follow field(s) with default value(s): Field `latitude` defined here without a default value +namedtuples_define_class.py:107:5: error[invalid-named-tuple-override] Cannot override NamedTuple field `x` inherited from `Point` +namedtuples_define_class.py:137:19: error[invalid-argument-type] Argument is incorrect: Expected `str`, found `float` +namedtuples_define_class.py:144:24: error[invalid-named-tuple] NamedTuple class `Unit` cannot use multiple inheritance except with `Generic[]` """ diff --git a/conformance/results/ty/typeddicts_class_syntax.toml b/conformance/results/ty/typeddicts_class_syntax.toml index 691787e7c..f5f0a4af1 100644 --- a/conformance/results/ty/typeddicts_class_syntax.toml +++ b/conformance/results/ty/typeddicts_class_syntax.toml @@ -1,10 +1,16 @@ -conformance_automated = "Pass" +conformant = "Partial" +notes = """ +Errors on version-conditional items in TypedDict definitions. +""" +conformance_automated = "Fail" errors_diff = """ +Line 58: Unexpected errors ['typeddicts_class_syntax.py:58:5: error[invalid-typed-dict-statement] invalid statement in TypedDict class body'] """ output = """ -typeddicts_class_syntax.py:29:5: error[invalid-typed-dict-statement] TypedDict class cannot have methods -typeddicts_class_syntax.py:33:5: error[invalid-typed-dict-statement] TypedDict class cannot have methods -typeddicts_class_syntax.py:38:5: error[invalid-typed-dict-statement] TypedDict class cannot have methods -typeddicts_class_syntax.py:44:32: error[invalid-typed-dict-header] Custom metaclasses are not supported in `TypedDict` definitions -typeddicts_class_syntax.py:49:32: error[unknown-argument] Unknown keyword argument `other` in `TypedDict` definition +typeddicts_class_syntax.py:30:5: error[invalid-typed-dict-statement] TypedDict class cannot have methods +typeddicts_class_syntax.py:34:5: error[invalid-typed-dict-statement] TypedDict class cannot have methods +typeddicts_class_syntax.py:39:5: error[invalid-typed-dict-statement] TypedDict class cannot have methods +typeddicts_class_syntax.py:45:32: error[invalid-typed-dict-header] Custom metaclasses are not supported in `TypedDict` definitions +typeddicts_class_syntax.py:50:32: error[unknown-argument] Unknown keyword argument `other` in `TypedDict` definition +typeddicts_class_syntax.py:58:5: error[invalid-typed-dict-statement] invalid statement in TypedDict class body """ diff --git a/conformance/results/zuban/namedtuples_define_class.toml b/conformance/results/zuban/namedtuples_define_class.toml index e2e3edeb4..b54a9d0f7 100644 --- a/conformance/results/zuban/namedtuples_define_class.toml +++ b/conformance/results/zuban/namedtuples_define_class.toml @@ -1,21 +1,27 @@ +conformant = "Partial" notes = """ +Does not support version-conditional fields in NamedTuple definitions. """ -conformance_automated = "Pass" +conformance_automated = "Fail" errors_diff = """ +Line 114: Unexpected errors ['namedtuples_define_class.py:114: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc]'] +Line 118: Unexpected errors ['namedtuples_define_class.py:118: error: Too many arguments for "ConditionalField" [call-arg]'] """ output = """ -namedtuples_define_class.py:32: error: Tuple index out of range [misc] namedtuples_define_class.py:33: error: Tuple index out of range [misc] -namedtuples_define_class.py:44: error: Missing positional argument "y" in call to "Point" [call-arg] +namedtuples_define_class.py:34: error: Tuple index out of range [misc] namedtuples_define_class.py:45: error: Missing positional argument "y" in call to "Point" [call-arg] -namedtuples_define_class.py:46: error: Argument 2 to "Point" has incompatible type "str"; expected "int" [arg-type] -namedtuples_define_class.py:47: error: Argument "units" to "Point" has incompatible type "int"; expected "str" [arg-type] -namedtuples_define_class.py:48: error: Too many arguments for "Point" [call-arg] -namedtuples_define_class.py:49: error: Unexpected keyword argument "other" for "Point" [call-arg] -namedtuples_define_class.py:69: error: Too many arguments for "Point2" [call-arg] -namedtuples_define_class.py:76: error: NamedTuple field name cannot start with an underscore: _y [misc] -namedtuples_define_class.py:86: error: Non-default NamedTuple fields cannot follow default fields [misc] -namedtuples_define_class.py:106: error: NamedTuple attributes cannot be overridden in subclasses [misc] -namedtuples_define_class.py:125: error: Argument 2 to "Property" has incompatible type "float"; expected "str" [arg-type] -namedtuples_define_class.py:132: error: NamedTuple should be a single base [misc] +namedtuples_define_class.py:46: error: Missing positional argument "y" in call to "Point" [call-arg] +namedtuples_define_class.py:47: error: Argument 2 to "Point" has incompatible type "str"; expected "int" [arg-type] +namedtuples_define_class.py:48: error: Argument "units" to "Point" has incompatible type "int"; expected "str" [arg-type] +namedtuples_define_class.py:49: error: Too many arguments for "Point" [call-arg] +namedtuples_define_class.py:50: error: Unexpected keyword argument "other" for "Point" [call-arg] +namedtuples_define_class.py:70: error: Too many arguments for "Point2" [call-arg] +namedtuples_define_class.py:77: error: NamedTuple field name cannot start with an underscore: _y [misc] +namedtuples_define_class.py:87: error: Non-default NamedTuple fields cannot follow default fields [misc] +namedtuples_define_class.py:107: error: NamedTuple attributes cannot be overridden in subclasses [misc] +namedtuples_define_class.py:114: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc] +namedtuples_define_class.py:118: error: Too many arguments for "ConditionalField" [call-arg] +namedtuples_define_class.py:137: error: Argument 2 to "Property" has incompatible type "float"; expected "str" [arg-type] +namedtuples_define_class.py:144: error: NamedTuple should be a single base [misc] """ diff --git a/conformance/results/zuban/typeddicts_class_syntax.toml b/conformance/results/zuban/typeddicts_class_syntax.toml index 68741c76d..588fe8697 100644 --- a/conformance/results/zuban/typeddicts_class_syntax.toml +++ b/conformance/results/zuban/typeddicts_class_syntax.toml @@ -1,10 +1,18 @@ -conformance_automated = "Pass" +conformant = "Partial" +notes = """ +Does not support version-conditional items in TypedDict definitions. +""" +conformance_automated = "Fail" errors_diff = """ +Line 58: Unexpected errors ['typeddicts_class_syntax.py:58: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc]'] +Line 62: Unexpected errors ['typeddicts_class_syntax.py:62: error: Extra key "y" for TypedDict "ConditionalField" [typeddict-unknown-key]'] """ output = """ -typeddicts_class_syntax.py:29: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] -typeddicts_class_syntax.py:33: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] -typeddicts_class_syntax.py:38: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] -typeddicts_class_syntax.py:44: error: Unexpected keyword argument "metaclass" for "TypedDict" [call-arg] -typeddicts_class_syntax.py:49: error: Unexpected keyword argument "other" for "TypedDict" [call-arg] +typeddicts_class_syntax.py:30: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] +typeddicts_class_syntax.py:34: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] +typeddicts_class_syntax.py:39: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] +typeddicts_class_syntax.py:45: error: Unexpected keyword argument "metaclass" for "TypedDict" [call-arg] +typeddicts_class_syntax.py:50: error: Unexpected keyword argument "other" for "TypedDict" [call-arg] +typeddicts_class_syntax.py:58: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] +typeddicts_class_syntax.py:62: error: Extra key "y" for TypedDict "ConditionalField" [typeddict-unknown-key] """ diff --git a/conformance/tests/namedtuples_define_class.py b/conformance/tests/namedtuples_define_class.py index 5e6e9c4cc..bf6acc2c9 100644 --- a/conformance/tests/namedtuples_define_class.py +++ b/conformance/tests/namedtuples_define_class.py @@ -7,6 +7,7 @@ # > Type checkers should support the class syntax from typing import Generic, NamedTuple, TypeVar, assert_type +import sys class Point(NamedTuple): @@ -105,6 +106,17 @@ class BadPointWithName(Point): name: str = "" # OK x: int = 0 # E +# > Namedtuple fields may be conditional, via checks of the same statically-known +# > conditions that a type-checker understands elsewhere, such as Python version:: + +class ConditionalField(NamedTuple): + x: int + if sys.version_info >= (3, 12): + y: str + +# The conformance suite runs type checkers configured to Python 3.12 or later: +ConditionalField(1, "hello") + # > In Python 3.11 and newer, the class syntax supports generic named tuple classes. # > Type checkers should support this. diff --git a/conformance/tests/typeddicts_class_syntax.py b/conformance/tests/typeddicts_class_syntax.py index b83f50bf7..f281fc84d 100644 --- a/conformance/tests/typeddicts_class_syntax.py +++ b/conformance/tests/typeddicts_class_syntax.py @@ -5,6 +5,7 @@ # Specification: https://typing.readthedocs.io/en/latest/spec/typeddict.html#typeddict from typing import Generic, TypeVar, TypedDict +import sys class Movie(TypedDict): @@ -49,6 +50,17 @@ class BadTypedDict2(TypedDict, metaclass=type): # E class BadTypedDict3(TypedDict, other=True): # E name: str +# > `if` conditions that the type checker is able to +# > statically evaluate are also permitted (e.g. `if sys.version_info > (3, 14)`), +# > in order to specify items that exist only under the given conditions. +class ConditionalField(TypedDict): + x: int + if sys.version_info >= (3, 12): + y: str + +# The conformance suite runs type checkers configured to Python 3.12 or later: +ConditionalField(x=1, y="hello") + # > TypedDicts may be made generic by adding Generic[T] among the bases. T = TypeVar("T") diff --git a/docs/spec/namedtuples.rst b/docs/spec/namedtuples.rst index 5ccf9d5b2..371fa8cf6 100644 --- a/docs/spec/namedtuples.rst +++ b/docs/spec/namedtuples.rst @@ -54,6 +54,14 @@ in the base class:: name: str # OK x: int # Type error (invalid override of named tuple field) +Namedtuple fields may be conditional, via checks of the same statically-known +conditions that a type-checker understands elsewhere, such as Python version:: + + class ConditionalField(NamedTuple): + x: int + if sys.version_info >= (3, 14): + y: str + In Python 3.11 and newer, the class syntax supports generic named tuple classes. Type checkers should support this:: diff --git a/docs/spec/typeddict.rst b/docs/spec/typeddict.rst index 81b72ea9c..b1496c104 100644 --- a/docs/spec/typeddict.rst +++ b/docs/spec/typeddict.rst @@ -124,8 +124,11 @@ in the class definition: The body of the class definition defines the :term:`items ` of the TypedDict type. It may also contain a docstring or ``pass`` statements (primarily to allow the creation of -an empty TypedDict). No other statements are allowed, and type checkers should report an -error if any are present. Type comments are not supported for creating TypedDict items. +an empty TypedDict). `if` conditions that the type checker is able to +statically evaluate are also permitted (e.g. `if sys.version_info > (3, 14)`), +in order to specify items that exist only under the given conditions. No other +statements are allowed, and type checkers should report an error if any are +present. Type comments are not supported for creating TypedDict items. .. _`required-notrequired`: .. _`required`: From ccd1133e2ea1ff2d002fa396295aecf701918009 Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Fri, 17 Apr 2026 17:55:19 -0700 Subject: [PATCH 2/3] crosslinks --- docs/spec/namedtuples.rst | 5 +++-- docs/spec/typeddict.rst | 16 +++++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/docs/spec/namedtuples.rst b/docs/spec/namedtuples.rst index 371fa8cf6..87a6e4332 100644 --- a/docs/spec/namedtuples.rst +++ b/docs/spec/namedtuples.rst @@ -54,8 +54,9 @@ in the base class:: name: str # OK x: int # Type error (invalid override of named tuple field) -Namedtuple fields may be conditional, via checks of the same statically-known -conditions that a type-checker understands elsewhere, such as Python version:: +Namedtuple fields may be conditional, via checks of the same +:ref:`statically-known conditions` +that a type-checker understands elsewhere, such as Python version:: class ConditionalField(NamedTuple): x: int diff --git a/docs/spec/typeddict.rst b/docs/spec/typeddict.rst index b1496c104..cff7e8499 100644 --- a/docs/spec/typeddict.rst +++ b/docs/spec/typeddict.rst @@ -122,13 +122,15 @@ in the class definition: :term:`read-only`. Other type qualifiers are not allowed. If the extra items type is ``Never``, no extra items are allowed, so this is equivalent to ``closed=True``. -The body of the class definition defines the :term:`items ` of the TypedDict type. -It may also contain a docstring or ``pass`` statements (primarily to allow the creation of -an empty TypedDict). `if` conditions that the type checker is able to -statically evaluate are also permitted (e.g. `if sys.version_info > (3, 14)`), -in order to specify items that exist only under the given conditions. No other -statements are allowed, and type checkers should report an error if any are -present. Type comments are not supported for creating TypedDict items. +The body of the class definition defines the :term:`items ` of the +TypedDict type. It may also contain a docstring or ``pass`` statements +(primarily to allow the creation of an empty TypedDict). `if` conditions that +the type checker is able to +:ref:`statically evaluate` are also permitted (e.g. +`if sys.version_info > (3, 14)`), in order to specify items that exist only under +the given conditions. No other statements are allowed, and type checkers should +report an error if any are present. Type comments are not supported for +creating TypedDict items. .. _`required-notrequired`: .. _`required`: From 7453d9cec31420fa54366095afbea614e07d5485 Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Mon, 20 Apr 2026 15:48:12 -0700 Subject: [PATCH 3/3] Clarify enums and dataclasses, more thorough test --- .../results/mypy/dataclasses_usage.toml | 25 ++++++++++--------- .../results/mypy/enums_definition.toml | 1 + .../mypy/namedtuples_define_class.toml | 11 +++++--- .../results/mypy/typeddicts_class_syntax.toml | 7 ++++-- .../results/pyrefly/dataclasses_usage.toml | 23 +++++++++-------- .../results/pyrefly/enums_definition.toml | 1 + .../pyrefly/namedtuples_define_class.toml | 5 ++-- .../pyrefly/typeddicts_class_syntax.toml | 1 + .../results/pyright/dataclasses_usage.toml | 25 ++++++++++--------- .../results/pyright/enums_definition.toml | 2 ++ .../pyright/namedtuples_define_class.toml | 5 ++-- .../pyright/typeddicts_class_syntax.toml | 4 +++ conformance/results/results.html | 2 +- conformance/results/ty/dataclasses_usage.toml | 23 +++++++++-------- conformance/results/ty/enums_definition.toml | 5 ++-- .../results/ty/namedtuples_define_class.toml | 5 ++-- .../results/ty/typeddicts_class_syntax.toml | 8 +++--- .../results/zuban/dataclasses_usage.toml | 23 +++++++++-------- .../results/zuban/enums_definition.toml | 3 ++- .../zuban/namedtuples_define_class.toml | 11 +++++--- .../zuban/typeddicts_class_syntax.toml | 7 ++++-- conformance/tests/dataclasses_usage.py | 18 +++++++++++++ conformance/tests/enums_definition.py | 18 +++++++++++++ conformance/tests/namedtuples_define_class.py | 7 ++++-- conformance/tests/typeddicts_class_syntax.py | 7 ++++-- docs/spec/dataclasses.rst | 13 ++++++++++ docs/spec/enums.rst | 9 +++++++ 27 files changed, 181 insertions(+), 88 deletions(-) diff --git a/conformance/results/mypy/dataclasses_usage.toml b/conformance/results/mypy/dataclasses_usage.toml index 978642d09..25f6f3026 100644 --- a/conformance/results/mypy/dataclasses_usage.toml +++ b/conformance/results/mypy/dataclasses_usage.toml @@ -3,18 +3,19 @@ notes = """ Does not detect unannotated usage of `dataclasses.field()`. """ output = """ -dataclasses_usage.py:35: error: Accessing "__init__" on an instance is unsound, since instance.__init__ could be from an incompatible subclass [misc] -dataclasses_usage.py:50: error: Missing positional argument "unit_price" in call to "InventoryItem" [call-arg] -dataclasses_usage.py:51: error: Argument 2 to "InventoryItem" has incompatible type "str"; expected "float" [arg-type] -dataclasses_usage.py:52: error: Too many arguments for "InventoryItem" [call-arg] -dataclasses_usage.py:61: error: Attributes without a default cannot follow attributes with one [misc] -dataclasses_usage.py:67: error: Attributes without a default cannot follow attributes with one [misc] -dataclasses_usage.py:73: error: Attributes without a default cannot follow attributes with one [misc] -dataclasses_usage.py:83: error: Too many arguments for "DC4" [call-arg] -dataclasses_usage.py:88: error: Incompatible types in assignment (expression has type "str", variable has type "int") [assignment] -dataclasses_usage.py:127: error: Too many arguments for "DC7" [call-arg] -dataclasses_usage.py:130: error: Missing positional argument "y" in call to "DC8" [call-arg] -dataclasses_usage.py:179: error: Too many arguments for "DC13" [call-arg] +dataclasses_usage.py:36: error: Accessing "__init__" on an instance is unsound, since instance.__init__ could be from an incompatible subclass [misc] +dataclasses_usage.py:51: error: Missing positional argument "unit_price" in call to "InventoryItem" [call-arg] +dataclasses_usage.py:52: error: Argument 2 to "InventoryItem" has incompatible type "str"; expected "float" [arg-type] +dataclasses_usage.py:53: error: Too many arguments for "InventoryItem" [call-arg] +dataclasses_usage.py:62: error: Attributes without a default cannot follow attributes with one [misc] +dataclasses_usage.py:68: error: Attributes without a default cannot follow attributes with one [misc] +dataclasses_usage.py:74: error: Attributes without a default cannot follow attributes with one [misc] +dataclasses_usage.py:84: error: Too many arguments for "DC4" [call-arg] +dataclasses_usage.py:89: error: Incompatible types in assignment (expression has type "str", variable has type "int") [assignment] +dataclasses_usage.py:128: error: Too many arguments for "DC7" [call-arg] +dataclasses_usage.py:131: error: Missing positional argument "y" in call to "DC8" [call-arg] +dataclasses_usage.py:180: error: Too many arguments for "DC13" [call-arg] +dataclasses_usage.py:246: error: Too many arguments for "DC19" [call-arg] """ conformance_automated = "Pass" errors_diff = """ diff --git a/conformance/results/mypy/enums_definition.toml b/conformance/results/mypy/enums_definition.toml index 513dbe853..06368c88e 100644 --- a/conformance/results/mypy/enums_definition.toml +++ b/conformance/results/mypy/enums_definition.toml @@ -2,5 +2,6 @@ conformant = "Pass" errors_diff = """ """ output = """ +enums_definition.py:92: error: "type[Color12]" has no attribute "BLUE" [attr-defined] """ conformance_automated = "Pass" diff --git a/conformance/results/mypy/namedtuples_define_class.toml b/conformance/results/mypy/namedtuples_define_class.toml index 72785e42f..12c4dc552 100644 --- a/conformance/results/mypy/namedtuples_define_class.toml +++ b/conformance/results/mypy/namedtuples_define_class.toml @@ -18,9 +18,11 @@ namedtuples_define_class.py:68: error: Too many values to unpack (2 expected, 3 namedtuples_define_class.py:77: error: NamedTuple field name cannot start with an underscore: _y [misc] namedtuples_define_class.py:87: error: Non-default NamedTuple fields cannot follow default fields [misc] namedtuples_define_class.py:114: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc] -namedtuples_define_class.py:118: error: Too many arguments for "ConditionalField" [call-arg] -namedtuples_define_class.py:137: error: Argument 2 to "Property" has incompatible type "float"; expected "str" [arg-type] -namedtuples_define_class.py:144: error: NamedTuple should be a single base [misc] +namedtuples_define_class.py:116: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc] +namedtuples_define_class.py:120: error: Too many arguments for "ConditionalField" [call-arg] +namedtuples_define_class.py:121: error: Too many arguments for "ConditionalField" [call-arg] +namedtuples_define_class.py:140: error: Argument 2 to "Property" has incompatible type "float"; expected "str" [arg-type] +namedtuples_define_class.py:147: error: NamedTuple should be a single base [misc] """ conformance_automated = "Fail" errors_diff = """ @@ -30,5 +32,6 @@ Line 60: Unexpected errors ['namedtuples_define_class.py:60: error: Invalid stat Line 66: Unexpected errors ['namedtuples_define_class.py:66: error: Missing positional argument "units" in call to "Point2" [call-arg]'] Line 68: Unexpected errors ['namedtuples_define_class.py:68: error: Too many values to unpack (2 expected, 3 provided) [misc]'] Line 114: Unexpected errors ['namedtuples_define_class.py:114: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc]'] -Line 118: Unexpected errors ['namedtuples_define_class.py:118: error: Too many arguments for "ConditionalField" [call-arg]'] +Line 116: Unexpected errors ['namedtuples_define_class.py:116: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc]'] +Line 120: Unexpected errors ['namedtuples_define_class.py:120: error: Too many arguments for "ConditionalField" [call-arg]'] """ diff --git a/conformance/results/mypy/typeddicts_class_syntax.toml b/conformance/results/mypy/typeddicts_class_syntax.toml index 573c04e3e..29220811d 100644 --- a/conformance/results/mypy/typeddicts_class_syntax.toml +++ b/conformance/results/mypy/typeddicts_class_syntax.toml @@ -9,10 +9,13 @@ typeddicts_class_syntax.py:39: error: Invalid statement in TypedDict definition; typeddicts_class_syntax.py:45: error: Unexpected keyword argument "metaclass" for "__init_subclass__" of "TypedDict" [call-arg] typeddicts_class_syntax.py:50: error: Unexpected keyword argument "other" for "__init_subclass__" of "TypedDict" [call-arg] typeddicts_class_syntax.py:58: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] -typeddicts_class_syntax.py:62: error: Extra key "y" for TypedDict "ConditionalField" [typeddict-unknown-key] +typeddicts_class_syntax.py:60: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] +typeddicts_class_syntax.py:64: error: Extra key "y" for TypedDict "ConditionalField" [typeddict-unknown-key] +typeddicts_class_syntax.py:65: error: Extra keys ("y", "z") for TypedDict "ConditionalField" [typeddict-unknown-key] """ conformance_automated = "Fail" errors_diff = """ Line 58: Unexpected errors ['typeddicts_class_syntax.py:58: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc]'] -Line 62: Unexpected errors ['typeddicts_class_syntax.py:62: error: Extra key "y" for TypedDict "ConditionalField" [typeddict-unknown-key]'] +Line 60: Unexpected errors ['typeddicts_class_syntax.py:60: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc]'] +Line 64: Unexpected errors ['typeddicts_class_syntax.py:64: error: Extra key "y" for TypedDict "ConditionalField" [typeddict-unknown-key]'] """ diff --git a/conformance/results/pyrefly/dataclasses_usage.toml b/conformance/results/pyrefly/dataclasses_usage.toml index c8156fc6e..a289244ab 100644 --- a/conformance/results/pyrefly/dataclasses_usage.toml +++ b/conformance/results/pyrefly/dataclasses_usage.toml @@ -3,15 +3,16 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ -ERROR dataclasses_usage.py:50:19-27: Missing argument `unit_price` in function `InventoryItem.__init__` [missing-argument] -ERROR dataclasses_usage.py:51:28-35: Argument `Literal['price']` is not assignable to parameter `unit_price` with type `float` in function `InventoryItem.__init__` [bad-argument-type] -ERROR dataclasses_usage.py:52:36-37: Expected 3 positional arguments, got 4 in function `InventoryItem.__init__` [bad-argument-count] -ERROR dataclasses_usage.py:61:5-6: Dataclass field `b` without a default may not follow dataclass field with a default [bad-class-definition] -ERROR dataclasses_usage.py:67:5-6: Dataclass field `b` without a default may not follow dataclass field with a default [bad-class-definition] -ERROR dataclasses_usage.py:73:5-6: Dataclass field `b` without a default may not follow dataclass field with a default [bad-class-definition] -ERROR dataclasses_usage.py:83:13-14: Expected 1 positional argument, got 2 in function `DC4.__init__` [bad-argument-count] -ERROR dataclasses_usage.py:88:14-40: `str` is not assignable to `int` [bad-assignment] -ERROR dataclasses_usage.py:127:8-9: Expected 1 positional argument, got 2 in function `DC7.__init__` [bad-argument-count] -ERROR dataclasses_usage.py:130:4-7: Missing argument `y` in function `DC8.__init__` [missing-argument] -ERROR dataclasses_usage.py:179:6-7: Expected 0 positional arguments, got 1 in function `object.__init__` [bad-argument-count] +ERROR dataclasses_usage.py:51:19-27: Missing argument `unit_price` in function `InventoryItem.__init__` [missing-argument] +ERROR dataclasses_usage.py:52:28-35: Argument `Literal['price']` is not assignable to parameter `unit_price` with type `float` in function `InventoryItem.__init__` [bad-argument-type] +ERROR dataclasses_usage.py:53:36-37: Expected 3 positional arguments, got 4 in function `InventoryItem.__init__` [bad-argument-count] +ERROR dataclasses_usage.py:62:5-6: Dataclass field `b` without a default may not follow dataclass field with a default [bad-class-definition] +ERROR dataclasses_usage.py:68:5-6: Dataclass field `b` without a default may not follow dataclass field with a default [bad-class-definition] +ERROR dataclasses_usage.py:74:5-6: Dataclass field `b` without a default may not follow dataclass field with a default [bad-class-definition] +ERROR dataclasses_usage.py:84:13-14: Expected 1 positional argument, got 2 in function `DC4.__init__` [bad-argument-count] +ERROR dataclasses_usage.py:89:14-40: `str` is not assignable to `int` [bad-assignment] +ERROR dataclasses_usage.py:128:8-9: Expected 1 positional argument, got 2 in function `DC7.__init__` [bad-argument-count] +ERROR dataclasses_usage.py:131:4-7: Missing argument `y` in function `DC8.__init__` [missing-argument] +ERROR dataclasses_usage.py:180:6-7: Expected 0 positional arguments, got 1 in function `object.__init__` [bad-argument-count] +ERROR dataclasses_usage.py:246:12-13: Expected 2 positional arguments, got 3 in function `DC19.__init__` [bad-argument-count] """ diff --git a/conformance/results/pyrefly/enums_definition.toml b/conformance/results/pyrefly/enums_definition.toml index be211bd5b..22ed73f5d 100644 --- a/conformance/results/pyrefly/enums_definition.toml +++ b/conformance/results/pyrefly/enums_definition.toml @@ -3,4 +3,5 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ +ERROR enums_definition.py:92:1-13: Class `Color12` has no class attribute `BLUE` [missing-attribute] """ diff --git a/conformance/results/pyrefly/namedtuples_define_class.toml b/conformance/results/pyrefly/namedtuples_define_class.toml index 67af61d9e..e98b6c716 100644 --- a/conformance/results/pyrefly/namedtuples_define_class.toml +++ b/conformance/results/pyrefly/namedtuples_define_class.toml @@ -15,6 +15,7 @@ ERROR namedtuples_define_class.py:70:20-22: Expected 2 positional arguments, got ERROR namedtuples_define_class.py:77:5-7: NamedTuple field name may not start with an underscore: `_y` [bad-class-definition] ERROR namedtuples_define_class.py:87:5-13: NamedTuple field 'latitude' without a default may not follow NamedTuple field with a default [bad-class-definition] ERROR namedtuples_define_class.py:107:5-6: Cannot override named tuple element `x` [bad-override] -ERROR namedtuples_define_class.py:137:19-22: Argument `float` is not assignable to parameter `value` with type `str` in function `Property.__new__` [bad-argument-type] -ERROR namedtuples_define_class.py:144:7-11: Named tuples do not support multiple inheritance [invalid-inheritance] +ERROR namedtuples_define_class.py:121:24-25: Expected 2 positional arguments, got 3 in function `ConditionalField.__new__` [bad-argument-count] +ERROR namedtuples_define_class.py:140:19-22: Argument `float` is not assignable to parameter `value` with type `str` in function `Property.__new__` [bad-argument-type] +ERROR namedtuples_define_class.py:147:7-11: Named tuples do not support multiple inheritance [invalid-inheritance] """ diff --git a/conformance/results/pyrefly/typeddicts_class_syntax.toml b/conformance/results/pyrefly/typeddicts_class_syntax.toml index 58e3bff54..2917003cf 100644 --- a/conformance/results/pyrefly/typeddicts_class_syntax.toml +++ b/conformance/results/pyrefly/typeddicts_class_syntax.toml @@ -8,4 +8,5 @@ ERROR typeddicts_class_syntax.py:35:9-16: TypedDict members must be declared in ERROR typeddicts_class_syntax.py:40:9-16: TypedDict members must be declared in the form `field: Annotation` with no assignment [bad-class-definition] ERROR typeddicts_class_syntax.py:45:7-20: Metaclass of `BadTypedDict2` has type `type[Any]` that is not a simple class type [invalid-inheritance] ERROR typeddicts_class_syntax.py:50:7-20: TypedDict does not support keyword argument `other` [bad-typed-dict] +ERROR typeddicts_class_syntax.py:65:17-32: No matching overload found for function `ConditionalField.__init__` called with arguments: (x=Literal[1], y=Literal[2], z=Literal[3]) [no-matching-overload] """ diff --git a/conformance/results/pyright/dataclasses_usage.toml b/conformance/results/pyright/dataclasses_usage.toml index 67ec33f28..62d5a0cb7 100644 --- a/conformance/results/pyright/dataclasses_usage.toml +++ b/conformance/results/pyright/dataclasses_usage.toml @@ -1,19 +1,20 @@ conformant = "Pass" output = """ -dataclasses_usage.py:50:6 - error: Argument missing for parameter "unit_price" (reportCallIssue) -dataclasses_usage.py:51:28 - error: Argument of type "Literal['price']" cannot be assigned to parameter "unit_price" of type "float" in function "__init__" +dataclasses_usage.py:51:6 - error: Argument missing for parameter "unit_price" (reportCallIssue) +dataclasses_usage.py:52:28 - error: Argument of type "Literal['price']" cannot be assigned to parameter "unit_price" of type "float" in function "__init__"   "Literal['price']" is not assignable to "float" (reportArgumentType) -dataclasses_usage.py:52:36 - error: Expected 3 positional arguments (reportCallIssue) -dataclasses_usage.py:61:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues) -dataclasses_usage.py:67:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues) -dataclasses_usage.py:73:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues) -dataclasses_usage.py:83:13 - error: Expected 1 positional argument (reportCallIssue) -dataclasses_usage.py:88:14 - error: Type "str" is not assignable to declared type "int" +dataclasses_usage.py:53:36 - error: Expected 3 positional arguments (reportCallIssue) +dataclasses_usage.py:62:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues) +dataclasses_usage.py:68:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues) +dataclasses_usage.py:74:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues) +dataclasses_usage.py:84:13 - error: Expected 1 positional argument (reportCallIssue) +dataclasses_usage.py:89:14 - error: Type "str" is not assignable to declared type "int"   "str" is not assignable to "int" (reportAssignmentType) -dataclasses_usage.py:127:8 - error: Expected 1 positional argument (reportCallIssue) -dataclasses_usage.py:130:1 - error: Argument missing for parameter "y" (reportCallIssue) -dataclasses_usage.py:179:6 - error: Expected 0 positional arguments (reportCallIssue) -dataclasses_usage.py:228:9 - error: Dataclass field without type annotation will cause runtime exception (reportGeneralTypeIssues) +dataclasses_usage.py:128:8 - error: Expected 1 positional argument (reportCallIssue) +dataclasses_usage.py:131:1 - error: Argument missing for parameter "y" (reportCallIssue) +dataclasses_usage.py:180:6 - error: Expected 0 positional arguments (reportCallIssue) +dataclasses_usage.py:229:9 - error: Dataclass field without type annotation will cause runtime exception (reportGeneralTypeIssues) +dataclasses_usage.py:246:12 - error: Expected 2 positional arguments (reportCallIssue) """ conformance_automated = "Pass" errors_diff = """ diff --git a/conformance/results/pyright/enums_definition.toml b/conformance/results/pyright/enums_definition.toml index 513dbe853..6741494f1 100644 --- a/conformance/results/pyright/enums_definition.toml +++ b/conformance/results/pyright/enums_definition.toml @@ -2,5 +2,7 @@ conformant = "Pass" errors_diff = """ """ output = """ +enums_definition.py:92:9 - error: Cannot access attribute "BLUE" for class "type[Color12]" +  Attribute "BLUE" is unknown (reportAttributeAccessIssue) """ conformance_automated = "Pass" diff --git a/conformance/results/pyright/namedtuples_define_class.toml b/conformance/results/pyright/namedtuples_define_class.toml index b4cc632cd..59049fa48 100644 --- a/conformance/results/pyright/namedtuples_define_class.toml +++ b/conformance/results/pyright/namedtuples_define_class.toml @@ -14,9 +14,10 @@ namedtuples_define_class.py:70:20 - error: Expected 2 positional arguments (repo namedtuples_define_class.py:77:5 - error: Named tuple field names cannot start with an underscore (reportGeneralTypeIssues) namedtuples_define_class.py:87:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues) namedtuples_define_class.py:107:5 - error: Cannot override "x" because parent class "Point" is a named tuple (reportIncompatibleVariableOverride) -namedtuples_define_class.py:137:19 - error: Argument of type "float" cannot be assigned to parameter "value" of type "str" in function "__new__" +namedtuples_define_class.py:121:24 - error: Expected 2 positional arguments (reportCallIssue) +namedtuples_define_class.py:140:19 - error: Argument of type "float" cannot be assigned to parameter "value" of type "str" in function "__new__"   "float" is not assignable to "str" (reportArgumentType) -namedtuples_define_class.py:144:7 - error: Multiple inheritance with NamedTuple is not supported (reportGeneralTypeIssues) +namedtuples_define_class.py:147:7 - error: Multiple inheritance with NamedTuple is not supported (reportGeneralTypeIssues) """ conformance_automated = "Pass" errors_diff = """ diff --git a/conformance/results/pyright/typeddicts_class_syntax.toml b/conformance/results/pyright/typeddicts_class_syntax.toml index 5558eb7cc..e77eac4c6 100644 --- a/conformance/results/pyright/typeddicts_class_syntax.toml +++ b/conformance/results/pyright/typeddicts_class_syntax.toml @@ -9,8 +9,12 @@ typeddicts_class_syntax.py:39:5 - error: TypedDict classes can contain only type typeddicts_class_syntax.py:45:32 - error: TypedDict does not support __init_subclass__ parameter "metaclass" (reportGeneralTypeIssues) typeddicts_class_syntax.py:50:32 - error: TypedDict does not support __init_subclass__ parameter "other" (reportGeneralTypeIssues) typeddicts_class_syntax.py:58:5 - error: TypedDict classes can contain only type annotations (reportGeneralTypeIssues) +typeddicts_class_syntax.py:60:5 - error: TypedDict classes can contain only type annotations (reportGeneralTypeIssues) +typeddicts_class_syntax.py:65:1 - error: No overloads for "__init__" match the provided arguments +  Argument types: (Literal[1], Literal[2], Literal[3]) (reportCallIssue) """ conformance_automated = "Fail" errors_diff = """ Line 58: Unexpected errors ['typeddicts_class_syntax.py:58:5 - error: TypedDict classes can contain only type annotations (reportGeneralTypeIssues)'] +Line 60: Unexpected errors ['typeddicts_class_syntax.py:60:5 - error: TypedDict classes can contain only type annotations (reportGeneralTypeIssues)'] """ diff --git a/conformance/results/results.html b/conformance/results/results.html index ac24b2b80..f34dcbe90 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -940,7 +940,7 @@

Python Type System Conformance Test Results

Partial

Does not support version-conditional items in TypedDict definitions.

Partial

Does not support version-conditional items in TypedDict definitions.

Pass -
Partial

Errors on version-conditional items in TypedDict definitions.

+Pass      typeddicts_extra_items
Unsupported

Not supported.

diff --git a/conformance/results/ty/dataclasses_usage.toml b/conformance/results/ty/dataclasses_usage.toml index 3e80b64be..989dd39fa 100644 --- a/conformance/results/ty/dataclasses_usage.toml +++ b/conformance/results/ty/dataclasses_usage.toml @@ -2,15 +2,16 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ -dataclasses_usage.py:50:6: error[missing-argument] No argument provided for required parameter `unit_price` -dataclasses_usage.py:51:28: error[invalid-argument-type] Argument is incorrect: Expected `int | float`, found `Literal["price"]` -dataclasses_usage.py:52:36: error[too-many-positional-arguments] Too many positional arguments: expected 3, got 4 -dataclasses_usage.py:61:5: error[dataclass-field-order] Required field `b` cannot be defined after fields with default values -dataclasses_usage.py:67:5: error[dataclass-field-order] Required field `b` cannot be defined after fields with default values -dataclasses_usage.py:73:5: error[dataclass-field-order] Required field `b` cannot be defined after fields with default values -dataclasses_usage.py:83:13: error[too-many-positional-arguments] Too many positional arguments: expected 1, got 2 -dataclasses_usage.py:88:14: error[invalid-assignment] Object of type `dataclasses.Field[str]` is not assignable to `int` -dataclasses_usage.py:127:8: error[too-many-positional-arguments] Too many positional arguments: expected 1, got 2 -dataclasses_usage.py:130:1: error[missing-argument] No argument provided for required parameter `y` of `DC8.__init__` -dataclasses_usage.py:179:6: error[too-many-positional-arguments] Too many positional arguments to `object.__init__`: expected 1, got 2 +dataclasses_usage.py:51:6: error[missing-argument] No argument provided for required parameter `unit_price` +dataclasses_usage.py:52:28: error[invalid-argument-type] Argument is incorrect: Expected `int | float`, found `Literal["price"]` +dataclasses_usage.py:53:36: error[too-many-positional-arguments] Too many positional arguments: expected 3, got 4 +dataclasses_usage.py:62:5: error[dataclass-field-order] Required field `b` cannot be defined after fields with default values +dataclasses_usage.py:68:5: error[dataclass-field-order] Required field `b` cannot be defined after fields with default values +dataclasses_usage.py:74:5: error[dataclass-field-order] Required field `b` cannot be defined after fields with default values +dataclasses_usage.py:84:13: error[too-many-positional-arguments] Too many positional arguments: expected 1, got 2 +dataclasses_usage.py:89:14: error[invalid-assignment] Object of type `dataclasses.Field[str]` is not assignable to `int` +dataclasses_usage.py:128:8: error[too-many-positional-arguments] Too many positional arguments: expected 1, got 2 +dataclasses_usage.py:131:1: error[missing-argument] No argument provided for required parameter `y` of `DC8.__init__` +dataclasses_usage.py:180:6: error[too-many-positional-arguments] Too many positional arguments to `object.__init__`: expected 1, got 2 +dataclasses_usage.py:246:12: error[too-many-positional-arguments] Too many positional arguments: expected 2, got 3 """ diff --git a/conformance/results/ty/enums_definition.toml b/conformance/results/ty/enums_definition.toml index f857c5186..09271fcdf 100644 --- a/conformance/results/ty/enums_definition.toml +++ b/conformance/results/ty/enums_definition.toml @@ -2,6 +2,7 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ -enums_definition.py:24:32: error[too-many-positional-arguments] Too many positional arguments to function `Enum`: expected 2, got 4 -enums_definition.py:33:33: error[invalid-type-form] Type arguments for `Literal` must be `None`, a literal value (int, bool, str, or bytes), or an enum member +enums_definition.py:25:32: error[too-many-positional-arguments] Too many positional arguments to function `Enum`: expected 2, got 4 +enums_definition.py:34:33: error[invalid-type-form] Type arguments for `Literal` must be `None`, a literal value (int, bool, str, or bytes), or an enum member +enums_definition.py:92:1: error[unresolved-attribute] Class `Color12` has no attribute `BLUE` """ diff --git a/conformance/results/ty/namedtuples_define_class.toml b/conformance/results/ty/namedtuples_define_class.toml index d42221707..e5e7bc787 100644 --- a/conformance/results/ty/namedtuples_define_class.toml +++ b/conformance/results/ty/namedtuples_define_class.toml @@ -14,6 +14,7 @@ namedtuples_define_class.py:70:20: error[too-many-positional-arguments] Too many namedtuples_define_class.py:77:5: error[invalid-named-tuple] NamedTuple field `_y` cannot start with an underscore namedtuples_define_class.py:87:5: error[invalid-named-tuple] NamedTuple field without default value cannot follow field(s) with default value(s): Field `latitude` defined here without a default value namedtuples_define_class.py:107:5: error[invalid-named-tuple-override] Cannot override NamedTuple field `x` inherited from `Point` -namedtuples_define_class.py:137:19: error[invalid-argument-type] Argument is incorrect: Expected `str`, found `float` -namedtuples_define_class.py:144:24: error[invalid-named-tuple] NamedTuple class `Unit` cannot use multiple inheritance except with `Generic[]` +namedtuples_define_class.py:121:24: error[too-many-positional-arguments] Too many positional arguments: expected 3, got 4 +namedtuples_define_class.py:140:19: error[invalid-argument-type] Argument is incorrect: Expected `str`, found `float` +namedtuples_define_class.py:147:24: error[invalid-named-tuple] NamedTuple class `Unit` cannot use multiple inheritance except with `Generic[]` """ diff --git a/conformance/results/ty/typeddicts_class_syntax.toml b/conformance/results/ty/typeddicts_class_syntax.toml index f5f0a4af1..ccf44582f 100644 --- a/conformance/results/ty/typeddicts_class_syntax.toml +++ b/conformance/results/ty/typeddicts_class_syntax.toml @@ -1,10 +1,8 @@ -conformant = "Partial" +conformant = "Pass" notes = """ -Errors on version-conditional items in TypedDict definitions. """ -conformance_automated = "Fail" +conformance_automated = "Pass" errors_diff = """ -Line 58: Unexpected errors ['typeddicts_class_syntax.py:58:5: error[invalid-typed-dict-statement] invalid statement in TypedDict class body'] """ output = """ typeddicts_class_syntax.py:30:5: error[invalid-typed-dict-statement] TypedDict class cannot have methods @@ -12,5 +10,5 @@ typeddicts_class_syntax.py:34:5: error[invalid-typed-dict-statement] TypedDict c typeddicts_class_syntax.py:39:5: error[invalid-typed-dict-statement] TypedDict class cannot have methods typeddicts_class_syntax.py:45:32: error[invalid-typed-dict-header] Custom metaclasses are not supported in `TypedDict` definitions typeddicts_class_syntax.py:50:32: error[unknown-argument] Unknown keyword argument `other` in `TypedDict` definition -typeddicts_class_syntax.py:58:5: error[invalid-typed-dict-statement] invalid statement in TypedDict class body +typeddicts_class_syntax.py:65:28: error[invalid-key] Unknown key "z" for TypedDict `ConditionalField` """ diff --git a/conformance/results/zuban/dataclasses_usage.toml b/conformance/results/zuban/dataclasses_usage.toml index 197dc1715..8e2a7cccd 100644 --- a/conformance/results/zuban/dataclasses_usage.toml +++ b/conformance/results/zuban/dataclasses_usage.toml @@ -2,15 +2,16 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ -dataclasses_usage.py:50: error: Missing positional argument "unit_price" in call to "InventoryItem" [call-arg] -dataclasses_usage.py:51: error: Argument 2 to "InventoryItem" has incompatible type "str"; expected "float" [arg-type] -dataclasses_usage.py:52: error: Too many arguments for "InventoryItem" [call-arg] -dataclasses_usage.py:61: error: Attributes without a default cannot follow attributes with one [misc] -dataclasses_usage.py:67: error: Attributes without a default cannot follow attributes with one [misc] -dataclasses_usage.py:73: error: Attributes without a default cannot follow attributes with one [misc] -dataclasses_usage.py:83: error: Too many arguments for "DC4" [call-arg] -dataclasses_usage.py:88: error: Argument "default_factory" to "field" has incompatible type "type[str]"; expected "Callable[[], int]" [arg-type] -dataclasses_usage.py:127: error: Too many arguments for "DC7" [call-arg] -dataclasses_usage.py:130: error: Missing positional argument "y" in call to "DC8" [call-arg] -dataclasses_usage.py:179: error: Too many arguments for "DC13" [call-arg] +dataclasses_usage.py:51: error: Missing positional argument "unit_price" in call to "InventoryItem" [call-arg] +dataclasses_usage.py:52: error: Argument 2 to "InventoryItem" has incompatible type "str"; expected "float" [arg-type] +dataclasses_usage.py:53: error: Too many arguments for "InventoryItem" [call-arg] +dataclasses_usage.py:62: error: Attributes without a default cannot follow attributes with one [misc] +dataclasses_usage.py:68: error: Attributes without a default cannot follow attributes with one [misc] +dataclasses_usage.py:74: error: Attributes without a default cannot follow attributes with one [misc] +dataclasses_usage.py:84: error: Too many arguments for "DC4" [call-arg] +dataclasses_usage.py:89: error: Argument "default_factory" to "field" has incompatible type "type[str]"; expected "Callable[[], int]" [arg-type] +dataclasses_usage.py:128: error: Too many arguments for "DC7" [call-arg] +dataclasses_usage.py:131: error: Missing positional argument "y" in call to "DC8" [call-arg] +dataclasses_usage.py:180: error: Too many arguments for "DC13" [call-arg] +dataclasses_usage.py:246: error: Too many arguments for "DC19" [call-arg] """ diff --git a/conformance/results/zuban/enums_definition.toml b/conformance/results/zuban/enums_definition.toml index a98bcdae3..300aa75aa 100644 --- a/conformance/results/zuban/enums_definition.toml +++ b/conformance/results/zuban/enums_definition.toml @@ -2,5 +2,6 @@ conformance_automated = "Pass" errors_diff = """ """ output = """ -enums_definition.py:24: error: Too many arguments for Enum() [call-arg] +enums_definition.py:25: error: Too many arguments for Enum() [call-arg] +enums_definition.py:92: error: "type[Color12]" has no attribute "BLUE" [attr-defined] """ diff --git a/conformance/results/zuban/namedtuples_define_class.toml b/conformance/results/zuban/namedtuples_define_class.toml index b54a9d0f7..abad1ec53 100644 --- a/conformance/results/zuban/namedtuples_define_class.toml +++ b/conformance/results/zuban/namedtuples_define_class.toml @@ -5,7 +5,8 @@ Does not support version-conditional fields in NamedTuple definitions. conformance_automated = "Fail" errors_diff = """ Line 114: Unexpected errors ['namedtuples_define_class.py:114: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc]'] -Line 118: Unexpected errors ['namedtuples_define_class.py:118: error: Too many arguments for "ConditionalField" [call-arg]'] +Line 116: Unexpected errors ['namedtuples_define_class.py:116: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc]'] +Line 120: Unexpected errors ['namedtuples_define_class.py:120: error: Too many arguments for "ConditionalField" [call-arg]'] """ output = """ namedtuples_define_class.py:33: error: Tuple index out of range [misc] @@ -21,7 +22,9 @@ namedtuples_define_class.py:77: error: NamedTuple field name cannot start with a namedtuples_define_class.py:87: error: Non-default NamedTuple fields cannot follow default fields [misc] namedtuples_define_class.py:107: error: NamedTuple attributes cannot be overridden in subclasses [misc] namedtuples_define_class.py:114: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc] -namedtuples_define_class.py:118: error: Too many arguments for "ConditionalField" [call-arg] -namedtuples_define_class.py:137: error: Argument 2 to "Property" has incompatible type "float"; expected "str" [arg-type] -namedtuples_define_class.py:144: error: NamedTuple should be a single base [misc] +namedtuples_define_class.py:116: error: Invalid statement in NamedTuple definition; expected "field_name: field_type [= default]" [misc] +namedtuples_define_class.py:120: error: Too many arguments for "ConditionalField" [call-arg] +namedtuples_define_class.py:121: error: Too many arguments for "ConditionalField" [call-arg] +namedtuples_define_class.py:140: error: Argument 2 to "Property" has incompatible type "float"; expected "str" [arg-type] +namedtuples_define_class.py:147: error: NamedTuple should be a single base [misc] """ diff --git a/conformance/results/zuban/typeddicts_class_syntax.toml b/conformance/results/zuban/typeddicts_class_syntax.toml index 588fe8697..cf2dfe8c8 100644 --- a/conformance/results/zuban/typeddicts_class_syntax.toml +++ b/conformance/results/zuban/typeddicts_class_syntax.toml @@ -5,7 +5,8 @@ Does not support version-conditional items in TypedDict definitions. conformance_automated = "Fail" errors_diff = """ Line 58: Unexpected errors ['typeddicts_class_syntax.py:58: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc]'] -Line 62: Unexpected errors ['typeddicts_class_syntax.py:62: error: Extra key "y" for TypedDict "ConditionalField" [typeddict-unknown-key]'] +Line 60: Unexpected errors ['typeddicts_class_syntax.py:60: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc]'] +Line 64: Unexpected errors ['typeddicts_class_syntax.py:64: error: Extra key "y" for TypedDict "ConditionalField" [typeddict-unknown-key]'] """ output = """ typeddicts_class_syntax.py:30: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] @@ -14,5 +15,7 @@ typeddicts_class_syntax.py:39: error: Invalid statement in TypedDict definition; typeddicts_class_syntax.py:45: error: Unexpected keyword argument "metaclass" for "TypedDict" [call-arg] typeddicts_class_syntax.py:50: error: Unexpected keyword argument "other" for "TypedDict" [call-arg] typeddicts_class_syntax.py:58: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] -typeddicts_class_syntax.py:62: error: Extra key "y" for TypedDict "ConditionalField" [typeddict-unknown-key] +typeddicts_class_syntax.py:60: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] +typeddicts_class_syntax.py:64: error: Extra key "y" for TypedDict "ConditionalField" [typeddict-unknown-key] +typeddicts_class_syntax.py:65: error: Extra keys ("y", "z") for TypedDict "ConditionalField" [typeddict-unknown-key] """ diff --git a/conformance/tests/dataclasses_usage.py b/conformance/tests/dataclasses_usage.py index d26eaeb53..6e9c0e6bd 100644 --- a/conformance/tests/dataclasses_usage.py +++ b/conformance/tests/dataclasses_usage.py @@ -7,6 +7,7 @@ from dataclasses import InitVar, dataclass, field from typing import Any, Callable, ClassVar, Generic, Protocol, TypeVar, assert_type +import sys T = TypeVar("T") @@ -226,3 +227,20 @@ class DC18: # This may generate a type checker error because an unannotated field # will result in a runtime exception. y = field() # E? + + +# > Dataclass fields may be conditional, via checks of the same +# > statically-known conditions that a type-checker understands elsewhere, +# > such as Python version: + +@dataclass +class DC19: + x: int + if sys.version_info >= (3, 12): + y: int + if sys.version_info >= (4, 0): + z: int + +# The conformance suite runs type checkers configured to Python 3.12 or later: +DC19(1, 2) +DC19(1, 2, 3) # E diff --git a/conformance/tests/enums_definition.py b/conformance/tests/enums_definition.py index 31a137c40..480a06510 100644 --- a/conformance/tests/enums_definition.py +++ b/conformance/tests/enums_definition.py @@ -6,6 +6,7 @@ from enum import Enum, EnumType from typing import Literal, assert_type +import sys # > Type checkers should support the class syntax @@ -73,3 +74,20 @@ class Color11(CustomEnum2): assert_type(Color11.RED, Literal[Color11.RED]) + +# > Enum members may be conditional, via checks of the same +# > statically-known conditions that a type-checker understands elsewhere, +# > such as Python version: + +class Color12(Enum): + RED = 1 + if sys.version_info >= (3, 12): + GREEN = 2 + if sys.version_info >= (4, 0): + BLUE = 3 + +# The conformance suite runs type checkers configured to Python 3.12 or later: +assert_type(Color12.RED, Literal[Color12.RED]) +assert_type(Color12.GREEN, Literal[Color12.GREEN]) +Color12.BLUE # E + diff --git a/conformance/tests/namedtuples_define_class.py b/conformance/tests/namedtuples_define_class.py index bf6acc2c9..03a631bfc 100644 --- a/conformance/tests/namedtuples_define_class.py +++ b/conformance/tests/namedtuples_define_class.py @@ -112,10 +112,13 @@ class BadPointWithName(Point): class ConditionalField(NamedTuple): x: int if sys.version_info >= (3, 12): - y: str + y: int + if sys.version_info >= (4, 0): + z: int # The conformance suite runs type checkers configured to Python 3.12 or later: -ConditionalField(1, "hello") +ConditionalField(1, 2) +ConditionalField(1, 2, 3) # E # > In Python 3.11 and newer, the class syntax supports generic named tuple classes. diff --git a/conformance/tests/typeddicts_class_syntax.py b/conformance/tests/typeddicts_class_syntax.py index f281fc84d..923bf1552 100644 --- a/conformance/tests/typeddicts_class_syntax.py +++ b/conformance/tests/typeddicts_class_syntax.py @@ -56,10 +56,13 @@ class BadTypedDict3(TypedDict, other=True): # E class ConditionalField(TypedDict): x: int if sys.version_info >= (3, 12): - y: str + y: int + if sys.version_info >= (4, 0): + z: int # The conformance suite runs type checkers configured to Python 3.12 or later: -ConditionalField(x=1, y="hello") +ConditionalField(x=1, y=2) +ConditionalField(x=1, y=2, z=3) # E # > TypedDicts may be made generic by adding Generic[T] among the bases. diff --git a/docs/spec/dataclasses.rst b/docs/spec/dataclasses.rst index 77a775745..ef08344b4 100644 --- a/docs/spec/dataclasses.rst +++ b/docs/spec/dataclasses.rst @@ -122,6 +122,19 @@ Metaclass example id: int name: str +Conditional fields +"""""""""""""""""" + +Dataclass fields may be conditional, via checks of the same +:ref:`statically-known conditions` +that a type-checker understands elsewhere, such as Python version:: + + @dataclass + class Person: + name: str + if sys.version_info >= (3, 14): + age: int + Decorator function and class/metaclass parameters ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/spec/enums.rst b/docs/spec/enums.rst index b90e5dbd1..ecb283d55 100644 --- a/docs/spec/enums.rst +++ b/docs/spec/enums.rst @@ -59,6 +59,15 @@ checkers should treat such classes as enums:: GREEN = 2 BLUE = 3 +Enum members may be conditional, via checks of the same +:ref:`statically-known conditions` +that a type-checker understands elsewhere, such as Python version:: + + class Color(Enum): + RED = 1 + if sys.version_info >= (3, 14): + BLUE = 2 + Enum Behaviors --------------