diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..2a4a0579d --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +conformance/results/results.html linguist-generated diff --git a/conformance/pyproject.toml b/conformance/pyproject.toml index e44dadf64..17c4adfd2 100644 --- a/conformance/pyproject.toml +++ b/conformance/pyproject.toml @@ -3,14 +3,16 @@ name = "typing-conformance" version = "0.1.0" requires-python = "==3.12.*" dependencies = [ + "jinja2", + "markdown", "mypy", "pycroscope", "pyrefly", "pyright", - "tomli", "tomlkit", - "zuban", "ty", + "types-markdown", + "zuban", ] [tool.uv] diff --git a/conformance/results/mypy/aliases_typealiastype.toml b/conformance/results/mypy/aliases_typealiastype.toml index 1a034e810..b757d9edd 100644 --- a/conformance/results/mypy/aliases_typealiastype.toml +++ b/conformance/results/mypy/aliases_typealiastype.toml @@ -1,7 +1,7 @@ conformant = "Partial" notes = """ -Incorrectly rejects some recursive type aliases using TypeAliasType. -Incorrectly rejects the use of a class-scoped TypeVar in a TypeAliasType definition. +Incorrectly rejects some recursive type aliases using `TypeAliasType`. +Incorrectly rejects the use of a class-scoped `TypeVar` in a `TypeAliasType` definition. """ output = """ aliases_typealiastype.py:20: error: Cannot resolve name "GoodAlias5" (possible cyclic definition) [misc] diff --git a/conformance/results/mypy/annotations_forward_refs.toml b/conformance/results/mypy/annotations_forward_refs.toml index fd9c48687..15211054e 100644 --- a/conformance/results/mypy/annotations_forward_refs.toml +++ b/conformance/results/mypy/annotations_forward_refs.toml @@ -1,7 +1,7 @@ conformant = "Partial" notes = """ Does not report error for a forward reference that is not enclosed in quotes. -Does not report error for use of quoted type with "|" operator (runtime error). +Does not report error for use of quoted type with `|` operator (runtime error). Incorrectly generates error for quoted type defined in class scope. """ output = """ diff --git a/conformance/results/mypy/annotations_generators.toml b/conformance/results/mypy/annotations_generators.toml index e14ede973..3e86b6ced 100644 --- a/conformance/results/mypy/annotations_generators.toml +++ b/conformance/results/mypy/annotations_generators.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not report incompatible Generator type in `yield from` statement. +Does not report incompatible `Generator` type in `yield from` statement. """ output = """ annotations_generators.py:51: error: Missing return statement [return] diff --git a/conformance/results/mypy/callables_annotation.toml b/conformance/results/mypy/callables_annotation.toml index 11daf6205..f19579654 100644 --- a/conformance/results/mypy/callables_annotation.toml +++ b/conformance/results/mypy/callables_annotation.toml @@ -1,7 +1,7 @@ conformant = "Partial" notes = """ -Incorrectly treats "*args: T, **kwargs: T" as "..." when T is specialized to Any. -Does not treat "*args: Any, **kargs: Any" as "..." when separated by keyword parameter. +Incorrectly treats `*args: T, **kwargs: T` as `...` when `T` is specialized to `Any`. +Does not treat `*args: Any, **kargs: Any` as `...` when separated by keyword parameter. """ output = """ callables_annotation.py:25: error: Too few arguments [call-arg] diff --git a/conformance/results/mypy/callables_kwargs.toml b/conformance/results/mypy/callables_kwargs.toml index 571931b13..0586ed15b 100644 --- a/conformance/results/mypy/callables_kwargs.toml +++ b/conformance/results/mypy/callables_kwargs.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Allows callable without kwargs to be assigned to callable with unpacked kwargs +Allows callable without kwargs to be assigned to callable with unpacked kwargs. """ output = """ callables_kwargs.py:46: error: Missing named argument "v1" for "func1" [call-arg] diff --git a/conformance/results/mypy/classes_classvar.toml b/conformance/results/mypy/classes_classvar.toml index bddc8f0b6..853c49684 100644 --- a/conformance/results/mypy/classes_classvar.toml +++ b/conformance/results/mypy/classes_classvar.toml @@ -1,9 +1,9 @@ conformant = "Partial" notes = """ -Internal error if TypeVarTuple is used in ClassVar. -Does not reject use of ParamSpec in ClassVar. -Rejects ClassVar nested in Annotated. -Does not reject use of ClassVar in TypeAlias definition. +Internal error if `TypeVarTuple` is used in `ClassVar`. +Does not reject use of `ParamSpec` in `ClassVar`. +Rejects `ClassVar` nested in `Annotated`. +Does not reject use of `ClassVar` in `TypeAlias` definition. """ output = """ classes_classvar.py:38: error: ClassVar[...] must have at most one type argument [valid-type] diff --git a/conformance/results/mypy/constructors_call_init.toml b/conformance/results/mypy/constructors_call_init.toml index d8680ec9d..f2d7df715 100644 --- a/conformance/results/mypy/constructors_call_init.toml +++ b/conformance/results/mypy/constructors_call_init.toml @@ -1,7 +1,7 @@ conformant = "Partial" notes = """ -Does not report errors during binding to self parameter of __init__ method. -Does not reject use of class-scoped type variables in annotation of self parameter in __init__ method. +Does not report errors during binding to self parameter of `__init__` method. +Does not reject use of class-scoped type variables in annotation of self parameter in `__init__` method. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/mypy/constructors_call_metaclass.toml b/conformance/results/mypy/constructors_call_metaclass.toml index fb84e85db..a06679970 100644 --- a/conformance/results/mypy/constructors_call_metaclass.toml +++ b/conformance/results/mypy/constructors_call_metaclass.toml @@ -1,7 +1,7 @@ conformant = "Unsupported" notes = """ -Does not honor metaclass __call__ method when evaluating constructor call. -Does not skip evaluation of __new__ and __init__ if custom metaclass call returns non-class. +Does not honor metaclass `__call__` method when evaluating constructor call. +Does not skip evaluation of `__new__` and `__init__` if custom metaclass call returns non-class. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/mypy/constructors_call_new.toml b/conformance/results/mypy/constructors_call_new.toml index a325d9e54..49860361e 100644 --- a/conformance/results/mypy/constructors_call_new.toml +++ b/conformance/results/mypy/constructors_call_new.toml @@ -1,8 +1,8 @@ conformant = "Partial" notes = """ -Does not support __new__ return type that is not a subclass of the class being constructed. -Does not skip evaluation of __init__ based on __new__ return type. -Does not report errors during binding to cls parameter of __new__ method. +Does not support `__new__` return type that is not a subclass of the class being constructed. +Does not skip evaluation of `__init__` based on `__new__` return type. +Does not report errors during binding to `cls` parameter of `__new__` method. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/mypy/constructors_call_type.toml b/conformance/results/mypy/constructors_call_type.toml index 7ba573760..c94564c53 100644 --- a/conformance/results/mypy/constructors_call_type.toml +++ b/conformance/results/mypy/constructors_call_type.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not validate call to custom metaclass __call__ method through type[T]. +Does not validate call to custom metaclass `__call__` method through `type[T]`. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/mypy/constructors_callable.toml b/conformance/results/mypy/constructors_callable.toml index af573bd2e..edf923406 100644 --- a/conformance/results/mypy/constructors_callable.toml +++ b/conformance/results/mypy/constructors_callable.toml @@ -1,8 +1,8 @@ conformant = "Partial" notes = """ -Does not generate a union type for __new__ and __init__ when converting class to callable. -Does not ignore __init__ based on __new__ return type when converting class to callable. -Does not support __new__ return type that is different from class being constructed. +Does not generate a union type for `__new__` and `__init__` when converting class to callable. +Does not ignore `__init__` based on `__new__` return type when converting class to callable. +Does not support `__new__` return type that is different from class being constructed. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/mypy/constructors_consistency.toml b/conformance/results/mypy/constructors_consistency.toml index 654ebaa96..5195baef1 100644 --- a/conformance/results/mypy/constructors_consistency.toml +++ b/conformance/results/mypy/constructors_consistency.toml @@ -1,6 +1,6 @@ conformant = "Pass" notes = """ -Does not report inconsistency between __new__ and __init__ (optional). +Does not report inconsistency between `__new__` and `__init__` (optional). """ conformance_automated = "Pass" errors_diff = """ diff --git a/conformance/results/mypy/dataclasses_final.toml b/conformance/results/mypy/dataclasses_final.toml index ddfb29575..ea61c82bc 100644 --- a/conformance/results/mypy/dataclasses_final.toml +++ b/conformance/results/mypy/dataclasses_final.toml @@ -1,7 +1,7 @@ conformant = "Partial" notes = """ -Wrongly requires a Final dataclass field to be initialized at class level. -Doesn't support Final nested inside ClassVar. +Wrongly requires a `Final` dataclass field to be initialized at class level. +Doesn't support `Final` nested inside `ClassVar`. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/mypy/dataclasses_hash.toml b/conformance/results/mypy/dataclasses_hash.toml index 08809153e..e4c6a663f 100644 --- a/conformance/results/mypy/dataclasses_hash.toml +++ b/conformance/results/mypy/dataclasses_hash.toml @@ -2,7 +2,7 @@ conformant = "Unsupported" notes = """ Does not synthesize `__hash__ = None` as a class attribute for unhashable dataclasses. Does not report when an unhashable dataclass has `__hash__` called directly on an instance. -Does not report when dataclass is not compatible with Hashable protocol. +Does not report when dataclass is not compatible with `Hashable` protocol. """ output = """ dataclasses_hash.py:14: error: Expression is of type "Callable[[object], int]", not "None" [assert-type] diff --git a/conformance/results/mypy/dataclasses_slots.toml b/conformance/results/mypy/dataclasses_slots.toml index 4a6d76337..7addfa5c1 100644 --- a/conformance/results/mypy/dataclasses_slots.toml +++ b/conformance/results/mypy/dataclasses_slots.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not reject write to instance variable that is not defined in __slots__. +Does not reject write to instance variable that is not defined in `__slots__`. """ output = """ dataclasses_slots.py:11: error: "DC1" both defines "__slots__" and is used with "slots=True" [misc] diff --git a/conformance/results/mypy/directives_type_ignore.toml b/conformance/results/mypy/directives_type_ignore.toml index 318b2b2a2..576b2b0d9 100644 --- a/conformance/results/mypy/directives_type_ignore.toml +++ b/conformance/results/mypy/directives_type_ignore.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not honor "# type: ignore" comment if comment includes additional text. +Does not honor `# type: ignore` comment if comment includes additional text. """ output = """ directives_type_ignore.py:11: error: Invalid "type: ignore" comment [syntax] diff --git a/conformance/results/mypy/directives_version_platform.toml b/conformance/results/mypy/directives_version_platform.toml index e1fcc5822..80c6eecff 100644 --- a/conformance/results/mypy/directives_version_platform.toml +++ b/conformance/results/mypy/directives_version_platform.toml @@ -1,7 +1,7 @@ conformant = "Pass" notes = """ -Does not understand three-element form of sys.version checks. -Does not understand os.name checks. +Does not understand three-element form of `sys.version` checks. +Does not understand `os.name` checks. """ output = """ directives_version_platform.py:26: error: Expression is of type "int | str", not "int" [assert-type] diff --git a/conformance/results/mypy/enums_expansion.toml b/conformance/results/mypy/enums_expansion.toml index 9858edfea..8b6a14aa0 100644 --- a/conformance/results/mypy/enums_expansion.toml +++ b/conformance/results/mypy/enums_expansion.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Improperly applies narrowing to Flag subclass. +Improperly applies narrowing to `Flag` subclass. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/mypy/generics_defaults.toml b/conformance/results/mypy/generics_defaults.toml index 5b18af90b..ce9174469 100644 --- a/conformance/results/mypy/generics_defaults.toml +++ b/conformance/results/mypy/generics_defaults.toml @@ -1,7 +1,7 @@ conformant = "Partial" notes = """ -Does not detect a TypeVar with a default used after a TypeVarTuple. -Does not fully support defaults on TypeVarTuple and ParamSpec. +Does not detect a `TypeVar` with a default used after a `TypeVarTuple`. +Does not fully support defaults on `TypeVarTuple` and `ParamSpec`. """ output = """ generics_defaults.py:24: error: "T" cannot appear after "DefaultStrT" in type parameter list because it has no default type [misc] diff --git a/conformance/results/mypy/generics_defaults_referential.toml b/conformance/results/mypy/generics_defaults_referential.toml index e8484dc7d..6bedb442a 100644 --- a/conformance/results/mypy/generics_defaults_referential.toml +++ b/conformance/results/mypy/generics_defaults_referential.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not correctly handle defaults referencing other TypeVars. +Does not correctly handle defaults referencing other `TypeVar`s. """ output = """ generics_defaults_referential.py:23: error: Expression is of type "type[slice[StartT, StopT, StepT]]", not "type[slice[int, int, int | None]]" [assert-type] diff --git a/conformance/results/mypy/generics_type_erasure.toml b/conformance/results/mypy/generics_type_erasure.toml index 46c739fee..dd13b4464 100644 --- a/conformance/results/mypy/generics_type_erasure.toml +++ b/conformance/results/mypy/generics_type_erasure.toml @@ -1,7 +1,7 @@ conformant = "Partial" notes = """ -Infers Node[Never] instead of Node[Any] when argument is not provided. -False negative on instance attribute access on type(node). +Infers `Node[Never]` instead of `Node[Any]` when argument is not provided. +False negative on instance attribute access on `type(node)`. """ output = """ generics_type_erasure.py:19: error: Expression is of type "Node[Never]", not "Node[Any]" [assert-type] diff --git a/conformance/results/mypy/generics_typevartuple_args.toml b/conformance/results/mypy/generics_typevartuple_args.toml index 43d9fa078..5920b7325 100644 --- a/conformance/results/mypy/generics_typevartuple_args.toml +++ b/conformance/results/mypy/generics_typevartuple_args.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not enforce that tuples captured by TypeVarTuple are of the same length. +Does not enforce that tuples captured by `TypeVarTuple` are of the same length. """ output = """ generics_typevartuple_args.py:33: error: Argument 3 to "exec_le" has incompatible type "str"; expected "Env" [arg-type] diff --git a/conformance/results/mypy/generics_typevartuple_basic.toml b/conformance/results/mypy/generics_typevartuple_basic.toml index 37140c379..c9a734127 100644 --- a/conformance/results/mypy/generics_typevartuple_basic.toml +++ b/conformance/results/mypy/generics_typevartuple_basic.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not enforce that tuples captured by TypeVarTuple are same length. +Does not enforce that tuples captured by `TypeVarTuple` are same length. """ output = """ generics_typevartuple_basic.py:42: error: Argument 1 to "Array" has incompatible type "Height"; expected "tuple[Height, Width]" [arg-type] diff --git a/conformance/results/mypy/generics_typevartuple_specialization.toml b/conformance/results/mypy/generics_typevartuple_specialization.toml index 7d23a81f1..280f9266d 100644 --- a/conformance/results/mypy/generics_typevartuple_specialization.toml +++ b/conformance/results/mypy/generics_typevartuple_specialization.toml @@ -1,7 +1,7 @@ conformant = "Partial" notes = """ -Incorrectly specializes generic alias that includes a TypeVar and TypeVarTuple if no type arguments are provided. -Rejects specialization of generic type alias defined as a tuple containing a TypeVar. +Incorrectly specializes generic alias that includes a `TypeVar` and `TypeVarTuple` if no type arguments are provided. +Rejects specialization of generic type alias defined as a tuple containing a `TypeVar`. """ output = """ generics_typevartuple_specialization.py:85: error: Argument 1 to "takes_float_array_with_specific_shape" has incompatible type "Array2[float, *tuple[Any, ...]]"; expected "Array2[float, Height, Width]" [arg-type] diff --git a/conformance/results/mypy/generics_variance.toml b/conformance/results/mypy/generics_variance.toml index 30810aacf..2dff34a72 100644 --- a/conformance/results/mypy/generics_variance.toml +++ b/conformance/results/mypy/generics_variance.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not reject use of class-scoped TypeVar used in a base class when variance is incompatible. +Does not reject use of class-scoped `TypeVar` used in a base class when variance is incompatible. """ output = """ generics_variance.py:14: error: TypeVar cannot be both covariant and contravariant [misc] diff --git a/conformance/results/mypy/literals_parameterizations.toml b/conformance/results/mypy/literals_parameterizations.toml index 730d531db..eac516519 100644 --- a/conformance/results/mypy/literals_parameterizations.toml +++ b/conformance/results/mypy/literals_parameterizations.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not reject tuple within Literal. +Does not reject tuple within `Literal`. """ output = """ literals_parameterizations.py:41: error: Invalid type: Literal[...] cannot contain arbitrary expressions [valid-type] diff --git a/conformance/results/mypy/overloads_definitions.toml b/conformance/results/mypy/overloads_definitions.toml index 80b29a62f..e653284f3 100644 --- a/conformance/results/mypy/overloads_definitions.toml +++ b/conformance/results/mypy/overloads_definitions.toml @@ -1,7 +1,7 @@ conformant = "Partial" conformance_automated = "Fail" notes = """ -Allows @override to be on all overloads and implementation, instead of just implementation. +Allows `@override` to be on all overloads and implementation, instead of just implementation. """ errors_diff = """ Lines 226, 227, 228, 231, 232: Expected error (tag 'override_impl') diff --git a/conformance/results/mypy/overloads_definitions_stub.toml b/conformance/results/mypy/overloads_definitions_stub.toml index 51a1aa393..1a4dc4fa7 100644 --- a/conformance/results/mypy/overloads_definitions_stub.toml +++ b/conformance/results/mypy/overloads_definitions_stub.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Allows @override to appear in a stub file not on the first overload. +Allows `@override` to appear in a stub file not on the first overload. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/mypy/overloads_evaluation.toml b/conformance/results/mypy/overloads_evaluation.toml index 4ddeaca2d..61c5af6a8 100644 --- a/conformance/results/mypy/overloads_evaluation.toml +++ b/conformance/results/mypy/overloads_evaluation.toml @@ -1,10 +1,10 @@ conformant = "Partial" notes = """ -Does not expand boolean arguments to Literal[True] and Literal[False]. +Does not expand boolean arguments to `Literal[True]` and `Literal[False]`. Does not expand enum arguments to literal variants. Does not expand tuple arguments to possible combinations. -Does not evaluate Any in some cases where overload is ambiguous. -Evaluates Any in some cases where overload is not ambiguous. +Does not evaluate `Any` in some cases where overload is ambiguous. +Evaluates `Any` in some cases where overload is not ambiguous. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/mypy/protocols_runtime_checkable.toml b/conformance/results/mypy/protocols_runtime_checkable.toml index 63124dc56..859ffd725 100644 --- a/conformance/results/mypy/protocols_runtime_checkable.toml +++ b/conformance/results/mypy/protocols_runtime_checkable.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not report unsafe overlap for runtime_checkable protocol. +Does not report unsafe overlap for `runtime_checkable` protocol. """ output = """ protocols_runtime_checkable.py:23: error: Only @runtime_checkable protocols can be used with instance and class checks [misc] diff --git a/conformance/results/mypy/qualifiers_annotated.toml b/conformance/results/mypy/qualifiers_annotated.toml index 6fba939f9..e3cfd8ab9 100644 --- a/conformance/results/mypy/qualifiers_annotated.toml +++ b/conformance/results/mypy/qualifiers_annotated.toml @@ -1,10 +1,10 @@ conformant = "Partial" notes = """ -Does not allow ClassVar to be nested within Annotated. -Does not allow Final to be nested within Annotated. -Does not allow Required and NotRequired to be nested within Annotated. -Does not reject type[T] compatibility for type alias defined with Annotated. -Does not reject call of type alias defined with Annotated. +Does not allow `ClassVar` to be nested within `Annotated`. +Does not allow `Final` to be nested within `Annotated`. +Does not allow `Required` and `NotRequired` to be nested within `Annotated`. +Does not reject `type[T]` compatibility for type alias defined with `Annotated`. +Does not reject call of type alias defined with `Annotated`. """ output = """ qualifiers_annotated.py:38: error: Bracketed expression "[...]" is not valid as a type [valid-type] diff --git a/conformance/results/mypy/qualifiers_final_annotation.toml b/conformance/results/mypy/qualifiers_final_annotation.toml index 2d0cea337..137e9f808 100644 --- a/conformance/results/mypy/qualifiers_final_annotation.toml +++ b/conformance/results/mypy/qualifiers_final_annotation.toml @@ -1,9 +1,9 @@ conformant = "Partial" notes = """ -Does not treat use of Final name as if it was replaced by the literal in NamedTuple definition. -Does not allow conditional assignment of Final instance variable in __init__ method. -Does not allow redefinition of private class variable that is marked Final in parent class. -Does not report modification of local Final variable via "for" statement. +Does not treat use of `Final` name as if it was replaced by the literal in `NamedTuple` definition. +Does not allow conditional assignment of `Final` instance variable in `__init__` method. +Does not allow redefinition of private class variable that is marked `Final` in parent class. +Does not report modification of local `Final` variable via `for` statement. """ output = """ qualifiers_final_annotation.py:16: error: Type in Final[...] can only be omitted if there is an initializer [misc] diff --git a/conformance/results/mypy/specialtypes_type.toml b/conformance/results/mypy/specialtypes_type.toml index ea8d59f2a..d83279230 100644 --- a/conformance/results/mypy/specialtypes_type.toml +++ b/conformance/results/mypy/specialtypes_type.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not treat `type` same as `type[Any]` for assert_type. +Does not treat `type` same as `type[Any]` for `assert_type`. Does not allow access to unknown attributes from object of type `type[Any]`. """ output = """ diff --git a/conformance/results/mypy/typeddicts_class_syntax.toml b/conformance/results/mypy/typeddicts_class_syntax.toml index 29220811d..a005f5d63 100644 --- a/conformance/results/mypy/typeddicts_class_syntax.toml +++ b/conformance/results/mypy/typeddicts_class_syntax.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not support version-conditional items in TypedDict definitions. +Does not support version-conditional items in `TypedDict` definitions. """ output = """ typeddicts_class_syntax.py:30: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] diff --git a/conformance/results/mypy/typeddicts_extra_items.toml b/conformance/results/mypy/typeddicts_extra_items.toml index e7c58f8bc..0938d870e 100644 --- a/conformance/results/mypy/typeddicts_extra_items.toml +++ b/conformance/results/mypy/typeddicts_extra_items.toml @@ -1,7 +1,4 @@ conformant = "Unsupported" -notes = """ -Not supported. -""" conformance_automated = "Fail" errors_diff = """ Line 215: Expected 1 errors diff --git a/conformance/results/mypy/typeddicts_readonly_inheritance.toml b/conformance/results/mypy/typeddicts_readonly_inheritance.toml index 46bc4ce00..4bd44ff08 100644 --- a/conformance/results/mypy/typeddicts_readonly_inheritance.toml +++ b/conformance/results/mypy/typeddicts_readonly_inheritance.toml @@ -1,8 +1,8 @@ conformant = "Partial" notes = """ -Incorrectly rejects non-ReadOnly override of ReadOnly item. -Incorrectly rejects override of ReadOnly item with another ReadOnly item with narrower type. -Incorrectly rejects override of NotRequired ReadOnly item with a Required ReadOnly item. +Incorrectly rejects non-`ReadOnly` override of `ReadOnly` item. +Incorrectly rejects override of `ReadOnly` item with another `ReadOnly` item with narrower type. +Incorrectly rejects override of `NotRequired ReadOnly` item with a `Required ReadOnly` item. """ output = """ typeddicts_readonly_inheritance.py:19: error: Overwriting TypedDict field "name" while extending [misc] diff --git a/conformance/results/mypy/typeddicts_readonly_update.toml b/conformance/results/mypy/typeddicts_readonly_update.toml index c53706fc4..aa147b3ee 100644 --- a/conformance/results/mypy/typeddicts_readonly_update.toml +++ b/conformance/results/mypy/typeddicts_readonly_update.toml @@ -1,7 +1,7 @@ conformant = "Partial" notes = """ -Incorrectly allows update of ReadOnly item. -Incorrectly rejects update involving an item with Never type. +Incorrectly allows update of `ReadOnly` item. +Incorrectly rejects update involving an item with `Never` type. """ output = """ typeddicts_readonly_update.py:34: error: Argument 1 to "update" of "TypedDict" has incompatible type "B"; expected "TypedDict({'x'?=: int, 'y': int})" [typeddict-item] diff --git a/conformance/results/mypy/typeforms_typeform.toml b/conformance/results/mypy/typeforms_typeform.toml index 483dc9723..14f1ba107 100644 --- a/conformance/results/mypy/typeforms_typeform.toml +++ b/conformance/results/mypy/typeforms_typeform.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not support assigning Union and GenericAlias objects to their runtime types. +Does not support assigning `Union` and `GenericAlias` objects to their runtime types. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pycroscope/aliases_typealiastype.toml b/conformance/results/pycroscope/aliases_typealiastype.toml index 2708a2ee4..09556fcfd 100644 --- a/conformance/results/pycroscope/aliases_typealiastype.toml +++ b/conformance/results/pycroscope/aliases_typealiastype.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Rejects valid ParamSpec specialization. +Rejects valid `ParamSpec` specialization. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pycroscope/annotations_forward_refs.toml b/conformance/results/pycroscope/annotations_forward_refs.toml index 11cedda9e..63fbfc009 100644 --- a/conformance/results/pycroscope/annotations_forward_refs.toml +++ b/conformance/results/pycroscope/annotations_forward_refs.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Fails to reject "x" | int annotations that fail at runtime. +Fails to reject `"x" | int` annotations that fail at runtime. Rejects some valid quoted annotations. """ conformance_automated = "Fail" diff --git a/conformance/results/pycroscope/dataclasses_descriptors.toml b/conformance/results/pycroscope/dataclasses_descriptors.toml index e5410991c..5b89c7ef9 100644 --- a/conformance/results/pycroscope/dataclasses_descriptors.toml +++ b/conformance/results/pycroscope/dataclasses_descriptors.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Conformance suite is questionable; see https://github.com/python/typing/issues/2259 +Conformance suite is questionable; see """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pycroscope/generics_defaults.toml b/conformance/results/pycroscope/generics_defaults.toml index 93d9e5fb4..3e3cc4f3a 100644 --- a/conformance/results/pycroscope/generics_defaults.toml +++ b/conformance/results/pycroscope/generics_defaults.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Numerous issues; does not support TypeVarTuple and ParamSpec defaults. +Numerous issues; does not support `TypeVarTuple` and `ParamSpec` defaults. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pycroscope/protocols_class_objects.toml b/conformance/results/pycroscope/protocols_class_objects.toml index e40edf15f..0df48dfc7 100644 --- a/conformance/results/pycroscope/protocols_class_objects.toml +++ b/conformance/results/pycroscope/protocols_class_objects.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Abstract type[Proto] still allows protocol class objects in some paths. +Abstract `type[Proto]` still allows protocol class objects in some paths. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pycroscope/qualifiers_annotated.toml b/conformance/results/pycroscope/qualifiers_annotated.toml index 97000ee40..13fd7743f 100644 --- a/conformance/results/pycroscope/qualifiers_annotated.toml +++ b/conformance/results/pycroscope/qualifiers_annotated.toml @@ -1,7 +1,7 @@ conformant = "Partial" notes = """ Fails to reject various weird annotations. -False positive on lambda in Annotated. +False positive on lambda in `Annotated`. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pycroscope/specialtypes_never.toml b/conformance/results/pycroscope/specialtypes_never.toml index e6f61291a..47dfa3ac0 100644 --- a/conformance/results/pycroscope/specialtypes_never.toml +++ b/conformance/results/pycroscope/specialtypes_never.toml @@ -1,7 +1,7 @@ conformant = "Partial" notes = """ Does not enforce invariance in some contexts -Does not allow Any to be assigned to Never +Does not allow `Any` to be assigned to `Never` """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pycroscope/typeddicts_type_consistency.toml b/conformance/results/pycroscope/typeddicts_type_consistency.toml index 62d6661c8..cf2aaa072 100644 --- a/conformance/results/pycroscope/typeddicts_type_consistency.toml +++ b/conformance/results/pycroscope/typeddicts_type_consistency.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Considers TypedDicts to be assignable to plain dict types. +Considers `TypedDict`s to be assignable to plain `dict` types. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pyrefly/callables_annotation.toml b/conformance/results/pyrefly/callables_annotation.toml index efbdf98e8..01f1ec75e 100644 --- a/conformance/results/pyrefly/callables_annotation.toml +++ b/conformance/results/pyrefly/callables_annotation.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Parameter names are lost when resolving ParamSpec +Parameter names are lost when resolving `ParamSpec`. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pyrefly/dataclasses_descriptors.toml b/conformance/results/pyrefly/dataclasses_descriptors.toml index 03625f94d..5f36bae96 100644 --- a/conformance/results/pyrefly/dataclasses_descriptors.toml +++ b/conformance/results/pyrefly/dataclasses_descriptors.toml @@ -1,7 +1,7 @@ conformant = "Partial" notes = """ -* Assumes descriptor behavior only when field is assigned in class body -* Doesn't allow non-data descriptors or data descriptors with differing `__get__` and `__set__` types +Assumes descriptor behavior only when field is assigned in class body +Doesn't allow non-data descriptors or data descriptors with differing `__get__` and `__set__` types """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pyrefly/exceptions_context_managers.toml b/conformance/results/pyrefly/exceptions_context_managers.toml index d9b225e74..fe2a3282d 100644 --- a/conformance/results/pyrefly/exceptions_context_managers.toml +++ b/conformance/results/pyrefly/exceptions_context_managers.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Some error suppressing context managers are not detected +Some error suppressing context managers are not detected. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pyrefly/generics_scoping.toml b/conformance/results/pyrefly/generics_scoping.toml index 236c49f06..0a4b9c40e 100644 --- a/conformance/results/pyrefly/generics_scoping.toml +++ b/conformance/results/pyrefly/generics_scoping.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not implement several scoping checks/restrictions for generics +Does not implement several scoping checks/restrictions for generics. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pyrefly/generics_self_advanced.toml b/conformance/results/pyrefly/generics_self_advanced.toml index fb11f7c63..797430280 100644 --- a/conformance/results/pyrefly/generics_self_advanced.toml +++ b/conformance/results/pyrefly/generics_self_advanced.toml @@ -1,6 +1,6 @@ conformant = "Pass" notes = """ -Treats attributes not initialized on the class as instance-only +Treats attributes not initialized on the class as instance-only. """ conformance_automated = "Pass" errors_diff = """ diff --git a/conformance/results/pyright/generics_defaults_specialization.toml b/conformance/results/pyright/generics_defaults_specialization.toml index 28c6cdced..f1d5bc216 100644 --- a/conformance/results/pyright/generics_defaults_specialization.toml +++ b/conformance/results/pyright/generics_defaults_specialization.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Allows incorrect assignment to type[]. +Allows incorrect assignment to `type[]`. """ output = """ generics_defaults_specialization.py:30:15 - error: Too many type arguments provided for "MyAlias[DefaultStrT@MyAlias]"; expected 1 but received 2 (reportInvalidTypeForm) diff --git a/conformance/results/pyright/generics_paramspec_semantics.toml b/conformance/results/pyright/generics_paramspec_semantics.toml index e24a0a9c8..ba9b447a9 100644 --- a/conformance/results/pyright/generics_paramspec_semantics.toml +++ b/conformance/results/pyright/generics_paramspec_semantics.toml @@ -1,6 +1,6 @@ conformant = "Pass" notes = """ -Constraint solver doesn't find common type for two signatures captured by a single ParamSpec (allowed). +Constraint solver doesn't find common type for two signatures captured by a single `ParamSpec` (allowed). """ output = """ generics_paramspec_semantics.py:26:6 - error: Expected 2 more positional arguments (reportCallIssue) diff --git a/conformance/results/pyright/generics_typevartuple_args.toml b/conformance/results/pyright/generics_typevartuple_args.toml index 65c6a1992..a2756d559 100644 --- a/conformance/results/pyright/generics_typevartuple_args.toml +++ b/conformance/results/pyright/generics_typevartuple_args.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not correctly solve TypeVarTuple with heterogeneous bounds. +Does not correctly solve `TypeVarTuple` with heterogeneous bounds. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pyright/generics_typevartuple_basic.toml b/conformance/results/pyright/generics_typevartuple_basic.toml index 7e5cfa403..4021237e7 100644 --- a/conformance/results/pyright/generics_typevartuple_basic.toml +++ b/conformance/results/pyright/generics_typevartuple_basic.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not correctly solve TypeVarTuple with heterogeneous bounds. +Does not correctly solve `TypeVarTuple` with heterogeneous bounds. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pyright/overloads_basic.toml b/conformance/results/pyright/overloads_basic.toml index 14bfb58bf..78bfb673a 100644 --- a/conformance/results/pyright/overloads_basic.toml +++ b/conformance/results/pyright/overloads_basic.toml @@ -1,6 +1,4 @@ conformant = "Pass" -notes = """ -""" output = """ overloads_basic.py:39:1 - error: No overloads for "__getitem__" match the provided arguments (reportCallIssue) overloads_basic.py:39:1 - error: Argument of type "Literal['']" cannot be assigned to parameter "__s" of type "slice[Any, Any, Any]" in function "__getitem__" diff --git a/conformance/results/pyright/overloads_evaluation.toml b/conformance/results/pyright/overloads_evaluation.toml index 7b41dc4e1..cb63679bf 100644 --- a/conformance/results/pyright/overloads_evaluation.toml +++ b/conformance/results/pyright/overloads_evaluation.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not evaluate Any in some cases where overload is ambiguous. +Does not evaluate `Any` in some cases where overload is ambiguous. """ conformance_automated = "Fail" errors_diff = """ diff --git a/conformance/results/pyright/typeddicts_class_syntax.toml b/conformance/results/pyright/typeddicts_class_syntax.toml index e77eac4c6..b1c81614c 100644 --- a/conformance/results/pyright/typeddicts_class_syntax.toml +++ b/conformance/results/pyright/typeddicts_class_syntax.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -Does not support version-conditional items in TypedDict definitions. +Does not support version-conditional items in `TypedDict` definitions. """ output = """ typeddicts_class_syntax.py:30:5 - error: TypedDict classes can contain only type annotations (reportGeneralTypeIssues) diff --git a/conformance/results/results.html b/conformance/results/results.html index 733c4d22f..e220e0455 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -1,1397 +1,2666 @@ - + + + + + + + Python Type System Conformance Test Results + - + /* Add an asterisk if there are notes to display for a "Pass". */ + &.conformant::after { + content: "*"; + position: absolute; + } - -
+ .notes { + background-color: light-dark(var(--light-main-bg), var(--dark-main-bg)); + border-radius: 5px; + box-shadow: 0 0 3px light-dark(var(--light-shadow), var(--dark-shadow)); + color: light-dark(var(--light-main-fg), var(--dark-main-fg)); + cursor: default; + font-size: .8em; + inset-block-start: calc(50% - 5px); + inset-inline-end: 50%; + line-height: 1.6; + list-style-position: inside; + min-inline-size: 500px; + padding: 10px 15px; + position: absolute; + text-align: start; + visibility: hidden; + z-index: 2; + & > li { + padding: 3px 0; + text-indent: 1.3em hanging; + } + } + + &:hover .notes { + visibility: visible; + } + } + + .disclaimer { + color: var(--dark-muted-fg); + font-size: 0.9rem; + font-weight: normal; + line-height: 1.4; + margin: 1rem auto; + max-inline-size: 720px; + } + + form:has(#color-scheme) { + background: inherit; + inset-block-start: 1rem; + inset-inline-end: 1rem; + position: absolute; + } + + #color-scheme { + appearance: none; + background: inherit; + border-color: var(--dark-muted-fg); + border-radius: 5px; + border-style: solid; + border-width: 1px; + color: inherit; + padding: 0.5rem; + &:focus { + border-color: inherit; + outline: none; + } + &:hover { + border-color: inherit; + } + } + + + +
-

Python Type System Conformance Test Results

+

Python Type System Conformance Test Results

- While spec conformance is important for the ecosystem, we don't recommend using it - as the primary basis for choosing a type checker. It is not representative + While specification conformance is important for the ecosystem, we don't recommend + using it as the primary basis for choosing a type checker. It is not representative of many of the things users typically care about.

+
+ + +
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
mypy 2.1.0
-
pyright 1.1.410
-
zuban 0.8.2
-
pyrefly 1.1.0
-
pycroscope 0.4.0
-
ty 0.0.50
-
-Type annotations -
     annotations_coroutinesPassPassPassPassPassPass
     annotations_forward_refs
Partial

Does not report error for a forward reference that is not enclosed in quotes.

Does not report error for use of quoted type with "|" operator (runtime error).

Incorrectly generates error for quoted type defined in class scope.

Pass
Partial

Incorrectly generates error for quoted type defined in class scope.

Partial

Types in quotes incorrectly refer to shadowing class member.

Does not reject some type forms that require quotes.

Partial

Fails to reject "x" | int annotations that fail at runtime.

Rejects some valid quoted annotations.

Partial

Resolves references in type annotations as referring to end-of-scope types (https://discuss.python.org/t/annotation-string-references-in-class-scope-in-conformance-tests/105439, https://github.com/python/typing/pull/2144)

     annotations_generators
Partial

Does not report incompatible Generator type in `yield from` statement.

PassPassPassPassPass
     annotations_methods
Pass*

Type evaluation differs from other type checkers because of ambiguity in the spec related to method bindings.

Pass*

Type evaluation differs from other type checkers because of ambiguity in the spec related to method bindings.

PassPassPassPass
     annotations_typeexprPassPassPassPass
Partial

Fails to reject various weird annotations

Pass
-Type forms -
     typeforms_typeform
Partial

Does not support assigning Union and GenericAlias objects to their runtime types.

UnsupportedPassPass
Partial

Fails to reject various weird annotations

Pass
-Special types in annotations -
     specialtypes_anyPassPassPassPassPassPass
     specialtypes_neverPassPassPassPass
Partial

Does not enforce invariance in some contexts

Does not allow Any to be assigned to Never

Pass
     specialtypes_nonePassPassPassPassPassPass
     specialtypes_promotionsPassPassPassPassPassPass
     specialtypes_type
Partial

Does not treat `type` same as `type[Any]` for assert_type.

Does not allow access to unknown attributes from object of type `type[Any]`.

PassPassPassPass
Partial

Allows arbitrary attributes to be accessed on `TA` where `TA = typing.Type[typing.Any]` or `TA = type[typing.Any]`.

Treats `type` equivalently to `type[object]` rather than `type[typing.Any]`.

-Generics -
     generics_base_class
Partial

Does not detect inconsistent type variable ordering.

PassPassPassPassPass
     generics_basicPassPassPassPassPass
Partial

Incorrectly allows constrained type variables to be solved to a union of their constraints.

     generics_defaults
Partial

Does not detect a TypeVar with a default used after a TypeVarTuple.

Does not fully support defaults on TypeVarTuple and ParamSpec.

PassPassPass
Partial

Numerous issues; does not support TypeVarTuple and ParamSpec defaults.

Partial

Does not forbid a `TypeVar` immediately following a `TypeVarTuple` in a parameter list from having a default.

Does not support `TypeVarTuple`.

     generics_defaults_referential
Partial

Does not correctly handle defaults referencing other TypeVars.

PassPassPass
Partial

Fails to apply default specializations in some cases.

Pass
     generics_defaults_specialization
Partial

Does not correctly resolve defaults when classes are used directly.

Partial

Allows incorrect assignment to type[].

PassPassPass
Partial

Does not reject subscription of an already-specialized generic class.

     generics_paramspec_basicPassPassPassPassPassPass
     generics_paramspec_componentsPassPassPassPassPass
Partial

Incorrectly allows using `*args: P.args` and `**kwargs: P.kwargs` when `P` has not been put into scope by any other parameter annotation or enclosing scope.

     generics_paramspec_semanticsPass
Pass*

Constraint solver doesn't find common type for two signatures captured by a single ParamSpec (allowed).

PassPassPassPass
     generics_paramspec_specializationPassPassPassPassPassPass
     generics_scopingPassPassPass
Partial

Does not implement several scoping checks/restrictions for generics

Pass
Partial

Does not reject `list[T]()` in the global scope, where `T` is an unbound type variable.

Does nto reject `alias: TypeAlias = list[T]` in the body scope of a class generic over a type variable `T`.

     generics_self_advanced
Partial

Does not infer the type of an unannotated `self` parameter to be type `Self`.

Does not retain `Self` when calling method that returns `Self`.

Does not infer the type of an unannotated `cls` parameter to be type `type[Self]`.

Does not retain `Self` when accessing attribute through `type[Self]`.

PassPass
Pass*

Treats attributes not initialized on the class as instance-only

PassPass
     generics_self_attributesPassPassPassPassPassPass
     generics_self_basicPassPassPassPassPassPass
     generics_self_protocolsPassPassPassPassPassPass
     generics_self_usagePassPassPassPassPass
Partial

Does not reject `Self` used in a return annotation when `self` is annotated using another type variable.

     generics_syntax_compatibilityPassPassPassPassPassPass
     generics_syntax_declarationsPassPassPassPassPassPass
     generics_syntax_infer_variance
Unsupported

Type parameter syntax not yet supported.

PassPassPassPassPass
     generics_syntax_scoping
Partial

Does not following runtime scoping rules for type parameters in all cases.

PassPassPass
Partial

Misses some details of scoping rules.

Pass
     generics_type_erasure
Partial

Infers Node[Never] instead of Node[Any] when argument is not provided.

False negative on instance attribute access on type(node).

PassPassPassPass
Partial

Does not reject access of generic instance variable from the class object.

     generics_typevartuple_args
Partial

Does not enforce that tuples captured by TypeVarTuple are of the same length.

Partial

Does not correctly solve TypeVarTuple with heterogeneous bounds.

PassPassPass
Partial

Supports PEP-646 unpacked tuples but not TypeVarTuple.

     generics_typevartuple_basic
Partial

Does not enforce that tuples captured by TypeVarTuple are same length.

Partial

Does not correctly solve TypeVarTuple with heterogeneous bounds.

PassPassPassUnsupported
     generics_typevartuple_callablePassPassPassPassPassUnsupported
     generics_typevartuple_concatPassPassPassPassPassUnsupported
     generics_typevartuple_overloadsPassPassPassPassPassPass
     generics_typevartuple_specialization
Partial

Incorrectly specializes generic alias that includes a TypeVar and TypeVarTuple if no type arguments are provided.

Rejects specialization of generic type alias defined as a tuple containing a TypeVar.

PassPassPassPassUnsupported
     generics_typevartuple_unpackPassPassPassPassPassUnsupported
     generics_upper_bound
Partial

Does not reject use of type variable within an upper bound.

PassPassPassPassPass
     generics_variance
Partial

Does not reject use of class-scoped TypeVar used in a base class when variance is incompatible.

PassPassPassPassPass
     generics_variance_inferencePassPassPassPassPassPass
-Type qualifiers -
     qualifiers_annotated
Partial

Does not allow ClassVar to be nested within Annotated.

Does not allow Final to be nested within Annotated.

Does not allow Required and NotRequired to be nested within Annotated.

Does not reject type[T] compatibility for type alias defined with Annotated.

Does not reject call of type alias defined with Annotated.

PassPassPass
Partial

Fails to reject various weird annotations.

False positive on lambda in Annotated.

Pass
     qualifiers_final_annotation
Partial

Does not treat use of Final name as if it was replaced by the literal in NamedTuple definition.

Does not allow conditional assignment of Final instance variable in __init__ method.

Does not allow redefinition of private class variable that is marked Final in parent class.

Does not report modification of local Final variable via "for" statement.

PassPassPassPassPass
     qualifiers_final_decoratorPassPassPassPassPassPass
-Class type compatibility -
     classes_classvar
Partial

Internal error if TypeVarTuple is used in ClassVar.

Does not reject use of ParamSpec in ClassVar.

Rejects ClassVar nested in Annotated.

Does not reject use of ClassVar in TypeAlias definition.

PassPassPassPassPass
     classes_overridePassPassPassPassPassPass
-Type aliases -
     aliases_explicit
Partial

Does not reject specialization of type alias that has already been implicitly specialized.

PassPassPassPass
Partial

Does not emit a diagnostic if a type alias to a union, in which every element of the union is implicitly specialized with `Unknown`, is invalidly specialized again.

     aliases_implicitPassPassPassPass
Partial

Fails to handle various weird annotations.

Various bugs with resolving generic aliases.

Partial

Does not reject variables with `Any` or `Unknown` types when used as implicit type aliases.

Falls short on full syntactic validation of type aliases.

     aliases_newtype
Partial

`NewType`s are incorrectly considered to be classes.

PassPassPassPassPass
     aliases_recursivePassPassPassPassPassUnsupported
     aliases_type_statementPassPassPassPass
Partial

Fails to reject various weird annotations.

Partial

Does not reject circular definitions of type aliases.

Does not support `type` statements generic over `TypeVarTuple`s.

     aliases_typealiastype
Partial

Incorrectly rejects some recursive type aliases using TypeAliasType.

Incorrectly rejects the use of a class-scoped TypeVar in a TypeAliasType definition.

PassPassPass
Partial

Rejects valid ParamSpec specialization.

Partial

Does not reject specializing a type parameter in a generic type alias with a type inconsistent with the parameter's upper bound.

Does not reject declaring a type alias with a type variable that is not in scope.

Does not reject declaring a type alias with a non-literal tuple passed to the `type_params` parameter.

Does not reject cyclically defined type aliases.

     aliases_variancePassPassPassPassPassPass
-Literals -
     literals_interactions
Pass*

Does not narrow `str` or `LiteralString` types to `Literal` string types via equality or containment checks.

PassPassPassPass
Pass*

Deliberately does not allow `str` to be narrowed to literal string types through equality or containment checks due to the possibility of `str` subclasses that could have unexpected equality semantics.

     literals_literalstring
Unsupported

Support for `LiteralString` is not implemented.

PassPassPassPassPass
     literals_parameterizations
Partial

Does not reject tuple within Literal.

PassPassPass
Partial

Fails to reject various invalid literal parameterizations.

Pass
     literals_semanticsPassPassPassPassPassPass
-Protocols -
     protocols_class_objectsPassPassPassPass
Partial

Abstract type[Proto] still allows protocol class objects in some paths.

Unsupported

`type[Proto]` is not yet supported.

`ClassVar` protocol members are not yet supported.

`@property` protocol members are only partially supported.

A class object `C` is only considered to inhabit a protocol type with a method member `f` if `f` exists as an attribute on the metaclass of `C`.

     protocols_definition
Partial

Does not detect protocol mismatch if concrete method is missing annotations.

Does not detect protocol mismatch if concrete method's parameters are position-only.

PassPassPassPass
Partial

Does not reject implicit instance attributes in `Protocol` methods.

Does not support `ClassVar` protocol members.

Incorrectly considers `ClassVar` attributes on concrete classes as satisfying non-`ClassVar` attribute members on protocols.

Only has partial support for `@property` protocol members.

     protocols_explicit
Pass*

Does not report unimplemented attributes for class that explicitly derives from protocol until it is instantiated.

PassPassPassPass
Unsupported

Allows implicitly abstract protocol methods to be called via `super()` on a protocol subclass.

Allows instantiation of abstract subclasses of protocol classes.

     protocols_genericPassPassPassPass
Partial

Fails to reject duplicate generic/protocol bases.

Treats global object as a literal.

Partial

Only partially supports `@property` protocol members.

     protocols_mergingPassPassPassPassPass
Partial

Does not reject attempted instantiation of abstract subclasses of protocols.

     protocols_modulesPassPassPassPassPass
Partial

Never considers a module as satisfying a protocol with a method member due to the fact that the method will never exist on the class `types.ModuleType`, only on a given specific module instance.

     protocols_recursivePassPassPassPassPass
Partial

Fails to solve a type variable involving a recursive generic protocol.

     protocols_runtime_checkable
Partial

Does not report unsafe overlap for runtime_checkable protocol.

PassPassPassPass
Partial

Does not reject `isinstance()` or `issubclass()` calls against runtime-checkable protocols where there is an unsafe overlap between the type of the first argument and the protocol.

     protocols_selfPassPassPassPassPassPass
     protocols_subtypingPassPassPassPassPassPass
     protocols_variancePassPassPassPassPassUnsupported
-Callables -
     callables_annotation
Partial

Incorrectly treats "*args: T, **kwargs: T" as "..." when T is specialized to Any.

Does not treat "*args: Any, **kargs: Any" as "..." when separated by keyword parameter.

PassPass
Partial

Parameter names are lost when resolving ParamSpec

Pass
Partial

Infers a callback protocol as being a gradual type if the callback has signature `__call__[T](self, *args: T, **kwargs: T)` and `T` has been explicitly specialized to `Any`.

     callables_kwargs
Partial

Allows callable without kwargs to be assigned to callable with unpacked kwargs

PassPassPassPassPass
     callables_protocolPassPassPassPassPassPass
     callables_subtypingPassPassPassPassPassPass
-Constructors -
     constructors_call_init
Partial

Does not report errors during binding to self parameter of __init__ method.

Does not reject use of class-scoped type variables in annotation of self parameter in __init__ method.

PassPassPassPass
Partial

Does not reject invalid argument types to an inherited constructor in a specialized subclass of a generic superclass.

Does not reject class-scoped type variables used in the `self` annotation.

     constructors_call_metaclass
Unsupported

Does not honor metaclass __call__ method when evaluating constructor call.

Does not skip evaluation of __new__ and __init__ if custom metaclass call returns non-class.

PassPassPassPassPass
     constructors_call_new
Partial

Does not support __new__ return type that is not a subclass of the class being constructed.

Does not skip evaluation of __init__ based on __new__ return type.

Does not report errors during binding to cls parameter of __new__ method.

PassPassPassPassPass
     constructors_call_type
Partial

Does not validate call to custom metaclass __call__ method through type[T].

PassPassPassPass
Partial

Has overly lenient handling of calls to `type[T]` if `T` is a type variable without an upper bound.

     constructors_callable
Partial

Does not generate a union type for __new__ and __init__ when converting class to callable.

Does not ignore __init__ based on __new__ return type when converting class to callable.

Does not support __new__ return type that is different from class being constructed.

PassPass
Partial

Converting constructor to callable does not preserve class-scoped type params.

Pass
Partial

Does not include `__init__` when `__new__` returns `Self`.

Does not ignore `__init__` when `__new__` returns `Any`.

Unions overload return types.

     constructors_consistency
Pass*

Does not report inconsistency between __new__ and __init__ (optional).

PassPassPassPassPass
-Overloads -
     overloads_basicPassPassPassPass
Partial

Does less literal promotion than the test asks for.

Pass
     overloads_consistencyPassPassPassPassPassPass
     overloads_definitions
Partial

Allows @override to be on all overloads and implementation, instead of just implementation.

PassPassPassPassPass
     overloads_definitions_stub
Partial

Allows @override to appear in a stub file not on the first overload.

PassPassPass
Unsupported

Does not support checking stubs.

Pass
     overloads_evaluation
Partial

Does not expand boolean arguments to Literal[True] and Literal[False].

Does not expand enum arguments to literal variants.

Does not expand tuple arguments to possible combinations.

Does not evaluate Any in some cases where overload is ambiguous.

Evaluates Any in some cases where overload is not ambiguous.

Partial

Does not evaluate Any in some cases where overload is ambiguous.

PassPassPassPass
-Exceptions -
     exceptions_context_managersPassPassPass
Partial

Some error suppressing context managers are not detected

PassUnsupported
-Dataclasses -
     dataclasses_descriptors
Partial

Assumes descriptor behavior only when field is assigned in class body.

Does not correctly evaluate type of descriptor access.

PassPass
Partial

* Assumes descriptor behavior only when field is assigned in class body

* Doesn't allow non-data descriptors or data descriptors with differing `__get__` and `__set__` types

Partial

Conformance suite is questionable; see https://github.com/python/typing/issues/2259

Partial

Only infers a descriptor `__get__` method as being called when a descriptor attribute is accessed on an instance if the descriptor attribute is present in the class namespace.

     dataclasses_final
Partial

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

Doesn't support Final nested inside ClassVar.

PassPassPassPassPass
     dataclasses_frozenPassPassPassPassPassPass
     dataclasses_hash
Unsupported

Does not synthesize `__hash__ = None` as a class attribute for unhashable dataclasses.

Does not report when an unhashable dataclass has `__hash__` called directly on an instance.

Does not report when dataclass is not compatible with Hashable protocol.

PassPassPassPass
Partial

Understands the `Hashable` protocol as equivalent to `object`.

     dataclasses_inheritancePassPassPassPassPassPass
     dataclasses_kwonlyPassPassPassPassPassPass
     dataclasses_match_argsPassPassPassPassPassPass
     dataclasses_orderPassPassPassPassPassPass
     dataclasses_postinitPassPassPassPassPassPass
     dataclasses_slots
Partial

Does not reject write to instance variable that is not defined in __slots__.

PassPassPassPass
Partial

Synthesizes a `__slots__` attribute but does not validate attribute assignments against `__slots__`.

     dataclasses_transform_classPassPassPassPassPassPass
     dataclasses_transform_converter
Unsupported

Converter parameter not yet supported.

PassPassPassPassPass
     dataclasses_transform_field
Partial

Does not properly handle field constructor that has default value for `kw_only` or `init` parameter.

PassPassPassPassPass
     dataclasses_transform_func
Partial

Does not handle `kw_only=False` override when `kw_only_default=True`.

Does not report error when `order=False` and comparison operators are used.

PassPassPassPassPass
     dataclasses_transform_metaPassPassPassPassPassPass
     dataclasses_usage
Pass*

Does not detect unannotated usage of `dataclasses.field()`.

PassPassPassPassPass
-Typed dictionaries -
     typeddicts_alt_syntax
Pass*

Does not support keyword-argument form of alternative syntax (deprecated in 3.11).

PassPassPassPassPass
     typeddicts_class_syntax
Partial

Does not support version-conditional items in TypedDict definitions.

Partial

Does not support version-conditional items in TypedDict definitions.

PassPassPassPass
     typeddicts_extra_items
Unsupported

Not supported.

PassPassPassPassPass
     typeddicts_finalPassPassPassPassPassPass
     typeddicts_inheritancePassPassPassPassPassPass
     typeddicts_operationsPassPassPassPassPassPass
     typeddicts_readonlyPassPassPassPassPassPass
     typeddicts_readonly_consistencyPassPassPassPassPassPass
     typeddicts_readonly_inheritance
Partial

Incorrectly rejects non-ReadOnly override of ReadOnly item.

Incorrectly rejects override of ReadOnly item with another ReadOnly item with narrower type.

Incorrectly rejects override of NotRequired ReadOnly item with a Required ReadOnly item.

PassPassPassPassPass
     typeddicts_readonly_kwargsPassPassPassPassPassPass
     typeddicts_readonly_update
Partial

Incorrectly allows update of ReadOnly item.

Incorrectly rejects update involving an item with Never type.

PassPassPassPassPass
     typeddicts_requiredPassPassPassPassPassPass
     typeddicts_type_consistencyPassPassPassPass
Partial

Considers TypedDicts to be assignable to plain dict types.

Pass
     typeddicts_usagePassPassPassPassPassPass
-Tuples -
     tuples_type_compat
Partial

Does not support tuple narrowing based on `len()` type guard (optional).

Incorrectly marks a match case as unreachable.

PassPassPassPassPass
     tuples_type_formPassPassPassPassPassPass
     tuples_unpacked
Partial

"More than one unpack" error is missing in some cases.

PassPassPassPassPass
-Named tuples -
     namedtuples_define_class
Partial

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

Does not support version-conditional fields.

PassPassPass
Partial

Does not support precise type inference for slices over namedtuples.

Pass
     namedtuples_define_functionalPassPassPassPassPassPass
     namedtuples_type_compatPassPassPassPassPassPass
     namedtuples_usage
Partial

Does not reject attempt to delete named tuple field by name.

PassPassPassPassPass
-Enumerations -
     enums_behaviorsPassPassPassPassPassPass
     enums_definitionPassPassPassPass
Partial

Does not allow enum members to be conditional on version/platform checks.

Pass
     enums_expansion
Partial

Improperly applies narrowing to Flag subclass.

PassPassPassPass
Partial

Does not support `enum.Flag`.

     enums_member_names
Pass*

Does not support special-cased handling of member name literal types in some cases (optional).

PassPassPassPassPass
     enums_member_values
Partial

Does not enforce declared type of `_value_`.

Does not enforce assigned tuple types for enum members (optional).

PassPassPassPassPass
     enums_members
Partial

Does not treat attribute with annotation and no assignment as non-member.

Does not treat callables as non-members.

Does not honor `enum.member` as method decorator.

Does not properly handle aliased enum members.

Does not support `_ignore_` mechanism (optional).

Does not treat attributes with private names as non-members.

Pass*

Does not support `_ignore_` mechanism (optional).

PassPassPassPass
-Type narrowing -
     narrowing_typeguardPassPassPassPassPassPass
     narrowing_typeisPassPassPassPassPass
Partial

Intersects the pre-existing type with the top materialization of the bracketed type rather than the bracketed type itself.

-Type checker directives -
     directives_assert_typePassPassPassPassPassPass
     directives_castPassPassPassPassPassPass
     directives_deprecatedPassPassPassPassPass
Partial

Does not detect calls to deprecated overloads.

Does not detect implicit calls to deprecated dunder methods, for example via operators.

Does not detect accesses of, or attempts to set, deprecated properties.

     directives_disjoint_basePass
Unsupported

Does not support PEP 800 disjoint-base semantics.

PassPass
Partial

Does not reject invalid class definitions due to disjoint bases, but uses disjoint base information in type narrowing.

Pass
     directives_no_type_check
Partial

Does not honor `@no_type_check` class decorator (allowed).

Does not reject invalid call of `@no_type_check` function.

Pass*

Does not honor `@no_type_check` class decorator (allowed).

PassPassPassPass
     directives_reveal_typePassPassPassPassPassPass
     directives_type_checkingPassPassPassPassPassPass
     directives_type_ignore
Partial

Does not honor "# type: ignore" comment if comment includes additional text.

PassPassPassPassPass
     directives_type_ignore_file1PassPassPassPassPassPass
     directives_type_ignore_file2PassPassPassPassPassPass
     directives_version_platform
Pass*

Does not understand three-element form of sys.version checks.

Does not understand os.name checks.

PassPassPassPassPass
-Historical and deprecated features -
     historical_positional
Partial

Does not reject positional-only parameter after non-positional-only parameter.

Treats keyword-only parameter as positional-only.

Applies legacy positional-only rules when PEP 570 syntax is used.

PassPassPassPassPass
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
mypy 2.1.0pycroscope 0.4.0pyrefly 1.1.0pyright 1.1.410ty 0.0.50zuban 0.8.2
+ Type annotations +
annotations_coroutinesPassPassPassPassPassPass
annotations_forward_refs + Partial +
    +
  • Does not report error for a forward reference that is not enclosed in quotes.
  • +
  • Does not report error for use of quoted type with | operator (runtime error).
  • +
  • Incorrectly generates error for quoted type defined in class scope.
  • +
+
+ Partial +
    +
  • Fails to reject "x" | int annotations that fail at runtime.
  • +
  • Rejects some valid quoted annotations.
  • +
+
+ Partial +
    +
  • Types in quotes incorrectly refer to shadowing class member.
  • +
  • Does not reject some type forms that require quotes.
  • +
+
Pass + Partial + + + Partial +
    +
  • Incorrectly generates error for quoted type defined in class scope.
  • +
+
annotations_generators + Partial +
    +
  • Does not report incompatible Generator type in yield from statement.
  • +
+
PassPassPassPassPass
annotations_methods + Pass +
    +
  • Type evaluation differs from other type checkers because of ambiguity in the spec related to method bindings.
  • +
+
PassPass + Pass +
    +
  • Type evaluation differs from other type checkers because of ambiguity in the spec related to method bindings.
  • +
+
PassPass
annotations_typeexprPass + Partial +
    +
  • Fails to reject various weird annotations
  • +
+
PassPassPassPass
4 / 5 • 80.0%4 / 5 • 80.0%4.5 / 5 • 90.0%5 / 5 • 100.0%4.5 / 5 • 90.0%4.5 / 5 • 90.0%
+ Type forms +
typeforms_typeform + Partial +
    +
  • Does not support assigning Union and GenericAlias objects to their runtime types.
  • +
+
+ Partial +
    +
  • Fails to reject various weird annotations
  • +
+
PassUnsupportedPassPass
0.5 / 1 • 50.0%0.5 / 1 • 50.0%1 / 1 • 100.0%0 / 1 • 0.0%1 / 1 • 100.0%1 / 1 • 100.0%
+ Special types in annotations +
specialtypes_anyPassPassPassPassPassPass
specialtypes_neverPass + Partial +
    +
  • Does not enforce invariance in some contexts
  • +
  • Does not allow Any to be assigned to Never
  • +
+
PassPassPassPass
specialtypes_nonePassPassPassPassPassPass
specialtypes_promotionsPassPassPassPassPassPass
specialtypes_type + Partial +
    +
  • Does not treat type same as type[Any] for assert_type.
  • +
  • Does not allow access to unknown attributes from object of type type[Any].
  • +
+
PassPassPass + Partial +
    +
  • Allows arbitrary attributes to be accessed on TA where TA = typing.Type[typing.Any] or TA = type[typing.Any].
  • +
  • Treats type equivalently to type[object] rather than type[typing.Any].
  • +
+
Pass
4.5 / 5 • 90.0%4.5 / 5 • 90.0%5 / 5 • 100.0%5 / 5 • 100.0%4.5 / 5 • 90.0%5 / 5 • 100.0%
+ Generics +
generics_base_class + Partial +
    +
  • Does not detect inconsistent type variable ordering.
  • +
+
PassPassPassPassPass
generics_basicPassPassPassPass + Partial +
    +
  • Incorrectly allows constrained type variables to be solved to a union of their constraints.
  • +
+
Pass
generics_defaults + Partial +
    +
  • Does not detect a TypeVar with a default used after a TypeVarTuple.
  • +
  • Does not fully support defaults on TypeVarTuple and ParamSpec.
  • +
+
+ Partial +
    +
  • Numerous issues; does not support TypeVarTuple and ParamSpec defaults.
  • +
+
PassPass + Partial +
    +
  • Does not forbid a TypeVar immediately following a TypeVarTuple in a parameter list from having a default.
  • +
  • Does not support TypeVarTuple.
  • +
+
Pass
generics_defaults_referential + Partial +
    +
  • Does not correctly handle defaults referencing other TypeVars.
  • +
+
+ Partial +
    +
  • Fails to apply default specializations in some cases.
  • +
+
PassPassPassPass
generics_defaults_specialization + Partial +
    +
  • Does not correctly resolve defaults when classes are used directly.
  • +
+
PassPass + Partial +
    +
  • Allows incorrect assignment to type[].
  • +
+
+ Partial +
    +
  • Does not reject subscription of an already-specialized generic class.
  • +
+
Pass
generics_paramspec_basicPassPassPassPassPassPass
generics_paramspec_componentsPassPassPassPass + Partial +
    +
  • Incorrectly allows using *args: P.args and **kwargs: P.kwargs when P has not been put into scope by any other parameter annotation or enclosing scope.
  • +
+
Pass
generics_paramspec_semanticsPassPassPass + Pass +
    +
  • Constraint solver doesn't find common type for two signatures captured by a single ParamSpec (allowed).
  • +
+
PassPass
generics_paramspec_specializationPassPassPassPassPassPass
generics_scopingPassPass + Partial +
    +
  • Does not implement several scoping checks/restrictions for generics.
  • +
+
Pass + Partial +
    +
  • Does not reject list[T]() in the global scope, where T is an unbound type variable.
  • +
  • Does not reject alias: TypeAlias = list[T] in the body scope of a class generic over a type variable T.
  • +
+
Pass
generics_self_advanced + Partial +
    +
  • Does not infer the type of an unannotated self parameter to be type Self.
  • +
  • Does not retain Self when calling method that returns Self.
  • +
  • Does not infer the type of an unannotated cls parameter to be type type[Self].
  • +
  • Does not retain Self when accessing attribute through type[Self].
  • +
+
Pass + Pass +
    +
  • Treats attributes not initialized on the class as instance-only.
  • +
+
PassPassPass
generics_self_attributesPassPassPassPassPassPass
generics_self_basicPassPassPassPassPassPass
generics_self_protocolsPassPassPassPassPassPass
generics_self_usagePassPassPassPass + Partial +
    +
  • Does not reject Self used in a return annotation when self is annotated using another type variable.
  • +
+
Pass
generics_syntax_compatibilityPassPassPassPassPassPass
generics_syntax_declarationsPassPassPassPassPassPass
generics_syntax_infer_variance + Unsupported +
    +
  • Type parameter syntax not yet supported.
  • +
+
PassPassPassPassPass
generics_syntax_scoping + Partial +
    +
  • Does not following runtime scoping rules for type parameters in all cases.
  • +
+
+ Partial +
    +
  • Misses some details of scoping rules.
  • +
+
PassPassPassPass
generics_type_erasure + Partial +
    +
  • Infers Node[Never] instead of Node[Any] when argument is not provided.
  • +
  • False negative on instance attribute access on type(node).
  • +
+
PassPassPass + Partial +
    +
  • Does not reject access of generic instance variable from the class object.
  • +
+
Pass
generics_typevartuple_args + Partial +
    +
  • Does not enforce that tuples captured by TypeVarTuple are of the same length.
  • +
+
PassPass + Partial +
    +
  • Does not correctly solve TypeVarTuple with heterogeneous bounds.
  • +
+
+ Partial +
    +
  • Supports PEP-646 unpacked tuples but not TypeVarTuple.
  • +
+
Pass
generics_typevartuple_basic + Partial +
    +
  • Does not enforce that tuples captured by TypeVarTuple are same length.
  • +
+
PassPass + Partial +
    +
  • Does not correctly solve TypeVarTuple with heterogeneous bounds.
  • +
+
UnsupportedPass
generics_typevartuple_callablePassPassPassPassUnsupportedPass
generics_typevartuple_concatPassPassPassPassUnsupportedPass
generics_typevartuple_overloadsPassPassPassPassPassPass
generics_typevartuple_specialization + Partial +
    +
  • Incorrectly specializes generic alias that includes a TypeVar and TypeVarTuple if no type arguments are provided.
  • +
  • Rejects specialization of generic type alias defined as a tuple containing a TypeVar.
  • +
+
PassPassPassUnsupportedPass
generics_typevartuple_unpackPassPassPassPassUnsupportedPass
generics_upper_bound + Partial +
    +
  • Does not reject use of type variable within an upper bound.
  • +
+
PassPassPassPassPass
generics_variance + Partial +
    +
  • Does not reject use of class-scoped TypeVar used in a base class when variance is incompatible.
  • +
+
PassPassPassPassPass
generics_variance_inferencePassPassPassPassPassPass
23 / 30 • 76.7%28.5 / 30 • 95.0%29.5 / 30 • 98.3%28.5 / 30 • 95.0%21 / 30 • 70.0%30 / 30 • 100.0%
+ Type qualifiers +
qualifiers_annotated + Partial +
    +
  • Does not allow ClassVar to be nested within Annotated.
  • +
  • Does not allow Final to be nested within Annotated.
  • +
  • Does not allow Required and NotRequired to be nested within Annotated.
  • +
  • Does not reject type[T] compatibility for type alias defined with Annotated.
  • +
  • Does not reject call of type alias defined with Annotated.
  • +
+
+ Partial +
    +
  • Fails to reject various weird annotations.
  • +
  • False positive on lambda in Annotated.
  • +
+
PassPassPassPass
qualifiers_final_annotation + Partial +
    +
  • Does not treat use of Final name as if it was replaced by the literal in NamedTuple definition.
  • +
  • Does not allow conditional assignment of Final instance variable in __init__ method.
  • +
  • Does not allow redefinition of private class variable that is marked Final in parent class.
  • +
  • Does not report modification of local Final variable via for statement.
  • +
+
PassPassPassPassPass
qualifiers_final_decoratorPassPassPassPassPassPass
2 / 3 • 66.7%2.5 / 3 • 83.3%3 / 3 • 100.0%3 / 3 • 100.0%3 / 3 • 100.0%3 / 3 • 100.0%
+ Class type compatibility +
classes_classvar + Partial +
    +
  • Internal error if TypeVarTuple is used in ClassVar.
  • +
  • Does not reject use of ParamSpec in ClassVar.
  • +
  • Rejects ClassVar nested in Annotated.
  • +
  • Does not reject use of ClassVar in TypeAlias definition.
  • +
+
PassPassPassPassPass
classes_overridePassPassPassPassPassPass
1.5 / 2 • 75.0%2 / 2 • 100.0%2 / 2 • 100.0%2 / 2 • 100.0%2 / 2 • 100.0%2 / 2 • 100.0%
+ Type aliases +
aliases_explicit + Partial +
    +
  • Does not reject specialization of type alias that has already been implicitly specialized.
  • +
+
PassPassPass + Partial +
    +
  • Does not emit a diagnostic if a type alias to a union, in which every element of the union is implicitly specialized with Unknown, is invalidly specialized again.
  • +
+
Pass
aliases_implicitPass + Partial +
    +
  • Fails to handle various weird annotations.
  • +
  • Various bugs with resolving generic aliases.
  • +
+
PassPass + Partial +
    +
  • Does not reject variables with Any or Unknown types when used as implicit type aliases.
  • +
  • Falls short on full syntactic validation of type aliases.
  • +
+
Pass
aliases_newtype + Partial +
    +
  • NewTypes are incorrectly considered to be classes.
  • +
+
PassPassPassPassPass
aliases_recursivePassPassPassPassUnsupportedPass
aliases_type_statementPass + Partial +
    +
  • Fails to reject various weird annotations.
  • +
+
PassPass + Partial +
    +
  • Does not reject circular definitions of type aliases.
  • +
  • Does not support type statements generic over TypeVarTuples.
  • +
+
Pass
aliases_typealiastype + Partial +
    +
  • Incorrectly rejects some recursive type aliases using TypeAliasType.
  • +
  • Incorrectly rejects the use of a class-scoped TypeVar in a TypeAliasType definition.
  • +
+
+ Partial +
    +
  • Rejects valid ParamSpec specialization.
  • +
+
PassPass + Partial +
    +
  • Does not reject specializing a type parameter in a generic type alias with a type inconsistent with the parameter's upper bound.
  • +
  • Does not reject declaring a type alias with a type variable that is not in scope.
  • +
  • Does not reject declaring a type alias with a non-literal tuple passed to the type_params parameter.
  • +
  • Does not reject cyclically defined type aliases.
  • +
+
Pass
aliases_variancePassPassPassPassPassPass
5.5 / 7 • 78.6%5.5 / 7 • 78.6%7 / 7 • 100.0%7 / 7 • 100.0%4 / 7 • 57.1%7 / 7 • 100.0%
+ Literals +
literals_interactions + Pass +
    +
  • Does not narrow str or LiteralString types to Literal string types via equality or containment checks.
  • +
+
PassPassPass + Pass +
    +
  • Deliberately does not allow str to be narrowed to literal string types through equality or containment checks due to the possibility of str subclasses that could have unexpected equality semantics.
  • +
+
Pass
literals_literalstring + Unsupported +
    +
  • Support for LiteralString is not implemented.
  • +
+
PassPassPassPassPass
literals_parameterizations + Partial +
    +
  • Does not reject tuple within Literal.
  • +
+
+ Partial +
    +
  • Fails to reject various invalid literal parameterizations.
  • +
+
PassPassPassPass
literals_semanticsPassPassPassPassPassPass
2.5 / 4 • 62.5%3.5 / 4 • 87.5%4 / 4 • 100.0%4 / 4 • 100.0%4 / 4 • 100.0%4 / 4 • 100.0%
+ Protocols +
protocols_class_objectsPass + Partial +
    +
  • Abstract type[Proto] still allows protocol class objects in some paths.
  • +
+
PassPass + Unsupported +
    +
  • type[Proto] is not yet supported.
  • +
  • ClassVar protocol members are not yet supported.
  • +
  • @property protocol members are only partially supported.
  • +
  • A class object C is only considered to inhabit a protocol type with a method member f if f exists as an attribute on the metaclass of C.
  • +
+
Pass
protocols_definition + Partial +
    +
  • Does not detect protocol mismatch if concrete method is missing annotations.
  • +
  • Does not detect protocol mismatch if concrete method's parameters are position-only.
  • +
+
PassPassPass + Partial +
    +
  • Does not reject implicit instance attributes in Protocol methods.
  • +
  • Does not support ClassVar protocol members.
  • +
  • Incorrectly considers ClassVar attributes on concrete classes as satisfying non-ClassVar attribute members on protocols.
  • +
  • Only has partial support for @property protocol members.
  • +
+
Pass
protocols_explicit + Pass +
    +
  • Does not report unimplemented attributes for class that explicitly derives from protocol until it is instantiated.
  • +
+
PassPassPass + Unsupported +
    +
  • Allows implicitly abstract protocol methods to be called via super() on a protocol subclass.
  • +
  • Allows instantiation of abstract subclasses of protocol classes.
  • +
+
Pass
protocols_genericPass + Partial +
    +
  • Fails to reject duplicate generic/protocol bases.
  • +
  • Treats global object as a literal.
  • +
+
PassPass + Partial +
    +
  • Only partially supports @property protocol members.
  • +
+
Pass
protocols_mergingPassPassPassPass + Partial +
    +
  • Does not reject attempted instantiation of abstract subclasses of protocols.
  • +
+
Pass
protocols_modulesPassPassPassPass + Partial +
    +
  • Never considers a module as satisfying a protocol with a method member due to the fact that the method will never exist on the class types.ModuleType, only on a given specific module instance.
  • +
+
Pass
protocols_recursivePassPassPassPass + Partial +
    +
  • Fails to solve a type variable involving a recursive generic protocol.
  • +
+
Pass
protocols_runtime_checkable + Partial +
    +
  • Does not report unsafe overlap for runtime_checkable protocol.
  • +
+
PassPassPass + Partial +
    +
  • Does not reject isinstance() or issubclass() calls against runtime-checkable protocols where there is an unsafe overlap between the type of the first argument and the protocol.
  • +
+
Pass
protocols_selfPassPassPassPassPassPass
protocols_subtypingPassPassPassPassPassPass
protocols_variancePassPassPassPassUnsupportedPass
10 / 11 • 90.9%10 / 11 • 90.9%11 / 11 • 100.0%11 / 11 • 100.0%5 / 11 • 45.5%11 / 11 • 100.0%
+ Callables +
callables_annotation + Partial +
    +
  • Incorrectly treats *args: T, **kwargs: T as ... when T is specialized to Any.
  • +
  • Does not treat *args: Any, **kargs: Any as ... when separated by keyword parameter.
  • +
+
Pass + Partial +
    +
  • Parameter names are lost when resolving ParamSpec.
  • +
+
Pass + Partial +
    +
  • Infers a callback protocol as being a gradual type if the callback has signature __call__[T](self, *args: T, **kwargs: T) and T has been explicitly specialized to Any.
  • +
+
Pass
callables_kwargs + Partial +
    +
  • Allows callable without kwargs to be assigned to callable with unpacked kwargs.
  • +
+
PassPassPassPassPass
callables_protocolPassPassPassPassPassPass
callables_subtypingPassPassPassPassPassPass
3 / 4 • 75.0%4 / 4 • 100.0%3.5 / 4 • 87.5%4 / 4 • 100.0%3.5 / 4 • 87.5%4 / 4 • 100.0%
+ Constructors +
constructors_call_init + Partial +
    +
  • Does not report errors during binding to self parameter of __init__ method.
  • +
  • Does not reject use of class-scoped type variables in annotation of self parameter in __init__ method.
  • +
+
PassPassPass + Partial +
    +
  • Does not reject invalid argument types to an inherited constructor in a specialized subclass of a generic superclass.
  • +
  • Does not reject class-scoped type variables used in the self annotation.
  • +
+
Pass
constructors_call_metaclass + Unsupported +
    +
  • Does not honor metaclass __call__ method when evaluating constructor call.
  • +
  • Does not skip evaluation of __new__ and __init__ if custom metaclass call returns non-class.
  • +
+
PassPassPassPassPass
constructors_call_new + Partial +
    +
  • Does not support __new__ return type that is not a subclass of the class being constructed.
  • +
  • Does not skip evaluation of __init__ based on __new__ return type.
  • +
  • Does not report errors during binding to cls parameter of __new__ method.
  • +
+
PassPassPassPassPass
constructors_call_type + Partial +
    +
  • Does not validate call to custom metaclass __call__ method through type[T].
  • +
+
PassPassPass + Partial +
    +
  • Has overly lenient handling of calls to type[T] if T is a type variable without an upper bound.
  • +
+
Pass
constructors_callable + Partial +
    +
  • Does not generate a union type for __new__ and __init__ when converting class to callable.
  • +
  • Does not ignore __init__ based on __new__ return type when converting class to callable.
  • +
  • Does not support __new__ return type that is different from class being constructed.
  • +
+
Pass + Partial +
    +
  • Converting constructor to callable does not preserve class-scoped type params.
  • +
+
Pass + Partial +
    +
  • Does not include __init__ when __new__ returns Self.
  • +
  • Does not ignore __init__ when __new__ returns Any.
  • +
  • Unions overload return types.
  • +
+
Pass
constructors_consistency + Pass +
    +
  • Does not report inconsistency between __new__ and __init__ (optional).
  • +
+
PassPassPassPassPass
3 / 6 • 50.0%6 / 6 • 100.0%5.5 / 6 • 91.7%6 / 6 • 100.0%4.5 / 6 • 75.0%6 / 6 • 100.0%
+ Overloads +
overloads_basicPass + Partial +
    +
  • Does less literal promotion than the test asks for.
  • +
+
PassPassPassPass
overloads_consistencyPassPassPassPassPassPass
overloads_definitions + Partial +
    +
  • Allows @override to be on all overloads and implementation, instead of just implementation.
  • +
+
PassPassPassPassPass
overloads_definitions_stub + Partial +
    +
  • Allows @override to appear in a stub file not on the first overload.
  • +
+
+ Unsupported +
    +
  • Does not support checking stubs.
  • +
+
PassPassPassPass
overloads_evaluation + Partial +
    +
  • Does not expand boolean arguments to Literal[True] and Literal[False].
  • +
  • Does not expand enum arguments to literal variants.
  • +
  • Does not expand tuple arguments to possible combinations.
  • +
  • Does not evaluate Any in some cases where overload is ambiguous.
  • +
  • Evaluates Any in some cases where overload is not ambiguous.
  • +
+
PassPass + Partial +
    +
  • Does not evaluate Any in some cases where overload is ambiguous.
  • +
+
PassPass
3.5 / 5 • 70.0%3.5 / 5 • 70.0%5 / 5 • 100.0%4.5 / 5 • 90.0%5 / 5 • 100.0%5 / 5 • 100.0%
+ Exceptions +
exceptions_context_managersPassPass + Partial +
    +
  • Some error suppressing context managers are not detected.
  • +
+
PassUnsupportedPass
1 / 1 • 100.0%1 / 1 • 100.0%0.5 / 1 • 50.0%1 / 1 • 100.0%0 / 1 • 0.0%1 / 1 • 100.0%
+ Dataclasses +
dataclasses_descriptors + Partial +
    +
  • Assumes descriptor behavior only when field is assigned in class body.
  • +
  • Does not correctly evaluate type of descriptor access.
  • +
+
+ Partial + + + Partial +
    +
  • Assumes descriptor behavior only when field is assigned in class body
  • +
  • Doesn't allow non-data descriptors or data descriptors with differing __get__ and __set__ types
  • +
+
Pass + Partial +
    +
  • Only infers a descriptor __get__ method as being called when a descriptor attribute is accessed on an instance if the descriptor attribute is present in the class namespace.
  • +
+
Pass
dataclasses_final + Partial +
    +
  • Wrongly requires a Final dataclass field to be initialized at class level.
  • +
  • Doesn't support Final nested inside ClassVar.
  • +
+
PassPassPassPassPass
dataclasses_frozenPassPassPassPassPassPass
dataclasses_hash + Unsupported +
    +
  • Does not synthesize __hash__ = None as a class attribute for unhashable dataclasses.
  • +
  • Does not report when an unhashable dataclass has __hash__ called directly on an instance.
  • +
  • Does not report when dataclass is not compatible with Hashable protocol.
  • +
+
PassPassPass + Partial +
    +
  • Understands the Hashable protocol as equivalent to object.
  • +
+
Pass
dataclasses_inheritancePassPassPassPassPassPass
dataclasses_kwonlyPassPassPassPassPassPass
dataclasses_match_argsPassPassPassPassPassPass
dataclasses_orderPassPassPassPassPassPass
dataclasses_postinitPassPassPassPassPassPass
dataclasses_slots + Partial +
    +
  • Does not reject write to instance variable that is not defined in __slots__.
  • +
+
PassPassPass + Partial +
    +
  • Synthesizes a __slots__ attribute but does not validate attribute assignments against __slots__.
  • +
+
Pass
dataclasses_transform_classPassPassPassPassPassPass
dataclasses_transform_converter + Unsupported +
    +
  • Converter parameter not yet supported.
  • +
+
PassPassPassPassPass
dataclasses_transform_field + Partial +
    +
  • Does not properly handle field constructor that has default value for kw_only or init parameter.
  • +
+
PassPassPassPassPass
dataclasses_transform_func + Partial +
    +
  • Does not handle kw_only=False override when kw_only_default=True.
  • +
  • Does not report error when order=False and comparison operators are used.
  • +
+
PassPassPassPassPass
dataclasses_transform_metaPassPassPassPassPassPass
dataclasses_usage + Pass +
    +
  • Does not detect unannotated usage of dataclasses.field().
  • +
+
PassPassPassPassPass
11.5 / 16 • 71.9%15.5 / 16 • 96.9%15.5 / 16 • 96.9%16 / 16 • 100.0%14.5 / 16 • 90.6%16 / 16 • 100.0%
+ Typed dictionaries +
typeddicts_alt_syntax + Pass +
    +
  • Does not support keyword-argument form of alternative syntax (deprecated in 3.11).
  • +
+
PassPassPassPassPass
typeddicts_class_syntax + Partial +
    +
  • Does not support version-conditional items in TypedDict definitions.
  • +
+
PassPass + Partial +
    +
  • Does not support version-conditional items in TypedDict definitions.
  • +
+
PassPass
typeddicts_extra_itemsUnsupportedPassPassPassPassPass
typeddicts_finalPassPassPassPassPassPass
typeddicts_inheritancePassPassPassPassPassPass
typeddicts_operationsPassPassPassPassPassPass
typeddicts_readonlyPassPassPassPassPassPass
typeddicts_readonly_consistencyPassPassPassPassPassPass
typeddicts_readonly_inheritance + Partial +
    +
  • Incorrectly rejects non-ReadOnly override of ReadOnly item.
  • +
  • Incorrectly rejects override of ReadOnly item with another ReadOnly item with narrower type.
  • +
  • Incorrectly rejects override of NotRequired ReadOnly item with a Required ReadOnly item.
  • +
+
PassPassPassPassPass
typeddicts_readonly_kwargsPassPassPassPassPassPass
typeddicts_readonly_update + Partial +
    +
  • Incorrectly allows update of ReadOnly item.
  • +
  • Incorrectly rejects update involving an item with Never type.
  • +
+
PassPassPassPassPass
typeddicts_requiredPassPassPassPassPassPass
typeddicts_type_consistencyPass + Partial +
    +
  • Considers TypedDicts to be assignable to plain dict types.
  • +
+
PassPassPassPass
typeddicts_usagePassPassPassPassPassPass
11.5 / 14 • 82.1%13.5 / 14 • 96.4%14 / 14 • 100.0%13.5 / 14 • 96.4%14 / 14 • 100.0%14 / 14 • 100.0%
+ Tuples +
tuples_type_compat + Partial +
    +
  • Does not support tuple narrowing based on len() type guard (optional).
  • +
  • Incorrectly marks a match case as unreachable.
  • +
+
PassPassPassPassPass
tuples_type_formPassPassPassPassPassPass
tuples_unpacked + Partial +
    +
  • "More than one unpack" error is missing in some cases.
  • +
+
PassPassPassPassPass
2 / 3 • 66.7%3 / 3 • 100.0%3 / 3 • 100.0%3 / 3 • 100.0%3 / 3 • 100.0%3 / 3 • 100.0%
+ Named tuples +
namedtuples_define_class + Partial +
    +
  • Does not reject override of named tuple attribute in child class.
  • +
  • Does not support version-conditional fields.
  • +
+
+ Partial +
    +
  • Does not support precise type inference for slices over namedtuples.
  • +
+
PassPassPassPass
namedtuples_define_functionalPassPassPassPassPassPass
namedtuples_type_compatPassPassPassPassPassPass
namedtuples_usage + Partial +
    +
  • Does not reject attempt to delete named tuple field by name.
  • +
+
PassPassPassPassPass
3 / 4 • 75.0%3.5 / 4 • 87.5%4 / 4 • 100.0%4 / 4 • 100.0%4 / 4 • 100.0%4 / 4 • 100.0%
+ Enumerations +
enums_behaviorsPassPassPassPassPassPass
enums_definitionPass + Partial +
    +
  • Does not allow enum members to be conditional on version/platform checks.
  • +
+
PassPassPassPass
enums_expansion + Partial +
    +
  • Improperly applies narrowing to Flag subclass.
  • +
+
PassPassPass + Partial +
    +
  • Does not support enum.Flag.
  • +
+
Pass
enums_member_names + Pass +
    +
  • Does not support special-cased handling of member name literal types in some cases (optional).
  • +
+
PassPassPassPassPass
enums_member_values + Partial +
    +
  • Does not enforce declared type of _value_.
  • +
  • Does not enforce assigned tuple types for enum members (optional).
  • +
+
PassPassPassPassPass
enums_members + Partial +
    +
  • Does not treat attribute with annotation and no assignment as non-member.
  • +
  • Does not treat callables as non-members.
  • +
  • Does not honor enum.member as method decorator.
  • +
  • Does not properly handle aliased enum members.
  • +
  • Does not support _ignore_ mechanism (optional).
  • +
  • Does not treat attributes with private names as non-members.
  • +
+
PassPass + Pass +
    +
  • Does not support _ignore_ mechanism (optional).
  • +
+
PassPass
4.5 / 6 • 75.0%5.5 / 6 • 91.7%6 / 6 • 100.0%6 / 6 • 100.0%5.5 / 6 • 91.7%6 / 6 • 100.0%
+ Type narrowing +
narrowing_typeguardPassPassPassPassPassPass
narrowing_typeisPassPassPassPass + Partial +
    +
  • Intersects the pre-existing type with the top materialization of the bracketed type rather than the bracketed type itself.
  • +
+
Pass
2 / 2 • 100.0%2 / 2 • 100.0%2 / 2 • 100.0%2 / 2 • 100.0%1.5 / 2 • 75.0%2 / 2 • 100.0%
+ Type checker directives +
directives_assert_typePassPassPassPassPassPass
directives_castPassPassPassPassPassPass
directives_deprecatedPassPassPassPass + Partial +
    +
  • Does not detect calls to deprecated overloads.
  • +
  • Does not detect implicit calls to deprecated dunder methods, for example via operators.
  • +
  • Does not detect accesses of, or attempts to set, deprecated properties.
  • +
+
Pass
directives_disjoint_basePass + Partial +
    +
  • Does not reject invalid class definitions due to disjoint bases, but uses disjoint base information in type narrowing.
  • +
+
Pass + Unsupported +
    +
  • Does not support PEP 800 disjoint-base semantics.
  • +
+
PassPass
directives_no_type_check + Partial +
    +
  • Does not honor @no_type_check class decorator (allowed).
  • +
  • Does not reject invalid call of @no_type_check function.
  • +
+
PassPass + Pass +
    +
  • Does not honor @no_type_check class decorator (allowed).
  • +
+
PassPass
directives_reveal_typePassPassPassPassPassPass
directives_type_checkingPassPassPassPassPassPass
directives_type_ignore + Partial +
    +
  • Does not honor # type: ignore comment if comment includes additional text.
  • +
+
PassPassPassPassPass
directives_type_ignore_file1PassPassPassPassPassPass
directives_type_ignore_file2PassPassPassPassPassPass
directives_version_platform + Pass +
    +
  • Does not understand three-element form of sys.version checks.
  • +
  • Does not understand os.name checks.
  • +
+
PassPassPassPassPass
10 / 11 • 90.9%10.5 / 11 • 95.5%11 / 11 • 100.0%10 / 11 • 90.9%10.5 / 11 • 95.5%11 / 11 • 100.0%
+ Historical and deprecated features +
historical_positional + Partial +
    +
  • Does not reject positional-only parameter after non-positional-only parameter.
  • +
  • Treats keyword-only parameter as positional-only.
  • +
  • Applies legacy positional-only rules when PEP 570 syntax is used.
  • +
+
PassPassPassPassPass
0.5 / 1 • 50.0%1 / 1 • 100.0%1 / 1 • 100.0%1 / 1 • 100.0%1 / 1 • 100.0%1 / 1 • 100.0%
109 / 141 • 77.3%130 / 141 • 92.2%138 / 141 • 97.9%136.5 / 141 • 96.8%116 / 141 • 82.3%140.5 / 141 • 99.6%
+
+ + + \ No newline at end of file diff --git a/conformance/results/ty/annotations_forward_refs.toml b/conformance/results/ty/annotations_forward_refs.toml index 5944683d0..d176548df 100644 --- a/conformance/results/ty/annotations_forward_refs.toml +++ b/conformance/results/ty/annotations_forward_refs.toml @@ -1,7 +1,7 @@ conformance_automated = "Fail" conformant = "Partial" notes = """ -Resolves references in type annotations as referring to end-of-scope types (https://discuss.python.org/t/annotation-string-references-in-class-scope-in-conformance-tests/105439, https://github.com/python/typing/pull/2144) +Resolves references in type annotations as referring to end-of-scope types (, ) """ errors_diff = """ Line 87: Unexpected errors ['annotations_forward_refs.py:87:9: error[invalid-type-form] Function `int` is not valid in a type expression'] diff --git a/conformance/results/ty/generics_scoping.toml b/conformance/results/ty/generics_scoping.toml index b37df7322..330fcd0a8 100644 --- a/conformance/results/ty/generics_scoping.toml +++ b/conformance/results/ty/generics_scoping.toml @@ -2,7 +2,7 @@ conformance_automated = "Fail" conformant = "Partial" notes = """ Does not reject `list[T]()` in the global scope, where `T` is an unbound type variable. -Does nto reject `alias: TypeAlias = list[T]` in the body scope of a class generic over a type variable `T`. +Does not reject `alias: TypeAlias = list[T]` in the body scope of a class generic over a type variable `T`. """ errors_diff = """ Line 98: Expected 1 errors diff --git a/conformance/results/ty/generics_typevartuple_args.toml b/conformance/results/ty/generics_typevartuple_args.toml index 7de7af540..826f3333d 100644 --- a/conformance/results/ty/generics_typevartuple_args.toml +++ b/conformance/results/ty/generics_typevartuple_args.toml @@ -1,7 +1,7 @@ conformance_automated = "Fail" conformant = "Partial" notes = """ -Supports PEP-646 unpacked tuples but not TypeVarTuple. +Supports PEP-646 unpacked tuples but not `TypeVarTuple`. """ errors_diff = """ Line 33: Expected 1 errors diff --git a/conformance/results/zuban/enums_member_values.toml b/conformance/results/zuban/enums_member_values.toml index 9705e064b..0e71e68fa 100644 --- a/conformance/results/zuban/enums_member_values.toml +++ b/conformance/results/zuban/enums_member_values.toml @@ -1,5 +1,3 @@ -notes = """ -""" conformance_automated = "Pass" errors_diff = """ """ diff --git a/conformance/results/zuban/enums_members.toml b/conformance/results/zuban/enums_members.toml index 5176996e0..532bcb874 100644 --- a/conformance/results/zuban/enums_members.toml +++ b/conformance/results/zuban/enums_members.toml @@ -1,5 +1,3 @@ -notes = """ -""" conformance_automated = "Pass" errors_diff = """ """ diff --git a/conformance/src/main.py b/conformance/src/main.py index 005b3bd98..63f82ea72 100644 --- a/conformance/src/main.py +++ b/conformance/src/main.py @@ -2,14 +2,14 @@ Type system conformance test for static type checkers. """ -import os -from pathlib import Path +import contextlib import re import sys +import tomllib +from pathlib import Path from time import time from typing import Sequence -import tomli import tomlkit from options import parse_options @@ -182,11 +182,11 @@ def update_output_for_test( # Read the existing results file if present. try: with open(results_file, "rb") as f: - existing_results = tomli.load(f) + existing_results = tomllib.load(f) except FileNotFoundError: should_write = True existing_results = {} - except tomli.TOMLDecodeError: + except tomllib.TOMLDecodeError: print(f"Error decoding {results_file}") existing_results = {} @@ -244,10 +244,10 @@ def update_type_checker_info(type_checker: TypeChecker, root_dir: Path): # Read the existing version file if present. try: with open(version_file, "rb") as f: - existing_info = tomli.load(f) + existing_info = tomllib.load(f) except FileNotFoundError: existing_info = {} - except tomli.TOMLDecodeError: + except tomllib.TOMLDecodeError: print(f"Error decoding {version_file}") existing_info = {} @@ -275,16 +275,16 @@ def main(): test_cases = get_test_cases(test_groups, tests_dir) # Switch to the tests directory. - os.chdir(tests_dir) - - # Run each test case with each type checker. - for type_checker in TYPE_CHECKERS: - if options.only_run and options.only_run != type_checker.name: - continue - if not type_checker.install(): - print(f"Skipping tests for {type_checker.name}") - else: - run_tests(root_dir, type_checker, test_cases, verbose=options.verbose) + with contextlib.chdir(tests_dir): + + # Run each test case with each type checker. + for type_checker in TYPE_CHECKERS: + if options.only_run and options.only_run != type_checker.name: + continue + if not type_checker.install(): + print(f"Skipping tests for {type_checker.name}") + else: + run_tests(root_dir, type_checker, test_cases, verbose=options.verbose) # Generate a summary report. generate_summary(root_dir) diff --git a/conformance/src/reporting.py b/conformance/src/reporting.py index cff2dc465..63e2fd1f7 100644 --- a/conformance/src/reporting.py +++ b/conformance/src/reporting.py @@ -2,121 +2,226 @@ Generates a summary of the type checker conformant tests. """ +import itertools +import operator +import tomllib +from collections.abc import Sequence +from dataclasses import dataclass, field +from decimal import Decimal from pathlib import Path -import tomli +import jinja2 +import markdown +import markupsafe from test_groups import get_test_cases, get_test_groups -from type_checker import TYPE_CHECKERS +from type_checker import TYPE_CHECKERS, TypeChecker + + +@dataclass(frozen=True, kw_only=True, slots=True) +class TestResult: + type_checker: str + conformance: str + notes: list[markupsafe.Markup] = field(default_factory=list) + + +@dataclass(frozen=True, kw_only=True, slots=True) +class TestCase: + name: str + results: list[TestResult] = field(default_factory=list) + + +@dataclass(frozen=True, kw_only=True, slots=True) +class TestStat: + type_checker: str + total: int + passed: Decimal + + @property + def percentage(self) -> str: + return f"{self.passed / self.total:.1%}" + + +@dataclass(frozen=True, kw_only=True, slots=True) +class TestGroup: + slug: str + name: str + href: str + paths: list[Path] = field(default_factory=list) + cases: list[TestCase] = field(default_factory=list) + stats: list[TestStat] = field(default_factory=list) def generate_summary(root_dir: Path): print("Generating summary report") - template_file = root_dir / "src" / "results_template.html" - with open(template_file, "r") as f: - template = f.read() - summary = template.replace("{{summary}}", generate_summary_html(root_dir)) + env = jinja2.Environment( + loader=jinja2.FileSystemLoader(root_dir.joinpath("src/templates")), + autoescape=jinja2.select_autoescape(), + ) + env.filters["conformance_class"] = _conformance_class + + template = env.get_template("base.html") + + type_checkers = sorted(TYPE_CHECKERS, key=operator.attrgetter("name")) - results_file = root_dir / "results" / "results.html" + groups = _get_groups(root_dir, type_checkers) + totals = _get_totals(groups) + versions = _get_versions(root_dir, type_checkers) - with open(results_file, "w") as f: - f.write(summary) + results = template.render(groups=groups, totals=totals, versions=versions) + root_dir.joinpath("results", "results.html").write_text(results) -def generate_summary_html(root_dir: Path) -> str: - column_count = len(TYPE_CHECKERS) + 1 + +def _conformance_class(value: str) -> str: + if value == "Pass": + return "conformant" + if value == "Partial": + return "partially-conformant" + return "not-conformant" + + +def _get_groups( + root_dir: Path, + type_checkers: Sequence[TypeChecker], +) -> list[TestGroup]: test_groups = get_test_groups(root_dir) test_cases = get_test_cases(test_groups, root_dir / "tests") - summary_html = ['
'] - summary_html.append('') + groups = [] + + for test_group_slug, test_group in test_groups.items(): + paths = sorted( + [ + case + for case in test_cases + if case.name.startswith(f"{test_group_slug}_") + ], + key=operator.attrgetter("name"), + ) + + # Skip if there are no test cases in the group. + if not paths: + continue + + group = TestGroup( + slug=test_group_slug, + name=test_group.name, + href=test_group.href, + paths=paths, + ) + groups.append(group) + + for path in group.paths: + case = TestCase(name=path.stem) + group.cases.append(case) + + for type_checker in type_checkers: + result_path = ( + root_dir / "results" / type_checker.name / f"{case.name}.toml" + ) + try: + with result_path.open("rb") as f: + data = tomllib.load(f) + except FileNotFoundError: + data = {} + + conformance = data.get("conformant") + if not conformance: + # Try to look up the automated test results and use that if the test passes. + automated = data.get("conformance_automated") + conformance = "Pass" if automated == "Pass" else "Unknown" + + notes = [ + markupsafe.Markup( + markdown.markdown(note, output_format="html") + .removeprefix("

") + .removesuffix("

") + ) + for note in data.get("notes", "").strip().splitlines() + ] + + result = TestResult( + type_checker=type_checker.name, + conformance=conformance, + notes=notes, + ) + case.results.append(result) + + for n, type_checker in enumerate(type_checkers): + passed = Decimal("0.0") + + for case in group.cases: + match case.results[n].conformance: + case "Pass": + passed += Decimal("1.0") + case "Partial": + # For partial support, give half a mark :) + passed += Decimal("0.5") + + stat = TestStat( + type_checker=type_checker.name, + total=len(group.paths), + passed=_remove_exponent(passed), + ) + group.stats.append(stat) - for type_checker in TYPE_CHECKERS: - # Load the version file for the type checker. - version_file = root_dir / "results" / type_checker.name / "version.toml" + return groups - try: - with open(version_file, "rb") as f: - existing_info = tomli.load(f) - except FileNotFoundError: - existing_info = {} - except tomli.TOMLDecodeError: - print(f"Error decoding {version_file}") - existing_info = {} - version = existing_info["version"] or "Unknown version" +def _get_totals(groups: list[TestGroup]) -> list[TestStat]: + totals = [] - summary_html.append(f"") + # As we already sort by type checker above, we can sort and group by here and maintain the + # correct order for the totals output. + ordered = sorted( + [stat for group in groups for stat in group.stats], + key=operator.attrgetter("type_checker"), + ) - summary_html.append("") + for type_checker, stats_it in itertools.groupby( + ordered, operator.attrgetter("type_checker") + ): + stats = list(stats_it) + total = TestStat( + type_checker=type_checker, + total=sum([stat.total for stat in stats]), + passed=_remove_exponent( + sum([stat.passed for stat in stats], start=Decimal("0")) + ), + ) + totals.append(total) - for test_group_name, test_group in test_groups.items(): - tests_in_group = [ - case for case in test_cases if case.name.startswith(f"{test_group_name}_") - ] + return totals - tests_in_group.sort(key=lambda x: x.name) - # Are there any test cases in this group? - if len(tests_in_group) > 0: - summary_html.append(f'") - - for test_case in tests_in_group: - test_case_name = test_case.stem - - summary_html.append(f'') - - for type_checker in TYPE_CHECKERS: - try: - results_file = ( - root_dir - / "results" - / type_checker.name - / f"{test_case_name}.toml" - ) - with open(results_file, "rb") as f: - results = tomli.load(f) - except FileNotFoundError: - results = {} - - raw_notes = results.get("notes", "").strip() - conformance = results.get("conformant", "Unknown") - if conformance == "Unknown": - # Try to look up the automated test results and use - # that if the test passes - automated = results.get("conformance_automated") - if automated == "Pass": - conformance = "Pass" - notes = "".join( - [f"

{note}

" for note in raw_notes.split("\n")] - ) +def _get_versions( + root_dir: Path, + type_checkers: Sequence[TypeChecker], +) -> list[str]: + versions = [] - conformance_class = ( - "conformant" - if conformance == "Pass" - else "partially-conformant" - if conformance == "Partial" - else "not-conformant" - ) + for type_checker in type_checkers: + name = type_checker.name - # Add an asterisk if there are notes to display for a "Pass". - if raw_notes != "" and conformance == "Pass": - conformance = "Pass*" + try: + with root_dir.joinpath("results", name, "version.toml").open("rb") as f: + data = tomllib.load(f) + except (FileNotFoundError, tomllib.TOMLDecodeError): + version = None + else: + version = data.get("version") or None - conformance_cell = f"{conformance}" - if raw_notes != "": - conformance_cell = f'
{conformance_cell}{notes}
' + # If version file cannot be found or has missing/invalid content, fall back to name. + if version is None: + version = f"{type_checker.name} ?.?.?" - summary_html.append(f'') + versions.append(version) - summary_html.append("") + return versions - summary_html.append("
 
{version}
") - summary_html.append("
') - summary_html.append( - f'{test_group.name}' - ) - summary_html.append("
     {test_case_name}{conformance_cell}
\n") - return "\n".join(summary_html) +def _remove_exponent(d: Decimal) -> Decimal: + # See https://docs.python.org/3/library/decimal.html#decimal-faq + return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize() diff --git a/conformance/src/results_template.html b/conformance/src/results_template.html deleted file mode 100644 index 214f778ed..000000000 --- a/conformance/src/results_template.html +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - Type System Test Results - - - - -
-
-

Python Type System Conformance Test Results

-

- While spec conformance is important for the ecosystem, we don't recommend using it - as the primary basis for choosing a type checker. It is not representative - of many of the things users typically care about. -

-
- {{summary}} - -
- - - diff --git a/conformance/src/templates/base.html b/conformance/src/templates/base.html new file mode 100644 index 000000000..d1f5a3f27 --- /dev/null +++ b/conformance/src/templates/base.html @@ -0,0 +1,102 @@ +{%- set columns = versions|length -%} + + + + + + + + Python Type System Conformance Test Results + + + + +
+

Python Type System Conformance Test Results

+

+ While specification conformance is important for the ecosystem, we don't recommend + using it as the primary basis for choosing a type checker. It is not representative + of many of the things users typically care about. +

+
+ + +
+
+
+ + + + + + + + + {%- for version in versions %} + + {%- endfor %} + + + {%- for group in groups %} + + + + + {%- for case in group.cases %} + + + {%- for result in case.results %} + {%- if result.notes %} + + {%- else %} + + {%- endif %} + {%- endfor %} + + {%- endfor %} + + + {%- for stats in group.stats %} + + {%- endfor %} + + + {%- endfor %} + + + + {%- for stats in totals %} + + {%- endfor %} + + +
{{ version }}
+ {{ group.name }} +
{{ case.name }} + {{ result.conformance }} +
    + {%- for note in result.notes %} +
  • {{ note }}
  • + {%- endfor %} +
+
{{ result.conformance }}
{{ stats.passed }} / {{ stats.total }} • {{ stats.percentage }}
{{ stats.passed }} / {{ stats.total }} • {{ stats.percentage }}
+
+ + + diff --git a/conformance/src/templates/style.css b/conformance/src/templates/style.css new file mode 100644 index 000000000..e72684ace --- /dev/null +++ b/conformance/src/templates/style.css @@ -0,0 +1,227 @@ +:root { + --dark-main-bg: #333; + --dark-main-fg: #fff; + --dark-muted-fg: #ddd; + --dark-selection-bg: #ec6e4a; + --dark-shadow: #999; + --light-main-bg: #fff; + --light-main-fg: #000; + --light-muted-fg: #666; + --light-selection-bg: #ec6e4a; + --light-shadow: #ccc; + + --conformant: rgb(203, 255, 203); + --partially-conformant: rgb(251, 244, 166); + --not-conformant: rgb(242, 171, 171); + + color-scheme: light dark; + &:has(#color-scheme option[value="light"]:checked) { + color-scheme: light; + } + &:has(#color-scheme option[value="dark"]:checked) { + color-scheme: dark; + } +} + +* { + box-sizing: border-box; +} + +::selection { + background: light-dark(var(--light-selection-bg), var(--dark-selection-bg)); + color: light-dark(var(--dark-main-fg), var(--light-main-fg)); +} + +html { + background: light-dark(var(--light-main-bg), var(--dark-main-bg)); + color: light-dark(var(--light-main-fg), var(--dark-main-fg)); + font-family: "system-ui", "Segoe UI", Helvetica, Arial, sans-serif; + font-size: 0.85rem; +} + +body { + margin: 0; + padding: 0; +} + +header { + background-color: #2b5b84; + box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.03), inset 0 0 20px rgba(0, 0, 0, 0.03); + color: #fff; + padding: 1em; + text-align: center; +} + +main { + padding: 2em; +} + +a { + text-underline-offset: 2px; +} + +code { + background: light-dark(#eee, #666); + border: 1px solid light-dark(#ddd, #888); + border-radius: 3px; + padding: 0 2px; +} + +table { + border-collapse: collapse; + inline-size: 100%; + margin: 0; + padding: 0; +} + +th, +td { + border-color: transparent; + border-style: solid; + border-width: 0 10px; + margin: 0; + padding: 3px; + position: relative; + text-align: start; + + &:not(:first-child) { + text-align: center; + } +} + +thead { + background: light-dark(var(--light-main-bg), var(--dark-main-bg)); + inset-block-start: 0; + position: sticky; + z-index: 3; + & > tr > th { + padding-block: 1em; + } +} + +tbody > tr > th:not([colspan]) { + font-weight: normal; + padding-inline-start: 2em; +} + +tbody > tr.summary { + color: light-dark(var(--light-muted-fg), var(--dark-muted-fg)); +} + +tfoot td { + font-weight: bold; + padding-block-start: 1em; +} + +.col1 { + inline-size: 30%; +} + +.col2 { + inline-size: calc(70% / {{ columns }}); +} + +.conformant { + background-color: var(--conformant); + color: var(--light-main-fg); +} + +.partially-conformant { + background-color: var(--partially-conformant); + color: var(--light-main-fg); +} + +.not-conformant { + background-color: var(--not-conformant); + color: var(--light-main-fg); +} + +tbody > tr:hover { + th:not([colspan]) { + background-color: light-dark(#eee, #444); + border-color: light-dark(#eee, #444); + } + th:not([colspan]) ~ td { + border-color: light-dark(#eee, #444); + } + .conformant { + background-color: hsl(from var(--conformant) h s calc(l - 5)); + } + .partially-conformant { + background-color: hsl(from var(--partially-conformant) h s calc(l - 5)); + } + .not-conformant { + background-color: hsl(from var(--not-conformant) h s calc(l - 5)); + } +} + +.tooltip { + cursor: help; + + /* Add an asterisk if there are notes to display for a "Pass". */ + &.conformant::after { + content: "*"; + position: absolute; + } + + .notes { + background-color: light-dark(var(--light-main-bg), var(--dark-main-bg)); + border-radius: 5px; + box-shadow: 0 0 3px light-dark(var(--light-shadow), var(--dark-shadow)); + color: light-dark(var(--light-main-fg), var(--dark-main-fg)); + cursor: default; + font-size: .8em; + inset-block-start: calc(50% - 5px); + inset-inline-end: 50%; + line-height: 1.6; + list-style-position: inside; + min-inline-size: 500px; + padding: 10px 15px; + position: absolute; + text-align: start; + visibility: hidden; + z-index: 2; + & > li { + padding: 3px 0; + text-indent: 1.3em hanging; + } + } + + &:hover .notes { + visibility: visible; + } +} + +.disclaimer { + color: var(--dark-muted-fg); + font-size: 0.9rem; + font-weight: normal; + line-height: 1.4; + margin: 1rem auto; + max-inline-size: 720px; +} + +form:has(#color-scheme) { + background: inherit; + inset-block-start: 1rem; + inset-inline-end: 1rem; + position: absolute; +} + +#color-scheme { + appearance: none; + background: inherit; + border-color: var(--dark-muted-fg); + border-radius: 5px; + border-style: solid; + border-width: 1px; + color: inherit; + padding: 0.5rem; + &:focus { + border-color: inherit; + outline: none; + } + &:hover { + border-color: inherit; + } +} diff --git a/conformance/src/test_groups.py b/conformance/src/test_groups.py index b974d4016..ae8ab4bfa 100644 --- a/conformance/src/test_groups.py +++ b/conformance/src/test_groups.py @@ -3,13 +3,13 @@ conformance test suite. """ +import tomllib + from dataclasses import dataclass from itertools import chain from pathlib import Path from typing import Mapping, Sequence -import tomli - @dataclass class TestGroup: @@ -22,7 +22,7 @@ def get_test_groups(root_dir: Path) -> Mapping[str, TestGroup]: # group has a name that associated test cases must start with. test_group_file = root_dir / "src" / "test_groups.toml" with open(test_group_file, "rb") as f: - test_groups = tomli.load(f) + test_groups = tomllib.load(f) return { k: TestGroup(v.get("name", "unknown"), v.get("href", "")) diff --git a/conformance/src/type_checker.py b/conformance/src/type_checker.py index c7f28b5c7..d72ff9dbf 100644 --- a/conformance/src/type_checker.py +++ b/conformance/src/type_checker.py @@ -235,7 +235,7 @@ def run_tests(self, test_files: Sequence[str]) -> dict[str, str]: "--config-file=./ty.toml", ] proc = run(command, stdout=PIPE, text=True, encoding="utf-8") - results_dict = {} + results_dict: dict[str, str] = {} for line in proc.stdout.splitlines(): if not line.strip(): continue @@ -339,7 +339,14 @@ def get_version(self) -> str: def run_tests(self, test_files: Sequence[str]) -> dict[str, str]: proc = run( - ["pyrefly", "check", "--output-format", "min-text", "--summary=none", "--min-severity=warn"], + [ + "pyrefly", + "check", + "--output-format", + "min-text", + "--summary=none", + "--min-severity=warn", + ], stdout=PIPE, text=True, encoding="utf-8", diff --git a/conformance/uv.lock b/conformance/uv.lock index ac029a5b1..2aadb047b 100644 --- a/conformance/uv.lock +++ b/conformance/uv.lock @@ -35,6 +35,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8a/db/55a262f3606bebcae07cc14095338471ad7c0bbcaa37707e6f0ee49725b7/importlib_resources-7.1.0-py3-none-any.whl", hash = "sha256:1bd7b48b4088eddb2cd16382150bb515af0bd2c70128194392725f82ad2c96a1", size = 37232, upload-time = "2026-04-12T16:36:08.219Z" }, ] +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + [[package]] name = "librt" version = "0.11.0" @@ -56,6 +68,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/59/67/a6739ac96e28b7855808bdb0370e250606104a859750d209e5a0716fe7ab/librt-0.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f10cf143e4a9bb0f4f5af568a00df94a2d69ef41c2579584454bb0fe5cc642c", size = 103470, upload-time = "2026-05-10T18:16:10.369Z" }, ] +[[package]] +name = "markdown" +version = "3.10.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2b/f4/69fa6ed85ae003c2378ffa8f6d2e3234662abd02c10d216c0ba96081a238/markdown-3.10.2.tar.gz", hash = "sha256:994d51325d25ad8aa7ce4ebaec003febcce822c3f8c911e3b17c52f7f589f950", size = 368805, upload-time = "2026-02-09T14:57:26.942Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl", hash = "sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36", size = 108180, upload-time = "2026-02-09T14:57:25.787Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, +] + [[package]] name = "mypy" version = "2.1.0" @@ -151,24 +191,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d7/33/288b5868fa00846dacf249633719d747893e54aebd196b9968ac1878a5d3/pyright-1.1.410-py3-none-any.whl", hash = "sha256:5e961bed37cacf96b3f7cd7b1da39b350a9239aa2e69138d0e88f728cfaf296c", size = 6082448, upload-time = "2026-06-01T17:35:46.387Z" }, ] -[[package]] -name = "tomli" -version = "2.4.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/82/30/31573e9457673ab10aa432461bee537ce6cef177667deca369efb79df071/tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c", size = 17477, upload-time = "2026-01-11T11:22:38.165Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/43/7389a1869f2f26dba52404e1ef13b4784b6b37dac93bac53457e3ff24ca3/tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1", size = 154894, upload-time = "2026-01-11T11:21:56.07Z" }, - { url = "https://files.pythonhosted.org/packages/e9/05/2f9bf110b5294132b2edf13fe6ca6ae456204f3d749f623307cbb7a946f2/tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8", size = 149053, upload-time = "2026-01-11T11:21:57.467Z" }, - { url = "https://files.pythonhosted.org/packages/e8/41/1eda3ca1abc6f6154a8db4d714a4d35c4ad90adc0bcf700657291593fbf3/tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a", size = 243481, upload-time = "2026-01-11T11:21:58.661Z" }, - { url = "https://files.pythonhosted.org/packages/d2/6d/02ff5ab6c8868b41e7d4b987ce2b5f6a51d3335a70aa144edd999e055a01/tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1", size = 251720, upload-time = "2026-01-11T11:22:00.178Z" }, - { url = "https://files.pythonhosted.org/packages/7b/57/0405c59a909c45d5b6f146107c6d997825aa87568b042042f7a9c0afed34/tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b", size = 247014, upload-time = "2026-01-11T11:22:01.238Z" }, - { url = "https://files.pythonhosted.org/packages/2c/0e/2e37568edd944b4165735687cbaf2fe3648129e440c26d02223672ee0630/tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51", size = 251820, upload-time = "2026-01-11T11:22:02.727Z" }, - { url = "https://files.pythonhosted.org/packages/5a/1c/ee3b707fdac82aeeb92d1a113f803cf6d0f37bdca0849cb489553e1f417a/tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729", size = 97712, upload-time = "2026-01-11T11:22:03.777Z" }, - { url = "https://files.pythonhosted.org/packages/69/13/c07a9177d0b3bab7913299b9278845fc6eaaca14a02667c6be0b0a2270c8/tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da", size = 108296, upload-time = "2026-01-11T11:22:04.86Z" }, - { url = "https://files.pythonhosted.org/packages/18/27/e267a60bbeeee343bcc279bb9e8fbed0cbe224bc7b2a3dc2975f22809a09/tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3", size = 94553, upload-time = "2026-01-11T11:22:05.854Z" }, - { url = "https://files.pythonhosted.org/packages/23/d1/136eb2cb77520a31e1f64cbae9d33ec6df0d78bdf4160398e86eec8a8754/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a", size = 14477, upload-time = "2026-01-11T11:22:37.446Z" }, -] - [[package]] name = "tomlkit" version = "0.14.0" @@ -203,6 +225,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8c/4c/0c1ca628c5da7840e16801caa0bfeed1241e1113d8a5156a34245d4fa927/ty-0.0.50-py3-none-win_arm64.whl", hash = "sha256:96a84d970b59f2eddb92a4af3ba9906f24bda118cf487d923765ccd4ca24627b", size = 11635811, upload-time = "2026-06-17T21:37:07.191Z" }, ] +[[package]] +name = "types-markdown" +version = "3.10.2.20260508" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/62/4ca11db82799590117d9b6ef8fcd6515039cff80838304face5440f7d95c/types_markdown-3.10.2.20260508.tar.gz", hash = "sha256:64c405a30decd46cf78443bbcde8331f561f83752cc6d962ff3f5ccaabe26a8e", size = 19818, upload-time = "2026-05-08T04:49:45.095Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/9d/eae7125bcf063ff5f79aadad58f3d37675263941f84e025bf53de1735fe1/types_markdown-3.10.2.20260508-py3-none-any.whl", hash = "sha256:2ee5e462c7b821c27c3d8f75f4da873d3e3c87d24d7f2d741f8f4261e4024a99", size = 25811, upload-time = "2026-05-08T04:49:43.962Z" }, +] + [[package]] name = "typeshed-client" version = "2.11.0" @@ -221,25 +252,29 @@ name = "typing-conformance" version = "0.1.0" source = { virtual = "." } dependencies = [ + { name = "jinja2" }, + { name = "markdown" }, { name = "mypy" }, { name = "pycroscope" }, { name = "pyrefly" }, { name = "pyright" }, - { name = "tomli" }, { name = "tomlkit" }, { name = "ty" }, + { name = "types-markdown" }, { name = "zuban" }, ] [package.metadata] requires-dist = [ + { name = "jinja2" }, + { name = "markdown" }, { name = "mypy" }, { name = "pycroscope" }, { name = "pyrefly" }, { name = "pyright" }, - { name = "tomli" }, { name = "tomlkit" }, { name = "ty" }, + { name = "types-markdown" }, { name = "zuban" }, ]