diff --git a/.flake8 b/.flake8 index ff64f42c1..13a85deb9 100644 --- a/.flake8 +++ b/.flake8 @@ -1,6 +1,7 @@ [flake8] max-line-length = 90 +exclude = conformance ignore = # irrelevant plugins B3, diff --git a/conformance/.gitignore b/conformance/.gitignore new file mode 100644 index 000000000..5eae7a458 --- /dev/null +++ b/conformance/.gitignore @@ -0,0 +1,47 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Environments +.env +.venv + +# Tools +.mypy_cache +.pyre_configuration +.pyre +.coverage +htmlcov + +# General +.DS_Store + +# Editor temp files +.*.swp + +# Workspace configurations +.vscode diff --git a/conformance/README.md b/conformance/README.md new file mode 100644 index 000000000..ebc39986c --- /dev/null +++ b/conformance/README.md @@ -0,0 +1,71 @@ +# Type System Conformance + +## Motivation + +[PEP 729](https://peps.python.org/pep-0729/) provides a structured and documented way to specify and evolve the Python type system. In support of this effort, an official [Python typing spec](https://github.com/python/typing/tree/main/docs/spec) has been drafted. This spec consolidates details from various historical typing-related PEPs. The spec will be modified over time to clarify unspecified and under-specified parts of the type system. It will also be extended to cover new features of the type system. + +Accompanying the typing specification is this conformance test suite which validates the behavior of static type checkers against the specification. + +## Structure & Name + +This project contains test cases for behaviors defined in the Python typing spec. Tests are structured and grouped in accordance with the specification's chapter headings. + +* [concepts](https://typing.readthedocs.io/en/latest/spec/concepts.html) +* [annotations](https://typing.readthedocs.io/en/latest/spec/annotations.html) +* [specialtypes](https://typing.readthedocs.io/en/latest/spec/special-types.html) +* [generics](https://typing.readthedocs.io/en/latest/spec/generics.html) +* [qualifiers](https://typing.readthedocs.io/en/latest/spec/qualifiers.html) +* [classes](https://typing.readthedocs.io/en/latest/spec/class-compat.html) +* [aliases](https://typing.readthedocs.io/en/latest/spec/aliases.html) +* [literals](https://typing.readthedocs.io/en/latest/spec/literal.html) +* [protocols](https://typing.readthedocs.io/en/latest/spec/protocol.html) +* [callables](https://typing.readthedocs.io/en/latest/spec/callables.html) +* [overloads](https://typing.readthedocs.io/en/latest/spec/overload.html) +* [dataclasses](https://typing.readthedocs.io/en/latest/spec/dataclasses.html) +* [typeddicts](https://typing.readthedocs.io/en/latest/spec/typeddict.html) +* [narrowing](https://typing.readthedocs.io/en/latest/spec/narrowing.html) +* [directives](https://typing.readthedocs.io/en/latest/spec/directives.html) +* [distribution](https://typing.readthedocs.io/en/latest/spec/distributing.html) +* [historical](https://typing.readthedocs.io/en/latest/spec/historical.html) + +A test file is a ".py" file. The file name should start with one of the above names followed by a description of the test (with words separated by underscores). For example, `generics_paramspec_basic_usage.py` would contain the basic usage tests for `ParamSpec`. Each test file can contain multiple individual unit tests, but these tests should be related to each other. If the number of unit tests in a single test file exceeds ten, it may be desirable to split it into separate test files. This will help maintain a consistent level of granularity across tests. + +## Notes About Tests + +Tests are designed to run on all current and future static type checkers. They must therefore be type-checker agnostic and should not rely on functionality or behaviors that are specific to one type checker or another. + +Test cases are meant to be human readable. They should include comments that help explain their purpose (what is being tested, whether an error should be generated, etc.). They should also contain links to the typing spec, discussions, and issue trackers. + +The test suite focuses on static type checking not general Python semantics. Tests should therefore focus on static analysis behaviors, not runtime behaviors. + +## Running the Conformance Test Tool + +To run the conformance test suite: +* Clone the https://github.com/python/typing repo. +* Create and activate a Python 3.12 virtual environment. +* Switch to the `conformance` subdirectory and install all dependencies (`pip install -r requirements.txt`). +* Switch to the `src` subdirectory and run `python main.py`. + +Note that some type checkers may not run on some platforms. For example, pytype cannot be installed on Windows. If a type checker fails to install, tests will be skipped for that type checker. + +## Reporting Conformance Results + +Different type checkers report errors in different ways (with different wording in error messages and different line numbers or character ranges for errors). This variation makes it difficult to fully automate test validation given that tests will want to check for both false positive and false negative type errors. Some level of manual inspection will therefore be needed to determine whether a type checker is fully conformant with all tests in any given test file. This "scoring" process is required only when the output of a test changes — e.g. when a new version of that type checker is released and the tests are rerun. We assume that the output of a type checker will be the same from one run to the next unless/until a new version is released that fixes or introduces a bug. In this case, the output will need to be manually inspected and the conformance results re-scored for those tests whose output has changed. + +Conformance results are reported and summarized for each supported type checker. Initially, results will be reported for mypy and pyright. It is the goal and desire to add additional type checkers over time. + +## Adding a New Test Case + +To add a new test, create a new ".py" file in the `tests` directory. Its name must begin with one of the above test group names followed by an underscore. Write the contents of the test including a module docstring describing the purpose of the test. Next, run the conformance test tool. This will generate a new `.toml` file in the `results` subdirectory corresponding each type checker. Manually review the output from each type checker and determine whether it conforms to the specification. If so, add `conformant = "Pass"` to the `.toml` file. If it does not fully comply, add `conformant = "Partial"` and a `notes` section detailing where it is not compliant. If the type checker doesn't support the feature in the test add `conformant = "Unsupported"`. Once the conformance status has been updated, rerun the conformance test tool to regenerate the summary report. + +## Updating a Test Case + +If a test is updated (augmented or fixed), the process is similar to when adding a new test. Run the conformance test tool to generate new results and manually examine the output of each supported type checker. Then update the conformance status accordingly. Once the conformance status has been updated, rerun the conformance test tool to regenerate the summary report. + +## Updating a Type Checker + +If a new version of a type checker is released, re-run the test tool with the new version. If the type checker output has changed for any test cases, the tool will supply the old and new outputs. Examine these to determine whether the conformance status has changed. Once the conformance status has been updated, re-run the test tool again to regenerate the summary report. + +## Contributing + +Contributions are welcome! diff --git a/conformance/requirements.txt b/conformance/requirements.txt new file mode 100644 index 000000000..3f3979428 --- /dev/null +++ b/conformance/requirements.txt @@ -0,0 +1,7 @@ +tomli +tomlkit +pyright +mypy +pyre-check +pytype; platform_system != "Windows" + diff --git a/conformance/results/mypy/aliases_explicit.toml b/conformance/results/mypy/aliases_explicit.toml new file mode 100644 index 000000000..fafe98232 --- /dev/null +++ b/conformance/results/mypy/aliases_explicit.toml @@ -0,0 +1,28 @@ +conformant = "Partial" +notes = """ +Does not reject specialization of type alias that has already been implicitly specialized. +""" +output = """ +aliases_explicit.py:67: error: Bad number of arguments for type alias, expected: 0, given: 1 [type-arg] +aliases_explicit.py:68: error: Bad number of arguments for type alias, expected: 0, given: 1 [type-arg] +aliases_explicit.py:69: error: Bad number of arguments for type alias, expected: 1, given: 2 [type-arg] +aliases_explicit.py:70: error: Bad number of arguments for type alias, expected: 1, given: 2 [type-arg] +aliases_explicit.py:71: error: Can only replace ParamSpec with a parameter types list or another ParamSpec, got "int" [misc] +aliases_explicit.py:79: error: Invalid type alias: expression is not a valid type [valid-type] +aliases_explicit.py:80: error: Bracketed expression "[...]" is not valid as a type [valid-type] +aliases_explicit.py:81: error: Invalid type alias: expression is not a valid type [valid-type] +aliases_explicit.py:82: error: Invalid type alias: expression is not a valid type [valid-type] +aliases_explicit.py:83: error: Invalid type alias: expression is not a valid type [valid-type] +aliases_explicit.py:84: error: Invalid type alias: expression is not a valid type [valid-type] +aliases_explicit.py:85: error: Invalid type alias: expression is not a valid type [valid-type] +aliases_explicit.py:86: error: Invalid type alias: expression is not a valid type [valid-type] +aliases_explicit.py:87: error: Variable "aliases_explicit.var1" is not valid as a type [valid-type] +aliases_explicit.py:87: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_explicit.py:88: error: Invalid type: try using Literal[True] instead? [valid-type] +aliases_explicit.py:89: error: Invalid type: try using Literal[1] instead? [valid-type] +aliases_explicit.py:90: error: Invalid type alias: expression is not a valid type [valid-type] +aliases_explicit.py:90: error: Function "list" could always be true in boolean context [truthy-function] +aliases_explicit.py:91: error: Invalid type alias: expression is not a valid type [valid-type] +aliases_explicit.py:101: error: "" not callable [operator] +aliases_explicit.py:102: error: Bad number of arguments for type alias, expected: 0, given: 1 [type-arg] +""" diff --git a/conformance/results/mypy/aliases_implicit.toml b/conformance/results/mypy/aliases_implicit.toml new file mode 100644 index 000000000..732bcdf95 --- /dev/null +++ b/conformance/results/mypy/aliases_implicit.toml @@ -0,0 +1,40 @@ +conformant = "Pass" +output = """ +aliases_implicit.py:76: error: Bad number of arguments for type alias, expected: 0, given: 1 [type-arg] +aliases_implicit.py:77: error: Bad number of arguments for type alias, expected: 0, given: 1 [type-arg] +aliases_implicit.py:78: error: Bad number of arguments for type alias, expected: 1, given: 2 [type-arg] +aliases_implicit.py:79: error: Bad number of arguments for type alias, expected: 1, given: 2 [type-arg] +aliases_implicit.py:80: error: Can only replace ParamSpec with a parameter types list or another ParamSpec, got "int" [misc] +aliases_implicit.py:81: error: Type argument "str" of "GoodTypeAlias12" must be a subtype of "float" [type-var] +aliases_implicit.py:100: error: Function "list" could always be true in boolean context [truthy-function] +aliases_implicit.py:106: error: Variable "aliases_implicit.BadTypeAlias1" is not valid as a type [valid-type] +aliases_implicit.py:106: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_implicit.py:107: error: Variable "aliases_implicit.BadTypeAlias2" is not valid as a type [valid-type] +aliases_implicit.py:107: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_implicit.py:108: error: Variable "aliases_implicit.BadTypeAlias3" is not valid as a type [valid-type] +aliases_implicit.py:108: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_implicit.py:109: error: Variable "aliases_implicit.BadTypeAlias4" is not valid as a type [valid-type] +aliases_implicit.py:109: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_implicit.py:110: error: Variable "aliases_implicit.BadTypeAlias5" is not valid as a type [valid-type] +aliases_implicit.py:110: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_implicit.py:111: error: Variable "aliases_implicit.BadTypeAlias6" is not valid as a type [valid-type] +aliases_implicit.py:111: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_implicit.py:112: error: Variable "aliases_implicit.BadTypeAlias7" is not valid as a type [valid-type] +aliases_implicit.py:112: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_implicit.py:113: error: Variable "aliases_implicit.BadTypeAlias8" is not valid as a type [valid-type] +aliases_implicit.py:113: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_implicit.py:114: error: Variable "aliases_implicit.BadTypeAlias9" is not valid as a type [valid-type] +aliases_implicit.py:114: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_implicit.py:115: error: Variable "aliases_implicit.BadTypeAlias10" is not valid as a type [valid-type] +aliases_implicit.py:115: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_implicit.py:116: error: Variable "aliases_implicit.BadTypeAlias11" is not valid as a type [valid-type] +aliases_implicit.py:116: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_implicit.py:117: error: Variable "aliases_implicit.BadTypeAlias12" is not valid as a type [valid-type] +aliases_implicit.py:117: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_implicit.py:118: error: Variable "aliases_implicit.BadTypeAlias13" is not valid as a type [valid-type] +aliases_implicit.py:118: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_implicit.py:119: error: Variable "aliases_implicit.BadTypeAlias14" is not valid as a type [valid-type] +aliases_implicit.py:119: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_implicit.py:133: error: "" not callable [operator] +aliases_implicit.py:135: error: Bad number of arguments for type alias, expected: 0, given: 1 [type-arg] +""" diff --git a/conformance/results/mypy/aliases_newtype.toml b/conformance/results/mypy/aliases_newtype.toml new file mode 100644 index 000000000..b25a4de40 --- /dev/null +++ b/conformance/results/mypy/aliases_newtype.toml @@ -0,0 +1,18 @@ +conformant = "Pass" +output = """ +aliases_newtype.py:11: error: Argument 1 to "UserId" has incompatible type "str"; expected "int" [arg-type] +aliases_newtype.py:12: error: Incompatible types in assignment (expression has type "int", variable has type "UserId") [assignment] +aliases_newtype.py:20: error: Cannot use isinstance() with NewType type [misc] +aliases_newtype.py:23: error: Cannot subclass "NewType" [misc] +aliases_newtype.py:32: error: String argument 1 "BadName" to NewType(...) does not match variable name "GoodName" [misc] +aliases_newtype.py:36: error: "GoodNewType1" expects no type arguments, but 1 given [type-arg] +aliases_newtype.py:42: error: Argument 2 to NewType(...) must be subclassable (got "int | str") [valid-newtype] +aliases_newtype.py:45: error: Type variable "aliases_newtype.T" is unbound [valid-type] +aliases_newtype.py:45: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) +aliases_newtype.py:45: note: (Hint: Use "T" in function signature to bind "T" inside a function) +aliases_newtype.py:47: error: NewType cannot be used with protocol classes [misc] +aliases_newtype.py:49: error: Argument 2 to NewType(...) must be subclassable (got "Literal[7]") [valid-newtype] +aliases_newtype.py:56: error: Argument 2 to NewType(...) must be subclassable (got "TD1") [valid-newtype] +aliases_newtype.py:60: error: NewType(...) expects exactly two positional arguments [misc] +aliases_newtype.py:62: error: Argument 2 to NewType(...) must be subclassable (got "Any") [valid-newtype] +""" diff --git a/conformance/results/mypy/aliases_recursive.toml b/conformance/results/mypy/aliases_recursive.toml new file mode 100644 index 000000000..6d8137a2c --- /dev/null +++ b/conformance/results/mypy/aliases_recursive.toml @@ -0,0 +1,14 @@ +conformant = "Pass" +output = """ +aliases_recursive.py:19: error: Dict entry 1 has incompatible type "str": "complex"; expected "str": "int | str | float | list[Json] | dict[str, Json] | None" [dict-item] +aliases_recursive.py:20: error: List item 1 has incompatible type "complex"; expected "int | str | float | list[Json] | dict[str, Json] | None" [list-item] +aliases_recursive.py:38: error: Incompatible types in assignment (expression has type "tuple[int, tuple[str, int], tuple[int, tuple[int, list[int]]]]", variable has type "RecursiveTuple") [assignment] +aliases_recursive.py:39: error: Name "t6" already defined on line 38 [no-redef] +aliases_recursive.py:50: error: Dict entry 0 has incompatible type "str": "list[int]"; expected "str": "str | int | Mapping[str, RecursiveMapping]" [dict-item] +aliases_recursive.py:51: error: Dict entry 2 has incompatible type "str": "list[int]"; expected "str": "str | int | Mapping[str, RecursiveMapping]" [dict-item] +aliases_recursive.py:55: error: Dict entry 2 has incompatible type "str": "list[int]"; expected "str": "str | int | Mapping[str, RecursiveMapping]" [dict-item] +aliases_recursive.py:67: error: List item 0 has incompatible type "float"; expected "GenericTypeAlias1[str] | str" [list-item] +aliases_recursive.py:73: error: List item 0 has incompatible type "float"; expected "GenericTypeAlias2[str, int] | str | int" [list-item] +aliases_recursive.py:76: error: Invalid recursive alias: a union item of itself [misc] +aliases_recursive.py:81: error: Invalid recursive alias: a union item of itself [misc] +""" diff --git a/conformance/results/mypy/aliases_type_statement.toml b/conformance/results/mypy/aliases_type_statement.toml new file mode 100644 index 000000000..3774e7bf1 --- /dev/null +++ b/conformance/results/mypy/aliases_type_statement.toml @@ -0,0 +1,76 @@ +conformant = "Unsupported" +notes = """ +Does not support `type` statement. +""" +output = """ +aliases_type_statement.py: error: Cannot assign multiple types to name "BadTypeAlias14" without an explicit "Type[...]" annotation [misc] +aliases_type_statement.py:8: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:9: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:9: error: Name "S3" is not defined [name-defined] +aliases_type_statement.py:9: error: Name "S1" is not defined [name-defined] +aliases_type_statement.py:9: error: Name "S2" is not defined [name-defined] +aliases_type_statement.py:10: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:10: error: Value of type "UnionType" is not indexable [index] +aliases_type_statement.py:14: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:21: error: "type[int]" has no attribute "__value__" [attr-defined] +aliases_type_statement.py:23: error: "type[int]" has no attribute "other_attrib" [attr-defined] +aliases_type_statement.py:37: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:38: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:39: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:40: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:41: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:42: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:43: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:44: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:45: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:46: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:47: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:48: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:48: error: Function "list" could always be true in boolean context [truthy-function] +aliases_type_statement.py:49: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:52: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:54: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:58: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:64: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:64: error: Name "K" is not defined [name-defined] +aliases_type_statement.py:69: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:72: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:72: error: Name "T" is not defined [name-defined] +aliases_type_statement.py:72: error: Variable "aliases_type_statement.RecursiveTypeAlias1" is not valid as a type [valid-type] +aliases_type_statement.py:72: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_type_statement.py:74: error: Variable "aliases_type_statement.RecursiveTypeAlias1" is not valid as a type [valid-type] +aliases_type_statement.py:74: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_type_statement.py:75: error: Variable "aliases_type_statement.RecursiveTypeAlias1" is not valid as a type [valid-type] +aliases_type_statement.py:75: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_type_statement.py:77: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:77: error: Name "P" is not defined [name-defined] +aliases_type_statement.py:77: error: Name "T" is not defined [name-defined] +aliases_type_statement.py:77: error: Name "S" is not defined [name-defined] +aliases_type_statement.py:77: error: Variable "aliases_type_statement.RecursiveTypeAlias2" is not valid as a type [valid-type] +aliases_type_statement.py:77: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_type_statement.py:79: error: Unexpected "..." [misc] +aliases_type_statement.py:79: error: Variable "aliases_type_statement.RecursiveTypeAlias2" is not valid as a type [valid-type] +aliases_type_statement.py:79: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_type_statement.py:80: error: Unexpected "..." [misc] +aliases_type_statement.py:80: error: Variable "aliases_type_statement.RecursiveTypeAlias2" is not valid as a type [valid-type] +aliases_type_statement.py:80: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_type_statement.py:81: error: Unexpected "..." [misc] +aliases_type_statement.py:81: error: Variable "aliases_type_statement.RecursiveTypeAlias2" is not valid as a type [valid-type] +aliases_type_statement.py:81: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_type_statement.py:82: error: Bracketed expression "[...]" is not valid as a type [valid-type] +aliases_type_statement.py:82: error: Variable "aliases_type_statement.RecursiveTypeAlias2" is not valid as a type [valid-type] +aliases_type_statement.py:82: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_type_statement.py:84: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:84: error: Name "RecursiveTypeAlias3" is not defined [name-defined] +aliases_type_statement.py:86: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:86: error: Name "T" is not defined [name-defined] +aliases_type_statement.py:86: error: Cannot determine type of "RecursiveTypeAlias4" [has-type] +aliases_type_statement.py:88: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:88: error: Name "T" is not defined [name-defined] +aliases_type_statement.py:88: error: Variable "aliases_type_statement.RecursiveTypeAlias5" is not valid as a type [valid-type] +aliases_type_statement.py:88: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_type_statement.py:90: error: PEP 695 type aliases are not yet supported [valid-type] +aliases_type_statement.py:90: error: Cannot resolve name "RecursiveTypeAlias7" (possible cyclic definition) [misc] +aliases_type_statement.py:90: error: Name "RecursiveTypeAlias7" is used before definition [used-before-def] +aliases_type_statement.py:91: error: PEP 695 type aliases are not yet supported [valid-type] +""" diff --git a/conformance/results/mypy/aliases_typealiastype.toml b/conformance/results/mypy/aliases_typealiastype.toml new file mode 100644 index 000000000..4ed5f7931 --- /dev/null +++ b/conformance/results/mypy/aliases_typealiastype.toml @@ -0,0 +1,57 @@ +conformant = "Unsupported" +notes = """ +Support for TypeAliasType is not implemented. +""" +output = """ +aliases_typealiastype.py:17: error: Type variable "aliases_typealiastype.T" is unbound [valid-type] +aliases_typealiastype.py:17: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) +aliases_typealiastype.py:17: note: (Hint: Use "T" in function signature to bind "T" inside a function) +aliases_typealiastype.py:17: error: Argument "type_params" to "TypeAliasType" has incompatible type "tuple[object]"; expected "tuple[TypeVar | ParamSpec | TypeVarTuple, ...]" [arg-type] +aliases_typealiastype.py:18: error: Type variable "aliases_typealiastype.T" is unbound [valid-type] +aliases_typealiastype.py:18: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) +aliases_typealiastype.py:18: note: (Hint: Use "T" in function signature to bind "T" inside a function) +aliases_typealiastype.py:18: error: Type variable "aliases_typealiastype.S" is unbound [valid-type] +aliases_typealiastype.py:18: note: (Hint: Use "Generic[S]" or "Protocol[S]" base class to bind "S" inside a class) +aliases_typealiastype.py:18: note: (Hint: Use "S" in function signature to bind "S" inside a function) +aliases_typealiastype.py:18: error: Argument "type_params" to "TypeAliasType" has incompatible type "tuple[object, object]"; expected "tuple[TypeVar | ParamSpec | TypeVarTuple, ...]" [arg-type] +aliases_typealiastype.py:19: error: Cannot resolve name "GoodAlias4" (possible cyclic definition) [misc] +aliases_typealiastype.py:19: error: Argument "type_params" to "TypeAliasType" has incompatible type "tuple[object]"; expected "tuple[TypeVar | ParamSpec | TypeVarTuple, ...]" [arg-type] +aliases_typealiastype.py:22: error: Type variable "aliases_typealiastype.S" is unbound [valid-type] +aliases_typealiastype.py:22: note: (Hint: Use "Generic[S]" or "Protocol[S]" base class to bind "S" inside a class) +aliases_typealiastype.py:22: note: (Hint: Use "S" in function signature to bind "S" inside a function) +aliases_typealiastype.py:22: error: Cannot resolve name "GoodAlias5" (possible cyclic definition) [misc] +aliases_typealiastype.py:22: error: TypeVarTuple "Ts" is unbound [valid-type] +aliases_typealiastype.py:23: error: Argument "type_params" to "TypeAliasType" has incompatible type "tuple[object, object, object, object]"; expected "tuple[TypeVar | ParamSpec | TypeVarTuple, ...]" [arg-type] +aliases_typealiastype.py:32: error: "TypeAliasType" has no attribute "other_attrib" [attr-defined] +aliases_typealiastype.py:35: error: Variable "aliases_typealiastype.GoodAlias4" is not valid as a type [valid-type] +aliases_typealiastype.py:35: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_typealiastype.py:36: error: Variable "aliases_typealiastype.GoodAlias4" is not valid as a type [valid-type] +aliases_typealiastype.py:36: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_typealiastype.py:37: error: Unexpected "..." [misc] +aliases_typealiastype.py:37: error: Variable "aliases_typealiastype.GoodAlias5" is not valid as a type [valid-type] +aliases_typealiastype.py:37: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_typealiastype.py:38: error: Unexpected "..." [misc] +aliases_typealiastype.py:38: error: Variable "aliases_typealiastype.GoodAlias5" is not valid as a type [valid-type] +aliases_typealiastype.py:38: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_typealiastype.py:39: error: Bracketed expression "[...]" is not valid as a type [valid-type] +aliases_typealiastype.py:39: error: Variable "aliases_typealiastype.GoodAlias5" is not valid as a type [valid-type] +aliases_typealiastype.py:39: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_typealiastype.py:39: error: Unpack is only valid in a variadic position [valid-type] +aliases_typealiastype.py:40: error: Unexpected "..." [misc] +aliases_typealiastype.py:40: error: Variable "aliases_typealiastype.GoodAlias5" is not valid as a type [valid-type] +aliases_typealiastype.py:40: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +aliases_typealiastype.py:44: error: Type variable "aliases_typealiastype.S" is unbound [valid-type] +aliases_typealiastype.py:44: note: (Hint: Use "Generic[S]" or "Protocol[S]" base class to bind "S" inside a class) +aliases_typealiastype.py:44: note: (Hint: Use "S" in function signature to bind "S" inside a function) +aliases_typealiastype.py:44: error: Argument "type_params" to "TypeAliasType" has incompatible type "tuple[object]"; expected "tuple[TypeVar | ParamSpec | TypeVarTuple, ...]" [arg-type] +aliases_typealiastype.py:46: error: Type variable "aliases_typealiastype.S" is unbound [valid-type] +aliases_typealiastype.py:46: note: (Hint: Use "Generic[S]" or "Protocol[S]" base class to bind "S" inside a class) +aliases_typealiastype.py:46: note: (Hint: Use "S" in function signature to bind "S" inside a function) +aliases_typealiastype.py:48: error: Argument "type_params" to "TypeAliasType" has incompatible type "tuple[object, object]"; expected "tuple[TypeVar | ParamSpec | TypeVarTuple, ...]" [arg-type] +aliases_typealiastype.py:50: error: Cannot determine type of "BadAlias4" [has-type] +aliases_typealiastype.py:52: error: Cannot determine type of "BadAlias5" [has-type] +aliases_typealiastype.py:52: error: Argument "type_params" to "TypeAliasType" has incompatible type "tuple[object]"; expected "tuple[TypeVar | ParamSpec | TypeVarTuple, ...]" [arg-type] +aliases_typealiastype.py:54: error: Cannot determine type of "BadAlias7" [has-type] +aliases_typealiastype.py:54: error: Name "BadAlias7" is used before definition [used-before-def] +aliases_typealiastype.py:69: error: Function "list" could always be true in boolean context [truthy-function] +""" diff --git a/conformance/results/mypy/aliases_variance.toml b/conformance/results/mypy/aliases_variance.toml new file mode 100644 index 000000000..f20fc53d6 --- /dev/null +++ b/conformance/results/mypy/aliases_variance.toml @@ -0,0 +1,7 @@ +conformant = "Pass" +output = """ +aliases_variance.py:24: error: Variance of TypeVar "T_co" incompatible with variance in parent type [type-var] +aliases_variance.py:28: error: Variance of TypeVar "T_co" incompatible with variance in parent type [type-var] +aliases_variance.py:32: error: Variance of TypeVar "T_co" incompatible with variance in parent type [type-var] +aliases_variance.py:44: error: Variance of TypeVar "T_contra" incompatible with variance in parent type [type-var] +""" diff --git a/conformance/results/mypy/annotations_typeexpr.toml b/conformance/results/mypy/annotations_typeexpr.toml new file mode 100644 index 000000000..b5caec86b --- /dev/null +++ b/conformance/results/mypy/annotations_typeexpr.toml @@ -0,0 +1,20 @@ +conformant = "Pass" +output = """ +annotations_typeexpr.py:77: error: Invalid type comment or annotation [valid-type] +annotations_typeexpr.py:77: note: Suggestion: use eval[...] instead of eval(...) +annotations_typeexpr.py:78: error: Bracketed expression "[...]" is not valid as a type [valid-type] +annotations_typeexpr.py:79: error: Syntax error in type annotation [syntax] +annotations_typeexpr.py:79: note: Suggestion: Use Tuple[T1, ..., Tn] instead of (T1, ..., Tn) +annotations_typeexpr.py:80: error: Invalid type comment or annotation [valid-type] +annotations_typeexpr.py:81: error: Invalid type comment or annotation [valid-type] +annotations_typeexpr.py:82: error: Invalid type comment or annotation [valid-type] +annotations_typeexpr.py:83: error: Invalid type comment or annotation [valid-type] +annotations_typeexpr.py:84: error: Invalid type comment or annotation [valid-type] +annotations_typeexpr.py:85: error: Variable "annotations_typeexpr.var1" is not valid as a type [valid-type] +annotations_typeexpr.py:85: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +annotations_typeexpr.py:86: error: Invalid type: try using Literal[True] instead? [valid-type] +annotations_typeexpr.py:87: error: Invalid type: try using Literal[1] instead? [valid-type] +annotations_typeexpr.py:88: error: Invalid type: try using Literal[-1] instead? [valid-type] +annotations_typeexpr.py:89: error: Invalid type comment or annotation [valid-type] +annotations_typeexpr.py:90: error: Invalid type comment or annotation [valid-type] +""" diff --git a/conformance/results/mypy/callables_annotation.toml b/conformance/results/mypy/callables_annotation.toml new file mode 100644 index 000000000..a333e0fab --- /dev/null +++ b/conformance/results/mypy/callables_annotation.toml @@ -0,0 +1,16 @@ +conformant = "Pass" +output = """ +callables_annotation.py:13: error: Too few arguments [call-arg] +callables_annotation.py:14: error: Argument 2 has incompatible type "int"; expected "str" [arg-type] +callables_annotation.py:15: error: Too many arguments [call-arg] +callables_annotation.py:16: error: Unexpected keyword argument "a" [call-arg] +callables_annotation.py:16: error: Unexpected keyword argument "b" [call-arg] +callables_annotation.py:22: error: Too many arguments [call-arg] +callables_annotation.py:39: error: Please use "Callable[[], ]" or "Callable" [misc] +callables_annotation.py:40: error: The first argument to Callable must be a list of types, parameter specification, or "..." [valid-type] +callables_annotation.py:40: note: See https://mypy.readthedocs.io/en/stable/kinds_of_types.html#callable-types-and-lambdas +callables_annotation.py:41: error: Bracketed expression "[...]" is not valid as a type [valid-type] +callables_annotation.py:41: note: Did you mean "List[...]"? +callables_annotation.py:42: error: Please use "Callable[[], ]" or "Callable" [misc] +callables_annotation.py:43: error: Unexpected "..." [misc] +""" diff --git a/conformance/results/mypy/callables_kwargs.toml b/conformance/results/mypy/callables_kwargs.toml new file mode 100644 index 000000000..2e22ca6fe --- /dev/null +++ b/conformance/results/mypy/callables_kwargs.toml @@ -0,0 +1,23 @@ +conformant = "Pass" +output = """ +callables_kwargs.py:22: note: "func1" defined here +callables_kwargs.py:43: error: Missing named argument "v1" for "func1" [call-arg] +callables_kwargs.py:43: error: Missing named argument "v3" for "func1" [call-arg] +callables_kwargs.py:48: error: Unexpected keyword argument "v4" for "func1" [call-arg] +callables_kwargs.py:49: error: Too many positional arguments for "func1" [misc] +callables_kwargs.py:55: error: Argument 1 to "func1" has incompatible type "**dict[str, str]"; expected "int" [arg-type] +callables_kwargs.py:58: error: Argument 1 to "func1" has incompatible type "**dict[str, object]"; expected "int" [arg-type] +callables_kwargs.py:58: error: Argument 1 to "func1" has incompatible type "**dict[str, object]"; expected "str" [arg-type] +callables_kwargs.py:60: error: "func1" gets multiple values for keyword argument "v1" [misc] +callables_kwargs.py:61: error: "func2" gets multiple values for keyword argument "v3" [misc] +callables_kwargs.py:61: error: Argument 1 to "func2" has incompatible type "int"; expected "str" [arg-type] +callables_kwargs.py:62: error: "func2" gets multiple values for keyword argument "v1" [misc] +callables_kwargs.py:98: error: Incompatible types in assignment (expression has type "Callable[[KwArg(TD2)], None]", variable has type "TDProtocol3") [assignment] +callables_kwargs.py:98: note: "TDProtocol3.__call__" has type "Callable[[NamedArg(int, 'v1'), NamedArg(int, 'v2'), NamedArg(str, 'v3')], None]" +callables_kwargs.py:99: error: Incompatible types in assignment (expression has type "Callable[[KwArg(TD2)], None]", variable has type "TDProtocol4") [assignment] +callables_kwargs.py:99: note: "TDProtocol4.__call__" has type "Callable[[NamedArg(int, 'v1')], None]" +callables_kwargs.py:100: error: Incompatible types in assignment (expression has type "Callable[[KwArg(TD2)], None]", variable has type "TDProtocol5") [assignment] +callables_kwargs.py:100: note: "TDProtocol5.__call__" has type "Callable[[Arg(int, 'v1'), Arg(str, 'v3')], None]" +callables_kwargs.py:109: error: Overlap between argument names and ** TypedDict items: "v1" [misc] +callables_kwargs.py:121: error: Unpack item in ** argument must be a TypedDict [misc] +""" diff --git a/conformance/results/mypy/callables_protocol.toml b/conformance/results/mypy/callables_protocol.toml new file mode 100644 index 000000000..fdffbe3bf --- /dev/null +++ b/conformance/results/mypy/callables_protocol.toml @@ -0,0 +1,34 @@ +conformant = "Pass" +output = """ +callables_protocol.py:35: error: Incompatible types in assignment (expression has type "Callable[[VarArg(bytes), NamedArg(int | None, 'max_items')], list[bytes]]", variable has type "Proto1") [assignment] +callables_protocol.py:35: note: "Proto1.__call__" has type "Callable[[VarArg(bytes), DefaultNamedArg(int | None, 'max_len')], list[bytes]]" +callables_protocol.py:36: error: Incompatible types in assignment (expression has type "Callable[[VarArg(bytes)], list[bytes]]", variable has type "Proto1") [assignment] +callables_protocol.py:36: note: "Proto1.__call__" has type "Callable[[VarArg(bytes), DefaultNamedArg(int | None, 'max_len')], list[bytes]]" +callables_protocol.py:37: error: Incompatible types in assignment (expression has type "Callable[[VarArg(bytes), NamedArg(str | None, 'max_len')], list[bytes]]", variable has type "Proto1") [assignment] +callables_protocol.py:37: note: "Proto1.__call__" has type "Callable[[VarArg(bytes), DefaultNamedArg(int | None, 'max_len')], list[bytes]]" +callables_protocol.py:67: error: Incompatible types in assignment (expression has type "Callable[[VarArg(bytes)], Any]", variable has type "Proto2") [assignment] +callables_protocol.py:67: note: "Proto2.__call__" has type "Callable[[VarArg(bytes), KwArg(str)], None]" +callables_protocol.py:68: error: Incompatible types in assignment (expression has type "Callable[[VarArg(str), KwArg(str)], Any]", variable has type "Proto2") [assignment] +callables_protocol.py:68: note: "Proto2.__call__" has type "Callable[[VarArg(bytes), KwArg(str)], None]" +callables_protocol.py:69: error: Incompatible types in assignment (expression has type "Callable[[VarArg(bytes), KwArg(bytes)], Any]", variable has type "Proto2") [assignment] +callables_protocol.py:69: note: "Proto2.__call__" has type "Callable[[VarArg(bytes), KwArg(str)], None]" +callables_protocol.py:70: error: Incompatible types in assignment (expression has type "Callable[[KwArg(str)], Any]", variable has type "Proto2") [assignment] +callables_protocol.py:70: note: "Proto2.__call__" has type "Callable[[VarArg(bytes), KwArg(str)], None]" +callables_protocol.py:97: error: Incompatible types in assignment (expression has type "Callable[[int], None]", variable has type "Proto4") [assignment] +callables_protocol.py:97: note: "function" is missing following "Proto4" protocol member: +callables_protocol.py:97: note: other_attribute +callables_protocol.py:121: error: Incompatible types in assignment (expression has type "Callable[[VarArg(bytes), DefaultNamedArg(int | None, 'max_len')], list[bytes]]", variable has type "NotProto6") [assignment] +callables_protocol.py:169: error: Incompatible types in assignment (expression has type "Callable[[int], Any]", variable has type "Proto8") [assignment] +callables_protocol.py:169: note: "Proto8.__call__" has type overloaded function +callables_protocol.py:186: error: Incompatible types in assignment (expression has type "str", variable has type "int") [assignment] +callables_protocol.py:187: error: "Proto9[P, R]" has no attribute "xxx" [attr-defined] +callables_protocol.py:197: error: "Proto9[[int], str]" has no attribute "other_attribute2"; maybe "other_attribute"? [attr-defined] +callables_protocol.py:238: error: Incompatible types in assignment (expression has type "Callable[[int, str], Any]", variable has type "Proto11") [assignment] +callables_protocol.py:238: note: "Proto11.__call__" has type "Callable[[int, Arg(str, 'y')], Any]" +callables_protocol.py:260: error: Incompatible types in assignment (expression has type "Callable[[VarArg(Any), NamedArg(Any, 'kwarg0')], None]", variable has type "Proto12") [assignment] +callables_protocol.py:260: note: "Proto12.__call__" has type "Callable[[VarArg(Any), NamedArg(Any, 'kwarg0'), NamedArg(Any, 'kwarg1')], None]" +callables_protocol.py:284: error: Incompatible types in assignment (expression has type "Callable[[str], str]", variable has type "Proto13_Default") [assignment] +callables_protocol.py:284: note: "Proto13_Default.__call__" has type "Callable[[DefaultArg(str, 'path')], str]" +callables_protocol.py:311: error: Incompatible types in assignment (expression has type "Callable[[NamedArg(str, 'path')], str]", variable has type "Proto14_Default") [assignment] +callables_protocol.py:311: note: "Proto14_Default.__call__" has type "Callable[[DefaultNamedArg(str, 'path')], str]" +""" diff --git a/conformance/results/mypy/dataclasses_descriptors.toml b/conformance/results/mypy/dataclasses_descriptors.toml new file mode 100644 index 000000000..b3ba809c1 --- /dev/null +++ b/conformance/results/mypy/dataclasses_descriptors.toml @@ -0,0 +1,8 @@ +conformant = "Partial" +notes = """ +Does not correctly evaluate type of descriptor access. +""" +output = """ +dataclasses_descriptors.py:66: error: Expression is of type "Desc2[int]", not "int" [assert-type] +dataclasses_descriptors.py:67: error: Expression is of type "Desc2[str]", not "str" [assert-type] +""" diff --git a/conformance/results/mypy/dataclasses_frozen.toml b/conformance/results/mypy/dataclasses_frozen.toml new file mode 100644 index 000000000..a4d73884c --- /dev/null +++ b/conformance/results/mypy/dataclasses_frozen.toml @@ -0,0 +1,7 @@ +conformant = "Pass" +output = """ +dataclasses_frozen.py:16: error: Property "a" defined in "DC1" is read-only [misc] +dataclasses_frozen.py:17: error: Property "b" defined in "DC1" is read-only [misc] +dataclasses_frozen.py:23: error: Cannot inherit non-frozen dataclass from a frozen one [misc] +dataclasses_frozen.py:33: error: Cannot inherit frozen dataclass from a non-frozen one [misc] +""" diff --git a/conformance/results/mypy/dataclasses_hash.toml b/conformance/results/mypy/dataclasses_hash.toml new file mode 100644 index 000000000..a71f51ca0 --- /dev/null +++ b/conformance/results/mypy/dataclasses_hash.toml @@ -0,0 +1,6 @@ +conformant = "Partial" +notes = """ +Does not report when dataclass is not compatible with Hashable protocol. +""" +output = """ +""" diff --git a/conformance/results/mypy/dataclasses_inheritance.toml b/conformance/results/mypy/dataclasses_inheritance.toml new file mode 100644 index 000000000..72c6b22f9 --- /dev/null +++ b/conformance/results/mypy/dataclasses_inheritance.toml @@ -0,0 +1,5 @@ +conformant = "Pass" +output = """ +dataclasses_inheritance.py:60: error: Cannot override instance variable (previously declared on base class "DC6") with class variable [misc] +dataclasses_inheritance.py:64: error: Cannot override class variable (previously declared on base class "DC6") with instance variable [misc] +""" diff --git a/conformance/results/mypy/dataclasses_kwonly.toml b/conformance/results/mypy/dataclasses_kwonly.toml new file mode 100644 index 000000000..d693c57fe --- /dev/null +++ b/conformance/results/mypy/dataclasses_kwonly.toml @@ -0,0 +1,18 @@ +conformant = "Partial" +notes = """ +Incorrectly rejects kw_only field with default before positional field. +""" +output = """ +dataclasses_kwonly.py:23: error: Too many positional arguments for "DC1" [misc] +dataclasses_kwonly.py:29: error: Attributes without a default cannot follow attributes with one [misc] +dataclasses_kwonly.py:32: error: Too many positional arguments for "DC2" [misc] +dataclasses_kwonly.py:32: error: Too few arguments for "DC2" [call-arg] +dataclasses_kwonly.py:32: error: Argument 1 to "DC2" has incompatible type "str"; expected "int" [arg-type] +dataclasses_kwonly.py:35: error: "DC2" gets multiple values for keyword argument "b" [misc] +dataclasses_kwonly.py:35: error: Too few arguments for "DC2" [call-arg] +dataclasses_kwonly.py:35: error: Argument 1 to "DC2" has incompatible type "str"; expected "int" [arg-type] +dataclasses_kwonly.py:38: error: Too many positional arguments for "DC2" [misc] +dataclasses_kwonly.py:38: error: Argument 1 to "DC2" has incompatible type "str"; expected "int" [arg-type] +dataclasses_kwonly.py:38: error: Argument 2 to "DC2" has incompatible type "int"; expected "str" [arg-type] +dataclasses_kwonly.py:53: error: Too many positional arguments for "DC3" [misc] +""" diff --git a/conformance/results/mypy/dataclasses_order.toml b/conformance/results/mypy/dataclasses_order.toml new file mode 100644 index 000000000..f42a06aab --- /dev/null +++ b/conformance/results/mypy/dataclasses_order.toml @@ -0,0 +1,4 @@ +conformant = "Pass" +output = """ +dataclasses_order.py:50: error: Unsupported operand types for < ("DC1" and "DC2") [operator] +""" diff --git a/conformance/results/mypy/dataclasses_postinit.toml b/conformance/results/mypy/dataclasses_postinit.toml new file mode 100644 index 000000000..a94485d91 --- /dev/null +++ b/conformance/results/mypy/dataclasses_postinit.toml @@ -0,0 +1,11 @@ +conformant = "Pass" +output = """ +dataclasses_postinit.py:19: error: Argument 3 of "__post_init__" is incompatible with supertype "dataclass"; supertype defines the argument type as "str" [override] +dataclasses_postinit.py:28: error: "DC1" has no attribute "x" [attr-defined] +dataclasses_postinit.py:29: error: "DC1" has no attribute "y" [attr-defined] +dataclasses_postinit.py:36: error: Signature of "__post_init__" incompatible with supertype "dataclass" [override] +dataclasses_postinit.py:36: note: Superclass: +dataclasses_postinit.py:36: note: def __post_init__(self: DC2, x: int, y: str) -> None +dataclasses_postinit.py:36: note: Subclass: +dataclasses_postinit.py:36: note: def __post_init__(self: DC2, x: int) -> None +""" diff --git a/conformance/results/mypy/dataclasses_slots.toml b/conformance/results/mypy/dataclasses_slots.toml new file mode 100644 index 000000000..8c06b49e4 --- /dev/null +++ b/conformance/results/mypy/dataclasses_slots.toml @@ -0,0 +1,9 @@ +conformant = "Partial" +notes = """ +Does not reject write to instance variable that is not defined in __slots__. +""" +output = """ +dataclasses_slots.py:12: error: "DC1" both defines "__slots__" and is used with "slots=True" [misc] +dataclasses_slots.py:67: error: "type[DC6]" has no attribute "__slots__" [attr-defined] +dataclasses_slots.py:70: error: "DC6" has no attribute "__slots__" [attr-defined] +""" diff --git a/conformance/results/mypy/dataclasses_transform_class.toml b/conformance/results/mypy/dataclasses_transform_class.toml new file mode 100644 index 000000000..e3b63d2a1 --- /dev/null +++ b/conformance/results/mypy/dataclasses_transform_class.toml @@ -0,0 +1,9 @@ +conformant = "Pass" +output = """ +dataclasses_transform_class.py:48: error: Cannot inherit non-frozen dataclass from a frozen one [misc] +dataclasses_transform_class.py:60: error: Property "id" defined in "Customer1" is read-only [misc] +dataclasses_transform_class.py:63: error: Too many positional arguments for "Customer1" [misc] +dataclasses_transform_class.py:69: error: Unsupported left operand type for < ("Customer1") [operator] +dataclasses_transform_class.py:79: error: Too many positional arguments for "Customer2" [misc] +dataclasses_transform_class.py:119: error: Property "id" defined in "Customer3" is read-only [misc] +""" diff --git a/conformance/results/mypy/dataclasses_transform_field.toml b/conformance/results/mypy/dataclasses_transform_field.toml new file mode 100644 index 000000000..83d454d45 --- /dev/null +++ b/conformance/results/mypy/dataclasses_transform_field.toml @@ -0,0 +1,10 @@ +conformant = "Partial" +notes = """ +Does not properly handle field constructor that has default value for `kw_only` or `init` parameter. +""" +output = """ +dataclasses_transform_field.py:64: error: Unexpected keyword argument "id" for "CustomerModel1" [call-arg] +dataclasses_transform_field.py:75: error: Too many positional arguments for "CustomerModel2" [misc] +dataclasses_transform_field.py:75: error: Missing named argument "name" for "CustomerModel2" [call-arg] +dataclasses_transform_field.py:77: error: Missing named argument "id" for "CustomerModel2" [call-arg] +""" diff --git a/conformance/results/mypy/dataclasses_transform_func.toml b/conformance/results/mypy/dataclasses_transform_func.toml new file mode 100644 index 000000000..fdba05f46 --- /dev/null +++ b/conformance/results/mypy/dataclasses_transform_func.toml @@ -0,0 +1,13 @@ +conformant = "Partial" +notes = """ +Does not handle `kw_only=False` override when `kw_only_default=True`. +Does not report error when `order=False` and comparison operators are used. +""" +output = """ +dataclasses_transform_func.py:53: error: Too many positional arguments for "Customer1" [misc] +dataclasses_transform_func.py:57: error: Incompatible types in assignment (expression has type "int", variable has type "str") [assignment] +dataclasses_transform_func.py:65: error: Unexpected keyword argument "salary" for "Customer1" [call-arg] +dataclasses_transform_func.py:71: error: Too many positional arguments for "Customer2" [misc] +dataclasses_transform_func.py:90: error: Cannot inherit non-frozen dataclass from a frozen one [misc] +dataclasses_transform_func.py:97: error: Property "id" defined in "Customer3" is read-only [misc] +""" diff --git a/conformance/results/mypy/dataclasses_transform_meta.toml b/conformance/results/mypy/dataclasses_transform_meta.toml new file mode 100644 index 000000000..ca6df8752 --- /dev/null +++ b/conformance/results/mypy/dataclasses_transform_meta.toml @@ -0,0 +1,9 @@ +conformant = "Pass" +output = """ +dataclasses_transform_meta.py:48: error: Cannot inherit non-frozen dataclass from a frozen one [misc] +dataclasses_transform_meta.py:60: error: Property "id" defined in "Customer1" is read-only [misc] +dataclasses_transform_meta.py:63: error: Too many positional arguments for "Customer1" [misc] +dataclasses_transform_meta.py:70: error: Unsupported left operand type for < ("Customer1") [operator] +dataclasses_transform_meta.py:80: error: Too many positional arguments for "Customer2" [misc] +dataclasses_transform_meta.py:100: error: Property "id" defined in "Customer3" is read-only [misc] +""" diff --git a/conformance/results/mypy/dataclasses_usage.toml b/conformance/results/mypy/dataclasses_usage.toml new file mode 100644 index 000000000..7e66442d9 --- /dev/null +++ b/conformance/results/mypy/dataclasses_usage.toml @@ -0,0 +1,16 @@ +conformant = "Pass" +output = """ +dataclasses_usage.py:36: error: Accessing "__init__" on an instance is unsound, since instance.__init__ could be from an incompatible subclass [misc] +dataclasses_usage.py:51: error: Missing positional argument "unit_price" in call to "InventoryItem" [call-arg] +dataclasses_usage.py:52: error: Argument 2 to "InventoryItem" has incompatible type "str"; expected "float" [arg-type] +dataclasses_usage.py:53: error: Too many arguments for "InventoryItem" [call-arg] +dataclasses_usage.py:62: error: Attributes without a default cannot follow attributes with one [misc] +dataclasses_usage.py:68: error: Attributes without a default cannot follow attributes with one [misc] +dataclasses_usage.py:74: error: Attributes without a default cannot follow attributes with one [misc] +dataclasses_usage.py:84: error: Too many arguments for "DC4" [call-arg] +dataclasses_usage.py:89: error: Incompatible types in assignment (expression has type "str", variable has type "int") [assignment] +dataclasses_usage.py:127: error: Too many arguments for "DC7" [call-arg] +dataclasses_usage.py:130: error: Missing positional argument "y" in call to "DC8" [call-arg] +dataclasses_usage.py:179: error: Too many arguments for "DC13" [call-arg] +dataclasses_usage.py:207: error: Name "v1" already defined on line 25 [no-redef] +""" diff --git a/conformance/results/mypy/generics_self_advanced.toml b/conformance/results/mypy/generics_self_advanced.toml new file mode 100644 index 000000000..bfee9ad9e --- /dev/null +++ b/conformance/results/mypy/generics_self_advanced.toml @@ -0,0 +1,15 @@ +conformant = "Partial" +notes = """ +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]`. +""" +output = """ +generics_self_advanced.py:35: error: Expression is of type "ChildB", not "Self" [assert-type] +generics_self_advanced.py:38: error: Expression is of type "ChildB", not "Self" [assert-type] +generics_self_advanced.py:42: error: Expression is of type "type[ChildB]", not "type[Self]" [assert-type] +generics_self_advanced.py:43: error: Expression is of type "list[ChildB]", not "list[Self]" [assert-type] +generics_self_advanced.py:44: error: Expression is of type "ChildB", not "Self" [assert-type] +generics_self_advanced.py:45: error: Expression is of type "ChildB", not "Self" [assert-type] +""" diff --git a/conformance/results/mypy/generics_self_attributes.toml b/conformance/results/mypy/generics_self_attributes.toml new file mode 100644 index 000000000..ccd57fe29 --- /dev/null +++ b/conformance/results/mypy/generics_self_attributes.toml @@ -0,0 +1,5 @@ +conformant = "Pass" +output = """ +generics_self_attributes.py:26: error: Argument "next" to "OrdinalLinkedList" has incompatible type "LinkedList[int]"; expected "OrdinalLinkedList | None" [arg-type] +generics_self_attributes.py:32: error: Incompatible types in assignment (expression has type "LinkedList[int]", variable has type "OrdinalLinkedList | None") [assignment] +""" diff --git a/conformance/results/mypy/generics_self_basic.toml b/conformance/results/mypy/generics_self_basic.toml new file mode 100644 index 000000000..317f9ac13 --- /dev/null +++ b/conformance/results/mypy/generics_self_basic.toml @@ -0,0 +1,10 @@ +conformant = "Partial" +notes = """ +Does not properly handle constructor call through `cls` parameter. +""" +output = """ +generics_self_basic.py:19: error: Incompatible return value type (got "Shape", expected "Self") [return-value] +generics_self_basic.py:27: error: Too many arguments for "Shape" [call-arg] +generics_self_basic.py:32: error: Incompatible return value type (got "Shape", expected "Self") [return-value] +generics_self_basic.py:64: error: Self type cannot have type arguments [misc] +""" diff --git a/conformance/results/mypy/generics_self_protocols.toml b/conformance/results/mypy/generics_self_protocols.toml new file mode 100644 index 000000000..d3ef4c71b --- /dev/null +++ b/conformance/results/mypy/generics_self_protocols.toml @@ -0,0 +1,15 @@ +conformant = "Pass" +output = """ +generics_self_protocols.py:61: error: Argument 1 to "accepts_shape" has incompatible type "BadReturnType"; expected "ShapeProtocol" [arg-type] +generics_self_protocols.py:61: note: Following member(s) of "BadReturnType" have conflicts: +generics_self_protocols.py:61: note: Expected: +generics_self_protocols.py:61: note: def set_scale(self, scale: float) -> BadReturnType +generics_self_protocols.py:61: note: Got: +generics_self_protocols.py:61: note: def set_scale(self, scale: float) -> int +generics_self_protocols.py:64: error: Argument 1 to "accepts_shape" has incompatible type "ReturnDifferentClass"; expected "ShapeProtocol" [arg-type] +generics_self_protocols.py:64: note: Following member(s) of "ReturnDifferentClass" have conflicts: +generics_self_protocols.py:64: note: Expected: +generics_self_protocols.py:64: note: def set_scale(self, scale: float) -> ReturnDifferentClass +generics_self_protocols.py:64: note: Got: +generics_self_protocols.py:64: note: def set_scale(self, scale: float) -> ReturnConcreteShape +""" diff --git a/conformance/results/mypy/generics_self_usage.toml b/conformance/results/mypy/generics_self_usage.toml new file mode 100644 index 000000000..4bff8bf4f --- /dev/null +++ b/conformance/results/mypy/generics_self_usage.toml @@ -0,0 +1,19 @@ +conformant = "Pass" +output = """ +generics_self_usage.py:73: error: Self type is only allowed in annotations within class definition [misc] +generics_self_usage.py:76: error: Self type is only allowed in annotations within class definition [misc] +generics_self_usage.py:82: error: Method cannot have explicit self annotation and Self type [misc] +generics_self_usage.py:82: error: A function returning TypeVar should receive at least one argument containing the same TypeVar [type-var] +generics_self_usage.py:82: note: Consider using the upper bound "Foo2" instead +generics_self_usage.py:86: error: Incompatible return value type (got "Foo3", expected "Self") [return-value] +generics_self_usage.py:101: error: Self type is only allowed in annotations within class definition [misc] +generics_self_usage.py:103: error: Self type is only allowed in annotations within class definition [misc] +generics_self_usage.py:106: error: Self type is only allowed in annotations within class definition [misc] +generics_self_usage.py:106: error: Self type cannot be used in type alias target [misc] +generics_self_usage.py:111: error: Static methods cannot use Self type [misc] +generics_self_usage.py:111: error: A function returning TypeVar should receive at least one argument containing the same TypeVar [type-var] +generics_self_usage.py:111: note: Consider using the upper bound "Base" instead +generics_self_usage.py:116: error: Static methods cannot use Self type [misc] +generics_self_usage.py:121: error: Self type cannot be used in a metaclass [misc] +generics_self_usage.py:125: error: Self type cannot be used in a metaclass [misc] +""" diff --git a/conformance/results/mypy/literals_interactions.toml b/conformance/results/mypy/literals_interactions.toml new file mode 100644 index 000000000..b2b4ddbd0 --- /dev/null +++ b/conformance/results/mypy/literals_interactions.toml @@ -0,0 +1,12 @@ +conformant = "Partial" +notes = """ +Does not narrow type of `x` with `x in Literal` type guard pattern. +""" +output = """ +literals_interactions.py:15: error: Tuple index out of range [misc] +literals_interactions.py:16: error: Tuple index out of range [misc] +literals_interactions.py:17: error: Tuple index out of range [misc] +literals_interactions.py:18: error: Tuple index out of range [misc] +literals_interactions.py:106: error: Argument 1 to "expects_bad_status" has incompatible type "str"; expected "Literal['MALFORMED', 'ABORTED']" [arg-type] +literals_interactions.py:109: error: Argument 1 to "expects_pending_status" has incompatible type "str"; expected "Literal['PENDING']" [arg-type] +""" diff --git a/conformance/results/mypy/literals_literalstring.toml b/conformance/results/mypy/literals_literalstring.toml new file mode 100644 index 000000000..0f3409329 --- /dev/null +++ b/conformance/results/mypy/literals_literalstring.toml @@ -0,0 +1,15 @@ +conformant = "Unsupported" +notes = """ +Support for `LiteralString` is not implemented. +""" +output = """ +literals_literalstring.py:36: error: Parameter 2 of Literal[...] is invalid [valid-type] +literals_literalstring.py:37: error: Parameter 1 of Literal[...] is invalid [valid-type] +literals_literalstring.py:43: error: Incompatible types in assignment (expression has type "Literal['two']", variable has type "Literal['']") [assignment] +literals_literalstring.py:74: error: Incompatible types in assignment (expression has type "int", variable has type "str") [assignment] +literals_literalstring.py:75: error: Incompatible types in assignment (expression has type "bytes", variable has type "str") [assignment] +literals_literalstring.py:142: error: Overloaded function signatures 1 and 2 overlap with incompatible return types [overload-overlap] +literals_literalstring.py:142: error: Overloaded function signatures 1 and 3 overlap with incompatible return types [overload-overlap] +literals_literalstring.py:152: error: Overloaded function signature 3 will never be matched: signature 2's parameter type(s) are the same or broader [misc] +literals_literalstring.py:162: error: Expression is of type "bool", not "str" [assert-type] +""" diff --git a/conformance/results/mypy/literals_parameterizations.toml b/conformance/results/mypy/literals_parameterizations.toml new file mode 100644 index 000000000..2b099f547 --- /dev/null +++ b/conformance/results/mypy/literals_parameterizations.toml @@ -0,0 +1,22 @@ +conformant = "Partial" +notes = """ +Does not reject tuple within Literal. +""" +output = """ +literals_parameterizations.py:40: error: Invalid type: Literal[...] cannot contain arbitrary expressions [valid-type] +literals_parameterizations.py:41: error: Invalid type: Literal[...] cannot contain arbitrary expressions [valid-type] +literals_parameterizations.py:42: error: Invalid type: Literal[...] cannot contain arbitrary expressions [valid-type] +literals_parameterizations.py:43: error: Invalid type: Literal[...] cannot contain arbitrary expressions [valid-type] +literals_parameterizations.py:44: error: Invalid type: Literal[...] cannot contain arbitrary expressions [valid-type] +literals_parameterizations.py:46: error: Invalid type: Literal[...] cannot contain arbitrary expressions [valid-type] +literals_parameterizations.py:47: error: Parameter 1 of Literal[...] is invalid [valid-type] +literals_parameterizations.py:48: error: Parameter 1 of Literal[...] is invalid [valid-type] +literals_parameterizations.py:49: error: Parameter 1 of Literal[...] is invalid [valid-type] +literals_parameterizations.py:50: error: Parameter 1 of Literal[...] cannot be of type "float" [valid-type] +literals_parameterizations.py:51: error: Parameter 1 of Literal[...] cannot be of type "Any" [valid-type] +literals_parameterizations.py:52: error: Parameter 1 of Literal[...] is invalid [valid-type] +literals_parameterizations.py:55: error: Invalid type: Literal[...] cannot contain arbitrary expressions [valid-type] +literals_parameterizations.py:58: error: Literal[...] must have at least one parameter [valid-type] +literals_parameterizations.py:59: error: Parameter 1 of Literal[...] is invalid [valid-type] +literals_parameterizations.py:63: error: Incompatible types in assignment (expression has type "Literal[Color.RED]", variable has type "Literal['Color.RED']") [assignment] +""" diff --git a/conformance/results/mypy/literals_semantics.toml b/conformance/results/mypy/literals_semantics.toml new file mode 100644 index 000000000..589c39314 --- /dev/null +++ b/conformance/results/mypy/literals_semantics.toml @@ -0,0 +1,7 @@ +conformant = "Pass" +output = """ +literals_semantics.py:10: error: Incompatible types in assignment (expression has type "Literal[4]", variable has type "Literal[3]") [assignment] +literals_semantics.py:24: error: Incompatible types in assignment (expression has type "Literal[0]", variable has type "Literal[False]") [assignment] +literals_semantics.py:25: error: Incompatible types in assignment (expression has type "Literal[False]", variable has type "Literal[0]") [assignment] +literals_semantics.py:33: error: Incompatible types in assignment (expression has type "int", variable has type "Literal[3, 4, 5]") [assignment] +""" diff --git a/conformance/results/mypy/narrowing_typeguard.toml b/conformance/results/mypy/narrowing_typeguard.toml new file mode 100644 index 000000000..d8568da2a --- /dev/null +++ b/conformance/results/mypy/narrowing_typeguard.toml @@ -0,0 +1,5 @@ +conformant = "Pass" +output = """ +narrowing_typeguard.py:102: error: TypeGuard functions must have a positional argument [valid-type] +narrowing_typeguard.py:107: error: TypeGuard functions must have a positional argument [valid-type] +""" diff --git a/conformance/results/mypy/typeddicts_alt_syntax.toml b/conformance/results/mypy/typeddicts_alt_syntax.toml new file mode 100644 index 000000000..bb1da440f --- /dev/null +++ b/conformance/results/mypy/typeddicts_alt_syntax.toml @@ -0,0 +1,13 @@ +conformant = "Partial" +notes = """ +Does not support keyword-argument form of alternative syntax (deprecated in 3.11). +""" +output = """ +typeddicts_alt_syntax.py:23: error: TypedDict() expects a dictionary literal as the second argument [misc] +typeddicts_alt_syntax.py:27: error: Invalid TypedDict() field name [misc] +typeddicts_alt_syntax.py:31: error: First argument "WrongName" to TypedDict() does not match variable name "BadTypedDict3" [name-match] +typeddicts_alt_syntax.py:35: error: Too many arguments for TypedDict() [misc] +typeddicts_alt_syntax.py:41: error: Unexpected arguments to TypedDict() [misc] +typeddicts_alt_syntax.py:44: error: Extra keys ("name", "year") for TypedDict "Movie2" [typeddict-unknown-key] +typeddicts_alt_syntax.py:45: error: Extra keys ("name", "year") for TypedDict "Movie2" [typeddict-unknown-key] +""" diff --git a/conformance/results/mypy/typeddicts_class_syntax.toml b/conformance/results/mypy/typeddicts_class_syntax.toml new file mode 100644 index 000000000..3b229c3dd --- /dev/null +++ b/conformance/results/mypy/typeddicts_class_syntax.toml @@ -0,0 +1,8 @@ +conformant = "Pass" +output = """ +typeddicts_class_syntax.py:29: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] +typeddicts_class_syntax.py:33: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] +typeddicts_class_syntax.py:38: error: Invalid statement in TypedDict definition; expected "field_name: field_type" [misc] +typeddicts_class_syntax.py:44: error: Unexpected keyword argument "metaclass" for "__init_subclass__" of "TypedDict" [call-arg] +typeddicts_class_syntax.py:49: error: Unexpected keyword argument "other" for "__init_subclass__" of "TypedDict" [call-arg] +""" diff --git a/conformance/results/mypy/typeddicts_final.toml b/conformance/results/mypy/typeddicts_final.toml new file mode 100644 index 000000000..2146548eb --- /dev/null +++ b/conformance/results/mypy/typeddicts_final.toml @@ -0,0 +1,3 @@ +conformant = "Pass" +output = """ +""" diff --git a/conformance/results/mypy/typeddicts_inheritance.toml b/conformance/results/mypy/typeddicts_inheritance.toml new file mode 100644 index 000000000..231cc311e --- /dev/null +++ b/conformance/results/mypy/typeddicts_inheritance.toml @@ -0,0 +1,6 @@ +conformant = "Pass" +output = """ +typeddicts_inheritance.py:44: error: All bases of a new TypedDict must be TypedDict types [misc] +typeddicts_inheritance.py:55: error: Overwriting TypedDict field "x" while extending [misc] +typeddicts_inheritance.py:65: error: Overwriting TypedDict field "x" while merging [misc] +""" diff --git a/conformance/results/mypy/typeddicts_operations.toml b/conformance/results/mypy/typeddicts_operations.toml new file mode 100644 index 000000000..43718b8f1 --- /dev/null +++ b/conformance/results/mypy/typeddicts_operations.toml @@ -0,0 +1,14 @@ +conformant = "Pass" +output = """ +typeddicts_operations.py:22: error: Value of "name" has incompatible type "int"; expected "str" [typeddict-item] +typeddicts_operations.py:23: error: Value of "year" has incompatible type "str"; expected "int" [typeddict-item] +typeddicts_operations.py:24: error: TypedDict "Movie" has no key "other" [typeddict-unknown-key] +typeddicts_operations.py:26: error: TypedDict "Movie" has no key "other" [typeddict-item] +typeddicts_operations.py:28: error: Missing key "year" for TypedDict "Movie" [typeddict-item] +typeddicts_operations.py:29: error: Incompatible types (expression has type "float", TypedDict item "year" has type "int") [typeddict-item] +typeddicts_operations.py:32: error: Extra key "other" for TypedDict "Movie" [typeddict-unknown-key] +typeddicts_operations.py:37: error: Expected TypedDict key to be string literal [misc] +typeddicts_operations.py:47: error: "Movie" has no attribute "clear" [attr-defined] +typeddicts_operations.py:49: error: Key "name" of TypedDict "Movie" cannot be deleted [misc] +typeddicts_operations.py:62: error: "MovieOptional" has no attribute "clear" [attr-defined] +""" diff --git a/conformance/results/mypy/typeddicts_required.toml b/conformance/results/mypy/typeddicts_required.toml new file mode 100644 index 000000000..4e11a4ad6 --- /dev/null +++ b/conformance/results/mypy/typeddicts_required.toml @@ -0,0 +1,12 @@ +conformant = "Partial" +notes = """ +Does not support nesting of `Annotated` and `Required` or `NotRequired`. +""" +output = """ +typeddicts_required.py:12: error: Required[] can be only used in a TypedDict definition [valid-type] +typeddicts_required.py:16: error: NotRequired[] can be only used in a TypedDict definition [valid-type] +typeddicts_required.py:59: error: Required[] can be only used in a TypedDict definition [valid-type] +typeddicts_required.py:60: error: NotRequired[] can be only used in a TypedDict definition [valid-type] +typeddicts_required.py:65: error: Required[] can be only used in a TypedDict definition [valid-type] +typeddicts_required.py:67: error: Required[] can be only used in a TypedDict definition [valid-type] +""" diff --git a/conformance/results/mypy/typeddicts_type_consistency.toml b/conformance/results/mypy/typeddicts_type_consistency.toml new file mode 100644 index 000000000..a9c45d463 --- /dev/null +++ b/conformance/results/mypy/typeddicts_type_consistency.toml @@ -0,0 +1,14 @@ +conformant = "Pass" +output = """ +typeddicts_type_consistency.py:21: error: Incompatible types in assignment (expression has type "B1", variable has type "A1") [assignment] +typeddicts_type_consistency.py:38: error: Incompatible types in assignment (expression has type "B2", variable has type "A2") [assignment] +typeddicts_type_consistency.py:65: error: Incompatible types in assignment (expression has type "A3", variable has type "B3") [assignment] +typeddicts_type_consistency.py:69: error: Extra key "y" for TypedDict "A3" [typeddict-unknown-key] +typeddicts_type_consistency.py:76: error: Incompatible types in assignment (expression has type "B3", variable has type "dict[str, int]") [assignment] +typeddicts_type_consistency.py:77: error: Incompatible types in assignment (expression has type "B3", variable has type "dict[str, object]") [assignment] +typeddicts_type_consistency.py:78: error: Incompatible types in assignment (expression has type "B3", variable has type "dict[Any, Any]") [assignment] +typeddicts_type_consistency.py:82: error: Incompatible types in assignment (expression has type "B3", variable has type "Mapping[str, int]") [assignment] +typeddicts_type_consistency.py:99: error: Incompatible types in assignment (expression has type "str | None", variable has type "str") [assignment] +typeddicts_type_consistency.py:105: error: Incompatible types in assignment (expression has type "int | str", variable has type "int") [assignment] +typeddicts_type_consistency.py:124: error: Incompatible types (expression has type "int", TypedDict item "inner_key" has type "str") [typeddict-item] +""" diff --git a/conformance/results/mypy/typeddicts_usage.toml b/conformance/results/mypy/typeddicts_usage.toml new file mode 100644 index 000000000..d57132453 --- /dev/null +++ b/conformance/results/mypy/typeddicts_usage.toml @@ -0,0 +1,10 @@ +conformant = "Pass" +output = """ +typeddicts_usage.py:23: error: TypedDict "Movie" has no key "director" [typeddict-unknown-key] +typeddicts_usage.py:24: error: Value of "year" has incompatible type "str"; expected "int" [typeddict-item] +typeddicts_usage.py:28: error: Missing key "name" for TypedDict "Movie" [typeddict-item] +typeddicts_usage.py:28: error: Extra key "title" for TypedDict "Movie" [typeddict-unknown-key] +typeddicts_usage.py:35: error: Cannot use isinstance() with TypedDict type [misc] +typeddicts_usage.py:40: error: Variable "typing.TypedDict" is not valid as a type [valid-type] +typeddicts_usage.py:40: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +""" diff --git a/conformance/results/mypy/version.toml b/conformance/results/mypy/version.toml new file mode 100644 index 000000000..63c2f4d79 --- /dev/null +++ b/conformance/results/mypy/version.toml @@ -0,0 +1,2 @@ +version = "mypy 1.8.0" +test_duration = 0.3814089298248291 diff --git a/conformance/results/pyre/aliases_explicit.toml b/conformance/results/pyre/aliases_explicit.toml new file mode 100644 index 000000000..3137647ea --- /dev/null +++ b/conformance/results/pyre/aliases_explicit.toml @@ -0,0 +1,38 @@ +conformant = "Partial" +notes = """ +Incorrectly reports error for type alias defined with ParamSpec. +Incorrectly rejects some valid type aliases when used in annotations. +Incorrectly evaluates generic type alias with ParamSpec with missing type argument. +Does not report some illegal annotation forms as invalid type aliases. +Does not report invalid specialization of generic type aliases. +Incorrectly rejects import alias of `TypeAlias` when used to define type alias. +Does not report invalid specialization of already-specialized generic type alias. +""" +output = """ +aliases_explicit.py:23:0 Incompatible variable type [9]: GoodTypeAlias9 is declared to have type `TA` but is used as type `Type[typing.Callable[..., Variable[$synthetic_attribute_resolution_variable]]]`. +aliases_explicit.py:23:30 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[object, TypeVar]`. +aliases_explicit.py:26:0 Incompatible variable type [9]: GoodTypeAlias12 is declared to have type `TA` but is used as type `Type[typing.Callable[..., Variable[$synthetic_attribute_resolution_variable]]]`. +aliases_explicit.py:26:31 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[ParamSpec, None]`. +aliases_explicit.py:41:8 Undefined or invalid type [11]: Annotation `GoodTypeAlias9` is not defined as a type. +aliases_explicit.py:44:9 Undefined or invalid type [11]: Annotation `GoodTypeAlias12` is not defined as a type. +aliases_explicit.py:51:25 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `UnionType`. +aliases_explicit.py:53:26 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T_co](covariant)]` but got `Tuple[Type[str], typing.Any]`. +aliases_explicit.py:54:26 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T_co](covariant)]` but got `Tuple[Type[int], Type[int], Type[int], Type[str]]`. +aliases_explicit.py:57:29 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[List[Type[Union[int, str]]], None]`. +aliases_explicit.py:60:30 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[typing.Any, None]`. +aliases_explicit.py:62:26 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `UnionType`. +aliases_explicit.py:80:0 Incompatible variable type [9]: BadTypeAlias2 is declared to have type `TA` but is used as type `List[Type[Union[int, str]]]`. +aliases_explicit.py:81:0 Incompatible variable type [9]: BadTypeAlias3 is declared to have type `TA` but is used as type `Tuple[Tuple[Type[int], Type[str]]]`. +aliases_explicit.py:82:0 Incompatible variable type [9]: BadTypeAlias4 is declared to have type `TA` but is used as type `List[Type[int]]`. +aliases_explicit.py:83:0 Incompatible variable type [9]: BadTypeAlias5 is declared to have type `TA` but is used as type `Dict[str, str]`. +aliases_explicit.py:84:0 Incompatible variable type [9]: BadTypeAlias6 is declared to have type `TA` but is used as type `Type[int]`. +aliases_explicit.py:85:0 Incompatible variable type [9]: BadTypeAlias7 is declared to have type `TA` but is used as type `Type[int]`. +aliases_explicit.py:86:0 Incompatible variable type [9]: BadTypeAlias8 is declared to have type `TA` but is used as type `Type[Union[int, str]]`. +aliases_explicit.py:87:0 Incompatible variable type [9]: BadTypeAlias9 is declared to have type `TA` but is used as type `int`. +aliases_explicit.py:88:0 Incompatible variable type [9]: BadTypeAlias10 is declared to have type `TA` but is used as type `bool`. +aliases_explicit.py:89:0 Incompatible variable type [9]: BadTypeAlias11 is declared to have type `TA` but is used as type `int`. +aliases_explicit.py:90:0 Incompatible variable type [9]: BadTypeAlias12 is declared to have type `TA` but is used as type `Type[Union[list, set]]`. +aliases_explicit.py:91:0 Incompatible variable type [9]: BadTypeAlias13 is declared to have type `TA` but is used as type `str`. +aliases_explicit.py:97:16 Call error [29]: `TA` is not a function. +aliases_explicit.py:101:5 Call error [29]: `TA` is not a function. +""" diff --git a/conformance/results/pyre/aliases_implicit.toml b/conformance/results/pyre/aliases_implicit.toml new file mode 100644 index 000000000..8b34288a5 --- /dev/null +++ b/conformance/results/pyre/aliases_implicit.toml @@ -0,0 +1,34 @@ +conformant = "Partial" +notes = """ +Incorrectly reports error for type alias defined with ParamSpec. +Incorrectly rejects some valid type aliases when used in annotations. +Incorrectly evaluates generic type alias with ParamSpec with missing type argument. +Does not report invalid specialization of generic type aliases. +Does not report error for attempt to instantiate union type alias. +Does not report invalid specialization of already-specialized generic type alias. +""" +output = """ +aliases_implicit.py:38:26 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[object, TypeVar]`. +aliases_implicit.py:42:27 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[ParamSpec, None]`. +aliases_implicit.py:54:8 Undefined or invalid type [11]: Annotation `GoodTypeAlias9` is not defined as a type. +aliases_implicit.py:58:9 Undefined or invalid type [11]: Annotation `GoodTypeAlias13` is not defined as a type. +aliases_implicit.py:62:25 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `UnionType`. +aliases_implicit.py:64:26 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T_co](covariant)]` but got `Tuple[Type[str], typing.Any]`. +aliases_implicit.py:65:26 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T_co](covariant)]` but got `Tuple[Type[int], Type[int], Type[int], Type[str]]`. +aliases_implicit.py:68:29 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[List[Type[Union[int, str]]], None]`. +aliases_implicit.py:72:30 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[typing.Any, None]`. +aliases_implicit.py:106:8 Undefined or invalid type [11]: Annotation `BadTypeAlias1` is not defined as a type. +aliases_implicit.py:107:8 Undefined or invalid type [11]: Annotation `BadTypeAlias2` is not defined as a type. +aliases_implicit.py:108:8 Undefined or invalid type [11]: Annotation `BadTypeAlias3` is not defined as a type. +aliases_implicit.py:109:8 Undefined or invalid type [11]: Annotation `BadTypeAlias4` is not defined as a type. +aliases_implicit.py:110:8 Undefined or invalid type [11]: Annotation `BadTypeAlias5` is not defined as a type. +aliases_implicit.py:111:8 Undefined or invalid type [11]: Annotation `BadTypeAlias6` is not defined as a type. +aliases_implicit.py:112:8 Undefined or invalid type [11]: Annotation `BadTypeAlias7` is not defined as a type. +aliases_implicit.py:113:8 Undefined or invalid type [11]: Annotation `BadTypeAlias8` is not defined as a type. +aliases_implicit.py:114:8 Undefined or invalid type [11]: Annotation `BadTypeAlias9` is not defined as a type. +aliases_implicit.py:115:9 Undefined or invalid type [11]: Annotation `BadTypeAlias10` is not defined as a type. +aliases_implicit.py:116:9 Undefined or invalid type [11]: Annotation `BadTypeAlias11` is not defined as a type. +aliases_implicit.py:117:9 Undefined or invalid type [11]: Annotation `BadTypeAlias12` is not defined as a type. +aliases_implicit.py:118:9 Undefined or invalid type [11]: Annotation `BadTypeAlias13` is not defined as a type. +aliases_implicit.py:119:9 Undefined or invalid type [11]: Annotation `BadTypeAlias14` is not defined as a type. +""" diff --git a/conformance/results/pyre/aliases_newtype.toml b/conformance/results/pyre/aliases_newtype.toml new file mode 100644 index 000000000..c7094e2e6 --- /dev/null +++ b/conformance/results/pyre/aliases_newtype.toml @@ -0,0 +1,20 @@ +conformant = "Partial" +notes = """ +Does not reject use of NewType in `isinstance` call. +Does not reject use of NewType in class definition statement. +Does not report inconsistency between name of NewType and assigned identifier name. +Does not reject use of NewType with generic class with TypeVar. +Does not reject use of NewType with protocol class. +Does not reject use of NewType with TypedDict class. +Does not reject use of NewType with another NewType. +Does not reject use of NewType with Any. +""" +output = """ +aliases_newtype.py:11:7 Incompatible parameter type [6]: In call `UserId.__init__`, for 1st positional argument, expected `int` but got `str`. +aliases_newtype.py:12:0 Incompatible variable type [9]: u1 is declared to have type `UserId` but is used as type `int`. +aliases_newtype.py:36:5 Invalid type parameters [24]: Non-generic type `GoodNewType1` cannot take parameters. +aliases_newtype.py:42:37 Invalid inheritance [39]: `typing.Union[int, str]` is not a valid parent class. +aliases_newtype.py:49:37 Invalid inheritance [39]: `typing_extensions.Literal[7]` is not a valid parent class. +aliases_newtype.py:60:14 Too many arguments [19]: Call `NewType.__init__` expects 2 positional arguments, 3 were provided. +aliases_newtype.py:62:37 Invalid inheritance [39]: `typing.Any` is not a valid parent class. +""" diff --git a/conformance/results/pyre/aliases_recursive.toml b/conformance/results/pyre/aliases_recursive.toml new file mode 100644 index 000000000..b57ee1075 --- /dev/null +++ b/conformance/results/pyre/aliases_recursive.toml @@ -0,0 +1,21 @@ +conformant = "Partial" +notes = """ +Does not properly handle some recursive type aliases. +Does not properly handle specialization of generic recursive type aliases. +""" +output = """ +aliases_recursive.py:19:0 Incompatible variable type [9]: j4 is declared to have type `aliases_recursive.Json (resolves to Union[None, Dict[str, Json], List[Json], float, int, str])` but is used as type `Dict[str, complex]`. +aliases_recursive.py:20:0 Incompatible variable type [9]: j5 is declared to have type `aliases_recursive.Json (resolves to Union[None, Dict[str, Json], List[Json], float, int, str])` but is used as type `List[complex]`. +aliases_recursive.py:30:35 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T_co](covariant)]` but got `Tuple[str, typing.Any]`. +aliases_recursive.py:33:4 Undefined or invalid type [11]: Annotation `RecursiveTuple` is not defined as a type. +aliases_recursive.py:42:39 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[Type[Variable[_KT]], Type[Variable[_VT_co](covariant)]]` but got `Tuple[Type[str], str]`. +aliases_recursive.py:44:4 Undefined or invalid type [11]: Annotation `RecursiveMapping` is not defined as a type. +aliases_recursive.py:62:25 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `_SpecialForm`. +aliases_recursive.py:65:4 Undefined or invalid type [11]: Annotation `SpecializedTypeAlias1` is not defined as a type. +aliases_recursive.py:66:4 Undefined or invalid type [11]: Annotation `GenericTypeAlias1` is not defined as a type. +aliases_recursive.py:69:25 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `_SpecialForm`. +aliases_recursive.py:71:4 Undefined or invalid type [11]: Annotation `GenericTypeAlias2` is not defined as a type. +aliases_recursive.py:76:0 Incompatible variable type [9]: RecursiveUnion is declared to have type `TypeAlias` but is used as type `Type[typing.Any]`. +aliases_recursive.py:78:0 Incompatible variable type [9]: MutualReference1 is declared to have type `TypeAlias` but is used as type `Type[typing.Any]`. +aliases_recursive.py:81:0 Incompatible variable type [9]: MutualReference2 is declared to have type `TypeAlias` but is used as type `Type[typing.Any]`. +""" diff --git a/conformance/results/pyre/aliases_type_statement.toml b/conformance/results/pyre/aliases_type_statement.toml new file mode 100644 index 000000000..7b33dcff1 --- /dev/null +++ b/conformance/results/pyre/aliases_type_statement.toml @@ -0,0 +1,7 @@ +conformant = "Unsupported" +notes = """ +Does not support `type` statement. +""" +output = """ +aliases_type_statement.py:8:6 Parsing failure [404]: invalid syntax +""" diff --git a/conformance/results/pyre/aliases_typealiastype.toml b/conformance/results/pyre/aliases_typealiastype.toml new file mode 100644 index 000000000..25117d5d8 --- /dev/null +++ b/conformance/results/pyre/aliases_typealiastype.toml @@ -0,0 +1,45 @@ +conformant = "Unsupported" +notes = """ +Support for TypeAliasType is not implemented. +""" +output = """ +aliases_typealiastype.py:5:0 Undefined import [21]: Could not find a name `TypeAliasType` defined in module `typing`. +aliases_typealiastype.py:16:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:17:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:17:46 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `TypeVar`. +aliases_typealiastype.py:18:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:18:46 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `TypeVar`. +aliases_typealiastype.py:18:56 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `TypeVar`. +aliases_typealiastype.py:19:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:20:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:22:13 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Tuple[typing.Any, Type[Variable[$synthetic_attribute_resolution_variable]]]` but got `Tuple[ParamSpec, TypeVar]`. +aliases_typealiastype.py:22:29 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `TypeVar`. +aliases_typealiastype.py:22:71 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T_co](covariant)]` but got `typing.Tuple[typing.Any, ...]`. +aliases_typealiastype.py:27:17 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:27:50 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `TypeVar`. +aliases_typealiastype.py:35:4 Undefined or invalid type [11]: Annotation `GoodAlias4` is not defined as a type. +aliases_typealiastype.py:37:4 Undefined or invalid type [11]: Annotation `GoodAlias5` is not defined as a type. +aliases_typealiastype.py:39:4 Invalid type [31]: Expression `$local_aliases_typealiastype$GoodAlias5[(int, str, [int, str], *tuple[(int, str, int)])]` is not a valid type. +aliases_typealiastype.py:43:12 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:44:22 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `TypeVar`. +aliases_typealiastype.py:46:12 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:46:44 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `TypeVar`. +aliases_typealiastype.py:47:12 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:50:12 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:51:12 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:54:12 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:55:12 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:58:12 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:59:12 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:60:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:61:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:62:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:63:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:64:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:65:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:66:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:67:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:68:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:69:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +aliases_typealiastype.py:70:13 Undefined attribute [16]: Module `typing` has no attribute `TypeAliasType`. +""" diff --git a/conformance/results/pyre/aliases_variance.toml b/conformance/results/pyre/aliases_variance.toml new file mode 100644 index 000000000..029de6d60 --- /dev/null +++ b/conformance/results/pyre/aliases_variance.toml @@ -0,0 +1,7 @@ +conformant = "Pass" +output = """ +aliases_variance.py:24:0 Invalid type variance [46]: The type variable `Variable[T_co](covariant)` is incompatible with parent class type variable `Variable[T]` because subclasses cannot use more permissive type variables than their superclasses. +aliases_variance.py:28:0 Invalid type variance [46]: The type variable `Variable[T_co](covariant)` is incompatible with parent class type variable `Variable[T]` because subclasses cannot use more permissive type variables than their superclasses. +aliases_variance.py:32:0 Invalid type variance [46]: The type variable `Variable[T_co](covariant)` is incompatible with parent class type variable `Variable[T]` because subclasses cannot use more permissive type variables than their superclasses. +aliases_variance.py:44:0 Invalid type variance [46]: The type variable `Variable[T_contra](contravariant)` is incompatible with parent class type variable `Variable[T]` because subclasses cannot use more permissive type variables than their superclasses. +""" diff --git a/conformance/results/pyre/annotations_typeexpr.toml b/conformance/results/pyre/annotations_typeexpr.toml new file mode 100644 index 000000000..86bc19108 --- /dev/null +++ b/conformance/results/pyre/annotations_typeexpr.toml @@ -0,0 +1,19 @@ +conformant = "Pass" +output = """ +annotations_typeexpr.py:65:26 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T]]` but got `object`. +annotations_typeexpr.py:67:27 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T_co](covariant)]` but got `Tuple[object, typing.Any]`. +annotations_typeexpr.py:77:8 Invalid type [31]: Expression `eval("".join(map(chr, [105, 110, 116])))` is not a valid type. +annotations_typeexpr.py:78:8 Invalid type [31]: Expression `[int, str]` is not a valid type. +annotations_typeexpr.py:79:8 Invalid type [31]: Expression `(int, str)` is not a valid type. +annotations_typeexpr.py:80:8 Invalid type [31]: Expression `comprehension(int for generators(generator($target$i in range(1) if )))` is not a valid type. +annotations_typeexpr.py:81:8 Invalid type [31]: Expression `{ }` is not a valid type. +annotations_typeexpr.py:82:8 Invalid type [31]: Expression `lambda () (int)()` is not a valid type. +annotations_typeexpr.py:83:8 Invalid type [31]: Expression `[int][0]` is not a valid type. +annotations_typeexpr.py:84:8 Invalid type [31]: Expression `int if 1 < 3 else str` is not a valid type. +annotations_typeexpr.py:85:8 Undefined or invalid type [11]: Annotation `var1` is not defined as a type. +annotations_typeexpr.py:86:9 Invalid type [31]: Expression `True` is not a valid type. +annotations_typeexpr.py:87:9 Invalid type [31]: Expression `1` is not a valid type. +annotations_typeexpr.py:88:9 Invalid type [31]: Expression `-1` is not a valid type. +annotations_typeexpr.py:89:9 Invalid type [31]: Expression `int or str` is not a valid type. +annotations_typeexpr.py:90:9 Invalid type [31]: Expression `"int"` is not a valid type. +""" diff --git a/conformance/results/pyre/callables_annotation.toml b/conformance/results/pyre/callables_annotation.toml new file mode 100644 index 000000000..b7967a987 --- /dev/null +++ b/conformance/results/pyre/callables_annotation.toml @@ -0,0 +1,17 @@ +conformant = "Partial" +notes = """ +Does not evaluate correct type for `*args: int` parameter. +Does not reject illegal form `Callable[[...], int]`. +""" +output = """ +callables_annotation.py:13:4 Missing argument [20]: PositionalOnly call expects argument in position 1. +callables_annotation.py:14:10 Incompatible parameter type [6]: In anonymous call, for 2nd positional argument, expected `str` but got `int`. +callables_annotation.py:15:4 Too many arguments [19]: PositionalOnly call expects 2 positional arguments, 3 were provided. +callables_annotation.py:16:4 Unexpected keyword [28]: Unexpected keyword argument `a` to anonymous call. +callables_annotation.py:22:4 Too many arguments [19]: PositionalOnly call expects 0 positional arguments, 1 was provided. +callables_annotation.py:35:28 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T_co](covariant)]` but got `Tuple[Type[int], typing.Any]`. +callables_annotation.py:39:4 Invalid type [31]: Expression `typing.Callable[int]` is not a valid type. +callables_annotation.py:40:4 Invalid type [31]: Expression `typing.Callable[(int, int)]` is not a valid type. +callables_annotation.py:41:4 Invalid type [31]: Expression `typing.Callable[([], [int])]` is not a valid type. +callables_annotation.py:42:4 Invalid type [31]: Expression `typing.Callable[(int, int, int)]` is not a valid type. +""" diff --git a/conformance/results/pyre/callables_kwargs.toml b/conformance/results/pyre/callables_kwargs.toml new file mode 100644 index 000000000..013f9786a --- /dev/null +++ b/conformance/results/pyre/callables_kwargs.toml @@ -0,0 +1,12 @@ +conformant = "Unsupported" +notes = """ +Does not understand Unpack in the context of **kwargs annotation. +""" +output = """ +callables_kwargs.py:22:20 Undefined or invalid type [11]: Annotation `Unpack` is not defined as a type. +callables_kwargs.py:49:4 Too many arguments [19]: Call `func1` expects 1 positional argument, 4 were provided. +callables_kwargs.py:59:12 Incompatible parameter type [6]: In call `func2`, for 1st positional argument, expected `str` but got `object`. +callables_kwargs.py:61:10 Incompatible parameter type [6]: In call `func2`, for 1st positional argument, expected `str` but got `int`. +callables_kwargs.py:62:18 Incompatible parameter type [6]: In call `func2`, for 2nd positional argument, expected `str` but got `object`. +callables_kwargs.py:121:20 Invalid type variable [34]: The type variable `Variable[T (bound to callables_kwargs.TD2)]` isn't present in the function's parameters. +""" diff --git a/conformance/results/pyre/callables_protocol.toml b/conformance/results/pyre/callables_protocol.toml new file mode 100644 index 000000000..e48969c9b --- /dev/null +++ b/conformance/results/pyre/callables_protocol.toml @@ -0,0 +1,26 @@ +conformant = "Partial" +notes = """ +Does not correctly handle callback protocol that declares attributes in all functions. +Does not report type incompatibility for callback protocol with positional-only parameters. +Incorrectly reports type compatibility error with callback that has *args and **kwargs. +Does not report type incompatibility for callback missing a default argument for positional parameter. +Does not report type incompatibility for callback missing a default argument for keyword parameter. +""" +output = """ +callables_protocol.py:35:0 Incompatible variable type [9]: cb1 is declared to have type `Proto1` but is used as type `typing.Callable(cb1_bad1)[[Variable(bytes), KeywordOnly(max_items, Optional[int])], List[bytes]]`. +callables_protocol.py:36:0 Incompatible variable type [9]: cb1 is declared to have type `Proto1` but is used as type `typing.Callable(cb1_bad2)[[Variable(bytes)], List[bytes]]`. +callables_protocol.py:37:0 Incompatible variable type [9]: cb1 is declared to have type `Proto1` but is used as type `typing.Callable(cb1_bad3)[[Variable(bytes), KeywordOnly(max_len, Optional[str])], List[bytes]]`. +callables_protocol.py:67:0 Incompatible variable type [9]: cb2 is declared to have type `Proto2` but is used as type `typing.Callable(cb2_bad1)[[Variable(bytes)], typing.Any]`. +callables_protocol.py:68:0 Incompatible variable type [9]: cb2 is declared to have type `Proto2` but is used as type `typing.Callable(cb2_bad2)[[Variable(str), Keywords(str)], typing.Any]`. +callables_protocol.py:69:0 Incompatible variable type [9]: cb2 is declared to have type `Proto2` but is used as type `typing.Callable(cb2_bad3)[[Variable(bytes), Keywords(bytes)], typing.Any]`. +callables_protocol.py:70:0 Incompatible variable type [9]: cb2 is declared to have type `Proto2` but is used as type `typing.Callable(cb2_bad4)[[Keywords(str)], typing.Any]`. +callables_protocol.py:97:0 Incompatible variable type [9]: var4 is declared to have type `Proto4` but is used as type `typing.Callable(cb4_bad1)[[Named(x, int)], None]`. +callables_protocol.py:121:0 Incompatible variable type [9]: cb6 is declared to have type `NotProto6` but is used as type `typing.Callable(cb6_bad1)[[Variable(bytes), KeywordOnly(max_len, Optional[int], default)], List[bytes]]`. +callables_protocol.py:169:0 Incompatible variable type [9]: cb8 is declared to have type `Proto8` but is used as type `typing.Callable(cb8_bad1)[[Named(x, int)], typing.Any]`. +callables_protocol.py:186:4 Incompatible attribute type [8]: Attribute `other_attribute` declared in class `Proto9` has type `int` but is used as type `str`. +callables_protocol.py:187:4 Undefined attribute [16]: `Proto9` has no attribute `xxx`. +callables_protocol.py:197:6 Undefined attribute [16]: `Proto9` has no attribute `other_attribute2`. +callables_protocol.py:216:0 Incompatible variable type [9]: cb10 is declared to have type `Proto10` but is used as type `typing.Callable(cb10_good)[[], None]`. +callables_protocol.py:259:0 Incompatible variable type [9]: cb12 is declared to have type `Proto12` but is used as type `typing.Callable(cb12_good2)[[Variable(typing.Any), Keywords(typing.Any)], None]`. +callables_protocol.py:260:0 Incompatible variable type [9]: cb12 is declared to have type `Proto12` but is used as type `typing.Callable(cb12_bad1)[[Variable(typing.Any), KeywordOnly(kwarg0, typing.Any)], None]`. +""" diff --git a/conformance/results/pyre/dataclasses_descriptors.toml b/conformance/results/pyre/dataclasses_descriptors.toml new file mode 100644 index 000000000..1d031cd07 --- /dev/null +++ b/conformance/results/pyre/dataclasses_descriptors.toml @@ -0,0 +1,7 @@ +conformant = "Partial" +notes = """ +Incorrectly generates error when calling constructor of dataclass with descriptor. +""" +output = """ +dataclasses_descriptors.py:35:10 Incompatible parameter type [6]: In call `DC1.__init__`, for 1st positional argument, expected `Desc1` but got `int`. +""" diff --git a/conformance/results/pyre/dataclasses_frozen.toml b/conformance/results/pyre/dataclasses_frozen.toml new file mode 100644 index 000000000..152ccfc50 --- /dev/null +++ b/conformance/results/pyre/dataclasses_frozen.toml @@ -0,0 +1,9 @@ +conformant = "Partial" +notes = """ +Does not reject frozen dataclass inherited from non-frozen dataclass. +Does not reject non-frozen dataclass inherited from frozen dataclass. +""" +output = """ +dataclasses_frozen.py:16:0 Invalid assignment [41]: Cannot reassign final attribute `dc1.a`. +dataclasses_frozen.py:17:0 Invalid assignment [41]: Cannot reassign final attribute `dc1.b`. +""" diff --git a/conformance/results/pyre/dataclasses_hash.toml b/conformance/results/pyre/dataclasses_hash.toml new file mode 100644 index 000000000..a71f51ca0 --- /dev/null +++ b/conformance/results/pyre/dataclasses_hash.toml @@ -0,0 +1,6 @@ +conformant = "Partial" +notes = """ +Does not report when dataclass is not compatible with Hashable protocol. +""" +output = """ +""" diff --git a/conformance/results/pyre/dataclasses_inheritance.toml b/conformance/results/pyre/dataclasses_inheritance.toml new file mode 100644 index 000000000..5000e40e5 --- /dev/null +++ b/conformance/results/pyre/dataclasses_inheritance.toml @@ -0,0 +1,7 @@ +conformant = "Partial" +notes = """ +Does not reject ClassVar that is overridden by instance variable. +Does not reject instance variable that is overridden by ClassVar. +""" +output = """ +""" diff --git a/conformance/results/pyre/dataclasses_kwonly.toml b/conformance/results/pyre/dataclasses_kwonly.toml new file mode 100644 index 000000000..2ed61b5ae --- /dev/null +++ b/conformance/results/pyre/dataclasses_kwonly.toml @@ -0,0 +1,6 @@ +conformant = "Pass" +output = """ +dataclasses_kwonly.py:23:0 Too many arguments [19]: Call `DC1.__init__` expects 1 positional argument, 2 were provided. +dataclasses_kwonly.py:38:0 Too many arguments [19]: Call `DC2.__init__` expects 1 positional argument, 2 were provided. +dataclasses_kwonly.py:53:0 Too many arguments [19]: Call `DC3.__init__` expects 1 positional argument, 2 were provided. +""" diff --git a/conformance/results/pyre/dataclasses_order.toml b/conformance/results/pyre/dataclasses_order.toml new file mode 100644 index 000000000..4f4d92b02 --- /dev/null +++ b/conformance/results/pyre/dataclasses_order.toml @@ -0,0 +1,6 @@ +conformant = "Partial" +notes = """ +Does not report type incompatibility with comparison operator. +""" +output = """ +""" diff --git a/conformance/results/pyre/dataclasses_postinit.toml b/conformance/results/pyre/dataclasses_postinit.toml new file mode 100644 index 000000000..dd01d5656 --- /dev/null +++ b/conformance/results/pyre/dataclasses_postinit.toml @@ -0,0 +1,8 @@ +conformant = "Unsupported" +notes = """ +Does not perform validation of `__post_init__` method. +Does not reject access of `InitVar` from object. +""" +output = """ +dataclasses_postinit.py:54:4 Inconsistent override [14]: `dataclasses_postinit.DC4.__post_init__` overrides method defined in `DC3` inconsistently. Could not find parameter `_age` in overridden signature. +""" diff --git a/conformance/results/pyre/dataclasses_slots.toml b/conformance/results/pyre/dataclasses_slots.toml new file mode 100644 index 000000000..f23f3133f --- /dev/null +++ b/conformance/results/pyre/dataclasses_slots.toml @@ -0,0 +1,9 @@ +conformant = "Partial" +notes = """ +Does not report error when `slots=True` is used with `__slots__` definition. +Does not reject write to instance variable that is not defined in __slots__. +Does not reject access to `__slots__` from dataclass instance when `slots=False`. +""" +output = """ +dataclasses_slots.py:67:0 Undefined attribute [16]: `DC6` has no attribute `__slots__`. +""" diff --git a/conformance/results/pyre/dataclasses_transform_class.toml b/conformance/results/pyre/dataclasses_transform_class.toml new file mode 100644 index 000000000..1ce4be7d7 --- /dev/null +++ b/conformance/results/pyre/dataclasses_transform_class.toml @@ -0,0 +1,22 @@ +conformant = "Unsupported" +notes = """ +Does not understand @dataclass_transform. +""" +output = """ +dataclasses_transform_class.py:27:0 Uninitialized attribute [13]: Attribute `not_a_field` is declared in class `ModelBase` to have type `str` but is never initialized. +dataclasses_transform_class.py:52:0 Uninitialized attribute [13]: Attribute `id` is declared in class `Customer2` to have type `int` but is never initialized. +dataclasses_transform_class.py:57:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +dataclasses_transform_class.py:63:7 Too many arguments [19]: Call `object.__init__` expects 0 positional arguments, 2 were provided. +dataclasses_transform_class.py:65:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +dataclasses_transform_class.py:69:5 Unsupported operand [58]: `<` is not supported for operand types `Customer1` and `Customer1`. +dataclasses_transform_class.py:71:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +dataclasses_transform_class.py:73:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +dataclasses_transform_class.py:75:5 Unsupported operand [58]: `<` is not supported for operand types `Customer2` and `Customer2`. +dataclasses_transform_class.py:79:7 Too many arguments [19]: Call `object.__init__` expects 0 positional arguments, 2 were provided. +dataclasses_transform_class.py:86:0 Uninitialized attribute [13]: Attribute `not_a_field` is declared in class `GenericModelBase` to have type `Variable[T]` but is never initialized. +dataclasses_transform_class.py:103:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +dataclasses_transform_class.py:107:0 Uninitialized attribute [13]: Attribute `not_a_field` is declared in class `ModelBaseFrozen` to have type `str` but is never initialized. +dataclasses_transform_class.py:111:0 Uninitialized attribute [13]: Attribute `id` is declared in class `Customer3` to have type `int` but is never initialized. +dataclasses_transform_class.py:111:0 Uninitialized attribute [13]: Attribute `name` is declared in class `Customer3` to have type `str` but is never initialized. +dataclasses_transform_class.py:116:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +""" diff --git a/conformance/results/pyre/dataclasses_transform_field.toml b/conformance/results/pyre/dataclasses_transform_field.toml new file mode 100644 index 000000000..cbecc0d24 --- /dev/null +++ b/conformance/results/pyre/dataclasses_transform_field.toml @@ -0,0 +1,11 @@ +conformant = "Unsupported" +notes = """ +Does not understand @dataclass_transform. +""" +output = """ +dataclasses_transform_field.py:49:42 Invalid type variable [34]: The type variable `Variable[T]` isn't present in the function's parameters. +dataclasses_transform_field.py:60:0 Unexpected keyword [28]: Unexpected keyword argument `name` to call `object.__init__`. +dataclasses_transform_field.py:64:0 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +dataclasses_transform_field.py:75:0 Too many arguments [19]: Call `object.__init__` expects 0 positional arguments, 1 was provided. +dataclasses_transform_field.py:77:0 Unexpected keyword [28]: Unexpected keyword argument `name` to call `object.__init__`. +""" diff --git a/conformance/results/pyre/dataclasses_transform_func.toml b/conformance/results/pyre/dataclasses_transform_func.toml new file mode 100644 index 000000000..5c010ed56 --- /dev/null +++ b/conformance/results/pyre/dataclasses_transform_func.toml @@ -0,0 +1,26 @@ +conformant = "Unsupported" +notes = """ +Does not understand @dataclass_transform. +""" +output = """ +dataclasses_transform_func.py:20:0 Incompatible overload [43]: The implementation of `create_model` does not accept all possible arguments of overload defined on line `20`. +dataclasses_transform_func.py:25:5 Invalid type variable [34]: The type variable `Variable[T]` isn't present in the function's parameters. +dataclasses_transform_func.py:29:0 Incompatible overload [43]: This definition does not have the same decorators as the preceding overload(s). +dataclasses_transform_func.py:34:0 Uninitialized attribute [13]: Attribute `id` is declared in class `Customer1` to have type `int` but is never initialized. +dataclasses_transform_func.py:34:0 Uninitialized attribute [13]: Attribute `name` is declared in class `Customer1` to have type `str` but is never initialized. +dataclasses_transform_func.py:40:0 Uninitialized attribute [13]: Attribute `id` is declared in class `Customer2` to have type `int` but is never initialized. +dataclasses_transform_func.py:40:0 Uninitialized attribute [13]: Attribute `name` is declared in class `Customer2` to have type `str` but is never initialized. +dataclasses_transform_func.py:46:0 Uninitialized attribute [13]: Attribute `salary` is declared in class `Customer2Subclass` to have type `float` but is never initialized. +dataclasses_transform_func.py:50:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +dataclasses_transform_func.py:53:7 Too many arguments [19]: Call `object.__init__` expects 0 positional arguments, 2 were provided. +dataclasses_transform_func.py:57:0 Incompatible attribute type [8]: Attribute `name` declared in class `Customer1` has type `str` but is used as type `int`. +dataclasses_transform_func.py:61:5 Unsupported operand [58]: `<` is not supported for operand types `Customer1` and `Customer1`. +dataclasses_transform_func.py:65:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +dataclasses_transform_func.py:67:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +dataclasses_transform_func.py:71:7 Too many arguments [19]: Call `object.__init__` expects 0 positional arguments, 2 were provided. +dataclasses_transform_func.py:73:5 Unsupported operand [58]: `<` is not supported for operand types `Customer2` and `Customer2`. +dataclasses_transform_func.py:82:0 Uninitialized attribute [13]: Attribute `id` is declared in class `Customer3` to have type `int` but is never initialized. +dataclasses_transform_func.py:82:0 Uninitialized attribute [13]: Attribute `name` is declared in class `Customer3` to have type `str` but is never initialized. +dataclasses_transform_func.py:90:0 Uninitialized attribute [13]: Attribute `age` is declared in class `Customer3Subclass` to have type `int` but is never initialized. +dataclasses_transform_func.py:94:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +""" diff --git a/conformance/results/pyre/dataclasses_transform_meta.toml b/conformance/results/pyre/dataclasses_transform_meta.toml new file mode 100644 index 000000000..130917ca1 --- /dev/null +++ b/conformance/results/pyre/dataclasses_transform_meta.toml @@ -0,0 +1,19 @@ +conformant = "Unsupported" +notes = """ +Does not understand @dataclass_transform. +""" +output = """ +dataclasses_transform_meta.py:25:0 Uninitialized attribute [13]: Attribute `not_a_field` is declared in class `ModelMeta` to have type `str` but is never initialized. +dataclasses_transform_meta.py:52:0 Uninitialized attribute [13]: Attribute `id` is declared in class `Customer2` to have type `int` but is never initialized. +dataclasses_transform_meta.py:57:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +dataclasses_transform_meta.py:63:7 Too many arguments [19]: Call `object.__init__` expects 0 positional arguments, 2 were provided. +dataclasses_transform_meta.py:66:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +dataclasses_transform_meta.py:70:5 Unsupported operand [58]: `<` is not supported for operand types `Customer1` and `Customer1`. +dataclasses_transform_meta.py:72:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +dataclasses_transform_meta.py:74:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +dataclasses_transform_meta.py:76:5 Unsupported operand [58]: `<` is not supported for operand types `Customer2` and `Customer2`. +dataclasses_transform_meta.py:80:7 Too many arguments [19]: Call `object.__init__` expects 0 positional arguments, 2 were provided. +dataclasses_transform_meta.py:92:0 Uninitialized attribute [13]: Attribute `id` is declared in class `Customer3` to have type `int` but is never initialized. +dataclasses_transform_meta.py:92:0 Uninitialized attribute [13]: Attribute `name` is declared in class `Customer3` to have type `str` but is never initialized. +dataclasses_transform_meta.py:97:7 Unexpected keyword [28]: Unexpected keyword argument `id` to call `object.__init__`. +""" diff --git a/conformance/results/pyre/dataclasses_usage.toml b/conformance/results/pyre/dataclasses_usage.toml new file mode 100644 index 000000000..1f111055b --- /dev/null +++ b/conformance/results/pyre/dataclasses_usage.toml @@ -0,0 +1,20 @@ +conformant = "Partial" +notes = """ +Does not report error when field with no default follows field with default. +Incorrectly reports error with InitVar that has default value. +""" +output = """ +dataclasses_usage.py:51:5 Missing argument [20]: Call `InventoryItem.__init__` expects argument `unit_price`. +dataclasses_usage.py:52:27 Incompatible parameter type [6]: In call `InventoryItem.__init__`, for 2nd positional argument, expected `float` but got `str`. +dataclasses_usage.py:53:5 Too many arguments [19]: Call `InventoryItem.__init__` expects 3 positional arguments, 4 were provided. +dataclasses_usage.py:73:4 Incompatible attribute type [8]: Attribute `a` declared in class `DC3` has type `InitVar[int]` but is used as type `int`. +dataclasses_usage.py:84:5 Too many arguments [19]: Call `DC4.__init__` expects 1 positional argument, 2 were provided. +dataclasses_usage.py:89:4 Incompatible attribute type [8]: Attribute `a` declared in class `DC5` has type `int` but is used as type `str`. +dataclasses_usage.py:116:0 Uninitialized attribute [13]: Attribute `y` is declared in class `DC8` to have type `int` but is never initialized. +dataclasses_usage.py:127:0 Too many arguments [19]: Call `DC7.__init__` expects 1 positional argument, 2 were provided. +dataclasses_usage.py:130:0 Missing argument [20]: Call `DC8.__init__` expects argument `y`. +dataclasses_usage.py:172:0 Uninitialized attribute [13]: Attribute `x` is declared in class `DC13` to have type `int` but is never initialized. +dataclasses_usage.py:172:0 Uninitialized attribute [13]: Attribute `x_squared` is declared in class `DC13` to have type `int` but is never initialized. +dataclasses_usage.py:179:0 Too many arguments [19]: Call `object.__init__` expects 0 positional arguments, 1 was provided. +dataclasses_usage.py:207:0 Incompatible variable type [9]: v1 is declared to have type `DataclassProto` but is used as type `DC15`. +""" diff --git a/conformance/results/pyre/generics_self_advanced.toml b/conformance/results/pyre/generics_self_advanced.toml new file mode 100644 index 000000000..2930afeb0 --- /dev/null +++ b/conformance/results/pyre/generics_self_advanced.toml @@ -0,0 +1,15 @@ +conformant = "Unsupported" +notes = """ +Does not understand `Self` type. +""" +output = """ +generics_self_advanced.py:25:7 Undefined or invalid type [11]: Annotation `Self` is not defined as a type. +generics_self_advanced.py:35:26 Undefined attribute [16]: Module `typing` has no attribute `Self`. +generics_self_advanced.py:36:33 Undefined attribute [16]: Module `typing` has no attribute `Self`. +generics_self_advanced.py:37:31 Undefined attribute [16]: Module `typing` has no attribute `Self`. +generics_self_advanced.py:38:36 Undefined attribute [16]: Module `typing` has no attribute `Self`. +generics_self_advanced.py:42:30 Undefined attribute [16]: Module `typing` has no attribute `Self`. +generics_self_advanced.py:43:32 Undefined attribute [16]: Module `typing` has no attribute `Self`. +generics_self_advanced.py:44:30 Undefined attribute [16]: Module `typing` has no attribute `Self`. +generics_self_advanced.py:45:35 Undefined attribute [16]: Module `typing` has no attribute `Self`. +""" diff --git a/conformance/results/pyre/generics_self_attributes.toml b/conformance/results/pyre/generics_self_attributes.toml new file mode 100644 index 000000000..f772cd636 --- /dev/null +++ b/conformance/results/pyre/generics_self_attributes.toml @@ -0,0 +1,10 @@ +conformant = "Unsupported" +notes = """ +Does not understand `Self` type. +""" +output = """ +generics_self_attributes.py:16:10 Undefined or invalid type [11]: Annotation `Self` is not defined as a type. +generics_self_attributes.py:26:5 Unexpected keyword [28]: Unexpected keyword argument `next` to call `OrdinalLinkedList.__init__`. +generics_self_attributes.py:29:14 Unexpected keyword [28]: Unexpected keyword argument `next` to call `OrdinalLinkedList.__init__`. +generics_self_attributes.py:32:14 Unexpected keyword [28]: Unexpected keyword argument `next` to call `LinkedList.__init__`. +""" diff --git a/conformance/results/pyre/generics_self_basic.toml b/conformance/results/pyre/generics_self_basic.toml new file mode 100644 index 000000000..66191b50c --- /dev/null +++ b/conformance/results/pyre/generics_self_basic.toml @@ -0,0 +1,15 @@ +conformant = "Unsupported" +notes = """ +Does not understand `Self` type. +""" +output = """ +generics_self_basic.py:13:26 Undefined attribute [16]: Module `typing` has no attribute `Self`. +generics_self_basic.py:19:8 Incompatible return type [7]: Expected `Variable[_Self_generics_self_basic_Shape__ (bound to Shape)]` but got `Shape`. +generics_self_basic.py:26:30 Undefined attribute [16]: Module `typing` has no attribute `Self`. +generics_self_basic.py:27:15 Too many arguments [19]: Call `object.__init__` expects 0 positional arguments, 1 was provided. +generics_self_basic.py:32:8 Incompatible return type [7]: Expected `Variable[_Self_generics_self_basic_Shape__ (bound to Shape)]` but got `Shape`. +generics_self_basic.py:39:27 Undefined attribute [16]: Module `typing` has no attribute `Self`. +generics_self_basic.py:57:0 Uninitialized attribute [13]: Attribute `value` is declared in class `Container` to have type `Variable[T]` but is never initialized. +generics_self_basic.py:64:25 Undefined or invalid type [11]: Annotation `Self` is not defined as a type. +generics_self_basic.py:80:31 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[T]]` but got `TypeVar`. +""" diff --git a/conformance/results/pyre/generics_self_protocols.toml b/conformance/results/pyre/generics_self_protocols.toml new file mode 100644 index 000000000..3943248a8 --- /dev/null +++ b/conformance/results/pyre/generics_self_protocols.toml @@ -0,0 +1,7 @@ +conformant = "Partial" +notes = """ +Does not reject protocol compatibility due to method `Self` return type. +""" +output = """ +generics_self_protocols.py:61:18 Incompatible parameter type [6]: In call `accepts_shape`, for 1st positional argument, expected `ShapeProtocol` but got `BadReturnType`. +""" diff --git a/conformance/results/pyre/generics_self_usage.toml b/conformance/results/pyre/generics_self_usage.toml new file mode 100644 index 000000000..6349aa8a7 --- /dev/null +++ b/conformance/results/pyre/generics_self_usage.toml @@ -0,0 +1,10 @@ +conformant = "Unsupported" +notes = """ +Does not understand `Self` type. +""" +output = """ +generics_self_usage.py:20:34 Undefined or invalid type [11]: Annotation `Self` is not defined as a type. +generics_self_usage.py:86:8 Incompatible return type [7]: Expected `Variable[_Self_generics_self_usage_Foo3__ (bound to Foo3)]` but got `Foo3`. +generics_self_usage.py:106:0 Incompatible variable type [9]: TupleSelf is declared to have type `TypeAlias` but is used as type `Type[tuple[Variable[_T_co](covariant)]]`. +generics_self_usage.py:106:29 Undefined attribute [16]: Module `typing` has no attribute `Self`. +""" diff --git a/conformance/results/pyre/literals_interactions.toml b/conformance/results/pyre/literals_interactions.toml new file mode 100644 index 000000000..4f88bb35a --- /dev/null +++ b/conformance/results/pyre/literals_interactions.toml @@ -0,0 +1,11 @@ +conformant = "Partial" +notes = """ +Does not detect out-of-bound tuple literal index. +Does not narrow type of `x` with `x in Literal` type guard pattern. +Does not narrow type of `x` with `x == Literal` type guard pattern. +""" +output = """ +literals_interactions.py:51:38 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[AnyStr <: [str, bytes]]]` but got `object`. +literals_interactions.py:106:34 Incompatible parameter type [6]: In call `expects_bad_status`, for 1st positional argument, expected `Union[typing_extensions.Literal['ABORTED'], typing_extensions.Literal['MALFORMED']]` but got `str`. +literals_interactions.py:109:31 Non-literal string [62]: In call `expects_pending_status`, for 1st positional argument, expected `LiteralString` but got `str`. Ensure only a string literal or a `LiteralString` is used. +""" diff --git a/conformance/results/pyre/literals_literalstring.toml b/conformance/results/pyre/literals_literalstring.toml new file mode 100644 index 000000000..c60ee6199 --- /dev/null +++ b/conformance/results/pyre/literals_literalstring.toml @@ -0,0 +1,13 @@ +conformant = "Pass" +output = """ +literals_literalstring.py:36:11 Invalid type [31]: Expression `LiteralString` is not a literal value. +literals_literalstring.py:36:11 Undefined or invalid type [11]: Annotation `typing` is not defined as a type. +literals_literalstring.py:37:13 Invalid type [31]: Expression `LiteralString` is not a literal value. +literals_literalstring.py:43:4 Incompatible variable type [9]: x2 is declared to have type `typing_extensions.Literal['']` but is used as type `typing_extensions.Literal['two']`. +literals_literalstring.py:66:4 Incompatible variable type [9]: x1 is declared to have type `typing_extensions.LiteralString` but is used as type `str`. +literals_literalstring.py:74:4 Incompatible variable type [9]: x3 is declared to have type `typing_extensions.LiteralString` but is used as type `typing_extensions.Literal[3]`. +literals_literalstring.py:75:4 Incompatible variable type [9]: x4 is declared to have type `typing_extensions.LiteralString` but is used as type `typing_extensions.Literal[b'test']`. +literals_literalstring.py:120:21 Incompatible parameter type [6]: In call `literal_identity`, for 1st positional argument, expected `Variable[TLiteral (bound to typing_extensions.LiteralString)]` but got `str`. +literals_literalstring.py:134:50 Incompatible parameter type [6]: In call `Container.__init__`, for 1st positional argument, expected `Variable[T (bound to typing_extensions.LiteralString)]` but got `str`. +literals_literalstring.py:166:4 Incompatible variable type [9]: x1 is declared to have type `List[str]` but is used as type `List[typing_extensions.LiteralString]`. +""" diff --git a/conformance/results/pyre/literals_parameterizations.toml b/conformance/results/pyre/literals_parameterizations.toml new file mode 100644 index 000000000..89d38c177 --- /dev/null +++ b/conformance/results/pyre/literals_parameterizations.toml @@ -0,0 +1,30 @@ +conformant = "Partial" +notes = """ +Does not support type aliases in Literal type expression. +Does not support nested Literal type expression. +Does not reject unary + operator in Literal type expression. +Does not reject tuple in Literal type expression. +Does not reject "bare" Literal in type expression. +""" +output = """ +literals_parameterizations.py:32:0 Invalid type [31]: Expression `AppendMode` is not a literal value. +literals_parameterizations.py:32:0 Invalid type [31]: Expression `ReadOnlyMode` is not a literal value. +literals_parameterizations.py:32:0 Invalid type [31]: Expression `WriteAndTruncateMode` is not a literal value. +literals_parameterizations.py:32:0 Invalid type [31]: Expression `WriteNoTruncateMode` is not a literal value. +literals_parameterizations.py:32:0 Undefined or invalid type [11]: Annotation `` is not defined as a type. +literals_parameterizations.py:34:8 Invalid type [31]: Expression `typing.Literal[(typing.Literal[(typing.Literal[(1, 2, 3)], "foo")], 5, None)]` is not a valid type. +literals_parameterizations.py:40:6 Invalid type [31]: Expression `typing.Literal[3.__add__(4)]` is not a valid type. +literals_parameterizations.py:41:6 Invalid type [31]: Expression `typing.Literal["foo".replace("o", "b")]` is not a valid type. +literals_parameterizations.py:42:6 Invalid type [31]: Expression `typing.Literal[4.__add__(3.000000j)]` is not a valid type. +literals_parameterizations.py:44:6 Invalid type [31]: Expression `typing.Literal[not False]` is not a valid type. +literals_parameterizations.py:46:6 Invalid type [31]: Expression `typing.Literal[{ "a":"b","c":"d" }]` is not a valid type. +literals_parameterizations.py:47:6 Invalid type [31]: Expression `typing.Literal[int]` is not a valid type. +literals_parameterizations.py:48:6 Invalid type [31]: Expression `variable` is not a literal value. +literals_parameterizations.py:49:7 Invalid type [31]: Expression `T` is not a literal value. +literals_parameterizations.py:50:7 Invalid type [31]: Expression `typing.Literal[3.140000]` is not a valid type. +literals_parameterizations.py:51:7 Invalid type [31]: Expression `Any` is not a literal value. +literals_parameterizations.py:52:7 Invalid type [31]: Expression `typing.Literal[...]` is not a valid type. +literals_parameterizations.py:55:19 Invalid type [31]: Expression `typing.Literal[1.__add__(2)]` is not a valid type. +literals_parameterizations.py:59:3 Invalid type [31]: Expression `my_function` is not a literal value. +literals_parameterizations.py:63:4 Incompatible variable type [9]: x1 is declared to have type `typing_extensions.Literal['Color.RED']` but is used as type `typing_extensions.Literal[Color.RED]`. +""" diff --git a/conformance/results/pyre/literals_semantics.toml b/conformance/results/pyre/literals_semantics.toml new file mode 100644 index 000000000..c7f8f8c9f --- /dev/null +++ b/conformance/results/pyre/literals_semantics.toml @@ -0,0 +1,9 @@ +conformant = "Partial" +notes = """ +Does not reject augmented operation that modifies literal value. +""" +output = """ +literals_semantics.py:10:0 Incompatible variable type [9]: v2 is declared to have type `typing_extensions.Literal[3]` but is used as type `typing_extensions.Literal[4]`. +literals_semantics.py:24:4 Incompatible variable type [9]: x1 is declared to have type `typing_extensions.Literal[False]` but is used as type `typing_extensions.Literal[0]`. +literals_semantics.py:25:4 Incompatible variable type [9]: x2 is declared to have type `typing_extensions.Literal[0]` but is used as type `typing_extensions.Literal[False]`. +""" diff --git a/conformance/results/pyre/narrowing_typeguard.toml b/conformance/results/pyre/narrowing_typeguard.toml new file mode 100644 index 000000000..b14ed9e43 --- /dev/null +++ b/conformance/results/pyre/narrowing_typeguard.toml @@ -0,0 +1,9 @@ +conformant = "Partial" +notes = """ +Does not support `tuple` in `assert_type` call. +Does not reject TypeGuard method with too few parameters. +""" +output = """ +narrowing_typeguard.py:17:33 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T_co](covariant)]` but got `Tuple[Type[str], Type[str]]`. +narrowing_typeguard.py:19:33 Incompatible parameter type [6]: In call `typing.GenericMeta.__getitem__`, for 1st positional argument, expected `Type[Variable[_T_co](covariant)]` but got `Tuple[Type[str], typing.Any]`. +""" diff --git a/conformance/results/pyre/typeddicts_alt_syntax.toml b/conformance/results/pyre/typeddicts_alt_syntax.toml new file mode 100644 index 000000000..1435a730a --- /dev/null +++ b/conformance/results/pyre/typeddicts_alt_syntax.toml @@ -0,0 +1,10 @@ +conformant = "Partial" +notes = """ +Does not report when name of TypedDict doesn't match assigned identifier name. +Does not support keyword-argument form of alternative syntax (deprecated in 3.11). +""" +output = """ +typeddicts_alt_syntax.py:23:16 Call error [29]: `object` is not a function. +typeddicts_alt_syntax.py:41:9 Call error [29]: `object` is not a function. +typeddicts_alt_syntax.py:43:8 Undefined or invalid type [11]: Annotation `Movie2` is not defined as a type. +""" diff --git a/conformance/results/pyre/typeddicts_class_syntax.toml b/conformance/results/pyre/typeddicts_class_syntax.toml new file mode 100644 index 000000000..50ffee139 --- /dev/null +++ b/conformance/results/pyre/typeddicts_class_syntax.toml @@ -0,0 +1,11 @@ +conformant = "Partial" +notes = """ +Does not reject methods within TypedDict class. +Does not report when metaclass is provided. +Does not report when other keyword argument is provided. +Does not support generic TypedDict class. +""" +output = """ +typeddicts_class_syntax.py:57:0 Uninitialized attribute [13]: Attribute `name` is declared in class `GenericTypedDict` to have type `str` but is never initialized. +typeddicts_class_syntax.py:57:0 Uninitialized attribute [13]: Attribute `value` is declared in class `GenericTypedDict` to have type `Variable[T]` but is never initialized. +""" diff --git a/conformance/results/pyre/typeddicts_final.toml b/conformance/results/pyre/typeddicts_final.toml new file mode 100644 index 000000000..c55712229 --- /dev/null +++ b/conformance/results/pyre/typeddicts_final.toml @@ -0,0 +1,7 @@ +conformant = "Partial" +notes = """ +Does not handle value with literal type as index to TypedDict object. +""" +output = """ +typeddicts_final.py:26:17 Incompatible parameter type [6]: In call `TypedDictionary.__getitem__`, for 1st positional argument, expected `typing_extensions.Literal['name']` but got `Union[typing_extensions.Literal['name'], typing_extensions.Literal['year']]`. +""" diff --git a/conformance/results/pyre/typeddicts_inheritance.toml b/conformance/results/pyre/typeddicts_inheritance.toml new file mode 100644 index 000000000..d15915ca3 --- /dev/null +++ b/conformance/results/pyre/typeddicts_inheritance.toml @@ -0,0 +1,8 @@ +conformant = "Partial" +notes = """ +Does not reject TypedDict class that inherits from non-TypedDict class. +""" +output = """ +typeddicts_inheritance.py:54:0 Inconsistent override [15]: `x` overrides attribute defined in `X1` inconsistently. Type `int` is not a subtype of the overridden attribute `str`. +typeddicts_inheritance.py:65:0 Invalid inheritance [39]: Field `x` has type `int` in base class `X2` and type `str` in base class `Y2`. +""" diff --git a/conformance/results/pyre/typeddicts_operations.toml b/conformance/results/pyre/typeddicts_operations.toml new file mode 100644 index 000000000..202a0a974 --- /dev/null +++ b/conformance/results/pyre/typeddicts_operations.toml @@ -0,0 +1,14 @@ +conformant = "Pass" +output = """ +typeddicts_operations.py:22:16 Invalid TypedDict operation [54]: Expected `str` to be assigned to `Movie` field `name` but got `int`. +typeddicts_operations.py:23:16 Invalid TypedDict operation [54]: Expected `int` to be assigned to `Movie` field `year` but got `str`. +typeddicts_operations.py:24:6 TypedDict accessed with a missing key [27]: TypedDict `Movie` has no key `other`. +typeddicts_operations.py:26:12 TypedDict accessed with a missing key [27]: TypedDict `Movie` has no key `other`. +typeddicts_operations.py:28:8 TypedDict initialization error [55]: Missing required field `year` for TypedDict `Movie`. +typeddicts_operations.py:29:8 TypedDict initialization error [55]: Expected type `int` for `Movie` field `year` but got `float`. +typeddicts_operations.py:32:8 TypedDict initialization error [55]: TypedDict `Movie` has no field `other`. +typeddicts_operations.py:37:4 Incompatible variable type [9]: movie is declared to have type `Movie` but is used as type `Dict[str, Union[int, str]]`. +typeddicts_operations.py:44:10 TypedDict accessed with a missing key [27]: TypedDict `Movie` has no key `other`. +typeddicts_operations.py:47:0 Undefined attribute [16]: `Movie` has no attribute `clear`. +typeddicts_operations.py:62:0 Undefined attribute [16]: `MovieOptional` has no attribute `clear`. +""" diff --git a/conformance/results/pyre/typeddicts_required.toml b/conformance/results/pyre/typeddicts_required.toml new file mode 100644 index 000000000..9a654d815 --- /dev/null +++ b/conformance/results/pyre/typeddicts_required.toml @@ -0,0 +1,11 @@ +conformant = "Partial" +notes = """ +Does not reject use of `Required` in function parameter annotation. +Does not reject nested use of `Required` in type annotation. +Does not support recursive TypedDict definitions. +""" +output = """ +typeddicts_required.py:11:0 Uninitialized attribute [13]: Attribute `x` is declared in class `NotTypedDict` to have type `Required[int]` but is never initialized. +typeddicts_required.py:71:62 Undefined or invalid type [11]: Annotation `RecursiveMovie` is not defined as a type. +typeddicts_required.py:74:24 TypedDict initialization error [55]: Expected type `unknown` for `RecursiveMovie` field `predecessor` but got `typing.Dict[str, str]`. +""" diff --git a/conformance/results/pyre/typeddicts_type_consistency.toml b/conformance/results/pyre/typeddicts_type_consistency.toml new file mode 100644 index 000000000..28b9043e4 --- /dev/null +++ b/conformance/results/pyre/typeddicts_type_consistency.toml @@ -0,0 +1,19 @@ +conformant = "Partial" +notes = """ +Does not reject assignment of TypedDict with missing key. +Does not return non-Optional value from `get` method for required key. +Does not properly handle nested TypedDicts. +""" +output = """ +typeddicts_type_consistency.py:21:0 Incompatible variable type [9]: a1 is declared to have type `A1` but is used as type `B1`. +typeddicts_type_consistency.py:38:0 Incompatible variable type [9]: a2 is declared to have type `A2` but is used as type `B2`. +typeddicts_type_consistency.py:69:11 TypedDict initialization error [55]: TypedDict `A3` has no field `y`. +typeddicts_type_consistency.py:76:0 Incompatible variable type [9]: d1 is declared to have type `Dict[str, int]` but is used as type `B3`. +typeddicts_type_consistency.py:77:0 Incompatible variable type [9]: d2 is declared to have type `Dict[str, object]` but is used as type `B3`. +typeddicts_type_consistency.py:78:0 Incompatible variable type [9]: d3 is declared to have type `Dict[typing.Any, typing.Any]` but is used as type `B3`. +typeddicts_type_consistency.py:82:0 Incompatible variable type [9]: m1 is declared to have type `Mapping[str, int]` but is used as type `B3`. +typeddicts_type_consistency.py:99:0 Incompatible variable type [9]: name3 is declared to have type `str` but is used as type `Optional[str]`. +typeddicts_type_consistency.py:105:0 Incompatible variable type [9]: age4 is declared to have type `int` but is used as type `Union[str, int]`. +typeddicts_type_consistency.py:124:41 TypedDict initialization error [55]: Expected type `str` for `Inner1` field `inner_key` but got `int`. +typeddicts_type_consistency.py:150:0 Incompatible variable type [9]: o4 is declared to have type `Outer3` but is used as type `Outer2`. +""" diff --git a/conformance/results/pyre/typeddicts_usage.toml b/conformance/results/pyre/typeddicts_usage.toml new file mode 100644 index 000000000..739dbf331 --- /dev/null +++ b/conformance/results/pyre/typeddicts_usage.toml @@ -0,0 +1,10 @@ +conformant = "Partial" +notes = """ +Does not report errant use of TypedDict in `isinstance` call. +Does not reject use of TypedDict as TypeVar bound. +""" +output = """ +typeddicts_usage.py:23:6 TypedDict accessed with a missing key [27]: TypedDict `Movie` has no key `director`. +typeddicts_usage.py:24:16 Invalid TypedDict operation [54]: Expected `int` to be assigned to `Movie` field `year` but got `str`. +typeddicts_usage.py:28:16 TypedDict initialization error [55]: Missing required field `name` for TypedDict `Movie`. +""" diff --git a/conformance/results/pyre/version.toml b/conformance/results/pyre/version.toml new file mode 100644 index 000000000..91daa0eeb --- /dev/null +++ b/conformance/results/pyre/version.toml @@ -0,0 +1,2 @@ +version = "pyre 0.9.19" +test_duration = 1.5496571063995361 diff --git a/conformance/results/pyright/aliases_explicit.toml b/conformance/results/pyright/aliases_explicit.toml new file mode 100644 index 000000000..a69c20491 --- /dev/null +++ b/conformance/results/pyright/aliases_explicit.toml @@ -0,0 +1,51 @@ +conformant = "Partial" +notes = """ +Incorrectly evaluates type of specialized type alias parameterized with ParamSpec. +Allows some illegal annotation forms to be interpreted as valid type aliases. +""" +output = """ +aliases_explicit.py:57:17 - error: "assert_type" mismatch: expected "(int, str, str) -> None" but received "(int, str, str) -> None" (reportGeneralTypeIssues) +aliases_explicit.py:67:24 - error: Expected no type arguments for class "int" (reportGeneralTypeIssues) +aliases_explicit.py:67:24 - error: Expected no type arguments for class "NoneType" (reportGeneralTypeIssues) +aliases_explicit.py:68:9 - error: Type "list[int | None]" is already specialized (reportGeneralTypeIssues) +aliases_explicit.py:69:29 - error: Too many type arguments provided for "GoodTypeAlias4[T@GoodTypeAlias4]"; expected 1 but received 2 +aliases_explicit.py:70:29 - error: Too many type arguments provided for "GoodTypeAlias8[T@GoodTypeAlias8]"; expected 1 but received 2 +aliases_explicit.py:71:24 - error: Expected ParamSpec, ellipsis, or list of types +aliases_explicit.py:79:21 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_explicit.py:79:21 - error: Call expression not allowed in type expression (reportGeneralTypeIssues) +aliases_explicit.py:80:21 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_explicit.py:80:21 - error: List expression not allowed in type annotation +  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportGeneralTypeIssues) +aliases_explicit.py:80:21 - error: Expected type expression but received "list[Unknown]" (reportGeneralTypeIssues) +aliases_explicit.py:81:21 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_explicit.py:81:21 - error: Tuple expression not allowed in type annotation +  Use Tuple[T1, ..., Tn] to indicate a tuple type or Union[T1, T2] to indicate a union type (reportGeneralTypeIssues) +aliases_explicit.py:81:21 - error: Expected type expression but received "tuple[tuple[type[int], type[str]]]" (reportGeneralTypeIssues) +aliases_explicit.py:82:21 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_explicit.py:82:21 - error: List expression not allowed in type annotation +  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportGeneralTypeIssues) +aliases_explicit.py:82:21 - error: Expected type expression but received "list[type[int]]" (reportGeneralTypeIssues) +aliases_explicit.py:83:21 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_explicit.py:83:21 - error: Dictionary expression not allowed in type annotation +  Use Dict[T1, T2] to indicate a dictionary type (reportGeneralTypeIssues) +aliases_explicit.py:83:21 - error: Expected type expression but received "dict[str, str]" (reportGeneralTypeIssues) +aliases_explicit.py:84:21 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_explicit.py:84:21 - error: Call expression not allowed in type expression (reportGeneralTypeIssues) +aliases_explicit.py:85:21 - error: List expression not allowed in type annotation +  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportGeneralTypeIssues) +aliases_explicit.py:85:21 - error: Expected type expression but received "list[type[int]]" (reportGeneralTypeIssues) +aliases_explicit.py:86:21 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_explicit.py:86:21 - error: Ternary expression not allowed in type annotation +aliases_explicit.py:87:21 - error: Variable not allowed in type expression (reportGeneralTypeIssues) +aliases_explicit.py:88:22 - error: Expected type expression but received "Literal[True]" (reportGeneralTypeIssues) +aliases_explicit.py:89:22 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_explicit.py:89:22 - error: Expected type expression but received "Literal[1]" (reportGeneralTypeIssues) +aliases_explicit.py:90:22 - error: Binary operator not allowed in type annotation +aliases_explicit.py:91:22 - error: Expected expression +aliases_explicit.py:91:22 - error: Tuple expression not allowed in type annotation +  Use Tuple[T1, ..., Tn] to indicate a tuple type or Union[T1, T2] to indicate a union type (reportGeneralTypeIssues) +aliases_explicit.py:100:5 - error: Type "list[Unknown]" is already specialized (reportGeneralTypeIssues) +aliases_explicit.py:101:6 - error: Object of type "type[list[Unknown]] | type[set[Unknown]]" is not callable (reportGeneralTypeIssues) +aliases_explicit.py:102:5 - error: Type "list[Unknown]" is already specialized (reportGeneralTypeIssues) +aliases_explicit.py:102:5 - error: Type "set[Unknown]" is already specialized (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/aliases_implicit.toml b/conformance/results/pyright/aliases_implicit.toml new file mode 100644 index 000000000..be26d5c86 --- /dev/null +++ b/conformance/results/pyright/aliases_implicit.toml @@ -0,0 +1,31 @@ +conformant = "Partial" +notes = """ +Incorrectly evaluates type of specialized type alias parameterized with ParamSpec. +Allows some illegal annotation forms to be interpreted as valid type aliases. +""" +output = """ +aliases_implicit.py:68:17 - error: "assert_type" mismatch: expected "(int, str, str) -> None" but received "(int, str, str) -> None" (reportGeneralTypeIssues) +aliases_implicit.py:76:24 - error: Expected no type arguments for class "int" (reportGeneralTypeIssues) +aliases_implicit.py:76:24 - error: Expected no type arguments for class "NoneType" (reportGeneralTypeIssues) +aliases_implicit.py:77:9 - error: Type "list[int | None]" is already specialized (reportGeneralTypeIssues) +aliases_implicit.py:78:29 - error: Too many type arguments provided for "GoodTypeAlias4[T@GoodTypeAlias4]"; expected 1 but received 2 +aliases_implicit.py:79:29 - error: Too many type arguments provided for "GoodTypeAlias8[T@GoodTypeAlias8]"; expected 1 but received 2 +aliases_implicit.py:80:24 - error: Expected ParamSpec, ellipsis, or list of types +aliases_implicit.py:81:9 - error: Could not specialize type "GoodTypeAlias12[TFloat@GoodTypeAlias12]" +  Type "str" cannot be assigned to type "float" +    "str" is incompatible with "float" +aliases_implicit.py:106:9 - error: Variable not allowed in type expression (reportGeneralTypeIssues) +aliases_implicit.py:107:9 - error: Variable not allowed in type expression (reportGeneralTypeIssues) +aliases_implicit.py:108:9 - error: Variable not allowed in type expression (reportGeneralTypeIssues) +aliases_implicit.py:109:9 - error: Variable not allowed in type expression (reportGeneralTypeIssues) +aliases_implicit.py:110:9 - error: Variable not allowed in type expression (reportGeneralTypeIssues) +aliases_implicit.py:113:9 - error: Variable not allowed in type expression (reportGeneralTypeIssues) +aliases_implicit.py:114:9 - error: Variable not allowed in type expression (reportGeneralTypeIssues) +aliases_implicit.py:115:10 - error: Variable not allowed in type expression (reportGeneralTypeIssues) +aliases_implicit.py:116:10 - error: Variable not allowed in type expression (reportGeneralTypeIssues) +aliases_implicit.py:118:10 - error: Variable not allowed in type expression (reportGeneralTypeIssues) +aliases_implicit.py:119:10 - error: Variable not allowed in type expression (reportGeneralTypeIssues) +aliases_implicit.py:133:6 - error: Object of type "type[list[Unknown]] | type[set[Unknown]]" is not callable (reportGeneralTypeIssues) +aliases_implicit.py:135:5 - error: Type "list[Unknown]" is already specialized (reportGeneralTypeIssues) +aliases_implicit.py:135:5 - error: Type "set[Unknown]" is already specialized (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/aliases_newtype.toml b/conformance/results/pyright/aliases_newtype.toml new file mode 100644 index 000000000..5024de109 --- /dev/null +++ b/conformance/results/pyright/aliases_newtype.toml @@ -0,0 +1,21 @@ +conformant = "Partial" +notes = """ +Does not reject use of NewType in `isinstance` call. +Does not report inconsistency between name of NewType and assigned identifier name. +Does not reject use of NewType with TypedDict class. +Does not reject use of NewType with another NewType. +Does not reject use of NewType with Any. +""" +output = """ +aliases_newtype.py:11:8 - error: Argument of type "Literal['user']" cannot be assigned to parameter "_x" of type "int" in function "__init__" +  "Literal['user']" is incompatible with "int" (reportGeneralTypeIssues) +aliases_newtype.py:12:14 - error: Expression of type "Literal[42]" cannot be assigned to declared type "UserId" +  "Literal[42]" is incompatible with "UserId" (reportGeneralTypeIssues) +aliases_newtype.py:23:21 - error: Base class "UserId" is marked final and cannot be subclassed +aliases_newtype.py:36:19 - error: Expected no type arguments for class "GoodNewType1" (reportGeneralTypeIssues) +aliases_newtype.py:42:38 - error: Expected class as second argument to NewType +aliases_newtype.py:45:43 - error: Type variable "T" has no meaning in this context (reportGeneralTypeIssues) +aliases_newtype.py:47:38 - error: NewType cannot be used with protocol class +aliases_newtype.py:49:38 - error: NewType cannot be used with Literal type +aliases_newtype.py:60:15 - error: NewType requires two positional arguments (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/aliases_recursive.toml b/conformance/results/pyright/aliases_recursive.toml new file mode 100644 index 000000000..b4ff9fb57 --- /dev/null +++ b/conformance/results/pyright/aliases_recursive.toml @@ -0,0 +1,66 @@ +conformant = "Pass" +output = """ +aliases_recursive.py:19:12 - error: Expression of type "dict[str, int | complex]" cannot be assigned to declared type "Json" +  Type "dict[str, int | complex]" cannot be assigned to type "Json" +    "dict[str, int | complex]" is incompatible with "None" +    "dict[str, int | complex]" is incompatible with "int" +    "dict[str, int | complex]" is incompatible with "str" +    "dict[str, int | complex]" is incompatible with "float" +    "dict[str, int | complex]" is incompatible with "list[Json]" +    "dict[str, int | complex]" is incompatible with "dict[str, Json]" +      Type parameter "_VT@dict" is invariant, but "int | complex" is not the same as "Json" + ... (reportGeneralTypeIssues) +aliases_recursive.py:20:16 - error: Expression of type "list[int | complex]" cannot be assigned to declared type "Json" +  Type "complex" cannot be assigned to type "Json" +    "complex" is incompatible with "None" +    "complex" is incompatible with "int" +    "complex" is incompatible with "str" +    "complex" is incompatible with "float" +    "complex" is incompatible with "list[Json]" +    "complex" is incompatible with "dict[str, Json]" (reportGeneralTypeIssues) +aliases_recursive.py:38:22 - error: Expression of type "tuple[Literal[1], tuple[Literal['1'], Literal[1]], tuple[Literal[1], tuple[Literal[1], list[int]]]]" cannot be assigned to declared type "RecursiveTuple" +  Type "tuple[Literal[1], tuple[Literal['1'], Literal[1]], tuple[Literal[1], tuple[Literal[1], list[int]]]]" cannot be assigned to type "RecursiveTuple" +    "tuple[Literal[1], tuple[Literal['1'], Literal[1]], tuple[Literal[1], tuple[Literal[1], list[int]]]]" is incompatible with "str" +    "tuple[Literal[1], tuple[Literal['1'], Literal[1]], tuple[Literal[1], tuple[Literal[1], list[int]]]]" is incompatible with "int" +    "tuple[Literal[1], tuple[Literal['1'], Literal[1]], tuple[Literal[1], tuple[Literal[1], list[int]]]]" is incompatible with "tuple[RecursiveTuple, ...]" +      Tuple entry 1 is incorrect type (reportGeneralTypeIssues) +aliases_recursive.py:39:22 - error: Expression of type "tuple[Literal[1], list[int]]" cannot be assigned to declared type "RecursiveTuple" +  Type "tuple[Literal[1], list[int]]" cannot be assigned to type "RecursiveTuple" +    "tuple[Literal[1], list[int]]" is incompatible with "str" +    "tuple[Literal[1], list[int]]" is incompatible with "int" +    "tuple[Literal[1], list[int]]" is incompatible with "tuple[RecursiveTuple, ...]" +      Tuple entry 1 is incorrect type (reportGeneralTypeIssues) +aliases_recursive.py:50:24 - error: Expression of type "dict[str, list[int]]" cannot be assigned to declared type "RecursiveMapping" +  Type "dict[str, list[int]]" cannot be assigned to type "RecursiveMapping" +    "dict[str, list[int]]" is incompatible with "str" +    "dict[str, list[int]]" is incompatible with "int" +    "dict[str, list[int]]" is incompatible with "Mapping[str, RecursiveMapping]" +      Type parameter "_VT_co@Mapping" is covariant, but "list[int]" is not a subtype of "RecursiveMapping" +        Type "list[int]" cannot be assigned to type "RecursiveMapping" +          "list[int]" is incompatible with "str" +          "list[int]" is incompatible with "int" + ... (reportGeneralTypeIssues) +aliases_recursive.py:51:24 - error: Expression of type "dict[str, str | int | list[int]]" cannot be assigned to declared type "RecursiveMapping" +  Type "dict[str, str | int | list[int]]" cannot be assigned to type "RecursiveMapping" +    "dict[str, str | int | list[int]]" is incompatible with "str" +    "dict[str, str | int | list[int]]" is incompatible with "int" +    "dict[str, str | int | list[int]]" is incompatible with "Mapping[str, RecursiveMapping]" +      Type parameter "_VT_co@Mapping" is covariant, but "str | int | list[int]" is not a subtype of "RecursiveMapping" (reportGeneralTypeIssues) +aliases_recursive.py:52:24 - error: Expression of type "dict[str, str | int | dict[str, str | int | list[int]]]" cannot be assigned to declared type "RecursiveMapping" +  Type "dict[str, str | int | dict[str, str | int | list[int]]]" cannot be assigned to type "RecursiveMapping" +    "dict[str, str | int | dict[str, str | int | list[int]]]" is incompatible with "str" +    "dict[str, str | int | dict[str, str | int | list[int]]]" is incompatible with "int" +    "dict[str, str | int | dict[str, str | int | list[int]]]" is incompatible with "Mapping[str, RecursiveMapping]" +      Type parameter "_VT_co@Mapping" is covariant, but "str | int | dict[str, str | int | list[int]]" is not a subtype of "RecursiveMapping" (reportGeneralTypeIssues) +aliases_recursive.py:67:38 - error: Expression of type "list[str | list[float]]" cannot be assigned to declared type "GenericTypeAlias1[str]" +  Type "float" cannot be assigned to type "GenericTypeAlias1[T1@GenericTypeAlias1] | str" +    "float" is incompatible with "GenericTypeAlias1[T1@GenericTypeAlias1]" +    "float" is incompatible with "str" (reportGeneralTypeIssues) +aliases_recursive.py:73:51 - error: Expression of type "list[list[int | list[str | int | list[float]]] | str]" cannot be assigned to declared type "GenericTypeAlias2[str, int]" +  Type "float" cannot be assigned to type "GenericTypeAlias2[T1@GenericTypeAlias2, T2@GenericTypeAlias2] | str | int" +    "float" is incompatible with "GenericTypeAlias2[T1@GenericTypeAlias2, T2@GenericTypeAlias2]" +    "float" is incompatible with "str" +    "float" is incompatible with "int" (reportGeneralTypeIssues) +aliases_recursive.py:76:29 - error: Type alias "RecursiveUnion" cannot use itself in its definition (reportGeneralTypeIssues) +aliases_recursive.py:78:31 - error: Type alias "MutualReference1" cannot use itself in its definition (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/aliases_type_statement.toml b/conformance/results/pyright/aliases_type_statement.toml new file mode 100644 index 000000000..abc0dc775 --- /dev/null +++ b/conformance/results/pyright/aliases_type_statement.toml @@ -0,0 +1,48 @@ +conformant = "Partial" +notes = """ +Does not reject binary expression when used in type alias definition. +""" +output = """ +aliases_type_statement.py:44:26 - error: Statements must be separated by newlines or semicolons +aliases_type_statement.py:44:35 - error: Expected ":" +aliases_type_statement.py:17:12 - error: Cannot access member "bit_count" for type "TypeAliasType" +  Member "bit_count" is unknown (reportGeneralTypeIssues) +aliases_type_statement.py:19:1 - error: Object of type "TypeAliasType" is not callable (reportGeneralTypeIssues) +aliases_type_statement.py:23:18 - error: Cannot access member "other_attrib" for type "TypeAliasType" +  Member "other_attrib" is unknown (reportGeneralTypeIssues) +aliases_type_statement.py:26:18 - error: Expected type expression but received "TypeAliasType" (reportGeneralTypeIssues) +aliases_type_statement.py:31:22 - error: Argument of type "TypeAliasType" cannot be assigned to parameter "__class_or_tuple" of type "_ClassInfo" in function "isinstance" +  Type "TypeAliasType" cannot be assigned to type "_ClassInfo" +    "TypeAliasType" is incompatible with "type" +    "TypeAliasType" is incompatible with "UnionType" +    "TypeAliasType" is incompatible with "tuple[_ClassInfo, ...]" (reportGeneralTypeIssues) +aliases_type_statement.py:37:22 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_type_statement.py:38:22 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_type_statement.py:38:22 - error: Expected type expression but received "list[Unknown]" (reportGeneralTypeIssues) +aliases_type_statement.py:39:22 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_type_statement.py:39:22 - error: Expected type expression but received "tuple[tuple[type[int], type[str]]]" (reportGeneralTypeIssues) +aliases_type_statement.py:40:22 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_type_statement.py:40:22 - error: Expected type expression but received "list[type[int]]" (reportGeneralTypeIssues) +aliases_type_statement.py:41:22 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_type_statement.py:41:22 - error: Expected type expression but received "dict[str, str]" (reportGeneralTypeIssues) +aliases_type_statement.py:42:22 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_type_statement.py:43:22 - error: Expected type expression but received "list[type[int]]" (reportGeneralTypeIssues) +aliases_type_statement.py:45:22 - error: Expected type expression but received "int" (reportGeneralTypeIssues) +aliases_type_statement.py:46:23 - error: Expected type expression but received "Literal[True]" (reportGeneralTypeIssues) +aliases_type_statement.py:47:23 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_type_statement.py:47:23 - error: Expected type expression but received "Literal[1]" (reportGeneralTypeIssues) +aliases_type_statement.py:49:23 - error: Expected expression +aliases_type_statement.py:58:10 - error: A type statement can be used only within a module or class scope +aliases_type_statement.py:64:23 - error: Type parameter "V" is not included in the type parameter list for "TA1" (reportGeneralTypeIssues) +aliases_type_statement.py:69:17 - error: Type parameter "T1" is not included in the type parameter list for "TA2" (reportGeneralTypeIssues) +aliases_type_statement.py:79:7 - error: Could not specialize type "RecursiveTypeAlias2[S@RecursiveTypeAlias2, T@RecursiveTypeAlias2, P@RecursiveTypeAlias2]" +  Type "str" cannot be assigned to type "int" +    "str" is incompatible with "int" +aliases_type_statement.py:81:7 - error: Could not specialize type "RecursiveTypeAlias2[S@RecursiveTypeAlias2, T@RecursiveTypeAlias2, P@RecursiveTypeAlias2]" +  Type "int" cannot be assigned to type "str" +    "int" is incompatible with "str" +aliases_type_statement.py:84:28 - error: Type alias "RecursiveTypeAlias3" cannot use itself in its definition (reportGeneralTypeIssues) +aliases_type_statement.py:86:31 - error: Type alias "RecursiveTypeAlias4" cannot use itself in its definition (reportGeneralTypeIssues) +aliases_type_statement.py:90:28 - error: Type alias "RecursiveTypeAlias6" cannot use itself in its definition (reportGeneralTypeIssues) +aliases_type_statement.py:52:10 - error: Type alias declaration "BadTypeAlias14" is obscured by a declaration of the same name (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/aliases_typealiastype.toml b/conformance/results/pyright/aliases_typealiastype.toml new file mode 100644 index 000000000..34329cf9d --- /dev/null +++ b/conformance/results/pyright/aliases_typealiastype.toml @@ -0,0 +1,37 @@ +conformant = "Partial" +notes = """ +Does not reject type alias with TypeVar that is not in scope and not in `type_params`. +Does not allow access to `__value__` attribute of type alias. +Allows some illegal annotation forms to be interpreted as valid type aliases. +""" +output = """ +aliases_typealiastype.py:30:18 - error: Cannot access member "__value__" for type "GoodAlias1" +  Member "__value__" is unknown (reportGeneralTypeIssues) +aliases_typealiastype.py:32:18 - error: Cannot access member "other_attrib" for type "GoodAlias1" +  Member "other_attrib" is unknown (reportGeneralTypeIssues) +aliases_typealiastype.py:40:5 - error: Could not specialize type "GoodAlias5[S@GoodAlias5, TStr@GoodAlias5, P@GoodAlias5, Ts@GoodAlias5]" +  Type "int" cannot be assigned to type "str" +    "int" is incompatible with "str" +aliases_typealiastype.py:44:23 - error: Type variable "S" has no meaning in this context (reportGeneralTypeIssues) +aliases_typealiastype.py:48:35 - error: Type parameter list must be a tuple containing only TypeVar, TypeVarTuple, or ParamSpec +aliases_typealiastype.py:50:40 - error: Type alias "BadAlias4" cannot use itself in its definition (reportGeneralTypeIssues) +aliases_typealiastype.py:52:18 - error: Type alias "BadAlias5" cannot use itself in its definition (reportGeneralTypeIssues) +aliases_typealiastype.py:54:40 - error: Type alias "BadAlias6" cannot use itself in its definition (reportGeneralTypeIssues) +aliases_typealiastype.py:58:40 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_typealiastype.py:59:40 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_typealiastype.py:59:40 - error: Expected type expression but received "list[Unknown]" (reportGeneralTypeIssues) +aliases_typealiastype.py:60:42 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_typealiastype.py:60:42 - error: Expected type expression but received "tuple[tuple[type[int], type[str]]]" (reportGeneralTypeIssues) +aliases_typealiastype.py:61:42 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_typealiastype.py:61:42 - error: Expected type expression but received "list[type[int]]" (reportGeneralTypeIssues) +aliases_typealiastype.py:62:42 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_typealiastype.py:62:42 - error: Expected type expression but received "dict[str, str]" (reportGeneralTypeIssues) +aliases_typealiastype.py:63:42 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_typealiastype.py:64:42 - error: Expected type expression but received "list[type[int]]" (reportGeneralTypeIssues) +aliases_typealiastype.py:65:42 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_typealiastype.py:66:42 - error: Expected type expression but received "int" (reportGeneralTypeIssues) +aliases_typealiastype.py:67:42 - error: Expected type expression but received "Literal[True]" (reportGeneralTypeIssues) +aliases_typealiastype.py:68:42 - error: Invalid expression form for type alias definition (reportGeneralTypeIssues) +aliases_typealiastype.py:68:42 - error: Expected type expression but received "Literal[1]" (reportGeneralTypeIssues) +aliases_typealiastype.py:70:42 - error: Expected expression +""" diff --git a/conformance/results/pyright/aliases_variance.toml b/conformance/results/pyright/aliases_variance.toml new file mode 100644 index 000000000..c933cf7cf --- /dev/null +++ b/conformance/results/pyright/aliases_variance.toml @@ -0,0 +1,11 @@ +conformant = "Pass" +output = """ +aliases_variance.py:24:23 - error: Type "T_co@ClassA_1" cannot be assigned to type variable "T@ClassA" +  Variance of type argument "T_co@ClassA_1" is incompatible with base class "ClassA" (reportGeneralTypeIssues) +aliases_variance.py:28:26 - error: Could not specialize type "A_Alias_1[T_co@A_Alias_1]" +  Variance of type argument "T_co@ClassA_2" is incompatible with "T_co@A_Alias_1" +aliases_variance.py:32:26 - error: Could not specialize type "A_Alias_2[T_co@A_Alias_2]" +  Variance of type argument "T_co@ClassA_3" is incompatible with "T_co@A_Alias_2" +aliases_variance.py:44:26 - error: Could not specialize type "B_Alias_1[T_co@B_Alias_1, T_contra@B_Alias_1]" +  Variance of type argument "T_contra@ClassB_1" is incompatible with "T_co@B_Alias_1" +""" diff --git a/conformance/results/pyright/annotations_typeexpr.toml b/conformance/results/pyright/annotations_typeexpr.toml new file mode 100644 index 000000000..f1bd93080 --- /dev/null +++ b/conformance/results/pyright/annotations_typeexpr.toml @@ -0,0 +1,29 @@ +conformant = "Pass" +output = """ +annotations_typeexpr.py:77:9 - error: Call expression not allowed in type expression (reportGeneralTypeIssues) +annotations_typeexpr.py:78:9 - error: List expression not allowed in type annotation +  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportGeneralTypeIssues) +annotations_typeexpr.py:78:9 - error: Expected type expression but received "list[Unknown]" (reportGeneralTypeIssues) +annotations_typeexpr.py:79:9 - error: Tuple expression not allowed in type annotation +  Use Tuple[T1, ..., Tn] to indicate a tuple type or Union[T1, T2] to indicate a union type (reportGeneralTypeIssues) +annotations_typeexpr.py:79:9 - error: Expected type expression but received "tuple[type[int], type[str]]" (reportGeneralTypeIssues) +annotations_typeexpr.py:80:9 - error: List expression not allowed in type annotation +  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportGeneralTypeIssues) +annotations_typeexpr.py:80:9 - error: Expected type expression but received "list[type[int]]" (reportGeneralTypeIssues) +annotations_typeexpr.py:81:9 - error: Dictionary expression not allowed in type annotation +  Use Dict[T1, T2] to indicate a dictionary type (reportGeneralTypeIssues) +annotations_typeexpr.py:81:9 - error: Expected type expression but received "dict[Unknown, Unknown]" (reportGeneralTypeIssues) +annotations_typeexpr.py:82:9 - error: Call expression not allowed in type expression (reportGeneralTypeIssues) +annotations_typeexpr.py:83:9 - error: List expression not allowed in type annotation +  Use List[T] to indicate a list type or Union[T1, T2] to indicate a union type (reportGeneralTypeIssues) +annotations_typeexpr.py:83:9 - error: Expected type expression but received "list[type[int]]" (reportGeneralTypeIssues) +annotations_typeexpr.py:84:9 - error: Ternary expression not allowed in type annotation +annotations_typeexpr.py:85:9 - error: Variable not allowed in type expression (reportGeneralTypeIssues) +annotations_typeexpr.py:86:10 - error: Expected type expression but received "Literal[True]" (reportGeneralTypeIssues) +annotations_typeexpr.py:87:10 - error: Expected type expression but received "Literal[1]" (reportGeneralTypeIssues) +annotations_typeexpr.py:88:10 - error: Unary operator not allowed in type annotation +annotations_typeexpr.py:89:10 - error: Binary operator not allowed in type annotation +annotations_typeexpr.py:90:10 - error: Expected expression +annotations_typeexpr.py:90:10 - error: Tuple expression not allowed in type annotation +  Use Tuple[T1, ..., Tn] to indicate a tuple type or Union[T1, T2] to indicate a union type (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/callables_annotation.toml b/conformance/results/pyright/callables_annotation.toml new file mode 100644 index 000000000..eac02284e --- /dev/null +++ b/conformance/results/pyright/callables_annotation.toml @@ -0,0 +1,16 @@ +conformant = "Pass" +output = """ +callables_annotation.py:13:5 - error: Expected 1 more positional argument (reportGeneralTypeIssues) +callables_annotation.py:14:11 - error: Argument of type "Literal[2]" cannot be assigned to parameter of type "str" +  "Literal[2]" is incompatible with "str" (reportGeneralTypeIssues) +callables_annotation.py:15:15 - error: Expected 2 positional arguments (reportGeneralTypeIssues) +callables_annotation.py:16:10 - error: Expected 2 more positional arguments (reportGeneralTypeIssues) +callables_annotation.py:22:8 - error: Expected 0 positional arguments (reportGeneralTypeIssues) +callables_annotation.py:39:14 - error: Expected parameter type list or "..." +callables_annotation.py:39:5 - error: Expected return type as second type argument for "Callable" (reportGeneralTypeIssues) +callables_annotation.py:40:14 - error: Expected parameter type list or "..." +callables_annotation.py:41:18 - error: List expression not allowed for this type argument +callables_annotation.py:42:14 - error: Expected parameter type list or "..." +callables_annotation.py:42:24 - error: Expected only two type arguments to "Callable" +callables_annotation.py:43:15 - error: "..." is not allowed in this context +""" diff --git a/conformance/results/pyright/callables_kwargs.toml b/conformance/results/pyright/callables_kwargs.toml new file mode 100644 index 000000000..651eee9ea --- /dev/null +++ b/conformance/results/pyright/callables_kwargs.toml @@ -0,0 +1,30 @@ +conformant = "Pass" +output = """ +callables_kwargs.py:26:5 - error: Could not access item in TypedDict +  "v2" is not a required key in "*TD2", so access may result in runtime exception (reportTypedDictNotRequiredAccess) +callables_kwargs.py:43:5 - error: Arguments missing for parameters "v1", "v3" (reportGeneralTypeIssues) +callables_kwargs.py:48:32 - error: No parameter named "v4" (reportGeneralTypeIssues) +callables_kwargs.py:49:11 - error: Expected 0 positional arguments (reportGeneralTypeIssues) +callables_kwargs.py:55:13 - error: Argument of type "str" cannot be assigned to parameter "v1" of type "int" in function "func1" +  "str" is incompatible with "int" (reportGeneralTypeIssues) +callables_kwargs.py:60:19 - error: Unable to match unpacked TypedDict argument to parameters +  Parameter "v1" is already assigned (reportGeneralTypeIssues) +callables_kwargs.py:61:16 - error: Unable to match unpacked TypedDict argument to parameters +  Parameter "v3" is already assigned (reportGeneralTypeIssues) +callables_kwargs.py:62:19 - error: Unable to match unpacked TypedDict argument to parameters +  Parameter "v1" is already assigned (reportGeneralTypeIssues) +callables_kwargs.py:98:19 - error: Expression of type "(**kwargs: **TD2) -> None" cannot be assigned to declared type "TDProtocol3" +  Type "(**kwargs: **TD2) -> None" cannot be assigned to type "(*, v1: int, v2: int, v3: str) -> None" +    Keyword parameter "v2" of type "int" cannot be assigned to type "str" +      "int" is incompatible with "str" (reportGeneralTypeIssues) +callables_kwargs.py:99:19 - error: Expression of type "(**kwargs: **TD2) -> None" cannot be assigned to declared type "TDProtocol4" +  Type "(**kwargs: **TD2) -> None" cannot be assigned to type "(*, v1: int) -> None" +    Keyword parameter "v3" is missing in destination (reportGeneralTypeIssues) +callables_kwargs.py:100:19 - error: Expression of type "(**kwargs: **TD2) -> None" cannot be assigned to declared type "TDProtocol5" +  Type "(**kwargs: **TD2) -> None" cannot be assigned to type "(v1: int, v3: str) -> None" +    Function accepts too many positional parameters; expected 0 but received 2 +      Keyword parameter "v1" is missing in destination +      Keyword parameter "v3" is missing in destination (reportGeneralTypeIssues) +callables_kwargs.py:109:30 - error: Typed dictionary overlaps with keyword parameter: v1 (reportGeneralTypeIssues) +callables_kwargs.py:121:21 - error: Expected TypedDict type argument for Unpack (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/callables_protocol.toml b/conformance/results/pyright/callables_protocol.toml new file mode 100644 index 000000000..7e548a2a7 --- /dev/null +++ b/conformance/results/pyright/callables_protocol.toml @@ -0,0 +1,59 @@ +conformant = "Partial" +notes = """ +Does not report type incompatibility for callback protocol with positional-only parameters. +""" +output = """ +callables_protocol.py:35:7 - error: Expression of type "(*vals: bytes, max_items: int | None) -> list[bytes]" cannot be assigned to declared type "Proto1" +  Type "(*vals: bytes, max_items: int | None) -> list[bytes]" cannot be assigned to type "(*vals: bytes, max_len: int | None = None) -> list[bytes]" +    Keyword parameter "max_items" is missing in destination +    Keyword parameter "max_len" is missing in source (reportGeneralTypeIssues) +callables_protocol.py:36:7 - error: Expression of type "(*vals: bytes) -> list[bytes]" cannot be assigned to declared type "Proto1" +  Type "(*vals: bytes) -> list[bytes]" cannot be assigned to type "(*vals: bytes, max_len: int | None = None) -> list[bytes]" +    Keyword parameter "max_len" is missing in source (reportGeneralTypeIssues) +callables_protocol.py:37:7 - error: Expression of type "(*vals: bytes, max_len: str | None) -> list[bytes]" cannot be assigned to declared type "Proto1" +  Type "(*vals: bytes, max_len: str | None) -> list[bytes]" cannot be assigned to type "(*vals: bytes, max_len: int | None = None) -> list[bytes]" +    Keyword parameter "max_len" of type "int | None" cannot be assigned to type "str | None" +    Parameter "max_len" is missing default argument (reportGeneralTypeIssues) +callables_protocol.py:67:7 - error: Expression of type "(*a: bytes) -> None" cannot be assigned to declared type "Proto2" +  Type "(*a: bytes) -> None" cannot be assigned to type "(*vals: bytes, **kwargs: str) -> None" +    Parameter "**kwargs" has no corresponding parameter (reportGeneralTypeIssues) +callables_protocol.py:68:7 - error: Expression of type "(*a: str, **b: str) -> None" cannot be assigned to declared type "Proto2" +  Type "(*a: str, **b: str) -> None" cannot be assigned to type "(*vals: bytes, **kwargs: str) -> None" +    Parameter 1: type "*tuple[bytes, ...]" cannot be assigned to type "*tuple[str, ...]" +      "*tuple[bytes, ...]" is incompatible with "*tuple[str, ...]" +        Tuple entry 1 is incorrect type +          "bytes" is incompatible with "str" (reportGeneralTypeIssues) +callables_protocol.py:69:7 - error: Expression of type "(*a: bytes, **b: bytes) -> None" cannot be assigned to declared type "Proto2" +  Type "(*a: bytes, **b: bytes) -> None" cannot be assigned to type "(*vals: bytes, **kwargs: str) -> None" +    Parameter 2: type "str" cannot be assigned to type "bytes" +      "str" is incompatible with "bytes" (reportGeneralTypeIssues) +callables_protocol.py:70:7 - error: Expression of type "(**b: str) -> None" cannot be assigned to declared type "Proto2" +  Type "(**b: str) -> None" cannot be assigned to type "(*vals: bytes, **kwargs: str) -> None" +    Parameter "*vals" has no corresponding parameter (reportGeneralTypeIssues) +callables_protocol.py:97:16 - error: Expression of type "(x: int) -> None" cannot be assigned to declared type "Proto4" +  "function" is incompatible with protocol "Proto4" +    "other_attribute" is not present +    "__call__" is not present (reportGeneralTypeIssues) +callables_protocol.py:121:18 - error: Expression of type "(*vals: bytes, max_len: int | None = None) -> list[bytes]" cannot be assigned to declared type "NotProto6" +  "function" is incompatible with "NotProto6" (reportGeneralTypeIssues) +callables_protocol.py:169:7 - error: Expression of type "(x: int) -> Any" cannot be assigned to declared type "Proto8" +  One or more overloads of "__call__" is not assignable +    Type "(x: int) -> Any" cannot be assigned to type "(x: str) -> str" +      Parameter 1: type "str" cannot be assigned to type "int" +        "str" is incompatible with "int" (reportGeneralTypeIssues) +callables_protocol.py:186:33 - error: Cannot assign member "other_attribute" for type "Proto9[P@decorator1, R@decorator1]" +  "Literal['str']" is incompatible with "int" (reportGeneralTypeIssues) +callables_protocol.py:187:15 - error: Cannot assign member "xxx" for type "Proto9[P@decorator1, R@decorator1]" +  Member "xxx" is unknown (reportGeneralTypeIssues) +callables_protocol.py:197:16 - error: Cannot access member "other_attribute2" for type "Proto9[(x: int), str]" +  Member "other_attribute2" is unknown (reportGeneralTypeIssues) +callables_protocol.py:260:8 - error: Expression of type "(*args: Any, kwarg0: Any) -> None" cannot be assigned to declared type "Proto12" +  Type "(*args: Any, kwarg0: Any) -> None" cannot be assigned to type "(*args: Any, kwarg0: Any, kwarg1: Any) -> None" +    Keyword parameter "kwarg1" is missing in source (reportGeneralTypeIssues) +callables_protocol.py:284:27 - error: Expression of type "(path: str) -> str" cannot be assigned to declared type "Proto13_Default" +  Type "(path: str) -> str" cannot be assigned to type "(path: str = ...) -> str" +    Parameter "path" is missing default argument (reportGeneralTypeIssues) +callables_protocol.py:311:27 - error: Expression of type "(*, path: str) -> str" cannot be assigned to declared type "Proto14_Default" +  Type "(*, path: str) -> str" cannot be assigned to type "(*, path: str = ...) -> str" +    Parameter "path" is missing default argument (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/dataclasses_descriptors.toml b/conformance/results/pyright/dataclasses_descriptors.toml new file mode 100644 index 000000000..2146548eb --- /dev/null +++ b/conformance/results/pyright/dataclasses_descriptors.toml @@ -0,0 +1,3 @@ +conformant = "Pass" +output = """ +""" diff --git a/conformance/results/pyright/dataclasses_frozen.toml b/conformance/results/pyright/dataclasses_frozen.toml new file mode 100644 index 000000000..5af00da01 --- /dev/null +++ b/conformance/results/pyright/dataclasses_frozen.toml @@ -0,0 +1,11 @@ +conformant = "Pass" +output = """ +dataclasses_frozen.py:16:5 - error: Cannot assign member "a" for type "DC1" +  "DC1" is frozen +    Member "__set__" is unknown (reportGeneralTypeIssues) +dataclasses_frozen.py:17:5 - error: Cannot assign member "b" for type "DC1" +  "DC1" is frozen +    Member "__set__" is unknown (reportGeneralTypeIssues) +dataclasses_frozen.py:22:1 - error: A non-frozen class cannot inherit from a class that is frozen (reportGeneralTypeIssues) +dataclasses_frozen.py:32:12 - error: A frozen class cannot inherit from a class that is not frozen (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/dataclasses_hash.toml b/conformance/results/pyright/dataclasses_hash.toml new file mode 100644 index 000000000..0f8dcdf8d --- /dev/null +++ b/conformance/results/pyright/dataclasses_hash.toml @@ -0,0 +1,11 @@ +conformant = "Pass" +output = """ +dataclasses_hash.py:15:16 - error: Expression of type "DC1" cannot be assigned to declared type "Hashable" +  "DC1" is incompatible with protocol "Hashable" +    "__hash__" is an incompatible type +      Type "None" cannot be assigned to type "() -> int" (reportGeneralTypeIssues) +dataclasses_hash.py:32:16 - error: Expression of type "DC3" cannot be assigned to declared type "Hashable" +  "DC3" is incompatible with protocol "Hashable" +    "__hash__" is an incompatible type +      Type "None" cannot be assigned to type "() -> int" (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/dataclasses_inheritance.toml b/conformance/results/pyright/dataclasses_inheritance.toml new file mode 100644 index 000000000..6a1dfbd25 --- /dev/null +++ b/conformance/results/pyright/dataclasses_inheritance.toml @@ -0,0 +1,5 @@ +conformant = "Pass" +output = """ +dataclasses_inheritance.py:60:5 - error: Class variable "x" overrides instance variable of same name in class "DC6" (reportIncompatibleVariableOverride) +dataclasses_inheritance.py:64:5 - error: Instance variable "y" overrides class variable of same name in class "DC6" (reportIncompatibleVariableOverride) +""" diff --git a/conformance/results/pyright/dataclasses_kwonly.toml b/conformance/results/pyright/dataclasses_kwonly.toml new file mode 100644 index 000000000..da7cd69db --- /dev/null +++ b/conformance/results/pyright/dataclasses_kwonly.toml @@ -0,0 +1,6 @@ +conformant = "Pass" +output = """ +dataclasses_kwonly.py:23:11 - error: Expected 1 positional argument (reportGeneralTypeIssues) +dataclasses_kwonly.py:38:11 - error: Expected 1 positional argument (reportGeneralTypeIssues) +dataclasses_kwonly.py:53:11 - error: Expected 1 positional argument (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/dataclasses_order.toml b/conformance/results/pyright/dataclasses_order.toml new file mode 100644 index 000000000..15f99b753 --- /dev/null +++ b/conformance/results/pyright/dataclasses_order.toml @@ -0,0 +1,4 @@ +conformant = "Pass" +output = """ +dataclasses_order.py:50:4 - error: Operator "<" not supported for types "DC1" and "DC2" (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/dataclasses_postinit.toml b/conformance/results/pyright/dataclasses_postinit.toml new file mode 100644 index 000000000..3ac995fe2 --- /dev/null +++ b/conformance/results/pyright/dataclasses_postinit.toml @@ -0,0 +1,15 @@ +conformant = "Partial" +notes = """ +Reports incorrect error for incompatible `__post_init__` method override. +""" +output = """ +dataclasses_postinit.py:19:40 - error: Dataclass __post_init__ method parameter type mismatch for field "y" +  "str" is incompatible with "int" (reportGeneralTypeIssues) +dataclasses_postinit.py:28:11 - error: Cannot access member "x" for type "DC1" +  Member "x" is an init-only field (reportGeneralTypeIssues) +dataclasses_postinit.py:29:11 - error: Cannot access member "y" for type "DC1" +  Member "y" is an init-only field (reportGeneralTypeIssues) +dataclasses_postinit.py:36:9 - error: Dataclass __post_init__ incorrect parameter count; number of InitVar fields is 2 (reportGeneralTypeIssues) +dataclasses_postinit.py:54:9 - error: Method "__post_init__" overrides class "DC3" in an incompatible manner +  Positional parameter count mismatch; base method has 2, but override has 3 (reportIncompatibleMethodOverride) +""" diff --git a/conformance/results/pyright/dataclasses_slots.toml b/conformance/results/pyright/dataclasses_slots.toml new file mode 100644 index 000000000..945605048 --- /dev/null +++ b/conformance/results/pyright/dataclasses_slots.toml @@ -0,0 +1,10 @@ +conformant = "Pass" +output = """ +dataclasses_slots.py:11:12 - error: __slots__ is already defined in class (reportGeneralTypeIssues) +dataclasses_slots.py:26:14 - error: "y" is not specified in __slots__ (reportGeneralTypeIssues) +dataclasses_slots.py:39:14 - error: "y" is not specified in __slots__ (reportGeneralTypeIssues) +dataclasses_slots.py:67:5 - error: Cannot access member "__slots__" for type "type[DC6]" +  Member "__slots__" is unknown (reportGeneralTypeIssues) +dataclasses_slots.py:70:8 - error: Cannot access member "__slots__" for type "DC6" +  Member "__slots__" is unknown (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/dataclasses_transform_class.toml b/conformance/results/pyright/dataclasses_transform_class.toml new file mode 100644 index 000000000..dc746b85e --- /dev/null +++ b/conformance/results/pyright/dataclasses_transform_class.toml @@ -0,0 +1,13 @@ +conformant = "Pass" +output = """ +dataclasses_transform_class.py:48:7 - error: A non-frozen class cannot inherit from a class that is frozen (reportGeneralTypeIssues) +dataclasses_transform_class.py:60:6 - error: Cannot assign member "id" for type "Customer1" +  "Customer1" is frozen +    Member "__set__" is unknown (reportGeneralTypeIssues) +dataclasses_transform_class.py:63:18 - error: Expected 0 positional arguments (reportGeneralTypeIssues) +dataclasses_transform_class.py:69:6 - error: Operator "<" not supported for types "Customer1" and "Customer1" (reportGeneralTypeIssues) +dataclasses_transform_class.py:79:18 - error: Expected 0 positional arguments (reportGeneralTypeIssues) +dataclasses_transform_class.py:119:6 - error: Cannot assign member "id" for type "Customer3" +  "Customer3" is frozen +    Member "__set__" is unknown (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/dataclasses_transform_field.toml b/conformance/results/pyright/dataclasses_transform_field.toml new file mode 100644 index 000000000..ac0282c38 --- /dev/null +++ b/conformance/results/pyright/dataclasses_transform_field.toml @@ -0,0 +1,5 @@ +conformant = "Pass" +output = """ +dataclasses_transform_field.py:64:16 - error: No parameter named "id" (reportGeneralTypeIssues) +dataclasses_transform_field.py:75:16 - error: Expected 0 positional arguments (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/dataclasses_transform_func.toml b/conformance/results/pyright/dataclasses_transform_func.toml new file mode 100644 index 000000000..4db9df93a --- /dev/null +++ b/conformance/results/pyright/dataclasses_transform_func.toml @@ -0,0 +1,12 @@ +conformant = "Pass" +output = """ +dataclasses_transform_func.py:57:13 - error: Cannot assign member "name" for type "Customer1" +  "Literal[3]" is incompatible with "str" (reportGeneralTypeIssues) +dataclasses_transform_func.py:61:6 - error: Operator "<" not supported for types "Customer1" and "Customer1" (reportGeneralTypeIssues) +dataclasses_transform_func.py:65:36 - error: No parameter named "salary" (reportGeneralTypeIssues) +dataclasses_transform_func.py:71:18 - error: Expected 0 positional arguments (reportGeneralTypeIssues) +dataclasses_transform_func.py:89:1 - error: A non-frozen class cannot inherit from a class that is frozen (reportGeneralTypeIssues) +dataclasses_transform_func.py:97:6 - error: Cannot assign member "id" for type "Customer3" +  "Customer3" is frozen +    Member "__set__" is unknown (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/dataclasses_transform_meta.toml b/conformance/results/pyright/dataclasses_transform_meta.toml new file mode 100644 index 000000000..a1ef23798 --- /dev/null +++ b/conformance/results/pyright/dataclasses_transform_meta.toml @@ -0,0 +1,13 @@ +conformant = "Pass" +output = """ +dataclasses_transform_meta.py:48:36 - error: A non-frozen class cannot inherit from a class that is frozen (reportGeneralTypeIssues) +dataclasses_transform_meta.py:60:6 - error: Cannot assign member "id" for type "Customer1" +  "Customer1" is frozen +    Member "__set__" is unknown (reportGeneralTypeIssues) +dataclasses_transform_meta.py:63:18 - error: Expected 0 positional arguments (reportGeneralTypeIssues) +dataclasses_transform_meta.py:70:6 - error: Operator "<" not supported for types "Customer1" and "Customer1" (reportGeneralTypeIssues) +dataclasses_transform_meta.py:80:18 - error: Expected 0 positional arguments (reportGeneralTypeIssues) +dataclasses_transform_meta.py:100:6 - error: Cannot assign member "id" for type "Customer3" +  "Customer3" is frozen +    Member "__set__" is unknown (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/dataclasses_usage.toml b/conformance/results/pyright/dataclasses_usage.toml new file mode 100644 index 000000000..35dd7e6f0 --- /dev/null +++ b/conformance/results/pyright/dataclasses_usage.toml @@ -0,0 +1,17 @@ +conformant = "Pass" +output = """ +dataclasses_usage.py:51:6 - error: Argument missing for parameter "unit_price" (reportGeneralTypeIssues) +dataclasses_usage.py:52:28 - error: Argument of type "Literal['price']" cannot be assigned to parameter "unit_price" of type "float" in function "__init__" +  "Literal['price']" is incompatible with "float" (reportGeneralTypeIssues) +dataclasses_usage.py:53:36 - error: Expected 3 positional arguments (reportGeneralTypeIssues) +dataclasses_usage.py:62:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues) +dataclasses_usage.py:68:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues) +dataclasses_usage.py:74:5 - error: Fields without default values cannot appear after fields with default values (reportGeneralTypeIssues) +dataclasses_usage.py:84:13 - error: Expected 1 positional argument (reportGeneralTypeIssues) +dataclasses_usage.py:89:36 - error: Argument of type "type[str]" cannot be assigned to parameter "default_factory" of type "() -> _T@field" in function "field" +  No overloaded function matches type "() -> int" (reportGeneralTypeIssues) +dataclasses_usage.py:127:8 - error: Expected 1 positional argument (reportGeneralTypeIssues) +dataclasses_usage.py:130:1 - error: Argument missing for parameter "y" (reportGeneralTypeIssues) +dataclasses_usage.py:179:1 - error: Expected no arguments to "DC13" constructor (reportGeneralTypeIssues) +dataclasses_usage.py:230:9 - error: Dataclass field without type annotation will cause runtime exception (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/generics_self_advanced.toml b/conformance/results/pyright/generics_self_advanced.toml new file mode 100644 index 000000000..2146548eb --- /dev/null +++ b/conformance/results/pyright/generics_self_advanced.toml @@ -0,0 +1,3 @@ +conformant = "Pass" +output = """ +""" diff --git a/conformance/results/pyright/generics_self_attributes.toml b/conformance/results/pyright/generics_self_attributes.toml new file mode 100644 index 000000000..4ef1a5877 --- /dev/null +++ b/conformance/results/pyright/generics_self_attributes.toml @@ -0,0 +1,14 @@ +conformant = "Pass" +output = """ +generics_self_attributes.py:26:38 - error: Argument of type "LinkedList[int]" cannot be assigned to parameter "next" of type "OrdinalLinkedList | None" in function "__init__" +  Type "LinkedList[int]" cannot be assigned to type "OrdinalLinkedList | None" +    "LinkedList[int]" is incompatible with "OrdinalLinkedList" +    "LinkedList[int]" is incompatible with "None" (reportGeneralTypeIssues) +generics_self_attributes.py:32:8 - error: Cannot assign member "next" for type "OrdinalLinkedList" +  Expression of type "LinkedList[int]" cannot be assigned to member "next" of class "OrdinalLinkedList" +    Member "__set__" is unknown +    Member "__set__" is unknown +    Type "LinkedList[int]" cannot be assigned to type "OrdinalLinkedList | None" +      "LinkedList[int]" is incompatible with "OrdinalLinkedList" +      "LinkedList[int]" is incompatible with "None" (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/generics_self_basic.toml b/conformance/results/pyright/generics_self_basic.toml new file mode 100644 index 000000000..8cf34c522 --- /dev/null +++ b/conformance/results/pyright/generics_self_basic.toml @@ -0,0 +1,8 @@ +conformant = "Pass" +output = """ +generics_self_basic.py:19:16 - error: Expression of type "Shape" cannot be assigned to return type "Self@Shape" +  Type "Shape" cannot be assigned to type "Self@Shape" (reportGeneralTypeIssues) +generics_self_basic.py:32:16 - error: Expression of type "Shape" cannot be assigned to return type "Self@Shape" +  Type "Shape" cannot be assigned to type "Self@Shape" (reportGeneralTypeIssues) +generics_self_basic.py:64:31 - error: Expected no type arguments for class "Self" (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/generics_self_protocols.toml b/conformance/results/pyright/generics_self_protocols.toml new file mode 100644 index 000000000..713d768ff --- /dev/null +++ b/conformance/results/pyright/generics_self_protocols.toml @@ -0,0 +1,15 @@ +conformant = "Pass" +output = """ +generics_self_protocols.py:61:19 - error: Argument of type "BadReturnType" cannot be assigned to parameter "shape" of type "ShapeProtocol" in function "accepts_shape" +  "BadReturnType" is incompatible with protocol "ShapeProtocol" +    "set_scale" is an incompatible type +      Type "(scale: float) -> int" cannot be assigned to type "(scale: float) -> BadReturnType" +        Function return type "int" is incompatible with type "BadReturnType" +          "int" is incompatible with "BadReturnType" (reportGeneralTypeIssues) +generics_self_protocols.py:64:19 - error: Argument of type "ReturnDifferentClass" cannot be assigned to parameter "shape" of type "ShapeProtocol" in function "accepts_shape" +  "ReturnDifferentClass" is incompatible with protocol "ShapeProtocol" +    "set_scale" is an incompatible type +      Type "(scale: float) -> ReturnConcreteShape" cannot be assigned to type "(scale: float) -> ReturnDifferentClass" +        Function return type "ReturnConcreteShape" is incompatible with type "ReturnDifferentClass" +          "ReturnConcreteShape" is incompatible with "ReturnDifferentClass" (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/generics_self_usage.toml b/conformance/results/pyright/generics_self_usage.toml new file mode 100644 index 000000000..d20349701 --- /dev/null +++ b/conformance/results/pyright/generics_self_usage.toml @@ -0,0 +1,19 @@ +conformant = "Pass" +output = """ +generics_self_usage.py:73:14 - error: "Self" is not valid in this context (reportGeneralTypeIssues) +generics_self_usage.py:73:23 - error: "Self" is not valid in this context (reportGeneralTypeIssues) +generics_self_usage.py:76:6 - error: "Self" is not valid in this context (reportGeneralTypeIssues) +generics_self_usage.py:82:54 - error: "Self" cannot be used in a function with a `self` or `cls` parameter that has a type annotation other than "Self" (reportGeneralTypeIssues) +generics_self_usage.py:82:44 - warning: TypeVar "TFoo2" appears only once in generic function signature +  Use "Foo2" instead (reportInvalidTypeVarUse) +generics_self_usage.py:86:16 - error: Expression of type "Foo3" cannot be assigned to return type "Self@Foo3" +  Type "Foo3" cannot be assigned to type "Self@Foo3" (reportGeneralTypeIssues) +generics_self_usage.py:101:15 - error: "Self" is not valid in this context (reportGeneralTypeIssues) +generics_self_usage.py:103:12 - error: "Self" is not valid in this context (reportGeneralTypeIssues) +generics_self_usage.py:106:30 - error: "Self" is not valid in this context (reportGeneralTypeIssues) +generics_self_usage.py:111:19 - error: "Self" is not valid in this context (reportGeneralTypeIssues) +generics_self_usage.py:116:31 - error: "Self" is not valid in this context (reportGeneralTypeIssues) +generics_self_usage.py:116:40 - error: "Self" is not valid in this context (reportGeneralTypeIssues) +generics_self_usage.py:121:37 - error: "Self" cannot be used within a metaclass (a subclass of "type") (reportGeneralTypeIssues) +generics_self_usage.py:125:42 - error: "Self" cannot be used within a metaclass (a subclass of "type") (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/literals_interactions.toml b/conformance/results/pyright/literals_interactions.toml new file mode 100644 index 000000000..203a7064d --- /dev/null +++ b/conformance/results/pyright/literals_interactions.toml @@ -0,0 +1,7 @@ +conformant = "Pass" +output = """ +literals_interactions.py:15:5 - error: Index 5 is out of range for type tuple[int, str, list[bool]] (reportGeneralTypeIssues) +literals_interactions.py:16:5 - error: Index -5 is out of range for type tuple[int, str, list[bool]] (reportGeneralTypeIssues) +literals_interactions.py:17:5 - error: Index 4 is out of range for type tuple[int, str, list[bool]] (reportGeneralTypeIssues) +literals_interactions.py:18:5 - error: Index -4 is out of range for type tuple[int, str, list[bool]] (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/literals_literalstring.toml b/conformance/results/pyright/literals_literalstring.toml new file mode 100644 index 000000000..cf5f841ca --- /dev/null +++ b/conformance/results/pyright/literals_literalstring.toml @@ -0,0 +1,25 @@ +conformant = "Pass" +output = """ +literals_literalstring.py:36:29 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_literalstring.py:37:22 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_literalstring.py:43:23 - error: Expression of type "Literal['two']" cannot be assigned to declared type "Literal['']" +  "Literal['two']" cannot be assigned to type "Literal['']" (reportGeneralTypeIssues) +literals_literalstring.py:66:25 - error: Expression of type "str" cannot be assigned to declared type "LiteralString" +  "str" is incompatible with "LiteralString" (reportGeneralTypeIssues) +literals_literalstring.py:74:25 - error: Expression of type "Literal[3]" cannot be assigned to declared type "LiteralString" +  "Literal[3]" is incompatible with "LiteralString" (reportGeneralTypeIssues) +literals_literalstring.py:75:25 - error: Expression of type "Literal[b"test"]" cannot be assigned to declared type "LiteralString" +  "Literal[b"test"]" is incompatible with "LiteralString" (reportGeneralTypeIssues) +literals_literalstring.py:120:22 - error: Argument of type "str" cannot be assigned to parameter "s" of type "TLiteral@literal_identity" in function "literal_identity" +  Type "str" cannot be assigned to type "LiteralString" +    "str" is incompatible with "LiteralString" (reportGeneralTypeIssues) +literals_literalstring.py:134:51 - error: Argument of type "str" cannot be assigned to parameter "value" of type "T@Container" in function "__init__" +  Type "str" cannot be assigned to type "LiteralString" +    "str" is incompatible with "LiteralString" (reportGeneralTypeIssues) +literals_literalstring.py:142:5 - error: Overload 1 for "func8" overlaps overload 2 and returns an incompatible type (reportOverlappingOverload) +literals_literalstring.py:142:5 - error: Overload 1 for "func8" overlaps overload 3 and returns an incompatible type (reportOverlappingOverload) +literals_literalstring.py:166:21 - error: Expression of type "list[LiteralString]" cannot be assigned to declared type "list[str]" +  "list[LiteralString]" is incompatible with "list[str]" +    Type parameter "_T@list" is invariant, but "LiteralString" is not the same as "str" +    Consider switching from "list" to "Sequence" which is covariant (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/literals_parameterizations.toml b/conformance/results/pyright/literals_parameterizations.toml new file mode 100644 index 000000000..3ed2765d2 --- /dev/null +++ b/conformance/results/pyright/literals_parameterizations.toml @@ -0,0 +1,21 @@ +conformant = "Pass" +output = """ +literals_parameterizations.py:40:15 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:41:15 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:42:15 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:43:15 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:44:15 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:45:15 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:46:15 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:47:15 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:48:15 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:49:16 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:50:16 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:51:16 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:52:16 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:55:28 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:58:4 - error: "Literal" cannot be used in this context without a type argument +literals_parameterizations.py:59:12 - error: Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value +literals_parameterizations.py:63:32 - error: Expression of type "Literal[Color.RED]" cannot be assigned to declared type "Literal['Color.RED']" +  "Literal[Color.RED]" cannot be assigned to type "Literal['Color.RED']" (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/literals_semantics.toml b/conformance/results/pyright/literals_semantics.toml new file mode 100644 index 000000000..e9e40a1ee --- /dev/null +++ b/conformance/results/pyright/literals_semantics.toml @@ -0,0 +1,10 @@ +conformant = "Pass" +output = """ +literals_semantics.py:10:18 - error: Expression of type "Literal[4]" cannot be assigned to declared type "Literal[3]" +  "Literal[4]" cannot be assigned to type "Literal[3]" (reportGeneralTypeIssues) +literals_semantics.py:24:26 - error: Expression of type "Literal[0]" cannot be assigned to declared type "Literal[False]" +  "Literal[0]" cannot be assigned to type "Literal[False]" (reportGeneralTypeIssues) +literals_semantics.py:25:22 - error: Expression of type "Literal[False]" cannot be assigned to declared type "Literal[0]" +  "Literal[False]" cannot be assigned to type "Literal[0]" (reportGeneralTypeIssues) +literals_semantics.py:33:10 - error: Expression of type "Literal[6, 7, 8]" cannot be assigned to declared type "Literal[3, 4, 5]" (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/narrowing_typeguard.toml b/conformance/results/pyright/narrowing_typeguard.toml new file mode 100644 index 000000000..8ad960539 --- /dev/null +++ b/conformance/results/pyright/narrowing_typeguard.toml @@ -0,0 +1,5 @@ +conformant = "Pass" +output = """ +narrowing_typeguard.py:102:9 - error: User-defined type guard functions and methods must have at least one input parameter (reportGeneralTypeIssues) +narrowing_typeguard.py:107:9 - error: User-defined type guard functions and methods must have at least one input parameter (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/typeddicts_alt_syntax.toml b/conformance/results/pyright/typeddicts_alt_syntax.toml new file mode 100644 index 000000000..12142faae --- /dev/null +++ b/conformance/results/pyright/typeddicts_alt_syntax.toml @@ -0,0 +1,9 @@ +conformant = "Pass" +output = """ +typeddicts_alt_syntax.py:23:17 - error: Expected dict or keyword parameter as second parameter +typeddicts_alt_syntax.py:27:45 - error: Expected string literal for dictionary entry name +typeddicts_alt_syntax.py:31:1 - error: TypedDict must be assigned to a variable named "WrongName" +typeddicts_alt_syntax.py:35:78 - error: Extra TypedDict arguments not supported +typeddicts_alt_syntax.py:45:43 - error: Expression of type "dict[str, str]" cannot be assigned to declared type "Movie2" +  "Literal['']" is incompatible with "int" (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/typeddicts_class_syntax.toml b/conformance/results/pyright/typeddicts_class_syntax.toml new file mode 100644 index 000000000..96b9e5518 --- /dev/null +++ b/conformance/results/pyright/typeddicts_class_syntax.toml @@ -0,0 +1,8 @@ +conformant = "Pass" +output = """ +typeddicts_class_syntax.py:29:5 - error: TypedDict classes can contain only type annotations +typeddicts_class_syntax.py:33:5 - error: TypedDict classes can contain only type annotations +typeddicts_class_syntax.py:38:5 - error: TypedDict classes can contain only type annotations +typeddicts_class_syntax.py:44:32 - error: TypedDict does not support __init_subclass__ parameter "metaclass" +typeddicts_class_syntax.py:49:32 - error: TypedDict does not support __init_subclass__ parameter "other" +""" diff --git a/conformance/results/pyright/typeddicts_final.toml b/conformance/results/pyright/typeddicts_final.toml new file mode 100644 index 000000000..2146548eb --- /dev/null +++ b/conformance/results/pyright/typeddicts_final.toml @@ -0,0 +1,3 @@ +conformant = "Pass" +output = """ +""" diff --git a/conformance/results/pyright/typeddicts_inheritance.toml b/conformance/results/pyright/typeddicts_inheritance.toml new file mode 100644 index 000000000..d0470b408 --- /dev/null +++ b/conformance/results/pyright/typeddicts_inheritance.toml @@ -0,0 +1,9 @@ +conformant = "Pass" +output = """ +typeddicts_inheritance.py:44:7 - error: All base classes for TypedDict classes must also be TypedDict classes +  Class "NonTypedDict" is not a TypedDict +typeddicts_inheritance.py:55:4 - error: "x" overrides symbol of same name in class "X1" +  Variable is mutable so its type is invariant +    Override type "int" is not the same as base type "str" (reportIncompatibleVariableOverride) +typeddicts_inheritance.py:65:7 - error: Base classes for class "XYZ2" define variable "x" in incompatible way (reportIncompatibleVariableOverride) +""" diff --git a/conformance/results/pyright/typeddicts_operations.toml b/conformance/results/pyright/typeddicts_operations.toml new file mode 100644 index 000000000..cba0f0d79 --- /dev/null +++ b/conformance/results/pyright/typeddicts_operations.toml @@ -0,0 +1,24 @@ +conformant = "Pass" +output = """ +typeddicts_operations.py:22:1 - error: Could not assign item in TypedDict +  "Literal[1982]" is incompatible with "str" (reportGeneralTypeIssues) +typeddicts_operations.py:23:1 - error: Could not assign item in TypedDict +  "Literal['']" is incompatible with "int" (reportGeneralTypeIssues) +typeddicts_operations.py:24:1 - error: Could not assign item in TypedDict +  "other" is not a defined key in "Movie" (reportGeneralTypeIssues) +typeddicts_operations.py:26:7 - error: Could not access item in TypedDict +  "other" is not a defined key in "Movie" (reportGeneralTypeIssues) +typeddicts_operations.py:28:9 - error: Expression of type "dict[str, str]" cannot be assigned to declared type "Movie" +  "year" is required in "Movie" (reportGeneralTypeIssues) +typeddicts_operations.py:29:42 - error: Expression of type "dict[str, str | float]" cannot be assigned to declared type "Movie" +  "float" is incompatible with "int" (reportGeneralTypeIssues) +typeddicts_operations.py:32:36 - error: Expression of type "dict[str, str | int]" cannot be assigned to declared type "Movie" +  "other" is an undefined field in type "Movie" (reportGeneralTypeIssues) +typeddicts_operations.py:37:20 - error: Expression of type "dict[str, str | int]" cannot be assigned to declared type "Movie" (reportGeneralTypeIssues) +typeddicts_operations.py:47:7 - error: Cannot access member "clear" for type "Movie" +  Member "clear" is unknown (reportGeneralTypeIssues) +typeddicts_operations.py:49:5 - error: Could not delete item in TypedDict +  "name" is a required key and cannot be deleted (reportGeneralTypeIssues) +typeddicts_operations.py:62:16 - error: Cannot access member "clear" for type "MovieOptional" +  Member "clear" is unknown (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/typeddicts_required.toml b/conformance/results/pyright/typeddicts_required.toml new file mode 100644 index 000000000..55fc83dad --- /dev/null +++ b/conformance/results/pyright/typeddicts_required.toml @@ -0,0 +1,7 @@ +conformant = "Pass" +output = """ +typeddicts_required.py:12:8 - error: "Required" is not allowed in this context +typeddicts_required.py:16:8 - error: "NotRequired" is not allowed in this context +typeddicts_required.py:59:8 - error: "Required" is not allowed in this context +typeddicts_required.py:60:8 - error: "Required" is not allowed in this context +""" diff --git a/conformance/results/pyright/typeddicts_type_consistency.toml b/conformance/results/pyright/typeddicts_type_consistency.toml new file mode 100644 index 000000000..91b110b02 --- /dev/null +++ b/conformance/results/pyright/typeddicts_type_consistency.toml @@ -0,0 +1,25 @@ +conformant = "Pass" +output = """ +typeddicts_type_consistency.py:21:10 - error: Expression of type "B1" cannot be assigned to declared type "A1" +  "x" is an incompatible type +    Type "int" cannot be assigned to type "int | None" +      "int" is incompatible with "None" (reportGeneralTypeIssues) +typeddicts_type_consistency.py:38:10 - error: Expression of type "B2" cannot be assigned to declared type "A2" +  "x" is not required in "type[A2]" (reportGeneralTypeIssues) +typeddicts_type_consistency.py:65:6 - error: Expression of type "A3" cannot be assigned to declared type "B3" +  "y" is missing from "type[A3]" (reportGeneralTypeIssues) +typeddicts_type_consistency.py:69:21 - error: Expression of type "dict[str, int]" cannot be assigned to declared type "A3" +  "y" is an undefined field in type "A3" (reportGeneralTypeIssues) +typeddicts_type_consistency.py:76:22 - error: Expression of type "B3" cannot be assigned to declared type "dict[str, int]" +  "B3" is incompatible with "dict[str, int]" (reportGeneralTypeIssues) +typeddicts_type_consistency.py:77:25 - error: Expression of type "B3" cannot be assigned to declared type "dict[str, object]" +  "B3" is incompatible with "dict[str, object]" (reportGeneralTypeIssues) +typeddicts_type_consistency.py:78:22 - error: Expression of type "B3" cannot be assigned to declared type "dict[Any, Any]" +  "B3" is incompatible with "dict[Any, Any]" (reportGeneralTypeIssues) +typeddicts_type_consistency.py:82:25 - error: Expression of type "B3" cannot be assigned to declared type "Mapping[str, int]" +  "B3" is incompatible with "Mapping[str, int]" +    Type parameter "_VT_co@Mapping" is covariant, but "object" is not a subtype of "int" +      "object" is incompatible with "int" (reportGeneralTypeIssues) +typeddicts_type_consistency.py:124:56 - error: Expression of type "dict[str, dict[str, dict[str, int]]]" cannot be assigned to declared type "Outer1" +  "Literal[1]" is incompatible with "str" (reportGeneralTypeIssues) +""" diff --git a/conformance/results/pyright/typeddicts_usage.toml b/conformance/results/pyright/typeddicts_usage.toml new file mode 100644 index 000000000..d8894115b --- /dev/null +++ b/conformance/results/pyright/typeddicts_usage.toml @@ -0,0 +1,12 @@ +conformant = "Pass" +output = """ +typeddicts_usage.py:23:1 - error: Could not assign item in TypedDict +  "director" is not a defined key in "Movie" (reportGeneralTypeIssues) +typeddicts_usage.py:24:1 - error: Could not assign item in TypedDict +  "Literal['1982']" is incompatible with "int" (reportGeneralTypeIssues) +typeddicts_usage.py:28:18 - error: Expression of type "dict[str, str | int]" cannot be assigned to declared type "Movie" +  "title" is an undefined field in type "Movie" (reportGeneralTypeIssues) +typeddicts_usage.py:35:22 - error: Second argument to "isinstance" must be a class or tuple of classes +  TypedDict class not allowed for instance or class checks (reportGeneralTypeIssues) +typeddicts_usage.py:40:24 - error: "TypedDict" cannot be used in this context +""" diff --git a/conformance/results/pyright/version.toml b/conformance/results/pyright/version.toml new file mode 100644 index 000000000..281a67b40 --- /dev/null +++ b/conformance/results/pyright/version.toml @@ -0,0 +1,2 @@ +version = "pyright 1.1.343" +test_duration = 1.0995278358459473 diff --git a/conformance/results/pytype/aliases_explicit.toml b/conformance/results/pytype/aliases_explicit.toml new file mode 100644 index 000000000..f40717d66 --- /dev/null +++ b/conformance/results/pytype/aliases_explicit.toml @@ -0,0 +1,48 @@ +conformant = "Partial" +notes = """ +Incorrectly reports error for type alias defined with ParamSpec. +Does not report invalid specialization of generic type alias with bound TypeVar. +Incorrectly evaluates generic type alias with ParamSpec with missing type argument. +Does not report some illegal annotation forms as invalid type aliases. +Does not report invalid specialization of already-specialized generic type alias. +""" +output = """ +File "aliases_explicit.py", line 41, in : Invalid type annotation 'Callable[Concatenate[int, P], R][[str, str], None]' [invalid-annotation] + Callable[Concatenate[int, P], R] expected 1 parameter, got 2 +File "aliases_explicit.py", line 41, in : Invalid type annotation '[str, str]' [invalid-annotation] + Not a type +File "aliases_explicit.py", line 57, in good_type_aliases: Callable[Concatenate, Any] [assert-type] + Expected: Callable[[int, str, str], None] + Actual: Callable[Concatenate, Any] +File "aliases_explicit.py", line 60, in good_type_aliases: Callable[[Any], None] [assert-type] + Expected: Callable[..., None] + Actual: Callable[[Any], None] +File "aliases_explicit.py", line 67, in : Invalid type annotation 'Optional[int][int]' [invalid-annotation] + Optional[int] expected 0 parameters, got 1 +File "aliases_explicit.py", line 68, in : Invalid type annotation 'List[Optional[int]][int]' [invalid-annotation] + List[Optional[int]] expected 0 parameters, got 1 +File "aliases_explicit.py", line 69, in : Invalid type annotation 'List[T][int, int]' [invalid-annotation] + List[T] expected 1 parameter, got 2 +File "aliases_explicit.py", line 70, in : Invalid type annotation 'Callable[[int, T], T][int, int]' [invalid-annotation] + Callable[[int, T], T] expected 1 parameter, got 2 +File "aliases_explicit.py", line 71, in : Invalid type annotation 'Callable[Concatenate[int, P], R][int, int]' [invalid-annotation] + Callable[Concatenate[int, P], R] expected 1 parameter, got 2 +File "aliases_explicit.py", line 80, in : Invalid type annotation '[int, str]' for BadTypeAlias2 [invalid-annotation] + Not a type +File "aliases_explicit.py", line 81, in : Invalid type annotation '((int, str),)' for BadTypeAlias3 [invalid-annotation] + Not a type +File "aliases_explicit.py", line 82, in : Invalid type annotation '' for BadTypeAlias4 [invalid-annotation] + Not a type +File "aliases_explicit.py", line 83, in : Invalid type annotation "{'a': 'b'}" for BadTypeAlias5 [invalid-annotation] + Not a type +File "aliases_explicit.py", line 87, in : Invalid type annotation '3' for BadTypeAlias9 [invalid-annotation] + Not a type +File "aliases_explicit.py", line 88, in : Invalid type annotation 'True' for BadTypeAlias10 [invalid-annotation] + Not a type +File "aliases_explicit.py", line 89, in : Invalid type annotation '1' for BadTypeAlias11 [invalid-annotation] + Not a type +File "aliases_explicit.py", line 91, in : Invalid type annotation '' for BadTypeAlias13 [invalid-annotation] + Must be constant +File "aliases_explicit.py", line 102, in : Invalid type annotation 'Union[list, set][int]' [invalid-annotation] + Union[list, set] expected 0 parameters, got 1 +""" diff --git a/conformance/results/pytype/aliases_implicit.toml b/conformance/results/pytype/aliases_implicit.toml new file mode 100644 index 000000000..bf73de15f --- /dev/null +++ b/conformance/results/pytype/aliases_implicit.toml @@ -0,0 +1,46 @@ +conformant = "Partial" +notes = """ +Incorrectly reports error for type alias defined with ParamSpec. +Does not report invalid specialization of generic type alias with bound TypeVar. +Incorrectly evaluates generic type alias with ParamSpec with missing type argument. +Allows some illegal annotation forms to be interpreted as valid type aliases. +Does not report invalid specialization of already-specialized generic type alias. +""" +output = """ +File "aliases_implicit.py", line 54, in : Invalid type annotation 'Callable[Concatenate[int, P], R][[str, str], None]' [invalid-annotation] + Callable[Concatenate[int, P], R] expected 1 parameter, got 2 +File "aliases_implicit.py", line 54, in : Invalid type annotation '[str, str]' [invalid-annotation] + Not a type +File "aliases_implicit.py", line 68, in good_type_aliases: Callable[Concatenate, Any] [assert-type] + Expected: Callable[[int, str, str], None] + Actual: Callable[Concatenate, Any] +File "aliases_implicit.py", line 72, in good_type_aliases: Callable[[Any], None] [assert-type] + Expected: Callable[..., None] + Actual: Callable[[Any], None] +File "aliases_implicit.py", line 76, in : Invalid type annotation 'Optional[int][int]' [invalid-annotation] + Optional[int] expected 0 parameters, got 1 +File "aliases_implicit.py", line 77, in : Invalid type annotation 'List[Optional[int]][int]' [invalid-annotation] + List[Optional[int]] expected 0 parameters, got 1 +File "aliases_implicit.py", line 78, in : Invalid type annotation 'List[T][int, int]' [invalid-annotation] + List[T] expected 1 parameter, got 2 +File "aliases_implicit.py", line 79, in : Invalid type annotation 'Callable[[int, T], T][int, int]' [invalid-annotation] + Callable[[int, T], T] expected 1 parameter, got 2 +File "aliases_implicit.py", line 80, in : Invalid type annotation 'Callable[Concatenate[int, P], R][int, int]' [invalid-annotation] + Callable[Concatenate[int, P], R] expected 1 parameter, got 2 +File "aliases_implicit.py", line 105, in : Invalid type annotation '[int, str]' for p2 [invalid-annotation] + Not a type +File "aliases_implicit.py", line 105, in : Invalid type annotation '((int, str),)' for p3 [invalid-annotation] + Not a type +File "aliases_implicit.py", line 105, in : Invalid type annotation '' for p4 [invalid-annotation] + Not a type +File "aliases_implicit.py", line 105, in : Invalid type annotation "{'a': 'b'}" for p5 [invalid-annotation] + Not a type +File "aliases_implicit.py", line 105, in : Invalid type annotation '3' for p9 [invalid-annotation] + Not a type +File "aliases_implicit.py", line 105, in : Invalid type annotation 'True' for p10 [invalid-annotation] + Not a type +File "aliases_implicit.py", line 105, in : Invalid type annotation '1' for p11 [invalid-annotation] + Not a type +File "aliases_implicit.py", line 135, in : Invalid type annotation 'Union[list, set][int]' [invalid-annotation] + Union[list, set] expected 0 parameters, got 1 +""" diff --git a/conformance/results/pytype/aliases_newtype.toml b/conformance/results/pytype/aliases_newtype.toml new file mode 100644 index 000000000..b93e257df --- /dev/null +++ b/conformance/results/pytype/aliases_newtype.toml @@ -0,0 +1,24 @@ +conformant = "Partial" +notes = """ +Does not reject use of NewType in `isinstance` call. +Does not reject use of NewType in class definition statement. +Does not report inconsistency between name of NewType and assigned identifier name. +Does not reject use of NewType with generic class with TypeVar. +Does not reject use of NewType with protocol class. +Does not reject use of NewType with TypedDict class. +Does not reject use of NewType with another NewType. +Does not reject use of NewType with Any. +""" +output = """ +File "aliases_newtype.py", line 11, in : Function UserId.__init__ was called with the wrong arguments [wrong-arg-types] + Expected: (self, val: int) + Actually passed: (self, val: str) +File "aliases_newtype.py", line 12, in : Type annotation for u1 does not match type of assignment [annotation-type-mismatch] + Annotation: UserId + Assignment: int +File "aliases_newtype.py", line 36, in : class GoodNewType1 is not indexable [not-indexable] + ('GoodNewType1' does not subclass Generic) +File "aliases_newtype.py", line 60, in : Function typing.NewType expects 2 arg(s), got 3 [wrong-arg-count] + Expected: (name, tp) + Actually passed: (name, tp, _) +""" diff --git a/conformance/results/pytype/aliases_recursive.toml b/conformance/results/pytype/aliases_recursive.toml new file mode 100644 index 000000000..6009ddb60 --- /dev/null +++ b/conformance/results/pytype/aliases_recursive.toml @@ -0,0 +1,59 @@ +conformant = "Partial" +notes = """ +Does not detect type violation for some deeply-nested types. +Does not properly handle `|` for unions in some recursive type alias definitions. +Does not detect cyclical references in recursive type alias definition. +""" +output = """ +File "aliases_recursive.py", line 19, in : Type annotation for j4 does not match type of assignment [annotation-type-mismatch] + Annotation: Optional[Union[Dict[str, Json], List[Json], float, int, str]] + Assignment: Dict[str, Union[complex, int]] +File "aliases_recursive.py", line 20, in : Type annotation for j5 does not match type of assignment [annotation-type-mismatch] + Annotation: Optional[Union[Dict[str, Json], List[Json], float, int, str]] + Assignment: List[Union[complex, int]] +File "aliases_recursive.py", line 38, in : Type annotation for t6 does not match type of assignment [annotation-type-mismatch] + Annotation: Union[Tuple[RecursiveTuple, ...], Union[int, str]] + Assignment: Tuple[int, Tuple[str, int], Tuple[int, Tuple[int, List[int]]]] +File "aliases_recursive.py", line 39, in : Type annotation for t6 does not match type of assignment [annotation-type-mismatch] + Annotation: Union[Tuple[RecursiveTuple, ...], Union[int, str]] + Assignment: Tuple[int, List[int]] +File "aliases_recursive.py", line 50, in : Type annotation for m7 does not match type of assignment [annotation-type-mismatch] + Annotation: Union[Mapping[str, RecursiveMapping], Union[int, str]] + Assignment: Dict[str, List[int]] + Attributes of protocol Mapping[str, RecursiveMapping] are not implemented on list: get, items, keys, values +File "aliases_recursive.py", line 51, in : Type annotation for m8 does not match type of assignment [annotation-type-mismatch] + Annotation: Union[Mapping[str, RecursiveMapping], Union[int, str]] + Assignment: Dict[str, Union[List[int], int, str]] + Attributes of protocol Mapping[str, RecursiveMapping] are not implemented on list: get, items, keys, values +File "aliases_recursive.py", line 62, in : unsupported operand type(s) for |: ''GenericTypeAlias1[T1]': str' and 'T1: TypeVar' [unsupported-operands] + No attribute '__or__' on ''GenericTypeAlias1[T1]': str' or '__ror__' on 'T1: TypeVar' +File "aliases_recursive.py", line 63, in : Invalid type annotation 'list[str]' [invalid-annotation] + list expected 0 parameters, got 1 +File "aliases_recursive.py", line 66, in : Invalid type annotation 'GenericTypeAlias1[str]' [invalid-annotation] + Invalid type annotation 'list[str]' + list expected 0 parameters, got 1 +File "aliases_recursive.py", line 66, in : Invalid type annotation 'list[str]' [invalid-annotation] + list expected 0 parameters, got 1 +File "aliases_recursive.py", line 67, in : Invalid type annotation 'GenericTypeAlias1[str]' [invalid-annotation] + Invalid type annotation 'list[str]' + list expected 0 parameters, got 1 +File "aliases_recursive.py", line 67, in : Invalid type annotation 'list[str]' [invalid-annotation] + list expected 0 parameters, got 1 +File "aliases_recursive.py", line 69, in : unsupported operand type(s) for |: ''GenericTypeAlias2[T1, T2]': str' and 'T1: TypeVar' [unsupported-operands] + No attribute '__or__' on ''GenericTypeAlias2[T1, T2]': str' or '__ror__' on 'T1: TypeVar' +File "aliases_recursive.py", line 71, in : Invalid type annotation 'GenericTypeAlias2[str, int]' [invalid-annotation] + Invalid type annotation 'list[str, int]' + list expected 1 parameter, got 2 +File "aliases_recursive.py", line 71, in : Invalid type annotation 'list[str, int]' [invalid-annotation] + list expected 1 parameter, got 2 +File "aliases_recursive.py", line 72, in : Invalid type annotation 'GenericTypeAlias2[str, float]' [invalid-annotation] + Invalid type annotation 'list[str, float]' + list expected 1 parameter, got 2 +File "aliases_recursive.py", line 72, in : Invalid type annotation 'list[str, float]' [invalid-annotation] + list expected 1 parameter, got 2 +File "aliases_recursive.py", line 73, in : Invalid type annotation 'GenericTypeAlias2[str, int]' [invalid-annotation] + Invalid type annotation 'list[str, int]' + list expected 1 parameter, got 2 +File "aliases_recursive.py", line 73, in : Invalid type annotation 'list[str, int]' [invalid-annotation] + list expected 1 parameter, got 2 +""" diff --git a/conformance/results/pytype/aliases_type_statement.toml b/conformance/results/pytype/aliases_type_statement.toml new file mode 100644 index 000000000..49c698731 --- /dev/null +++ b/conformance/results/pytype/aliases_type_statement.toml @@ -0,0 +1,7 @@ +conformant = "Unsupported" +notes = """ +Does not support `type` statement. +""" +output = """ +File "aliases_type_statement.py", line 8: Type statement is only supported in Python 3.12 and greater [python-compiler-error] +""" diff --git a/conformance/results/pytype/aliases_typealiastype.toml b/conformance/results/pytype/aliases_typealiastype.toml new file mode 100644 index 000000000..ca246c9ea --- /dev/null +++ b/conformance/results/pytype/aliases_typealiastype.toml @@ -0,0 +1,18 @@ +conformant = "Unsupported" +notes = """ +Support for TypeAliasType is not implemented. +""" +output = """ +File "aliases_typealiastype.py", line 5, in : Can't find module 'typing.TypeAliasType'. [import-error] +File "aliases_typealiastype.py", line 5, in : typing.TypeVarTuple not supported yet [not-supported-yet] +File "aliases_typealiastype.py", line 11, in : Function TypeVarTuple.__init__ expects 1 arg(s), got 2 [wrong-arg-count] + Expected: (self) + Actually passed: (self, _) +File "aliases_typealiastype.py", line 19, in : Name 'GoodAlias4' is not defined [name-error] +File "aliases_typealiastype.py", line 22, in : Name 'GoodAlias5' is not defined [name-error] +File "aliases_typealiastype.py", line 22, in : Invalid type annotation '' [invalid-annotation] + Not a type +File "aliases_typealiastype.py", line 50, in : Name 'BadAlias4' is not defined [name-error] +File "aliases_typealiastype.py", line 52, in : Name 'BadAlias5' is not defined [name-error] +File "aliases_typealiastype.py", line 54, in : Name 'BadAlias7' is not defined [name-error] +""" diff --git a/conformance/results/pytype/aliases_variance.toml b/conformance/results/pytype/aliases_variance.toml new file mode 100644 index 000000000..4d08ba023 --- /dev/null +++ b/conformance/results/pytype/aliases_variance.toml @@ -0,0 +1,8 @@ +conformant = "Unsupported" +notes = """ +Does not detect variance incompatibility. +""" +output = """ +File "aliases_variance.py", line 9, in : argument "covariant" to TypeVar not supported yet [not-supported-yet] +File "aliases_variance.py", line 10, in : argument "contravariant" to TypeVar not supported yet [not-supported-yet] +""" diff --git a/conformance/results/pytype/annotations_typeexpr.toml b/conformance/results/pytype/annotations_typeexpr.toml new file mode 100644 index 000000000..6b91be0f3 --- /dev/null +++ b/conformance/results/pytype/annotations_typeexpr.toml @@ -0,0 +1,26 @@ +conformant = "Partial" +notes = """ +Does not reject call expressions in type annotation. +Does not reject call lambda expression in type annotation. +Does not reject list expression in type annotation. +Does not reject ternary expression in type annotation. +Does not reject f-string in type annotation. +""" +output = """ +File "annotations_typeexpr.py", line 76, in : Invalid type annotation '[int, str]' for p2 [invalid-annotation] + Not a type +File "annotations_typeexpr.py", line 76, in : Invalid type annotation '(int, str)' for p3 [invalid-annotation] + Not a type +File "annotations_typeexpr.py", line 76, in : Invalid type annotation '' for p4 [invalid-annotation] + Not a type +File "annotations_typeexpr.py", line 76, in : Invalid type annotation '{}' for p5 [invalid-annotation] + Not a type +File "annotations_typeexpr.py", line 76, in : Invalid type annotation '3' for p9 [invalid-annotation] + Not a type +File "annotations_typeexpr.py", line 76, in : Invalid type annotation 'True' for p10 [invalid-annotation] + Not a type +File "annotations_typeexpr.py", line 76, in : Invalid type annotation '1' for p11 [invalid-annotation] + Not a type +File "annotations_typeexpr.py", line 76, in : Invalid type annotation '-1' for p12 [invalid-annotation] + Not a type +""" diff --git a/conformance/results/pytype/callables_annotation.toml b/conformance/results/pytype/callables_annotation.toml new file mode 100644 index 000000000..b83d24273 --- /dev/null +++ b/conformance/results/pytype/callables_annotation.toml @@ -0,0 +1,32 @@ +conformant = "Pass" +output = """ +File "callables_annotation.py", line 13, in func1: Function expects 2 arg(s), got 1 [wrong-arg-count] + Expected: (_, _) + Actually passed: (_) +File "callables_annotation.py", line 14, in func1: Function was called with the wrong arguments [wrong-arg-types] + Expected: (_, _1: str) + Actually passed: (_, _1: int) +File "callables_annotation.py", line 15, in func1: Function expects 2 arg(s), got 3 [wrong-arg-count] + Expected: (_, _) + Actually passed: (_, _, _) +File "callables_annotation.py", line 16, in func1: Invalid keyword arguments (a, b) to function [wrong-keyword-args] + Expected: (_, _) + Actually passed: (a, b) +File "callables_annotation.py", line 22, in func2: Function expects 0 arg(s), got 1 [wrong-arg-count] + Expected: () + Actually passed: (_) +File "callables_annotation.py", line 39, in : Invalid type annotation 'int' [invalid-annotation] + First argument to Callable must be a list of argument types or ellipsis. +File "callables_annotation.py", line 39, in : Invalid type annotation 'Callable[Any]' [invalid-annotation] + Callable[_ARGS, _RET] expected 2 parameters, got 1 +File "callables_annotation.py", line 40, in : Invalid type annotation 'int' [invalid-annotation] + First argument to Callable must be a list of argument types or ellipsis. +File "callables_annotation.py", line 41, in : Invalid type annotation '[int]' [invalid-annotation] + Not a type +File "callables_annotation.py", line 42, in : Invalid type annotation 'int' [invalid-annotation] + First argument to Callable must be a list of argument types or ellipsis. +File "callables_annotation.py", line 42, in : Invalid type annotation 'Callable[Any, int, int]' [invalid-annotation] + Callable[_ARGS, _RET] expected 2 parameters, got 3 +File "callables_annotation.py", line 43, in : Invalid type annotation 'Ellipsis' [invalid-annotation] + Not allowed at index 0 in list +""" diff --git a/conformance/results/pytype/callables_kwargs.toml b/conformance/results/pytype/callables_kwargs.toml new file mode 100644 index 000000000..c7a2086f8 --- /dev/null +++ b/conformance/results/pytype/callables_kwargs.toml @@ -0,0 +1,48 @@ +conformant = "Unsupported" +notes = """ +Does not understand Unpack in the context of **kwargs annotation. +""" +output = """ +File "callables_kwargs.py", line 10, in : typing.NotRequired not supported yet [not-supported-yet] +File "callables_kwargs.py", line 10, in : typing.Required not supported yet [not-supported-yet] +File "callables_kwargs.py", line 10, in : typing.Unpack not supported yet [not-supported-yet] +File "callables_kwargs.py", line 24, in func1: Unpack[TD2] [assert-type] + Expected: int + Actual: Unpack[TD2] +File "callables_kwargs.py", line 30, in func1: Unpack[TD2] [assert-type] + Expected: str + Actual: Unpack[TD2] +File "callables_kwargs.py", line 33, in func1: Unpack[TD2] [assert-type] + Expected: str + Actual: Unpack[TD2] +File "callables_kwargs.py", line 39, in func2: Dict[str, Unpack[TD1]] [assert-type] + Expected: TD1 + Actual: Dict[str, Unpack[TD1]] +File "callables_kwargs.py", line 44, in func3: Function func1 was called with the wrong arguments [wrong-arg-types] + Expected: (v1: Unpack[TD2], ...) + Actually passed: (v1: int, ...) +File "callables_kwargs.py", line 46, in func3: Function TD2.__init__ was called with the wrong arguments [wrong-arg-types] + Expected: (*, v1: Required[int], ...) + Actually passed: (v1: int, ...) +File "callables_kwargs.py", line 48, in func3: Function func1 was called with the wrong arguments [wrong-arg-types] + Expected: (v1: Unpack[TD2], ...) + Actually passed: (v1: int, ...) +File "callables_kwargs.py", line 49, in func3: Function func1 expects 0 arg(s), got 3 [wrong-arg-count] + Expected: (**kwargs) + Actually passed: (_, _, _) +File "callables_kwargs.py", line 55, in func3: Function func1 was called with the wrong arguments [wrong-arg-types] + Expected: (**kwargs: Mapping[str, Unpack[TD2]]) + Actually passed: (kwargs: Dict[str, str]) +File "callables_kwargs.py", line 58, in func3: Function func1 was called with the wrong arguments [wrong-arg-types] + Expected: (v1: Unpack[TD2], ...) + Actually passed: (v1: int, ...) +File "callables_kwargs.py", line 60, in func3: Function func1 was called with the wrong arguments [wrong-arg-types] + Expected: (v1: Unpack[TD2], ...) + Actually passed: (v1: int, ...) +File "callables_kwargs.py", line 61, in func3: Function func2 was called with the wrong arguments [wrong-arg-types] + Expected: (v3: str, ...) + Actually passed: (v3: int, ...) +File "callables_kwargs.py", line 62, in func3: Function func2 was called with the wrong arguments [wrong-arg-types] + Expected: (v3, v1: Unpack[TD1], ...) + Actually passed: (v1: int, ...) +""" diff --git a/conformance/results/pytype/callables_protocol.toml b/conformance/results/pytype/callables_protocol.toml new file mode 100644 index 000000000..2afc6ae41 --- /dev/null +++ b/conformance/results/pytype/callables_protocol.toml @@ -0,0 +1,27 @@ +conformant = "Unsupported" +notes = """ +Does not properly handle type compatibility checks with callback protocols. +""" +output = """ +File "callables_protocol.py", line 9, in : argument "contravariant" to TypeVar not supported yet [not-supported-yet] +File "callables_protocol.py", line 10, in : argument "covariant" to TypeVar not supported yet [not-supported-yet] +File "callables_protocol.py", line 121, in : Type annotation for cb6 does not match type of assignment [annotation-type-mismatch] + Annotation: NotProto6 + Assignment: Callable[..., List[bytes]] +File "callables_protocol.py", line 173, in : argument "covariant" to TypeVar not supported yet [not-supported-yet] +File "callables_protocol.py", line 176, in : Invalid type annotation 'Protocol' [invalid-annotation] + Parameters to Generic[...] must all be type variables +File "callables_protocol.py", line 183, in : Invalid type annotation 'Proto9[P, R]' [invalid-annotation] + Proto9[R] expected 1 parameter, got 2 +File "callables_protocol.py", line 184, in decorator1: Invalid type annotation 'Proto9[P, R]' [invalid-annotation] + Proto9[R] expected 1 parameter, got 2 +File "callables_protocol.py", line 188, in decorator1: bad return type [bad-return-type] + Expected: Proto9 + Actually returned: Proto9 +Called from (traceback): + line 191, in current file +File "callables_protocol.py", line 197, in : No attribute 'other_attribute2' on Proto9 [attribute-error] +File "callables_protocol.py", line 199, in : Function Proto9.__call__ was called with the wrong arguments [wrong-arg-types] + Expected: (self, x: P.kwargs, ...) + Actually passed: (self, x: int) +""" diff --git a/conformance/results/pytype/dataclasses_descriptors.toml b/conformance/results/pytype/dataclasses_descriptors.toml new file mode 100644 index 000000000..e48da430c --- /dev/null +++ b/conformance/results/pytype/dataclasses_descriptors.toml @@ -0,0 +1,40 @@ +conformant = "Unsupported" +notes = """ +Does not understand descriptor objects in dataclass. +""" +output = """ +File "dataclasses_descriptors.py", line 24, in __get__: bad return type [bad-return-type] + Expected: int + Actually returned: None +Called from (traceback): + line 37, in current file +File "dataclasses_descriptors.py", line 24, in __get__: bad return type [bad-return-type] + Expected: Desc1 + Actually returned: None +Called from (traceback): + line 38, in current file +File "dataclasses_descriptors.py", line 35, in : Function DC1.__init__ was called with the wrong arguments [wrong-arg-types] + Expected: (self, y: Desc1 = ...) + Actually passed: (self, y: int) +File "dataclasses_descriptors.py", line 51, in __get__: bad return type [bad-return-type] + Expected: list + Actually returned: None +File "dataclasses_descriptors.py", line 61, in : list [assert-type] + Expected: List[int] + Actual: list +File "dataclasses_descriptors.py", line 62, in : list [assert-type] + Expected: List[str] + Actual: list +File "dataclasses_descriptors.py", line 63, in : list [assert-type] + Expected: List[str] + Actual: list +File "dataclasses_descriptors.py", line 66, in : Any [assert-type] + Expected: int + Actual: Any +File "dataclasses_descriptors.py", line 67, in : Any [assert-type] + Expected: str + Actual: Any +File "dataclasses_descriptors.py", line 68, in : Any [assert-type] + Expected: str + Actual: Any +""" diff --git a/conformance/results/pytype/dataclasses_frozen.toml b/conformance/results/pytype/dataclasses_frozen.toml new file mode 100644 index 000000000..4f832c2bf --- /dev/null +++ b/conformance/results/pytype/dataclasses_frozen.toml @@ -0,0 +1,8 @@ +conformant = "Unsupported" +notes = """ +Does not report assignment to field within frozen dataclass instance. +Does not reject frozen dataclass inherited from non-frozen dataclass. +Does not reject non-frozen dataclass inherited from frozen dataclass. +""" +output = """ +""" diff --git a/conformance/results/pytype/dataclasses_hash.toml b/conformance/results/pytype/dataclasses_hash.toml new file mode 100644 index 000000000..a71f51ca0 --- /dev/null +++ b/conformance/results/pytype/dataclasses_hash.toml @@ -0,0 +1,6 @@ +conformant = "Partial" +notes = """ +Does not report when dataclass is not compatible with Hashable protocol. +""" +output = """ +""" diff --git a/conformance/results/pytype/dataclasses_inheritance.toml b/conformance/results/pytype/dataclasses_inheritance.toml new file mode 100644 index 000000000..5000e40e5 --- /dev/null +++ b/conformance/results/pytype/dataclasses_inheritance.toml @@ -0,0 +1,7 @@ +conformant = "Partial" +notes = """ +Does not reject ClassVar that is overridden by instance variable. +Does not reject instance variable that is overridden by ClassVar. +""" +output = """ +""" diff --git a/conformance/results/pytype/dataclasses_kwonly.toml b/conformance/results/pytype/dataclasses_kwonly.toml new file mode 100644 index 000000000..153cca7a0 --- /dev/null +++ b/conformance/results/pytype/dataclasses_kwonly.toml @@ -0,0 +1,23 @@ +conformant = "Partial" +notes = """ +Incorrectly reports error when kw_only field has default value. +Incorrectly rejects kw_only field with default before positional field. +""" +output = """ +File "dataclasses_kwonly.py", line 38, in : Function DC2.__init__ expects 2 arg(s), got 3 [wrong-arg-count] + Expected: (self, a, *, b) + Actually passed: (self, a, _) +File "dataclasses_kwonly.py", line 47, in : Missing parameter 'a' in call to function DC3.__init__ [missing-parameter] + Expected: (self, *, a, b) + Actually passed: (self, _) +File "dataclasses_kwonly.py", line 50, in : Missing parameter 'a' in call to function DC3.__init__ [missing-parameter] + Expected: (self, *, a, b) + Actually passed: (self, b, _) +File "dataclasses_kwonly.py", line 53, in : Missing parameter 'a' in call to function DC3.__init__ [missing-parameter] + Expected: (self, *, a, b) + Actually passed: (self, _, _) +File "dataclasses_kwonly.py", line 57, in : In method __init__, non-default argument c follows default argument [invalid-function-definition] +File "dataclasses_kwonly.py", line 61, in : function DC4.__init__ got multiple values for keyword argument 'b' [duplicate-keyword-argument] + Expected: (self, a, b, c) + Actually passed: (self, a, b, b) +""" diff --git a/conformance/results/pytype/dataclasses_order.toml b/conformance/results/pytype/dataclasses_order.toml new file mode 100644 index 000000000..4f4d92b02 --- /dev/null +++ b/conformance/results/pytype/dataclasses_order.toml @@ -0,0 +1,6 @@ +conformant = "Partial" +notes = """ +Does not report type incompatibility with comparison operator. +""" +output = """ +""" diff --git a/conformance/results/pytype/dataclasses_postinit.toml b/conformance/results/pytype/dataclasses_postinit.toml new file mode 100644 index 000000000..58c6be024 --- /dev/null +++ b/conformance/results/pytype/dataclasses_postinit.toml @@ -0,0 +1,13 @@ +conformant = "Partial" +notes = """ +Does not validate `__post_init__` method. +Reports incorrect error for incompatible `__post_init__` method override. +""" +output = """ +File "dataclasses_postinit.py", line 28, in : No attribute 'x' on DC1 [attribute-error] +File "dataclasses_postinit.py", line 29, in : No attribute 'y' on DC1 [attribute-error] +File "dataclasses_postinit.py", line 54, in DC4: Overriding method signature mismatch [signature-mismatch] + Base signature: 'def DC3.__post_init__(self, _name: str) -> Any'. + Subclass signature: 'def DC4.__post_init__(self, _name: str, _age: int) -> Any'. + Parameter '_age' must have a default value. +""" diff --git a/conformance/results/pytype/dataclasses_slots.toml b/conformance/results/pytype/dataclasses_slots.toml new file mode 100644 index 000000000..f891c51ee --- /dev/null +++ b/conformance/results/pytype/dataclasses_slots.toml @@ -0,0 +1,12 @@ +conformant = "Partial" +notes = """ +Does not report error when `slots=True` is used with `__slots__` definition. +Does not reject write to instance variable that is not defined in __slots__. +Incorrectly reports error when accessing `__slots__` when `slots=True`. +""" +output = """ +File "dataclasses_slots.py", line 57, in : No attribute '__slots__' on Type[DC5] [attribute-error] +File "dataclasses_slots.py", line 58, in : No attribute '__slots__' on DC5 [attribute-error] +File "dataclasses_slots.py", line 67, in : No attribute '__slots__' on Type[DC6] [attribute-error] +File "dataclasses_slots.py", line 70, in : No attribute '__slots__' on DC6 [attribute-error] +""" diff --git a/conformance/results/pytype/dataclasses_transform_class.toml b/conformance/results/pytype/dataclasses_transform_class.toml new file mode 100644 index 000000000..b2f967610 --- /dev/null +++ b/conformance/results/pytype/dataclasses_transform_class.toml @@ -0,0 +1,15 @@ +conformant = "Unsupported" +notes = """ +Does not understand @dataclass_transform. +""" +output = """ +File "dataclasses_transform_class.py", line 23, in : Arguments to dataclass_transform not supported yet [not-supported-yet] +File "dataclasses_transform_class.py", line 57, in : Invalid keyword argument other_name to function Customer1.__init__ [wrong-keyword-args] + Expected: (self, id, name, name2) + Actually passed: (self, id, name, other_name) +File "dataclasses_transform_class.py", line 82, in : Arguments to dataclass_transform not supported yet [not-supported-yet] +File "dataclasses_transform_class.py", line 103, in : Invalid keyword argument id to function GenericCustomer.__init__ [wrong-keyword-args] + Expected: (self) + Actually passed: (self, id) +File "dataclasses_transform_class.py", line 106, in : Arguments to dataclass_transform not supported yet [not-supported-yet] +""" diff --git a/conformance/results/pytype/dataclasses_transform_field.toml b/conformance/results/pytype/dataclasses_transform_field.toml new file mode 100644 index 000000000..0f07a79e8 --- /dev/null +++ b/conformance/results/pytype/dataclasses_transform_field.toml @@ -0,0 +1,11 @@ +conformant = "Unsupported" +notes = """ +Does not understand @dataclass_transform. +""" +output = """ +File "dataclasses_transform_field.py", line 48, in : Arguments to dataclass_transform not supported yet [not-supported-yet] +File "dataclasses_transform_field.py", line 50, in create_model: bad return type [bad-return-type] + Expected: Callable[[type], type] + Actually returned: None + Attributes of protocol Callable[[Type[T]], Type[T]] are not implemented on None: __call__ +""" diff --git a/conformance/results/pytype/dataclasses_transform_func.toml b/conformance/results/pytype/dataclasses_transform_func.toml new file mode 100644 index 000000000..9c8ab708e --- /dev/null +++ b/conformance/results/pytype/dataclasses_transform_func.toml @@ -0,0 +1,36 @@ +conformant = "Unsupported" +notes = """ +Does not understand @dataclass_transform. +""" +output = """ +File "dataclasses_transform_func.py", line 13, in : Arguments to dataclass_transform not supported yet [not-supported-yet] +File "dataclasses_transform_func.py", line 19, in : Arguments to dataclass_transform not supported yet [not-supported-yet] +File "dataclasses_transform_func.py", line 30, in create_model: bad return type [bad-return-type] + Expected: Callable[[Any], Any] + Actually returned: None + Attributes of protocol Callable[[T], T] are not implemented on None: __call__ +File "dataclasses_transform_func.py", line 30, in create_model: bad return type [bad-return-type] + Expected: Type[Customer3Subclass] + Actually returned: None +Called from (traceback): + line 89, in current file +File "dataclasses_transform_func.py", line 50, in : Invalid keyword arguments (id, name) to function Customer1.__init__ [wrong-keyword-args] + Expected: (self) + Actually passed: (self, id, name) +File "dataclasses_transform_func.py", line 53, in : Function Customer1.__init__ expects 1 arg(s), got 3 [wrong-arg-count] + Expected: (self) + Actually passed: (self, _, _) +File "dataclasses_transform_func.py", line 57, in : Type annotation for name does not match type of assignment [annotation-type-mismatch] + Annotation: str + Assignment: int +File "dataclasses_transform_func.py", line 65, in : Invalid keyword arguments (id, name, salary) to function Customer1.__init__ [wrong-keyword-args] + Expected: (self) + Actually passed: (self, id, name, salary) +File "dataclasses_transform_func.py", line 67, in : Invalid keyword arguments (id, name) to function Customer2.__init__ [wrong-keyword-args] + Expected: (self) + Actually passed: (self, id, name) +File "dataclasses_transform_func.py", line 71, in : Function Customer2.__init__ expects 1 arg(s), got 3 [wrong-arg-count] + Expected: (self) + Actually passed: (self, _, _) +File "dataclasses_transform_func.py", line 76, in : Arguments to dataclass_transform not supported yet [not-supported-yet] +""" diff --git a/conformance/results/pytype/dataclasses_transform_meta.toml b/conformance/results/pytype/dataclasses_transform_meta.toml new file mode 100644 index 000000000..969655be0 --- /dev/null +++ b/conformance/results/pytype/dataclasses_transform_meta.toml @@ -0,0 +1,11 @@ +conformant = "Unsupported" +notes = """ +Does not understand @dataclass_transform. +""" +output = """ +File "dataclasses_transform_meta.py", line 21, in : Arguments to dataclass_transform not supported yet [not-supported-yet] +File "dataclasses_transform_meta.py", line 57, in : Invalid keyword argument other_name to function Customer1.__init__ [wrong-keyword-args] + Expected: (self, id, name, name2) + Actually passed: (self, id, name, other_name) +File "dataclasses_transform_meta.py", line 83, in : Arguments to dataclass_transform not supported yet [not-supported-yet] +""" diff --git a/conformance/results/pytype/dataclasses_usage.toml b/conformance/results/pytype/dataclasses_usage.toml new file mode 100644 index 000000000..883ea2462 --- /dev/null +++ b/conformance/results/pytype/dataclasses_usage.toml @@ -0,0 +1,38 @@ +conformant = "Pass" +output = """ +File "dataclasses_usage.py", line 51, in : Missing parameter 'unit_price' in call to function InventoryItem.__init__ [missing-parameter] + Expected: (self, name, unit_price, quantity_on_hand) + Actually passed: (self, name) +File "dataclasses_usage.py", line 52, in : Function InventoryItem.__init__ was called with the wrong arguments [wrong-arg-types] + Expected: (self, name, unit_price: float, ...) + Actually passed: (self, name, unit_price: str) +File "dataclasses_usage.py", line 53, in : Function InventoryItem.__init__ expects 3 arg(s), got 5 [wrong-arg-count] + Expected: (self, name, unit_price, quantity_on_hand) + Actually passed: (self, name, unit_price, quantity_on_hand, _) +File "dataclasses_usage.py", line 60, in : In method __init__, non-default argument b follows default argument [invalid-function-definition] +File "dataclasses_usage.py", line 66, in : In method __init__, non-default argument b follows default argument [invalid-function-definition] +File "dataclasses_usage.py", line 72, in : In method __init__, non-default argument b follows default argument [invalid-function-definition] +File "dataclasses_usage.py", line 84, in : Function DC4.__init__ expects 2 arg(s), got 3 [wrong-arg-count] + Expected: (self, b) + Actually passed: (self, b, _) +File "dataclasses_usage.py", line 89, in DC5: Type annotation for a does not match type of assignment [annotation-type-mismatch] + Annotation: int + Assignment: str +File "dataclasses_usage.py", line 127, in : Function DC7.__init__ expects 2 arg(s), got 3 [wrong-arg-count] + Expected: (self, x) + Actually passed: (self, x, _) +File "dataclasses_usage.py", line 130, in : Missing parameter 'y' in call to function DC8.__init__ [missing-parameter] + Expected: (self, a, y) + Actually passed: (self, a) +File "dataclasses_usage.py", line 152, in __init__: Type annotation for x_squared does not match type of assignment [annotation-type-mismatch] + Annotation: int + Assignment: float + In assignment of type: Union[float, int] +File "dataclasses_usage.py", line 165, in __init__: Type annotation for x_squared does not match type of assignment [annotation-type-mismatch] + Annotation: int + Assignment: float + In assignment of type: Union[float, int] +File "dataclasses_usage.py", line 179, in : Function DC13.__init__ expects 1 arg(s), got 2 [wrong-arg-count] + Expected: (self) + Actually passed: (self, _) +""" diff --git a/conformance/results/pytype/generics_self_advanced.toml b/conformance/results/pytype/generics_self_advanced.toml new file mode 100644 index 000000000..d980d2f3d --- /dev/null +++ b/conformance/results/pytype/generics_self_advanced.toml @@ -0,0 +1,51 @@ +conformant = "Unsupported" +notes = """ +Does not understand `Self` type. +""" +output = """ +File "generics_self_advanced.py", line 12, in prop1: bad return type [bad-return-type] + Expected: ParentA + Actually returned: None +Called from (traceback): + line 18, in current file +File "generics_self_advanced.py", line 12, in prop1: bad return type [bad-return-type] + Expected: ParentA + Actually returned: None +Called from (traceback): + line 19, in current file +File "generics_self_advanced.py", line 19, in : ParentA [assert-type] + Expected: ChildA + Actual: ParentA +File "generics_self_advanced.py", line 29, in method1: bad return type [bad-return-type] + Expected: ChildB + Actually returned: None +Called from (traceback): + line 38, in method2 +File "generics_self_advanced.py", line 29, in method1: bad return type [bad-return-type] + Expected: ParentB + Actually returned: None +File "generics_self_advanced.py", line 35, in method2: ChildB [assert-type] + Expected: Any + Actual: ChildB +File "generics_self_advanced.py", line 36, in method2: List[ChildB] [assert-type] + Expected: list + Actual: List[ChildB] +File "generics_self_advanced.py", line 37, in method2: ChildB [assert-type] + Expected: Any + Actual: ChildB +File "generics_self_advanced.py", line 38, in method2: ChildB [assert-type] + Expected: Any + Actual: ChildB +File "generics_self_advanced.py", line 42, in method3: Type[ChildB] [assert-type] + Expected: Any + Actual: Type[ChildB] +File "generics_self_advanced.py", line 43, in method3: List[ChildB] [assert-type] + Expected: list + Actual: List[ChildB] +File "generics_self_advanced.py", line 44, in method3: ChildB [assert-type] + Expected: Any + Actual: ChildB +File "generics_self_advanced.py", line 45, in method3: ChildB [assert-type] + Expected: Any + Actual: ChildB +""" diff --git a/conformance/results/pytype/generics_self_attributes.toml b/conformance/results/pytype/generics_self_attributes.toml new file mode 100644 index 000000000..ec77829e1 --- /dev/null +++ b/conformance/results/pytype/generics_self_attributes.toml @@ -0,0 +1,9 @@ +conformant = "Unsupported" +notes = """ +Does not understand `Self` type. +""" +output = """ +File "generics_self_attributes.py", line 26, in : Function OrdinalLinkedList.__init__ was called with the wrong arguments [wrong-arg-types] + Expected: (self, value, next: Optional[OrdinalLinkedList] = ...) + Actually passed: (self, value, next: LinkedList[int]) +""" diff --git a/conformance/results/pytype/generics_self_basic.toml b/conformance/results/pytype/generics_self_basic.toml new file mode 100644 index 000000000..768d64c2a --- /dev/null +++ b/conformance/results/pytype/generics_self_basic.toml @@ -0,0 +1,52 @@ +conformant = "Unsupported" +notes = """ +Does not understand `Self` type. +""" +output = """ +File "generics_self_basic.py", line 13, in set_scale: Shape [assert-type] + Expected: Any + Actual: Shape +File "generics_self_basic.py", line 13, in set_scale: Circle [assert-type] + Expected: Any + Actual: Circle +Called from (traceback): + line 51, in current file +File "generics_self_basic.py", line 26, in from_config: Type[Shape] [assert-type] + Expected: Any + Actual: Type[Shape] +Called from (traceback): + line 53, in current file +File "generics_self_basic.py", line 26, in from_config: Type[Circle] [assert-type] + Expected: Any + Actual: Type[Circle] +Called from (traceback): + line 54, in current file +File "generics_self_basic.py", line 27, in from_config: Function Shape.__init__ expects 1 arg(s), got 2 [wrong-arg-count] + Expected: (self) + Actually passed: (self, _) +Called from (traceback): + line 53, in current file +File "generics_self_basic.py", line 27, in from_config: Function Circle.__init__ expects 1 arg(s), got 2 [wrong-arg-count] + Expected: (self) + Actually passed: (self, _) +Called from (traceback): + line 54, in current file +File "generics_self_basic.py", line 39, in difference: Shape [assert-type] + Expected: Any + Actual: Shape +File "generics_self_basic.py", line 61, in set_value: bad return type [bad-return-type] + Expected: Container + Actually returned: None +File "generics_self_basic.py", line 61, in set_value: bad return type [bad-return-type] + Expected: Container[int] + Actually returned: None +Called from (traceback): + line 71, in object_with_concrete_type +File "generics_self_basic.py", line 61, in set_value: bad return type [bad-return-type] + Expected: Container[str] + Actually returned: None +Called from (traceback): + line 72, in object_with_concrete_type +File "generics_self_basic.py", line 64, in Container: unsupported operand type(s) for item retrieval: 'Self: TypeVar' and 'int: Type[int]' [unsupported-operands] + No attribute '__getitem__' on 'Self: TypeVar' +""" diff --git a/conformance/results/pytype/generics_self_protocols.toml b/conformance/results/pytype/generics_self_protocols.toml new file mode 100644 index 000000000..4b3a0000a --- /dev/null +++ b/conformance/results/pytype/generics_self_protocols.toml @@ -0,0 +1,6 @@ +conformant = "Partial" +notes = """ +Does not reject protocol compatibility due to method `Self` return type. +""" +output = """ +""" diff --git a/conformance/results/pytype/generics_self_usage.toml b/conformance/results/pytype/generics_self_usage.toml new file mode 100644 index 000000000..0326533e3 --- /dev/null +++ b/conformance/results/pytype/generics_self_usage.toml @@ -0,0 +1,31 @@ +conformant = "Unsupported" +notes = """ +Does not understand `Self` type. +""" +output = """ +File "generics_self_usage.py", line 58, in foo: Invalid type annotation 'Self' [invalid-annotation] + Cannot use 'typing.Self' outside of a class +File "generics_self_usage.py", line 73, in : Invalid type annotation 'Self' [invalid-annotation] + Cannot use 'typing.Self' outside of a class +File "generics_self_usage.py", line 76, in : Invalid type annotation 'Self' for bar [invalid-annotation] + TypeVar(s) 'Self' not in scope +File "generics_self_usage.py", line 82, in has_existing_self_annotation: bad return type [bad-return-type] + Expected: Foo2 + Actually returned: None +File "generics_self_usage.py", line 86, in return_concrete_type: bad return type [bad-return-type] + Expected: Foo3Child + Actually returned: Foo3 +Called from (traceback): + line 92, in child_method +File "generics_self_usage.py", line 103, in : Invalid base class: Self [base-class-error] +File "generics_self_usage.py", line 111, in Base: Invalid type annotation 'Self' [invalid-annotation] + Cannot use 'typing.Self' outside of a class +File "generics_self_usage.py", line 116, in Base: Invalid type annotation 'Self' [invalid-annotation] + Cannot use 'typing.Self' outside of a class +File "generics_self_usage.py", line 122, in __new__: bad return type [bad-return-type] + Expected: MyMetaclass + Actually returned: None +File "generics_self_usage.py", line 126, in __mul__: bad return type [bad-return-type] + Expected: List[MyMetaclass] + Actually returned: None +""" diff --git a/conformance/results/pytype/literals_interactions.toml b/conformance/results/pytype/literals_interactions.toml new file mode 100644 index 000000000..6b3e93b19 --- /dev/null +++ b/conformance/results/pytype/literals_interactions.toml @@ -0,0 +1,48 @@ +conformant = "Partial" +notes = """ +Incorrectly rejects some legal Literal annotations. +Does not reject some illegal Literal annotations. +Does not use Literal to distinguish overloads. +Does not narrow based on `x is Literal` type guard pattern. +Does not narrow based on `x == Literal` type guard pattern. +""" +output = """ +File "literals_interactions.py", line 11, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'int' at index 0 +File "literals_interactions.py", line 46, in open: bad return type [bad-return-type] + Expected: IO[str] + Actually returned: None +Called from (traceback): + line 49, in current file +File "literals_interactions.py", line 46, in open: bad return type [bad-return-type] + Expected: IO[bytes] + Actually returned: None +Called from (traceback): + line 50, in current file +File "literals_interactions.py", line 46, in open: bad return type [bad-return-type] + Expected: IO + Actually returned: None +Called from (traceback): + line 51, in current file +File "literals_interactions.py", line 61, in __add__: bad return type [bad-return-type] + Expected: Matrix[int, int] + Actually returned: None +File "literals_interactions.py", line 64, in __matmul__: bad return type [bad-return-type] + Expected: Matrix[int, int] + Actually returned: None +File "literals_interactions.py", line 67, in transpose: bad return type [bad-return-type] + Expected: Matrix[int, int] + Actually returned: None +File "literals_interactions.py", line 72, in func2: Matrix[Any, int] [assert-type] + Expected: Matrix[int, int] + Actual: Matrix[Any, int] +File "literals_interactions.py", line 93, in parse_status1: Union[Status, str] [assert-type] + Expected: str + Actual: Union[Status, str] +File "literals_interactions.py", line 106, in parse_status2: Function expects_bad_status was called with the wrong arguments [wrong-arg-types] + Expected: (status: Literal['ABORTED', 'MALFORMED']) + Actually passed: (status: str) +File "literals_interactions.py", line 109, in parse_status2: Function expects_pending_status was called with the wrong arguments [wrong-arg-types] + Expected: (status: Literal['PENDING']) + Actually passed: (status: str) +""" diff --git a/conformance/results/pytype/literals_literalstring.toml b/conformance/results/pytype/literals_literalstring.toml new file mode 100644 index 000000000..0ffdbe488 --- /dev/null +++ b/conformance/results/pytype/literals_literalstring.toml @@ -0,0 +1,6 @@ +conformant = "Unsupported" +notes = """ +Does not understand `LiteralString` special form. +""" +output = """ +""" diff --git a/conformance/results/pytype/literals_parameterizations.toml b/conformance/results/pytype/literals_parameterizations.toml new file mode 100644 index 000000000..f24946a15 --- /dev/null +++ b/conformance/results/pytype/literals_parameterizations.toml @@ -0,0 +1,41 @@ +conformant = "Unsupported" +notes = """ +Does not understand `Literal` type annotation. +""" +output = """ +File "literals_parameterizations.py", line 17, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'int' at index 0 +File "literals_parameterizations.py", line 18, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'int' at index 0 +File "literals_parameterizations.py", line 19, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'int' at index 0 +File "literals_parameterizations.py", line 32, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'Union' at index 0 + Bad parameter 'Union' at index 1 + Bad parameter 'Union' at index 2 + Bad parameter 'Union' at index 3 +File "literals_parameterizations.py", line 34, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'Union' at index 0 +File "literals_parameterizations.py", line 41, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'str' at index 0 +File "literals_parameterizations.py", line 42, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'complex' at index 0 +File "literals_parameterizations.py", line 46, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'dict' at index 0 +File "literals_parameterizations.py", line 47, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'int' at index 0 +File "literals_parameterizations.py", line 49, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'T' at index 0 +File "literals_parameterizations.py", line 50, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'float' at index 0 +File "literals_parameterizations.py", line 52, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter '...' at index 0 +File "literals_parameterizations.py", line 59, in : Invalid type annotation 'Literal[my_function]' [invalid-annotation] + Invalid type annotation 'Literal' + Bad parameter 'my_function' at index 0 +File "literals_parameterizations.py", line 59, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'my_function' at index 0 +File "literals_parameterizations.py", line 63, in func2: Type annotation for x1 does not match type of assignment [annotation-type-mismatch] + Annotation: Literal['Color.RED'] + Assignment: Color +""" diff --git a/conformance/results/pytype/literals_semantics.toml b/conformance/results/pytype/literals_semantics.toml new file mode 100644 index 000000000..e33ebf37b --- /dev/null +++ b/conformance/results/pytype/literals_semantics.toml @@ -0,0 +1,25 @@ +conformant = "Unsupported" +notes = """ +Does not understand `Literal` type annotation. +""" +output = """ +File "literals_semantics.py", line 10, in : Type annotation for v2 does not match type of assignment [annotation-type-mismatch] + Annotation: Literal[3] + Assignment: Literal[4] +File "literals_semantics.py", line 12, in : Invalid type annotation 'L[-3]' [invalid-annotation] + Invalid type annotation 'Literal' + Bad parameter 'int' at index 0 +File "literals_semantics.py", line 12, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'int' at index 0 +File "literals_semantics.py", line 16, in : Invalid type annotation 'Literal' [invalid-annotation] + Bad parameter 'int' at index 0 +File "literals_semantics.py", line 17, in func1: Invalid type annotation 'Literal[20]' [invalid-annotation] + Invalid type annotation 'Literal' + Bad parameter 'int' at index 0 +File "literals_semantics.py", line 18, in func1: Invalid type annotation 'Literal[20]' [invalid-annotation] + Invalid type annotation 'Literal' + Bad parameter 'int' at index 0 +File "literals_semantics.py", line 19, in func1: Invalid type annotation 'Literal[20]' [invalid-annotation] + Invalid type annotation 'Literal' + Bad parameter 'int' at index 0 +""" diff --git a/conformance/results/pytype/narrowing_typeguard.toml b/conformance/results/pytype/narrowing_typeguard.toml new file mode 100644 index 000000000..699b0799f --- /dev/null +++ b/conformance/results/pytype/narrowing_typeguard.toml @@ -0,0 +1,6 @@ +conformant = "Partial" +notes = """ +Does not reject TypeGuard method with too few parameters. +""" +output = """ +""" diff --git a/conformance/results/pytype/typeddicts_alt_syntax.toml b/conformance/results/pytype/typeddicts_alt_syntax.toml new file mode 100644 index 000000000..5bc176026 --- /dev/null +++ b/conformance/results/pytype/typeddicts_alt_syntax.toml @@ -0,0 +1,14 @@ +conformant = "Partial" +notes = """ +Does not reject use of variable as second argument to `TypedDict` call. +Does not report when name of TypedDict doesn't match assigned identifier name. +Does not support keyword-argument form of alternative syntax (deprecated in 3.11). +""" +output = """ +File "typeddicts_alt_syntax.py", line 27, in : Function typing.TypedDict was called with the wrong arguments [wrong-arg-types] + Expected: (name, fields: dict, ...) + Actually passed: (name, fields: Dict[int, Type[str]]) +File "typeddicts_alt_syntax.py", line 41, in : Function typing.TypedDict expects 2 arg(s), got 3 [wrong-arg-count] + Expected: (name, fields, *, total) + Actually passed: (name, name, year) +""" diff --git a/conformance/results/pytype/typeddicts_class_syntax.toml b/conformance/results/pytype/typeddicts_class_syntax.toml new file mode 100644 index 000000000..b187f00c5 --- /dev/null +++ b/conformance/results/pytype/typeddicts_class_syntax.toml @@ -0,0 +1,8 @@ +conformant = "Partial" +notes = """ +Does not reject methods within TypedDict class. +Does not report when metaclass is provided. +Does not report when other keyword argument is provided. +""" +output = """ +""" diff --git a/conformance/results/pytype/typeddicts_final.toml b/conformance/results/pytype/typeddicts_final.toml new file mode 100644 index 000000000..2146548eb --- /dev/null +++ b/conformance/results/pytype/typeddicts_final.toml @@ -0,0 +1,3 @@ +conformant = "Pass" +output = """ +""" diff --git a/conformance/results/pytype/typeddicts_inheritance.toml b/conformance/results/pytype/typeddicts_inheritance.toml new file mode 100644 index 000000000..6570b22c7 --- /dev/null +++ b/conformance/results/pytype/typeddicts_inheritance.toml @@ -0,0 +1,9 @@ +conformant = "Pass" +output = """ +File "typeddicts_inheritance.py", line 44, in : Invalid base class: NonTypedDict [base-class-error] + TypedDict BadTypedDict cannot inherit from a non-TypedDict class. +File "typeddicts_inheritance.py", line 54, in : Invalid base class: X1 [base-class-error] + Duplicate TypedDict key x in classes X1 and Y1 +File "typeddicts_inheritance.py", line 65, in : Invalid base class: Y2 [base-class-error] + Duplicate TypedDict key x in classes Y2 and X2 +""" diff --git a/conformance/results/pytype/typeddicts_operations.toml b/conformance/results/pytype/typeddicts_operations.toml new file mode 100644 index 000000000..8f53a4408 --- /dev/null +++ b/conformance/results/pytype/typeddicts_operations.toml @@ -0,0 +1,24 @@ +conformant = "Partial" +notes = """ +Does not report type violation with TypedDict value assignment. +Does not report reference to unknown key in TypedDict. +Does not reject `clear` method on TypedDict with required keys. +Does not reject delete operation for required key in TypedDict. +""" +output = """ +File "typeddicts_operations.py", line 28, in : Type annotation for movie does not match type of assignment [annotation-type-mismatch] + Annotation: Movie(TypedDict) + Assignment: Dict[str, str] +File "typeddicts_operations.py", line 29, in : Type annotation for movie does not match type of assignment [annotation-type-mismatch] + Annotation: Movie(TypedDict) + Assignment: Dict[str, Union[float, str]] +File "typeddicts_operations.py", line 32, in : Type annotation for movie does not match type of assignment [annotation-type-mismatch] + Annotation: Movie(TypedDict) + Assignment: Dict[str, Union[int, str]] +File "typeddicts_operations.py", line 37, in func1: Type annotation for movie does not match type of assignment [annotation-type-mismatch] + Annotation: Movie(TypedDict) + Assignment: Dict[str, Union[int, str]] +File "typeddicts_operations.py", line 60, in : str [assert-type] + Expected: Optional[str] + Actual: str +""" diff --git a/conformance/results/pytype/typeddicts_required.toml b/conformance/results/pytype/typeddicts_required.toml new file mode 100644 index 000000000..bdedbc7d6 --- /dev/null +++ b/conformance/results/pytype/typeddicts_required.toml @@ -0,0 +1,8 @@ +conformant = "Partial" +notes = """ +Does not reject use of `Required` in non-TypedDict class. +Does not reject use of `Required` in function parameter annotation. +Does not reject nested use of `Required` in type annotation. +""" +output = """ +""" diff --git a/conformance/results/pytype/typeddicts_type_consistency.toml b/conformance/results/pytype/typeddicts_type_consistency.toml new file mode 100644 index 000000000..b80ed1d7a --- /dev/null +++ b/conformance/results/pytype/typeddicts_type_consistency.toml @@ -0,0 +1,20 @@ +conformant = "Partial" +notes = """ +Does not report some type violations for TypedDict type compatibility. +Incorrectly reports type violation in cases where there is none. +Does not report type incompatibility between TypedDict and `dict[str, Any]`. +""" +output = """ +File "typeddicts_type_consistency.py", line 62, in : Type annotation for a3 does not match type of assignment [annotation-type-mismatch] + Annotation: A3(TypedDict) + Assignment: B3 +File "typeddicts_type_consistency.py", line 65, in : Type annotation for b3 does not match type of assignment [annotation-type-mismatch] + Annotation: B3(TypedDict) + Assignment: Dict[str, int] +File "typeddicts_type_consistency.py", line 69, in : Type annotation for a3_1 does not match type of assignment [annotation-type-mismatch] + Annotation: A3(TypedDict) + Assignment: Dict[str, int] +File "typeddicts_type_consistency.py", line 124, in : Type annotation for o2 does not match type of assignment [annotation-type-mismatch] + Annotation: Outer1(TypedDict) + Assignment: Dict[str, Dict[str, Dict[str, int]]] +""" diff --git a/conformance/results/pytype/typeddicts_usage.toml b/conformance/results/pytype/typeddicts_usage.toml new file mode 100644 index 000000000..41139d698 --- /dev/null +++ b/conformance/results/pytype/typeddicts_usage.toml @@ -0,0 +1,14 @@ +conformant = "Partial" +notes = """ +Does not report errant use of TypedDict in `isinstance` call. +Does not reject use of TypedDict as TypeVar bound. +""" +output = """ +File "typeddicts_usage.py", line 23, in : TypedDict Movie does not contain key director [typed-dict-error] +File "typeddicts_usage.py", line 24, in : Type annotation for key year in TypedDict Movie does not match type of assignment [annotation-type-mismatch] + Annotation: int + Assignment: str +File "typeddicts_usage.py", line 28, in : Type annotation for movie2 does not match type of assignment [annotation-type-mismatch] + Annotation: Movie(TypedDict) + Assignment: Dict[str, Union[int, str]] +""" diff --git a/conformance/results/pytype/version.toml b/conformance/results/pytype/version.toml new file mode 100644 index 000000000..6bfa30f74 --- /dev/null +++ b/conformance/results/pytype/version.toml @@ -0,0 +1,2 @@ +version = "pytype 2023.12.18" +test_duration = 51.5667941570282 diff --git a/conformance/results/results.html b/conformance/results/results.html new file mode 100644 index 000000000..b33903903 --- /dev/null +++ b/conformance/results/results.html @@ -0,0 +1,431 @@ + + + + + + + Type System Test Results + + + + +
+
+

Python Type System Conformance Test Results

+
+
mypy 1.8.0(0.40sec) +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Type annotations
     annotations_typeexprPass
+Generics
     generics_self_advancedPartialDoes 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]`.
     generics_self_attributesPass
     generics_self_basicPartialDoes not properly handle constructor call through `cls` parameter.
     generics_self_protocolsPass
     generics_self_usagePass
+Type aliases
     aliases_explicitPartialDoes not reject specialization of type alias that has already been implicitly specialized.
     aliases_implicitPass
     aliases_newtypePass
     aliases_recursivePass
     aliases_type_statementUnsupportedDoes not support `type` statement.
     aliases_typealiastypeUnsupportedSupport for TypeAliasType is not implemented.
     aliases_variancePass
+Literals
     literals_interactionsPartialDoes not narrow type of `x` with `x in Literal` type guard pattern.
     literals_literalstringUnsupportedSupport for `LiteralString` is not implemented.
     literals_parameterizationsPartialDoes not reject tuple within Literal.
     literals_semanticsPass
+Callables
     callables_annotationPass
     callables_kwargsPass
     callables_protocolPass
+Dataclasses
     dataclasses_descriptorsPartialDoes not correctly evaluate type of descriptor access.
     dataclasses_frozenPass
     dataclasses_hashPartialDoes not report when dataclass is not compatible with Hashable protocol.
     dataclasses_inheritancePass
     dataclasses_kwonlyPartialIncorrectly rejects kw_only field with default before positional field.
     dataclasses_orderPass
     dataclasses_postinitPass
     dataclasses_slotsPartialDoes not reject write to instance variable that is not defined in __slots__.
     dataclasses_transform_classPass
     dataclasses_transform_fieldPartialDoes not properly handle field constructor that has default value for `kw_only` or `init` parameter.
     dataclasses_transform_funcPartialDoes not handle `kw_only=False` override when `kw_only_default=True`.
Does not report error when `order=False` and comparison operators are used.
     dataclasses_transform_metaPass
     dataclasses_usagePass
+Typed dictionaries
     typeddicts_alt_syntaxPartialDoes not support keyword-argument form of alternative syntax (deprecated in 3.11).
     typeddicts_class_syntaxPass
     typeddicts_finalPass
     typeddicts_inheritancePass
     typeddicts_operationsPass
     typeddicts_requiredPartialDoes not support nesting of `Annotated` and `Required` or `NotRequired`.
     typeddicts_type_consistencyPass
     typeddicts_usagePass
+Type narrowing
     narrowing_typeguardPass
+
pyright 1.1.343(1.01sec) +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Type annotations
     annotations_typeexprPass
+Generics
     generics_self_advancedPass
     generics_self_attributesPass
     generics_self_basicPass
     generics_self_protocolsPass
     generics_self_usagePass
+Type aliases
     aliases_explicitPartialIncorrectly evaluates type of specialized type alias parameterized with ParamSpec.
Allows some illegal annotation forms to be interpreted as valid type aliases.
     aliases_implicitPartialIncorrectly evaluates type of specialized type alias parameterized with ParamSpec.
Allows some illegal annotation forms to be interpreted as valid type aliases.
     aliases_newtypePartialDoes not reject use of NewType in `isinstance` call.
Does not report inconsistency between name of NewType and assigned identifier name.
Does not reject use of NewType with TypedDict class.
Does not reject use of NewType with another NewType.
Does not reject use of NewType with Any.
     aliases_recursivePass
     aliases_type_statementPartialDoes not reject binary expression when used in type alias definition.
     aliases_typealiastypePartialDoes not reject type alias expression that uses TypeVar that is not in scope and not in `type_params`.
Does not allow access to `__value__` attribute of type alias.
Allows some illegal annotation forms to be interpreted as valid type aliases.
     aliases_variancePass
+Literals
     literals_interactionsPass
     literals_literalstringPass
     literals_parameterizationsPass
     literals_semanticsPass
+Callables
     callables_annotationPass
     callables_kwargsPass
     callables_protocolPartialDoes not report type incompatibility for callback protocol with positional-only parameters.
+Dataclasses
     dataclasses_descriptorsPass
     dataclasses_frozenPass
     dataclasses_hashPass
     dataclasses_inheritancePass
     dataclasses_kwonlyPass
     dataclasses_orderPass
     dataclasses_postinitPartialReports incorrect error for incompatible `__post_init__` method override.
     dataclasses_slotsPass
     dataclasses_transform_classPass
     dataclasses_transform_fieldPass
     dataclasses_transform_funcPass
     dataclasses_transform_metaPass
     dataclasses_usagePass
+Typed dictionaries
     typeddicts_alt_syntaxPass
     typeddicts_class_syntaxPass
     typeddicts_finalPass
     typeddicts_inheritancePass
     typeddicts_operationsPass
     typeddicts_requiredPass
     typeddicts_type_consistencyPass
     typeddicts_usagePass
+Type narrowing
     narrowing_typeguardPass
+
pyre 0.9.19(1.40sec) +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Type annotations
     annotations_typeexprPass
+Generics
     generics_self_advancedUnsupportedDoes not understand `Self` type.
     generics_self_attributesUnsupportedDoes not understand `Self` type.
     generics_self_basicUnsupportedDoes not understand `Self` type.
     generics_self_protocolsPartialDoes not reject protocol compatibility due to method `Self` return type.
     generics_self_usageUnsupportedDoes not understand `Self` type.
+Type aliases
     aliases_explicitPartialIncorrectly reports error for type alias defined with ParamSpec.
Incorrectly rejects some valid type aliases when used in annotations.
Incorrectly evaluates generic type alias with ParamSpec with missing type argument.
Does not report some illegal annotation forms as invalid type aliases.
Does not report invalid specialization of generic type aliases.
Incorrectly rejects import alias of `TypeAlias` when used to define type alias.
Does not report invalid specialization of already-specialized generic type alias.
     aliases_implicitPartialIncorrectly reports error for type alias defined with ParamSpec.
Incorrectly rejects some valid type aliases when used in annotations.
Incorrectly evaluates generic type alias with ParamSpec with missing type argument.
Does not report invalid specialization of generic type aliases.
Does not report error for attempt to instantiate union type alias.
Does not report invalid specialization of already-specialized generic type alias.
     aliases_newtypePartialDoes not reject use of NewType in `isinstance` call.
Does not reject use of NewType in class definition statement.
Does not report inconsistency between name of NewType and assigned identifier name.
Does not reject use of NewType with generic class with TypeVar.
Does not reject use of NewType with protocol class.
Does not reject use of NewType with TypedDict class.
Does not reject use of NewType with another NewType.
Does not reject use of NewType with Any.
     aliases_recursivePartialDoes not properly handle some recursive type aliases.
Does not properly handle specialization of generic recursive type aliases.
     aliases_type_statementUnsupportedDoes not support `type` statement.
     aliases_typealiastypeUnsupportedSupport for TypeAliasType is not implemented.
     aliases_variancePass
+Literals
     literals_interactionsPartialDoes not detect out-of-bound tuple literal index.
Does not narrow type of `x` with `x in Literal` type guard pattern.
Does not narrow type of `x` with `x == Literal` type guard pattern.
     literals_literalstringPass
     literals_parameterizationsPartialDoes not support type aliases in Literal type expression.
Does not support nested Literal type expression.
Does not reject unary + operator in Literal type expression.
Does not reject tuple in Literal type expression.
Does not reject "bare" Literal in type expression.
     literals_semanticsPartialDoes not reject augmented operation that modifies literal value.
+Callables
     callables_annotationPartialDoes not evaluate correct type for `*args: int` parameter.
Does not reject illegal form `Callable[[...], int]`.
     callables_kwargsUnsupportedDoes not understand Unpack in the context of **kwargs annotation.
     callables_protocolPartialDoes not correctly handle callback protocol that declares attributes in all functions.
Does not report type incompatibility for callback protocol with positional-only parameters.
Incorrectly reports type compatibility error with callback that has *args and **kwargs.
Does not report type incompatibility for callback missing a default argument for positional parameter.
Does not report type incompatibility for callback missing a default argument for keyword parameter.
+Dataclasses
     dataclasses_descriptorsPartialIncorrectly generates error when calling constructor of dataclass with descriptor.
     dataclasses_frozenPartialDoes not reject frozen dataclass inherited from non-frozen dataclass.
Does not reject non-frozen dataclass inherited from frozen dataclass.
     dataclasses_hashPartialDoes not report when dataclass is not compatible with Hashable protocol.
     dataclasses_inheritancePartialDoes not reject ClassVar that is overridden by instance variable.
Does not reject instance variable that is overridden by ClassVar.
     dataclasses_kwonlyPass
     dataclasses_orderPartialDoes not report type incompatibility with comparison operator.
     dataclasses_postinitUnsupportedDoes not perform validation of `__post_init__` method.
Does not reject access of `InitVar` from object.
     dataclasses_slotsPartialDoes not report error when `slots=True` is used with `__slots__` definition.
Does not reject write to instance variable that is not defined in __slots__.
Does not reject access to `__slots__` from dataclass instance when `slots=False`.
     dataclasses_transform_classUnsupportedDoes not understand @dataclass_transform.
     dataclasses_transform_fieldUnsupportedDoes not understand @dataclass_transform.
     dataclasses_transform_funcUnsupportedDoes not understand @dataclass_transform.
     dataclasses_transform_metaUnsupportedDoes not understand @dataclass_transform.
     dataclasses_usagePartialDoes not report error when field with no default follows field with default.
Incorrectly reports error with InitVar that has default value.
+Typed dictionaries
     typeddicts_alt_syntaxPartialDoes not report when name of TypedDict doesn't match assigned identifier name.
Does not support keyword-argument form of alternative syntax (deprecated in 3.11).
     typeddicts_class_syntaxPartialDoes not reject methods within TypedDict class.
Does not report when metaclass is provided.
Does not report when other keyword argument is provided.
Does not support generic TypedDict class.
     typeddicts_finalPartialDoes not handle value with literal type as index to TypedDict object.
     typeddicts_inheritancePartialDoes not reject TypedDict class that inherits from non-TypedDict class.
     typeddicts_operationsPass
     typeddicts_requiredPartialDoes not reject use of `Required` in function parameter annotation.
Does not reject nested use of `Required` in type annotation.
Does not support recursive TypedDict definitions.
     typeddicts_type_consistencyPartialDoes not reject assignment of TypedDict with missing key.
Does not return non-Optional value from `get` method for required key.
Does not properly handle nested TypedDicts.
     typeddicts_usagePartialDoes not report errant use of TypedDict in `isinstance` call.
Does not reject use of TypedDict as TypeVar bound.
+Type narrowing
     narrowing_typeguardPartialDoes not support `tuple` in `assert_type` call.
Does not reject TypeGuard method with too few parameters.
+
pytype 2023.12.18(51.57sec) +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+Type annotations
     annotations_typeexprPartialDoes not reject call expressions in type annotation.
Does not reject call lambda expression in type annotation.
Does not reject list expression in type annotation.
Does not reject ternary expression in type annotation.
Does not reject f-string in type annotation.
+Generics
     generics_self_advancedUnsupportedDoes not understand `Self` type.
     generics_self_attributesUnsupportedDoes not understand `Self` type.
     generics_self_basicUnsupportedDoes not understand `Self` type.
     generics_self_protocolsPartialDoes not reject protocol compatibility due to method `Self` return type.
     generics_self_usageUnsupportedDoes not understand `Self` type.
+Type aliases
     aliases_explicitPartialIncorrectly reports error for type alias defined with ParamSpec.
Does not report invalid specialization of generic type alias with bound TypeVar.
Incorrectly evaluates generic type alias with ParamSpec with missing type argument.
Does not report some illegal annotation forms as invalid type aliases.
Does not report invalid specialization of already-specialized generic type alias.
     aliases_implicitPartialIncorrectly reports error for type alias defined with ParamSpec.
Does not report invalid specialization of generic type alias with bound TypeVar.
Incorrectly evaluates generic type alias with ParamSpec with missing type argument.
Allows some illegal annotation forms to be interpreted as valid type aliases.
Does not report invalid specialization of already-specialized generic type alias.
     aliases_newtypePartialDoes not reject use of NewType in `isinstance` call.
Does not reject use of NewType in class definition statement.
Does not report inconsistency between name of NewType and assigned identifier name.
Does not reject use of NewType with generic class with TypeVar.
Does not reject use of NewType with protocol class.
Does not reject use of NewType with TypedDict class.
Does not reject use of NewType with another NewType.
Does not reject use of NewType with Any.
     aliases_recursivePartialDoes not detect type violation for some deeply-nested types.
Does not properly handle `|` for unions in some recursive type alias definitions.
Does not detect cyclical references in recursive type alias definition.
     aliases_type_statementUnsupportedDoes not support `type` statement.
     aliases_typealiastypeUnsupportedSupport for TypeAliasType is not implemented.
     aliases_varianceUnsupportedDoes not detect variance incompatibility.
+Literals
     literals_interactionsPartialIncorrectly rejects some legal Literal annotations.
Does not reject some illegal Literal annotations.
Does not use Literal to distinguish overloads.
Does not narrow based on `x is Literal` type guard pattern.
Does not narrow based on `x == Literal` type guard pattern.
     literals_literalstringUnsupportedDoes not understand `LiteralString` special form.
     literals_parameterizationsUnsupportedDoes not understand `Literal` type annotation.
     literals_semanticsUnsupportedDoes not understand `Literal` type annotation.
+Callables
     callables_annotationPass
     callables_kwargsUnsupportedDoes not understand Unpack in the context of **kwargs annotation.
     callables_protocolUnsupportedDoes not properly handle type compatibility checks with callback protocols.
+Dataclasses
     dataclasses_descriptorsUnsupportedDoes not understand descriptor objects in dataclass.
     dataclasses_frozenUnsupportedDoes not report assignment to field within frozen dataclass instance.
Does not reject frozen dataclass inherited from non-frozen dataclass.
Does not reject non-frozen dataclass inherited from frozen dataclass.
     dataclasses_hashPartialDoes not report when dataclass is not compatible with Hashable protocol.
     dataclasses_inheritancePartialDoes not reject ClassVar that is overridden by instance variable.
Does not reject instance variable that is overridden by ClassVar.
     dataclasses_kwonlyPartialIncorrectly reports error when kw_only field has default value.
Incorrectly rejects kw_only field with default before positional field.
     dataclasses_orderPartialDoes not report type incompatibility with comparison operator.
     dataclasses_postinitPartialDoes not validate `__post_init__` method.
Reports incorrect error for incompatible `__post_init__` method override.
     dataclasses_slotsPartialDoes not report error when `slots=True` is used with `__slots__` definition.
Does not reject write to instance variable that is not defined in __slots__.
Incorrectly reports error when accessing `__slots__` when `slots=True`.
     dataclasses_transform_classUnsupportedDoes not understand @dataclass_transform.
     dataclasses_transform_fieldUnsupportedDoes not understand @dataclass_transform.
     dataclasses_transform_funcUnsupportedDoes not understand @dataclass_transform.
     dataclasses_transform_metaUnsupportedDoes not understand @dataclass_transform.
     dataclasses_usagePass
+Typed dictionaries
     typeddicts_alt_syntaxPartialDoes not reject use of variable as second argument to `TypedDict` call.
Does not report when name of TypedDict doesn't match assigned identifier name.
Does not support keyword-argument form of alternative syntax (deprecated in 3.11).
     typeddicts_class_syntaxPartialDoes not reject methods within TypedDict class.
Does not report when metaclass is provided.
Does not report when other keyword argument is provided.
     typeddicts_finalPass
     typeddicts_inheritancePass
     typeddicts_operationsPartialDoes not report type violation with TypedDict value assignment.
Does not report reference to unknown key in TypedDict.
Does not reject `clear` method on TypedDict with required keys.
Does not reject delete operation for required key in TypedDict.
     typeddicts_requiredPartialDoes not reject use of `Required` in non-TypedDict class.
Does not reject use of `Required` in function parameter annotation.
Does not reject nested use of `Required` in type annotation.
     typeddicts_type_consistencyPartialDoes not report some type violations for TypedDict type compatibility.
Incorrectly reports type violation in cases where there is none.
Does not report type incompatibility between TypedDict and `dict[str, Any]`.
     typeddicts_usagePartialDoes not report errant use of TypedDict in `isinstance` call.
Does not reject use of TypedDict as TypeVar bound.
+Type narrowing
     narrowing_typeguardPartialDoes not reject TypeGuard method with too few parameters.
+ + +
+ + + \ No newline at end of file diff --git a/conformance/src/__init__.py b/conformance/src/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/conformance/src/main.py b/conformance/src/main.py new file mode 100644 index 000000000..be474bac0 --- /dev/null +++ b/conformance/src/main.py @@ -0,0 +1,129 @@ +""" +Type system conformance test for static type checkers. +""" + +import os +from pathlib import Path +import sys +from time import time +from typing import Sequence + +import tomli +import tomlkit + +from reporting import generate_summary +from test_groups import get_test_cases, get_test_groups +from type_checker import TYPE_CHECKERS, TypeChecker + + +def run_tests( + root_dir: Path, + type_checker: TypeChecker, + test_cases: Sequence[Path], +): + print(f"Running tests for {type_checker.name}") + + test_start_time = time() + tests_output = type_checker.run_tests([file.name for file in test_cases]) + test_duration = time() - test_start_time + + results_dir = root_dir / "results" / type_checker.name + + for test_case in test_cases: + update_output_for_test( + type_checker, results_dir, test_case, tests_output.get(test_case.name, "") + ) + + update_type_checker_info(type_checker, root_dir, test_duration) + + +def update_output_for_test( + type_checker: TypeChecker, + results_dir: Path, + test_case: Path, + output: str, +): + test_name = test_case.stem + output = f"\n{output}" + + results_file = results_dir / f"{test_name}.toml" + results_file.parent.mkdir(parents=True, exist_ok=True) + + # Read the existing results file if present. + try: + with open(results_file, "rb") as f: + existing_results = tomli.load(f) + except FileNotFoundError: + existing_results = {} + + old_output = existing_results.get("output", None) + old_output = f"\n{old_output}" + + # Did the type checker output change since last time the + # test was run? + if old_output != output: + print(f"Output changed for {test_name} when running {type_checker.name}") + print(f"Old output: {old_output}") + print(f"New output: {output}") + print("") + + # Use multiline formatting for any strings that contain newlines. + for key, value in existing_results.items(): + if isinstance(value, str) and "\n" in value: + existing_results[key] = tomlkit.string(f"\n{value}", multiline=True) + + existing_results["output"] = tomlkit.string(output, multiline=True) + + results_file.parent.mkdir(parents=True, exist_ok=True) + with open(results_file, "w") as f: + tomlkit.dump(existing_results, f) + + +def update_type_checker_info(type_checker: TypeChecker, root_dir: Path, test_duration: float): + # Record the version of the type checker used for the latest run. + version_file = root_dir / "results" / type_checker.name / "version.toml" + + # Read the existing version file if present. + try: + with open(version_file, "rb") as f: + existing_info = tomli.load(f) + except FileNotFoundError: + existing_info = {} + + existing_info["version"] = type_checker.get_version() + existing_info["test_duration"] = test_duration + + version_file.parent.mkdir(parents=True, exist_ok=True) + with open(version_file, "w") as f: + tomlkit.dump(existing_info, f) + + +def main(): + # Some tests cover features that are available only in the + # latest version of Python (3.12), so we need this version. + assert sys.version_info >= (3, 12) + + root_dir = Path(__file__).resolve().parent.parent + + tests_dir = root_dir / "tests" + assert tests_dir.is_dir() + + test_groups = get_test_groups(root_dir) + 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 not type_checker.install(): + print(f'Skipping tests for {type_checker.name}') + else: + run_tests(root_dir, type_checker, test_cases) + + # Generate a summary report. + generate_summary(root_dir) + + +if __name__ == "__main__": + main() diff --git a/conformance/src/reporting.py b/conformance/src/reporting.py new file mode 100644 index 000000000..95c9c14c3 --- /dev/null +++ b/conformance/src/reporting.py @@ -0,0 +1,104 @@ +""" +Generates a summary of the type checker conformant tests. +""" + +from pathlib import Path + +import tomli + +from test_groups import get_test_cases, get_test_groups +from type_checker import TYPE_CHECKERS + + +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)) + + results_file = root_dir / "results" / "results.html" + + with open(results_file, "w") as f: + f.write(summary) + + +def generate_summary_html(root_dir: Path): + test_groups = get_test_groups(root_dir) + test_cases = get_test_cases(test_groups, root_dir / "tests") + + summary_html = "" + + for type_checker in TYPE_CHECKERS: + # Load the version file for the type checker. + version_file = root_dir / "results" / type_checker.name / "version.toml" + + try: + with open(version_file, "rb") as f: + existing_info = tomli.load(f) + except FileNotFoundError: + existing_info = {} + + version = existing_info["version"] or "Unknown version" + test_duration = existing_info.get("test_duration") + + summary_html += f"
{version}" + if test_duration is not None: + summary_html += f"({test_duration:.2f}sec)\n" + summary_html += '
\n' + summary_html += '
\n' + summary_html += '\n' + + 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}_") + ] + + 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 += '\n" + + for test_case in tests_in_group: + test_case_name = test_case.stem + + 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 = {} + + conformance = results.get("conformant", "Unknown") + notes = results.get("notes", "").replace("\n", "
") + + conformance_class = ( + "conformant" + if conformance == "Pass" + else "partially-conformant" + if conformance == "Partial" + else "not-conformant" + ) + + summary_html += f"" + summary_html += f'' + summary_html += f'' + summary_html += f'\n' + + # Add spacer row after this group to help with readability. + summary_html += '\n' + + summary_html += "
\n' + summary_html += f'{test_group.name}' + summary_html += "
     {test_case_name}{conformance}{notes}
\n" + + return summary_html diff --git a/conformance/src/results_template.html b/conformance/src/results_template.html new file mode 100644 index 000000000..e15ada5bc --- /dev/null +++ b/conformance/src/results_template.html @@ -0,0 +1,147 @@ + + + + + + + Type System Test Results + + + + +
+
+

Python Type System Conformance Test Results

+
+ {{summary}} + +
+ + + \ No newline at end of file diff --git a/conformance/src/test_groups.py b/conformance/src/test_groups.py new file mode 100644 index 000000000..f0145ff11 --- /dev/null +++ b/conformance/src/test_groups.py @@ -0,0 +1,46 @@ +""" +Reads a template file that describes groups of tests in the +conformance test suite. +""" + +from dataclasses import dataclass +from pathlib import Path +from typing import Mapping, Sequence + +import tomli + + +@dataclass +class TestGroup: + name: str + href: str + + +def get_test_groups(root_dir: Path) -> Mapping[str, TestGroup]: + # Read the TOML file that defines the test groups. Each test + # 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) + + return { + k: TestGroup(v.get("name", "unknown"), v.get("href", "")) + for k, v in test_groups.items() + } + + +def get_test_cases( + test_groups: Mapping[str, TestGroup], tests_dir: Path +) -> Sequence[Path]: + test_group_names = test_groups.keys() + + # Filter test cases based on test group names. Files that do + # not begin with a known test group name are assumed to be + # files that support one or more tests. + test_cases = [ + p + for p in Path(tests_dir).glob("*.py") + if p.name.split("_")[0] in test_group_names + ] + + return test_cases diff --git a/conformance/src/test_groups.toml b/conformance/src/test_groups.toml new file mode 100644 index 000000000..e7a8ae629 --- /dev/null +++ b/conformance/src/test_groups.toml @@ -0,0 +1,68 @@ + +[concepts] +name = "Type system concepts" +href = "https://typing.readthedocs.io/en/latest/spec/concepts.html" + +[annotations] +name = "Type annotations" +href = "https://typing.readthedocs.io/en/latest/spec/annotations.html" + +[specialtypes] +name = "Special types in annotations" +href = "https://typing.readthedocs.io/en/latest/spec/special-types.html" + +[generics] +name = "Generics" +href = "https://typing.readthedocs.io/en/latest/spec/generics.html" + +[qualifiers] +name = "Type qualifiers" +href = "https://typing.readthedocs.io/en/latest/spec/qualifiers.html" + +[classes] +name = "Class type compatibility" +href = "https://typing.readthedocs.io/en/latest/spec/class-compat.html" + +[aliases] +name = "Type aliases" +href = "https://typing.readthedocs.io/en/latest/spec/aliases.html" + +[literals] +name = "Literals" +href = "https://typing.readthedocs.io/en/latest/spec/literal.html" + +[protocols] +name = "Protocols" +href = "https://typing.readthedocs.io/en/latest/spec/protocol.html" + +[callables] +name = "Callables" +href = "https://typing.readthedocs.io/en/latest/spec/callables.html" + +[overloads] +name = "Overloads" +href = "https://typing.readthedocs.io/en/latest/spec/overload.html" + +[dataclasses] +name = "Dataclasses" +href = "https://typing.readthedocs.io/en/latest/spec/dataclasses.html" + +[typeddicts] +name = "Typed dictionaries" +href = "https://typing.readthedocs.io/en/latest/spec/typeddict.html" + +[narrowing] +name = "Type narrowing" +href = "https://typing.readthedocs.io/en/latest/spec/narrowing.html" + +[directives] +name = "Type checker directives" +href = "https://typing.readthedocs.io/en/latest/spec/directives.html" + +[distribution] +name = "Distributing type information" +href = "https://typing.readthedocs.io/en/latest/spec/distributing.html" + +[historical] +name = "Historical and deprecated features" +href = "https://typing.readthedocs.io/en/latest/spec/historical.html" diff --git a/conformance/src/type_checker.py b/conformance/src/type_checker.py new file mode 100644 index 000000000..905d56296 --- /dev/null +++ b/conformance/src/type_checker.py @@ -0,0 +1,244 @@ +""" +Classes that abstract differences between type checkers. +""" + +from abc import ABC, abstractmethod +import json +from pathlib import Path +import re +from subprocess import PIPE, run +import sys +from typing import Sequence + + +class TypeChecker(ABC): + @property + @abstractmethod + def name(self) -> str: + """ + Returns the name of the type checker. + """ + raise NotImplementedError + + @abstractmethod + def install(self) -> bool: + """ + Ensures that the latest version of the type checker is installed. + Returns False if installation fails. + """ + raise NotImplementedError + + @abstractmethod + def get_version(self) -> str: + """ + Returns the current version string for the type checker. + """ + raise NotImplementedError + + @abstractmethod + def run_tests(self, test_files: Sequence[str]) -> dict[str, str]: + """ + Runs the type checker on the specified test file and + returns the output. + """ + raise NotImplementedError + + +class MypyTypeChecker(TypeChecker): + @property + def name(self) -> str: + return "mypy" + + def install(self) -> bool: + try: + run(f"{sys.executable} -m pip install mypy --upgrade", check=True, shell=True) + return True + except: + print('Unable to install mypy') + return False + + def get_version(self) -> str: + proc = run( + f"{sys.executable} -m mypy --version", stdout=PIPE, text=True, shell=True + ) + version = proc.stdout.strip() + + # Remove the " (compiled)" if it's present. + version = version.split(" (")[0] + return version + + def run_tests(self, test_files: Sequence[str]) -> dict[str, str]: + command = f"{sys.executable} -m mypy . --disable-error-code empty-body" + proc = run(command, stdout=PIPE, text=True, shell=True) + lines = proc.stdout.split("\n") + + # Add results to a dictionary keyed by the file name. + results_dict: dict[str, str] = {} + for line in lines: + file_name = line.split(":")[0].strip() + results_dict[file_name] = results_dict.get(file_name, "") + line + "\n" + + return results_dict + + +class PyrightTypeChecker(TypeChecker): + @property + def name(self) -> str: + return "pyright" + + def install(self) -> bool: + try: + # Install the Python wrapper if it's not installed. + run(f"{sys.executable} -m pip install pyright --upgrade", check=True, shell=True) + + # Force the Python wrapper to install node if needed + # and download the latest version of pyright. + self.get_version() + return True + except: + print('Unable to install pyright') + return False + + def get_version(self) -> str: + proc = run( + f"{sys.executable} -m pyright --version", stdout=PIPE, text=True, shell=True + ) + return proc.stdout.strip() + + def run_tests(self, test_files: Sequence[str]) -> dict[str, str]: + command = f"{sys.executable} -m pyright . --outputjson" + proc = run(command, stdout=PIPE, text=True, shell=True) + output_json = json.loads(proc.stdout) + diagnostics = output_json["generalDiagnostics"] + + # Add results to a dictionary keyed by the file name. + results_dict: dict[str, str] = {} + for diagnostic in diagnostics: + file_path = Path(diagnostic.get("file", "")) + file_name = file_path.name + line_number = diagnostic["range"]["start"]["line"] + 1 + col_number = diagnostic["range"]["start"]["character"] + 1 + severity = diagnostic["severity"] + message = diagnostic["message"] + rule = f" ({diagnostic['rule']})" if "rule" in diagnostic else "" + + line_text = f"{file_name}:{line_number}:{col_number} - {severity}: {message}{rule}\n" + results_dict[file_name] = results_dict.get(file_name, "") + line_text + + return results_dict + + +class PyreTypeChecker(TypeChecker): + @property + def name(self) -> str: + return "pyre" + + def install(self) -> bool: + try: + run(f"{sys.executable} -m pip install pyre-check --upgrade", check=True, shell=True) + + # Generate a default config file. + pyre_config = ( + '{"site_package_search_strategy": "pep561", "source_directories": ["."]}\n' + ) + with open(".pyre_configuration", "w") as f: + f.write(pyre_config) + + return True + except: + print('Unable to install pyre') + return False + + def get_version(self) -> str: + proc = run("pyre --version", stdout=PIPE, text=True, shell=True) + version = proc.stdout.strip() + version = version.replace("Client version:", "pyre") + return version + + def run_tests(self, test_files: Sequence[str]) -> dict[str, str]: + proc = run("pyre check", stdout=PIPE, text=True, shell=True) + lines = proc.stdout.split("\n") + + # Add results to a dictionary keyed by the file name. + results_dict: dict[str, str] = {} + for line in lines: + file_name = line.split(":")[0].strip() + results_dict[file_name] = results_dict.get(file_name, "") + line + "\n" + + return results_dict + + +class PytypeTypeChecker(TypeChecker): + @property + def name(self) -> str: + return "pytype" + + def install(self) -> bool: + try: + run(f"{sys.executable} -m pip install pytype --upgrade", check=True, shell=True) + return True + except: + print('Unable to install pytype on this platform') + return False + + def get_version(self) -> str: + proc = run( + f"{sys.executable} -m pytype --version", stdout=PIPE, text=True, shell=True + ) + version = proc.stdout.strip() + return f"pytype {version}" + + def run_tests(self, test_files: Sequence[str]) -> dict[str, str]: + # Specify 3.11 for now to work around the fact that pytype + # currently doesn't support 3.12 and emits an error when + # running on 3.12. + command = f"{sys.executable} -m pytype -V 3.11 -k *.py" + proc = run(command, stdout=PIPE, text=True, shell=True) + lines = proc.stdout.split("\n") + + # Add results to a dictionary keyed by the file name. + results_dict: dict[str, str] = {} + accumulated_lines: list[str] = [] + file_name: str | None = None + + def log_accumulated(): + if file_name is not None: + results_dict[file_name] = ( + results_dict.get(file_name, "") + "".join(accumulated_lines) + "\n" + ) + + for line in lines: + match = re.search(r'File "(.*?)",', line) + + if not match or match.start() != 0: + # An empty line precedes the summary for the file. Ignore + # everything after that line until we see diagnostics for + # the next file. + if line.strip() == "": + log_accumulated() + file_name = None + accumulated_lines = [] + elif file_name is not None: + accumulated_lines.append("\n" + line) + else: + log_accumulated() + + file_path = Path(match.group(1)) + file_name = file_path.name + + # Replace the full file path with the file name. + line = f'File "{file_name}",{line[match.end():]}' + accumulated_lines = [line] + + # Log the final accumulated lines. + log_accumulated() + + return results_dict + + +TYPE_CHECKERS: Sequence[TypeChecker] = ( + MypyTypeChecker(), + PyrightTypeChecker(), + PyreTypeChecker(), + PytypeTypeChecker(), +) diff --git a/conformance/tests/aliases_explicit.py b/conformance/tests/aliases_explicit.py new file mode 100644 index 000000000..a4168bb60 --- /dev/null +++ b/conformance/tests/aliases_explicit.py @@ -0,0 +1,102 @@ +""" +Tests explicit type aliases defined with `TypeAlias`. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/aliases.html#typealias + +from typing import Any, Callable, Concatenate, Literal, ParamSpec, TypeVar, Union, assert_type +from typing import TypeAlias as TA + +S = TypeVar("S") +T = TypeVar("T") +P = ParamSpec("P") +R = TypeVar("R") + +GoodTypeAlias1: TA = Union[int, str] +GoodTypeAlias2: TA = int | None +GoodTypeAlias3: TA = list[GoodTypeAlias2] +GoodTypeAlias4: TA = list[T] +GoodTypeAlias5: TA = tuple[T, ...] | list[T] +GoodTypeAlias6: TA = tuple[int, int, S, T] +GoodTypeAlias7: TA = Callable[..., int] +GoodTypeAlias8: TA = Callable[[int, T], T] +GoodTypeAlias9: TA = Callable[Concatenate[int, P], R] +GoodTypeAlias10: TA = Any +GoodTypeAlias11: TA = GoodTypeAlias1 | GoodTypeAlias2 | list[GoodTypeAlias4[int]] +GoodTypeAlias12: TA = Callable[P, None] +GoodTypeAlias13: TA = "int | str" +GoodTypeAlias14: TA = list["int | str"] +GoodTypeAlias15: TA = Literal[3, 4, 5, None] + + +def good_type_aliases( + p1: GoodTypeAlias1, + p2: GoodTypeAlias2, + p3: GoodTypeAlias3, + p4: GoodTypeAlias4[int], + p5: GoodTypeAlias5[str], + p6: GoodTypeAlias6[int, str], + p7: GoodTypeAlias7, + p8: GoodTypeAlias8[str], + p9: GoodTypeAlias9[[str, str], None], + p10: GoodTypeAlias10, + p11: GoodTypeAlias11, + p12: GoodTypeAlias12, + p13: GoodTypeAlias13, + p14: GoodTypeAlias14, + p15: GoodTypeAlias15, +): + assert_type(p1, int | str) + assert_type(p2, int | None) + assert_type(p3, list[int | None]) + assert_type(p4, list[int]) + assert_type(p5, tuple[str, ...] | list[str]) + assert_type(p6, tuple[int, int, int, str]) + assert_type(p7, Callable[..., int]) + assert_type(p8, Callable[[int, str], str]) + assert_type(p9, Callable[[int, str, str], None]) + assert_type(p10, Any) + assert_type(p11, int | str | None | list[list[int]]) + assert_type(p12, Callable[..., None]) + assert_type(p13, int | str) + assert_type(p14, list[int | str]) + assert_type(p15, Literal[3, 4, 5, None]) + + +def good_type_aliases_used_badly( + p1: GoodTypeAlias2[int], # Type error: type alias is not generic + p2: GoodTypeAlias3[int], # Type error: type alias is already specialized + p3: GoodTypeAlias4[int, int], # Type error: too many type arguments + p4: GoodTypeAlias8[int, int], # Type error: too many type arguments + p5: GoodTypeAlias9[int, int], # Type error: bad type argument for ParamSpec +): + pass + + +var1 = 3 + +# The following should not be allowed as type aliases. +BadTypeAlias1: TA = eval("".join(map(chr, [105, 110, 116]))) +BadTypeAlias2: TA = [int, str] +BadTypeAlias3: TA = ((int, str),) +BadTypeAlias4: TA = [int for i in range(1)] +BadTypeAlias5: TA = {"a": "b"} +BadTypeAlias6: TA = (lambda: int)() +BadTypeAlias7: TA = [int][0] +BadTypeAlias8: TA = int if 1 < 3 else str +BadTypeAlias9: TA = var1 +BadTypeAlias10: TA = True +BadTypeAlias11: TA = 1 +BadTypeAlias12: TA = list or set +BadTypeAlias13: TA = f"{'int'}" + + +ListAlias: TA = list +ListOrSetAlias: TA = list | set + +x1: list[str] = ListAlias() # OK +assert_type(x1, list[str]) + +x2: ListAlias[int] # Type error: already specialized +x3 = ListOrSetAlias() # Type error: cannot instantiate union +x4: ListOrSetAlias[int] # Type error: already specialized diff --git a/conformance/tests/aliases_implicit.py b/conformance/tests/aliases_implicit.py new file mode 100644 index 000000000..3d700d807 --- /dev/null +++ b/conformance/tests/aliases_implicit.py @@ -0,0 +1,136 @@ +""" +Tests traditional implicit type aliases. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/aliases.html + +from collections.abc import Iterable +from typing import Any, Callable, Concatenate, ParamSpec, TypeVar, Union, assert_type + +TFloat = TypeVar("TFloat", bound=float) +Vector = Iterable[tuple[TFloat, TFloat]] + + +def in_product(v: Vector[TFloat]) -> Iterable[TFloat]: + return [x for x, _ in v] + + +def dilate(v: Vector[float], scale: float) -> Vector[float]: + return ((x * scale, y * scale) for x, y in v) + + +# > Type aliases may be as complex as type hints in annotations – anything +# > that is acceptable as a type hint is acceptable in a type alias. + +S = TypeVar("S") +T = TypeVar("T") +P = ParamSpec("P") +R = TypeVar("R") + +GoodTypeAlias1 = Union[int, str] +GoodTypeAlias2 = int | None +GoodTypeAlias3 = list[GoodTypeAlias2] +GoodTypeAlias4 = list[T] +GoodTypeAlias5 = tuple[T, ...] | list[T] +GoodTypeAlias6 = tuple[int, int, S, T] +GoodTypeAlias7 = Callable[..., int] +GoodTypeAlias8 = Callable[[int, T], T] +GoodTypeAlias9 = Callable[Concatenate[int, P], R] +GoodTypeAlias10 = Any +GoodTypeAlias11 = GoodTypeAlias1 | GoodTypeAlias2 | list[GoodTypeAlias4[int]] +GoodTypeAlias12 = list[TFloat] +GoodTypeAlias13 = Callable[P, None] + + +def good_type_aliases( + p1: GoodTypeAlias1, + p2: GoodTypeAlias2, + p3: GoodTypeAlias3, + p4: GoodTypeAlias4[int], + p5: GoodTypeAlias5[str], + p6: GoodTypeAlias6[int, str], + p7: GoodTypeAlias7, + p8: GoodTypeAlias8[str], + p9: GoodTypeAlias9[[str, str], None], + p10: GoodTypeAlias10, + p11: GoodTypeAlias11, + p12: GoodTypeAlias12[bool], + p13: GoodTypeAlias13 +): + assert_type(p1, int | str) + assert_type(p2, int | None) + assert_type(p3, list[int | None]) + assert_type(p4, list[int]) + assert_type(p5, tuple[str, ...] | list[str]) + assert_type(p6, tuple[int, int, int, str]) + assert_type(p7, Callable[..., int]) + assert_type(p8, Callable[[int, str], str]) + assert_type(p9, Callable[[int, str, str], None]) + assert_type(p10, Any) + assert_type(p11, int | str | None | list[list[int]]) + assert_type(p12, list[bool]) + assert_type(p13, Callable[..., None]) + + +def good_type_aliases_used_badly( + p1: GoodTypeAlias2[int], # Type error: type alias is not generic + p2: GoodTypeAlias3[int], # Type error: type alias is already specialized + p3: GoodTypeAlias4[int, int], # Type error: too many type arguments + p4: GoodTypeAlias8[int, int], # Type error: too many type arguments + p5: GoodTypeAlias9[int, int], # Type error: bad type argument for ParamSpec + p6: GoodTypeAlias12[str], # Type error: type argument doesn't match bound +): + pass + + +var1 = 3 + +# The following should not be considered type aliases. +BadTypeAlias1 = eval("".join(map(chr, [105, 110, 116]))) +BadTypeAlias2 = [int, str] +BadTypeAlias3 = ((int, str),) +BadTypeAlias4 = [int for i in range(1)] +BadTypeAlias5 = {"a": "b"} +BadTypeAlias6 = (lambda: int)() +BadTypeAlias7 = [int][0] +BadTypeAlias8 = int if 1 < 3 else str +BadTypeAlias9 = var1 +BadTypeAlias10 = True +BadTypeAlias11 = 1 +BadTypeAlias12 = list or set +BadTypeAlias13 = f"int" +BadTypeAlias14 = "int | str" + + +def bad_type_aliases( + p1: BadTypeAlias1, # Type error: Invalid type annotation + p2: BadTypeAlias2, # Type error: Invalid type annotation + p3: BadTypeAlias3, # Type error: Invalid type annotation + p4: BadTypeAlias4, # Type error: Invalid type annotation + p5: BadTypeAlias5, # Type error: Invalid type annotation + p6: BadTypeAlias6, # Type error: Invalid type annotation + p7: BadTypeAlias7, # Type error: Invalid type annotation + p8: BadTypeAlias8, # Type error: Invalid type annotation + p9: BadTypeAlias9, # Type error: Invalid type annotation + p10: BadTypeAlias10, # Type error: Invalid type annotation + p11: BadTypeAlias11, # Type error: Invalid type annotation + p12: BadTypeAlias12, # Type error: Invalid type annotation + p13: BadTypeAlias13, # Type error: Invalid type annotation + p14: BadTypeAlias14, # Type error: Invalid type annotation +): + pass + + +ListAlias = list +ListOrSetAlias = list | set + +x1: list[str] = ListAlias() # OK +assert_type(x1, list[str]) + +x2 = ListAlias[int]() # OK +assert_type(x2, list[int]) + +x3 = ListOrSetAlias() # Type error: cannot instantiate union + +x4: ListOrSetAlias[int] # Type error: already specialized + diff --git a/conformance/tests/aliases_newtype.py b/conformance/tests/aliases_newtype.py new file mode 100644 index 000000000..92437c35b --- /dev/null +++ b/conformance/tests/aliases_newtype.py @@ -0,0 +1,62 @@ +""" +Tests the `typing.NewType` function. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/aliases.html#newtype + +from typing import Any, Hashable, Literal, NewType, TypeVar, TypedDict, assert_type + +UserId = NewType("UserId", int) + +UserId("user") # Type error: incorrect type +u1: UserId = 42 # Type error: incorrect type +u2: UserId = UserId(42) # OK + +assert_type(UserId(5) + 1, int) + +# > Both isinstance and issubclass, as well as subclassing will fail for +# > NewType('Derived', Base) since function objects don’t support these +# > operations. +isinstance(u2, UserId) # Type error: not allowed in isinstance call + + +class UserIdDerived(UserId): # Type error: subclassing not allowed + pass + + +# > NewType accepts exactly two arguments: a name for the new unique type, +# > and a base class. The latter should be a proper class (i.e., not a type +# > construct like Union, etc.), or another unique type created by +# > calling NewType. + +GoodName = NewType("BadName", int) # Type error: assigned name does not match + +GoodNewType1 = NewType("GoodNewType1", list) + +nt1: GoodNewType1[int] # Type error: NewType cannot be generic + +TypeAlias1 = dict[str, str] +GoodNewType2 = NewType("GoodNewType2", TypeAlias1) + + +BadNewType1 = NewType("BadNewType1", int | str) # Type error: cannot be generic + +T = TypeVar("T") +BadNewType2 = NewType("BadNewType2", list[T]) # Type error: cannot be generic + +BadNewType3 = NewType("BadNewType3", Hashable) # Type error: cannot be protocol + +BadNewType4 = NewType("BadNewType4", Literal[7]) # Type error: literal not allowed + + +class TD1(TypedDict): + a: int + + +BadNewType5 = NewType("BadNewType5", TD1) # Type error: cannot be TypedDict + +BadNewType6 = NewType("BadNewType6", GoodNewType1) # Type error: cannot be NewType + +BadNewType7 = NewType("BadNewType7", int, int) # Type error: too many arguments + +BadNewType8 = NewType("BadNewType8", Any) # Type error: cannot be Any diff --git a/conformance/tests/aliases_recursive.py b/conformance/tests/aliases_recursive.py new file mode 100644 index 000000000..9a459c9b2 --- /dev/null +++ b/conformance/tests/aliases_recursive.py @@ -0,0 +1,82 @@ +""" +Tests recursive (self-referential) type aliases. +""" + +# The typing specification doesn't mandate support for recursive +# (self-referential) type aliases prior to PEP 695, but it also +# doesn't indicates that they shouldn't work. +# Most type checkers now support them, and many libraries and code +# bases have started to rely on them. +# PEP 695 formally mandates that recursive type aliases work. + +from typing import Mapping, TypeAlias, TypeVar, Union + +Json = Union[None, int, str, float, list["Json"], dict[str, "Json"]] + +j1: Json = [1, {"a": 1}] # OK +j2: Json = 3.4 # OK +j3: Json = [1.2, None, [1.2, [""]]] # OK +j4: Json = {"a": 1, "b": 3j} # Type error: incompatible type +j5: Json = [2, 3j] # Type error: incompatible type + + +# This type alias should be equivalent to Json. +Json2 = Union[None, int, str, float, list["Json2"], dict[str, "Json2"]] + +def func1(j1: Json) -> Json2: + return j1 + + +RecursiveTuple = str | int | tuple["RecursiveTuple", ...] + + +t1: RecursiveTuple = (1, 1) # OK +t2: RecursiveTuple = (1, "1") # OK +t3: RecursiveTuple = (1, "1", 1, "2") # OK +t4: RecursiveTuple = (1, ("1", 1), "2") # OK +t5: RecursiveTuple = (1, ("1", 1), (1, (1, 2))) # OK +t6: RecursiveTuple = (1, ("1", 1), (1, (1, [2]))) # Type error +t6: RecursiveTuple = (1, [1]) # Type error + + +RecursiveMapping = str | int | Mapping[str, "RecursiveMapping"] + +m1: RecursiveMapping = 1 # OK +m2: RecursiveMapping = "1" # OK +m3: RecursiveMapping = {"1": "1"} # OK +m4: RecursiveMapping = {"1": "1", "2": 1} # OK +m5: RecursiveMapping = {"1": "1", "2": 1, "3": {}} # OK +m6: RecursiveMapping = {"1": "1", "2": 1, "3": {"0": "0", "1": "2", "2": {}}} # OK +m7: RecursiveMapping = {"1": [1]} # Type error +m8: RecursiveMapping = {"1": "1", "2": 1, "3": [1, 2]} # Type error +m9: RecursiveMapping = { + "1": "1", + "2": 1, + "3": {"0": "0", "1": 1, "2": [1, 2, 3]}, +} # Type error + + +T1 = TypeVar("T1", str, int) +T2 = TypeVar("T2") + +GenericTypeAlias1 = list["GenericTypeAlias1[T1]" | T1] +SpecializedTypeAlias1 = GenericTypeAlias1[str] + +g1: SpecializedTypeAlias1 = ["hi", ["hi", "hi"]] # OK +g2: GenericTypeAlias1[str] = ["hi", "bye", [""], [["hi"]]] # OK +g3: GenericTypeAlias1[str] = ["hi", [2.4]] # Type error + +GenericTypeAlias2 = list["GenericTypeAlias2[T1, T2]" | T1 | T2] + +g4: GenericTypeAlias2[str, int] = [[3, ["hi"]], "hi"] # OK +g5: GenericTypeAlias2[str, float] = [[3, ["hi", 3.4, [3.4]]], "hi"] # OK +g6: GenericTypeAlias2[str, int] = [[3, ["hi", 3, [3.4]]], "hi"] # Type error + + +RecursiveUnion: TypeAlias = Union["RecursiveUnion", int] # Type error: cyclical reference + +MutualReference1: TypeAlias = Union[ + "MutualReference2", int +] # Type error: cyclical reference +MutualReference2: TypeAlias = Union["MutualReference1", str] + diff --git a/conformance/tests/aliases_type_statement.py b/conformance/tests/aliases_type_statement.py new file mode 100644 index 000000000..d534ebff0 --- /dev/null +++ b/conformance/tests/aliases_type_statement.py @@ -0,0 +1,92 @@ +""" +Tests the "type" statement introduced in Python 3.12. +""" + +from typing import Callable, TypeVar + + +type GoodAlias1 = int +type GoodAlias2[S1, *S2, **S3] = Callable[S3, S1] | tuple[*S2] +type GoodAlias3 = GoodAlias2[int, tuple[int, str], ...] + + +class ClassA: + type GoodAlias4 = int | None + + +GoodAlias1.bit_count # Type error: cannot access attribute + +GoodAlias1() # Type error: cannot call alias + +print(GoodAlias1.__value__) # OK +print(GoodAlias1.__type_params__) # OK +print(GoodAlias1.other_attrib) # Type error: unknown attribute + + +class DerivedInt(GoodAlias1): # Type error: cannot use alias as base class + pass + + +def func2(x: object): + if isinstance(x, GoodAlias1): # Type error: cannot use alias in isinstance + pass + +var1 = 1 + +# The following should not be allowed as type aliases. +type BadTypeAlias1 = eval("".join(map(chr, [105, 110, 116]))) +type BadTypeAlias2 = [int, str] +type BadTypeAlias3 = ((int, str),) +type BadTypeAlias4 = [int for i in range(1)] +type BadTypeAlias5 = {"a": "b"} +type BadTypeAlias6 = (lambda: int)() +type BadTypeAlias7 = [int][0] +type BadTypeAlias8 = int if 1 < 3 else str +type BadTypeAlias9 = var1 +type BadTypeAlias10 = True +type BadTypeAlias11 = 1 +type BadTypeAlias12 = list or set +type BadTypeAlias13 = f"{'int'}" + +if 1 < 2: + type BadTypeAlias14 = int # Type error: redeclared +else: + type BadTypeAlias14 = int + + +def func3(): + type BadTypeAlias15 = int # Type error alias not allowed in function + + + +V = TypeVar("V") + +type TA1[K] = dict[K, V] # Type error: combines old and new TypeVars + + +T1 = TypeVar("T1") + +type TA2 = list[T1] # Type error: uses old TypeVar + + +type RecursiveTypeAlias1[T] = T | list[RecursiveTypeAlias1[T]] + +r1_1: RecursiveTypeAlias1[int] = 1 +r1_2: RecursiveTypeAlias1[int] = [1, [1, 2, 3]] + +type RecursiveTypeAlias2[S: int, T: str, **P] = Callable[P, T] | list[S] | list[RecursiveTypeAlias2[S, T, P]] + +r2_1: RecursiveTypeAlias2[str, str, ...] # Type error: not compatible with S bound +r2_2: RecursiveTypeAlias2[int, str, ...] +r2_3: RecursiveTypeAlias2[int, int, ...] # Type error: not compatible with T bound +r2_4: RecursiveTypeAlias2[int, str, [int, str]] + +type RecursiveTypeAlias3 = RecursiveTypeAlias3 # Type error: circular definition + +type RecursiveTypeAlias4[T] = T | RecursiveTypeAlias4[str] # Type error: circular definition + +type RecursiveTypeAlias5[T] = T | list[RecursiveTypeAlias5[T]] + +type RecursiveTypeAlias6 = RecursiveTypeAlias7 # Type error: circular definition +type RecursiveTypeAlias7 = RecursiveTypeAlias6 + diff --git a/conformance/tests/aliases_typealiastype.py b/conformance/tests/aliases_typealiastype.py new file mode 100644 index 000000000..9adad00f1 --- /dev/null +++ b/conformance/tests/aliases_typealiastype.py @@ -0,0 +1,70 @@ +""" +Tests the TypeAliasType call introduced in Python 3.12. +""" + +from typing import Callable, Generic, ParamSpec, TypeAliasType, TypeVar, TypeVarTuple + +S = TypeVar("S") +T = TypeVar("T") +TStr = TypeVar("TStr", bound=str) +P = ParamSpec("P") +Ts = TypeVarTuple("Ts") + +my_tuple = (S, T) +var1 = 3 + +GoodAlias1 = TypeAliasType("GoodAlias1", int) +GoodAlias2 = TypeAliasType("GoodAlias2", list[T], type_params=(T,)) +GoodAlias3 = TypeAliasType("GoodAlias3", list[T] | list[S], type_params=(S, T)) +GoodAlias4 = TypeAliasType("GoodAlias4", T | list[GoodAlias4[T]], type_params=(T,)) +GoodAlias5 = TypeAliasType( + "GoodAlias5", + Callable[P, TStr] | list[S] | list[GoodAlias5[S, TStr, P]] | tuple[*Ts], + type_params=(S, TStr, P, Ts), +) + +class ClassA(Generic[T]): + GoodAlias6 = TypeAliasType("GoodAlias6", list[T]) + + +print(GoodAlias1.__value__) # OK +print(GoodAlias1.__type_params__) # OK +print(GoodAlias1.other_attrib) # Type error: unknown attribute + + +x1: GoodAlias4[int] = 1 # OK +x2: GoodAlias4[int] = [1] # OK +x3: GoodAlias5[str, str, ..., int, str] # OK +x4: GoodAlias5[int, str, ..., int, str] # OK +x5: GoodAlias5[int, str, [int, str], *tuple[int, str, int]] # OK +x6: GoodAlias5[int, int, ...] # Type error: incorrect type arguments + + +BadAlias1 = TypeAliasType( + "BadAlias1", list[S], type_params=(T,) +) # Type error: S not in scope +BadAlias2 = TypeAliasType("BadAlias2", list[S]) # Type error: S not in scope +BadAlias3 = TypeAliasType( + "BadAlias3", int, type_params=my_tuple +) # Type error: not literal tuple +BadAlias4 = TypeAliasType("BadAlias4", BadAlias4) # Type error: circular dependency +BadAlias5 = TypeAliasType( + "BadAlias5", T | BadAlias5[str], type_params=(T,) +) # Type error: circular dependency +BadAlias6 = TypeAliasType("BadAlias6", BadAlias7) # Type error: circular dependency +BadAlias7 = TypeAliasType("BadAlias7", BadAlias6) + +# The following are invalid type expressions for a type alias. +BadAlias8 = TypeAliasType("BadAlias8", eval("".join(map(chr, [105, 110, 116])))) +BadAlias9 = TypeAliasType("BadAlias9", [int, str]) +BadAlias10 = TypeAliasType("BadAlias10", ((int, str),)) +BadAlias11 = TypeAliasType("BadAlias11", [int for i in range(1)]) +BadAlias12 = TypeAliasType("BadAlias12", {"a": "b"}) +BadAlias13 = TypeAliasType("BadAlias13", (lambda: int)()) +BadAlias14 = TypeAliasType("BadAlias14", [int][0]) +BadAlias15 = TypeAliasType("BadAlias15", int if 1 < 3 else str) +BadAlias16 = TypeAliasType("BadAlias16", var1) +BadAlias17 = TypeAliasType("BadAlias17", True) +BadAlias18 = TypeAliasType("BadAlias18", 1) +BadAlias19 = TypeAliasType("BadAlias19", list or set) +BadAlias20 = TypeAliasType("BadAlias20", f"{'int'}") diff --git a/conformance/tests/aliases_variance.py b/conformance/tests/aliases_variance.py new file mode 100644 index 000000000..b94b10be6 --- /dev/null +++ b/conformance/tests/aliases_variance.py @@ -0,0 +1,45 @@ +""" +Tests generic type aliases used in class declarations for +variance incompatibility. +""" + +from typing import Generic, TypeVar, TypeAlias + +T = TypeVar("T") +T_co = TypeVar("T_co", covariant=True) +T_contra = TypeVar("T_contra", contravariant=True) + + +class ClassA(Generic[T]): + pass + + +A_Alias_1: TypeAlias = ClassA[T_co] +A_Alias_2: TypeAlias = A_Alias_1[T_co] + +# Specialized type aliases used within a class declaration should +# result in the same variance incompatibility errors as their +# non-aliased counterparts. + +class ClassA_1(ClassA[T_co]): # Type error: incompatible variance + ... + + +class ClassA_2(A_Alias_1[T_co]): # Type error: incompatible variance + ... + + +class ClassA_3(A_Alias_2[T_co]): # Type error: incompatible variance + ... + + + +class ClassB(Generic[T, T_co]): + pass + + +B_Alias_1 = ClassB[T_co, T_contra] + + +class ClassB_1(B_Alias_1[T_contra, T_co]): # Type error: incompatible variance + ... diff --git a/conformance/tests/annotations_typeexpr.py b/conformance/tests/annotations_typeexpr.py new file mode 100644 index 000000000..064cac65c --- /dev/null +++ b/conformance/tests/annotations_typeexpr.py @@ -0,0 +1,99 @@ +""" +Test for type expressions used in annotations. +""" + +import abc +import abc +import types +import types +from typing import Any, Callable, Tuple, Union, assert_type + +# https://typing.readthedocs.io/en/latest/spec/annotations.html#valid-type-expression-forms + +def greeting(name: str) -> str: + return 'Hello ' + name + +assert_type(greeting('Monty'), str) + + +# > Expressions whose type is a subtype of a specific argument type are also accepted for that argument. +class StrSub(str): ... +assert_type(greeting(StrSub('Monty')), str) + + +# > Type hints may be built-in classes (including those defined in standard library or third-party +# > extension modules), abstract base classes, types available in the types module, and user-defined +# > classes (including those defined in the standard library or third-party modules). + + +class UserDefinedClass: ... +class AbstractBaseClass(abc.ABC): + @abc.abstractmethod + def abstract_method(self): ... + +# The following parameter annotations should all be considered +# valid and not generate errors. +def valid_annotations( + p1: int, + p2: str, + p3: bytes, + p4: bytearray, + p5: memoryview, + p6: complex, + p7: float, + p8: bool, + p9: object, + p10: type, + p11: types.ModuleType, + p12: types.FunctionType, + p13: types.BuiltinFunctionType, + p14: UserDefinedClass, + p15: AbstractBaseClass, + p16: int, + p17: Union[int, str], + p18: None, + p19: list, + p20: list[int], + p21: tuple, + p22: Tuple[int, ...], + p23: Tuple[int, int, str], + p24: Callable[..., int], + p25: Callable[[int, str], None], + p26: Any, +): + assert_type(p17, int | str) + assert_type(p19, list[Any]) + assert_type(p20, list[int]) + assert_type(p21, tuple[Any, ...]) + + +# > Annotations should be kept simple or static analysis tools may not be able to interpret the values. + +var1 = 3 + +# The following parameter annotations should all be considered +# invalid and generate errors. +def invalid_annotations( + p1: eval("".join(map(chr, [105, 110, 116]))), + p2: [int, str], + p3: (int, str), + p4: [int for i in range(1)], + p5: {}, + p6: (lambda : int)(), + p7: [int][0], + p8: int if 1 < 3 else str, + p9: var1, + p10: True, + p11: 1, + p12: -1, + p13: int or str, + p14: f"int", +): + pass + + +# > When used in a type hint, the expression None is considered equivalent to type(None). + +def takes_None(x: None) -> None: ... +assert_type(takes_None(None), None) + diff --git a/conformance/tests/callables_annotation.py b/conformance/tests/callables_annotation.py new file mode 100644 index 000000000..759e11d77 --- /dev/null +++ b/conformance/tests/callables_annotation.py @@ -0,0 +1,45 @@ +""" +Tests Callable annotation and parameter annotations for "def" statements. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/callables.html#callable + +from typing import Callable, assert_type + + +def func1(cb: Callable[[int, str], list[str]]) -> None: + assert_type(cb(1, ""), list[str]) + + cb(1) # Type error + cb(1, 2) # Type error + cb(1, "", 1) # Type error + cb(a=1, b="") # Type error + + +def func2(cb: Callable[[], dict[str, str]]) -> None: + assert_type(cb(), dict[str, str]) + + cb(1) # Type error + + +# > It is possible to declare the return type of a callable without specifying +# > the call signature by substituting a literal ellipsis (three dots) for the +# > list of arguments. +def func3(cb: Callable[..., list[str]]): + assert_type(cb(), list[str]) + assert_type(cb(""), list[str]) + assert_type(cb(1, ""), list[str]) + + +def func4(*args: int, **kwargs: int) -> None: + assert_type(args, tuple[int, ...]) + assert_type(kwargs, dict[str, int]) + + +v1: Callable[int] # Illegal form +v2: Callable[int, int] # Illegal form +v3: Callable[[], [int]] # Illegal form +v4: Callable[int, int, int] # Illegal form +v5: Callable[[...], int] # Illegal form + + diff --git a/conformance/tests/callables_kwargs.py b/conformance/tests/callables_kwargs.py new file mode 100644 index 000000000..070a45b71 --- /dev/null +++ b/conformance/tests/callables_kwargs.py @@ -0,0 +1,123 @@ +""" +Tests the use of an unpacked TypedDict for annotating **kwargs. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/callables.html#unpack-for-keyword-arguments + +# This sample tests the handling of Unpack[TypedDict] when used with +# a **kwargs parameter in a function signature. + +from typing import Protocol, TypeVar, TypedDict, NotRequired, Required, Unpack, assert_type + + +class TD1(TypedDict): + v1: Required[int] + v2: NotRequired[str] + + +class TD2(TD1): + v3: Required[str] + + +def func1(**kwargs: Unpack[TD2]) -> None: + v1 = kwargs["v1"] + assert_type(v1, int) + + kwargs["v2"] # Type error: v2 may not be present + + if "v2" in kwargs: + v2 = kwargs["v2"] + assert_type(v2, str) + + v3 = kwargs["v3"] + assert_type(v3, str) + + +def func2(v3: str, **kwargs: Unpack[TD1]) -> None: + # > When Unpack is used, type checkers treat kwargs inside the function + # > body as a TypedDict. + assert_type(kwargs, TD1) + + +def func3() -> None: + func1() # Type error: missing required keyword args + func1(v1=1, v2="", v3="5") # OK + + td2 = TD2(v1=2, v3="4") + func1(**td2) # OK + func1(v1=1, v2="", v3="5", v4=5) # Type error: v4 is not in TD2 + func1(1, "", "5") # Type error: args not passed by position + + # > Passing a dictionary of type dict[str, object] as a **kwargs argument + # > to a function that has **kwargs annotated with Unpack must generate a + # > type checker error. + my_dict: dict[str, str] = {} + func1(**my_dict) # Type error: untyped dict + + d1 = {"v1": 2, "v3": "4", "v4": 4} + func1(**d1) # OK or Type error (spec allows either) + func2(**td2) # OK + func1(v1=2, **td2) # Type error: v1 is already specified + func2(1, **td2) # Type error: v1 is already specified + func2(v1=1, **td2) # Type error: v1 is already specified + + +class TDProtocol1(Protocol): + def __call__(self, *, v1: int, v3: str) -> None: + ... + + +class TDProtocol2(Protocol): + def __call__(self, *, v1: int, v3: str, v2: str = "") -> None: + ... + + +class TDProtocol3(Protocol): + def __call__(self, *, v1: int, v2: int, v3: str) -> None: + ... + + +class TDProtocol4(Protocol): + def __call__(self, *, v1: int) -> None: + ... + + +class TDProtocol5(Protocol): + def __call__(self, v1: int, v3: str) -> None: + ... + + +class TDProtocol6(Protocol): + def __call__(self, **kwargs: Unpack[TD2]) -> None: + ... + +# Specification: https://typing.readthedocs.io/en/latest/spec/callables.html#assignment + +v1: TDProtocol1 = func1 # OK +v2: TDProtocol2 = func1 # OK +v3: TDProtocol3 = func1 # Type error: v2 is wrong type +v4: TDProtocol4 = func1 # Type error: v3 is missing +v5: TDProtocol5 = func1 # Type error: params are positional +v6: TDProtocol6 = func1 # OK + + +def func4(v1: int, /, **kwargs: Unpack[TD2]) -> None: + ... + + +# Type error: parameter v1 overlaps with the TypedDict. +def func5(v1: int, **kwargs: Unpack[TD2]) -> None: + ... + + +T = TypeVar("T", bound=TD2) + +# > TypedDict is the only permitted heterogeneous type for typing **kwargs. +# > Therefore, in the context of typing **kwargs, using Unpack with types other +# > than TypedDict should not be allowed and type checkers should generate +# > errors in such cases. + +# Type error: unpacked value must be a TypedDict, not a TypeVar bound to TypedDict. +def func6(**kwargs: Unpack[T]) -> None: + ... + diff --git a/conformance/tests/callables_protocol.py b/conformance/tests/callables_protocol.py new file mode 100644 index 000000000..dbe8108d7 --- /dev/null +++ b/conformance/tests/callables_protocol.py @@ -0,0 +1,313 @@ +""" +Tests handling of callback protocols. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/callables.html#callback-protocols + +from typing import Any, Callable, ParamSpec, Protocol, TypeVar, cast, overload + +InputT = TypeVar("InputT", contravariant=True) +OutputT = TypeVar("OutputT", covariant=True) + + +class Proto1(Protocol): + def __call__(self, *vals: bytes, max_len: int | None = None) -> list[bytes]: + ... + + +def cb1_good1(*vals: bytes, max_len: int | None = None) -> list[bytes]: + return [] + + +def cb1_bad1(*vals: bytes, max_items: int | None) -> list[bytes]: + return [] + + +def cb1_bad2(*vals: bytes) -> list[bytes]: + return [] + + +def cb1_bad3(*vals: bytes, max_len: str | None) -> list[bytes]: + return [] + + +cb1: Proto1 = cb1_good1 # OK +cb1 = cb1_bad1 # Type error: different names +cb1 = cb1_bad2 # Type error: parameter types +cb1 = cb1_bad3 # Type error: default argument + + +class Proto2(Protocol): + def __call__(self, *vals: bytes, **kwargs: str) -> None: + pass + + +def cb2_good1(*a: bytes, **b: str): + pass + + +def cb2_bad1(*a: bytes): + pass + + +def cb2_bad2(*a: str, **b: str): + pass + + +def cb2_bad3(*a: bytes, **b: bytes): + pass + + +def cb2_bad4(**b: str): + pass + + +cb2: Proto2 = cb2_good1 # OK + +cb2 = cb2_bad1 # Type error: missing **kwargs +cb2 = cb2_bad2 # Type error: parameter type +cb2 = cb2_bad3 # Type error: parameter type +cb2 = cb2_bad4 # Type error: missing parameter + + +class Proto3(Protocol): + def __call__(self) -> None: + pass + + +cb3: Proto3 = cb2_good1 # OK +cb3 = cb2_bad1 # OK +cb3 = cb2_bad2 # OK +cb3 = cb2_bad3 # OK +cb3 = cb2_bad4 # OK + + +# A callback protocol with other attributes. +class Proto4(Protocol): + other_attribute: int + + def __call__(self, x: int) -> None: + pass + + +def cb4_bad1(x: int) -> None: + pass + + +var4: Proto4 = cb4_bad1 # Type error: missing attribute + + +class Proto5(Protocol): + def __call__(self, *, a: int, b: str) -> int: + ... + + +def cb5_good1(a: int, b: str) -> int: + return 0 + + +cb5: Proto5 = cb5_good1 # OK + + +class NotProto6: + def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: + return [] + + +def cb6_bad1(*vals: bytes, max_len: int | None = None) -> list[bytes]: + return [] + + +cb6: NotProto6 = cb6_bad1 # Type error: NotProto6 isn't a protocol class + + +class Proto7(Protocol[InputT, OutputT]): + def __call__(self, inputs: InputT) -> OutputT: + ... + + +class Class7_1: + # Test for unannotated parameter. + def __call__(self, inputs) -> int: + return 5 + + +cb7_1: Proto7[int, int] = Class7_1() # OK + + +class Class7_2: + # Test for parameter with type Any. + def __call__(self, inputs: Any) -> int: + return 5 + + +cb7_2: Proto7[int, int] = Class7_2() # OK + + +class Proto8(Protocol): + @overload + def __call__(self, x: int) -> int: + ... + + @overload + def __call__(self, x: str) -> str: + ... + + def __call__(self, x: Any) -> Any: + ... + + +def cb8_good1(x: Any) -> Any: + return x + + +def cb8_bad1(x: int) -> Any: + return x + + +cb8: Proto8 = cb8_good1 # OK +cb8 = cb8_bad1 # Type error: parameter type + + +P = ParamSpec("P") +R = TypeVar("R", covariant=True) + + +class Proto9(Protocol[P, R]): + other_attribute: int + + def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: + ... + + +def decorator1(f: Callable[P, R]) -> Proto9[P, R]: + converted = cast(Proto9[P, R], f) + converted.other_attribute = 1 + converted.other_attribute = "str" # Type error: incompatible type + converted.xxx = 3 # Type error: unknown attribute + return converted + + +@decorator1 +def cb9_good(x: int) -> str: + return "" + + +print(cb9_good.other_attribute) # OK +print(cb9_good.other_attribute2) # Type error: unknown attribute + +cb9_good(x=3) + + +class Proto10(Protocol): + __name__: str + __module__: str + __qualname__: str + __annotations__: dict[str, Any] + + def __call__(self) -> None: + ... + + +def cb10_good() -> None: + pass + + +cb10: Proto10 = cb10_good # OK + + +class Proto11(Protocol): + def __call__(self, x: int, /, y: str) -> Any: + ... + + +def cb11_good1(x: int, /, y: str, z: None = None) -> Any: + pass + + +def cb11_good2(x: int, y: str, z: None = None) -> Any: + pass + + +def cb11_bad1(x: int, y: str, /) -> Any: + pass + + +cb11: Proto11 = cb11_good1 # OK +cb11 = cb11_good2 # OK +cb11 = cb11_bad1 # Type error: y is position-only + + +class Proto12(Protocol): + def __call__(self, *args: Any, kwarg0: Any, kwarg1: Any) -> None: + ... + + +def cb12_good1(*args: Any, kwarg0: Any, kwarg1: Any) -> None: + pass + + +def cb12_good2(*args: Any, **kwargs: Any) -> None: + pass + + +def cb12_bad1(*args: Any, kwarg0: Any) -> None: + pass + + +cb12: Proto12 = cb12_good1 # OK +cb12 = cb12_good2 # OK +cb12 = cb12_bad1 # Type error: missing kwarg1 + + +class Proto13_Default(Protocol): + # Callback with positional parameter with default arg value + def __call__(self, path: str = ...) -> str: + ... + + +class Proto13_NoDefault(Protocol): + # Callback with positional parameter but no default arg value + def __call__(self, path: str) -> str: + ... + + +def cb13_default(path: str = "") -> str: + return "" + + +def cb13_no_default(path: str) -> str: + return "" + + +cb13_1: Proto13_Default = cb13_default # OK +cb13_2: Proto13_Default = cb13_no_default # Type error: no default + +cb13_3: Proto13_NoDefault = cb13_default # OK +cb13_4: Proto13_NoDefault = cb13_no_default # OK + + +class Proto14_Default(Protocol): + # Callback with keyword parameter with default arg value + def __call__(self, *, path: str = ...) -> str: + ... + + +class Proto14_NoDefault(Protocol): + # Callback with keyword parameter with no default arg value + def __call__(self, *, path: str) -> str: + ... + + +def cb14_default(*, path: str = "") -> str: + return "" + + +def cb14_no_default(*, path: str) -> str: + return "" + + +cb14_1: Proto14_Default = cb14_default # OK +cb14_2: Proto14_Default = cb14_no_default # Type error: no default +cb14_3: Proto14_NoDefault = cb14_default # OK +cb14_4: Proto14_NoDefault = cb14_no_default # OK diff --git a/conformance/tests/dataclasses_descriptors.py b/conformance/tests/dataclasses_descriptors.py new file mode 100644 index 000000000..37dd1b36a --- /dev/null +++ b/conformance/tests/dataclasses_descriptors.py @@ -0,0 +1,68 @@ +""" +Tests the handling of descriptors within a dataclass. +""" + +# This portion of the dataclass spec is under-specified in the documentation, +# but its behavior can be determined from the runtime implementation. + +from dataclasses import dataclass +from typing import Any, Generic, TypeVar, assert_type, overload + +T = TypeVar("T") + + +class Desc1: + @overload + def __get__(self, __obj: None, __owner: Any) -> "Desc1": + ... + + @overload + def __get__(self, __obj: object, __owner: Any) -> int: + ... + + def __get__(self, __obj: object | None, __owner: Any) -> "int | Desc1": + ... + + def __set__(self, __obj: object, __value: int) -> None: + ... + + +@dataclass +class DC1: + y: Desc1 = Desc1() + + +dc1 = DC1(3) + +assert_type(dc1.y, int) +assert_type(DC1.y, Desc1) + + +class Desc2(Generic[T]): + @overload + def __get__(self, instance: None, owner: Any) -> list[T]: + ... + + @overload + def __get__(self, instance: object, owner: Any) -> T: + ... + + def __get__(self, instance: object | None, owner: Any) -> list[T] | T: + ... + + +@dataclass +class DC2: + x: Desc2[int] + y: Desc2[str] + z: Desc2[str] = Desc2() + + +assert_type(DC2.x, list[int]) +assert_type(DC2.y, list[str]) +assert_type(DC2.z, list[str]) + +dc2 = DC2(Desc2(), Desc2(), Desc2()) +assert_type(dc2.x, int) +assert_type(dc2.y, str) +assert_type(dc2.z, str) diff --git a/conformance/tests/dataclasses_frozen.py b/conformance/tests/dataclasses_frozen.py new file mode 100644 index 000000000..1717adf06 --- /dev/null +++ b/conformance/tests/dataclasses_frozen.py @@ -0,0 +1,42 @@ +""" +Tests validation of frozen dataclass instances. +""" + +# Specification: https://peps.python.org/pep-0557/#frozen-instances + +from dataclasses import dataclass + +@dataclass(frozen=True) +class DC1: + a: float + b: str + +dc1 = DC1(1, "") + +dc1.a = 1 # Type error: dataclass is frozen +dc1.b = "" # Type error: dataclass is frozen + + +# This should generate an error because a non-frozen dataclass +# cannot inherit from a frozen dataclass. +@dataclass +class DC2(DC1): + pass + +@dataclass +class DC3: + a: int + +# This should generate an error because a frozen dataclass +# cannot inherit from a non-frozen dataclass. +@dataclass(frozen=True) +class DC4(DC3): + pass + + +@dataclass(frozen=True) +class DC1Child(DC1): + # This should be allowed because attributes within a frozen + # dataclass are covariant rather than invariant. + a: int + diff --git a/conformance/tests/dataclasses_hash.py b/conformance/tests/dataclasses_hash.py new file mode 100644 index 000000000..83952b471 --- /dev/null +++ b/conformance/tests/dataclasses_hash.py @@ -0,0 +1,70 @@ +""" +Tests the synthesis of the __hash__ method in a dataclass. +""" + +from dataclasses import dataclass +from typing import Hashable + + +@dataclass +class DC1: + a: int + + +# This should generate an error because DC1 isn't hashable. +v1: Hashable = DC1(0) + + +@dataclass(eq=True, frozen=True) +class DC2: + a: int + + +v2: Hashable = DC2(0) + + +@dataclass(eq=True) +class DC3: + a: int + + +# This should generate an error because DC3 isn't hashable. +v3: Hashable = DC3(0) + + +@dataclass(frozen=True) +class DC4: + a: int + + +v4: Hashable = DC4(0) + + +@dataclass(eq=True, unsafe_hash=True) +class DC5: + a: int + + +v5: Hashable = DC5(0) + + +@dataclass(eq=True) +class DC6: + a: int + + def __hash__(self) -> int: + return 0 + + +v6: Hashable = DC6(0) + + +@dataclass(frozen=True) +class DC7: + a: int + + def __eq__(self, other) -> bool: + return self.a == other.a + + +v7: Hashable = DC7(0) diff --git a/conformance/tests/dataclasses_inheritance.py b/conformance/tests/dataclasses_inheritance.py new file mode 100644 index 000000000..5ae7e9a48 --- /dev/null +++ b/conformance/tests/dataclasses_inheritance.py @@ -0,0 +1,64 @@ +""" +Tests inheritance rules for dataclasses. +""" + +# Specification: https://peps.python.org/pep-0557/#inheritance + +from dataclasses import dataclass +from typing import Any, ClassVar + + +@dataclass +class DC1: + a: int + b: str = "" + + +@dataclass +class DC2(DC1): + b: str = "" + a: int = 1 + + +dc2_1 = DC2(1, "") + +dc2_2 = DC2() + + +@dataclass +class DC3: + x: float = 15.0 + y: str = "" + + +@dataclass +class DC4(DC3): + z: tuple[int] = (10,) + x: float = 15 + + +dc4_1 = DC4(0.0, "", (1,)) + + +@dataclass +class DC5: + # This should generate an error because a default value of + # type list, dict, or set generate a runtime error. + x: list[int] = [] + + +@dataclass +class DC6: + x: int + y: ClassVar[int] = 1 + + +@dataclass +class DC7(DC6): + # This should generate an error because a ClassVar cannot override + # an instance variable of the same name. + x: ClassVar[int] + + # This should generate an error because an instance variable cannot + # override a class variable of the same name. + y: int diff --git a/conformance/tests/dataclasses_kwonly.py b/conformance/tests/dataclasses_kwonly.py new file mode 100644 index 000000000..011a88eb1 --- /dev/null +++ b/conformance/tests/dataclasses_kwonly.py @@ -0,0 +1,62 @@ +""" +Tests the keyword-only feature of dataclass added in Python 3.10. +""" + +# Specification: https://docs.python.org/3/library/dataclasses.html#module-contents + +from dataclasses import dataclass, KW_ONLY, field + + +@dataclass +class DC1: + a: str + _: KW_ONLY + b: int = 0 + + +DC1("hi") +DC1(a="hi") +DC1(a="hi", b=1) +DC1("hi", b=1) + +# This should generate an error because "b" is keyword-only. +DC1("hi", 1) + + +@dataclass +class DC2: + b: int = field(kw_only=True, default=3) + a: str + + +DC2("hi") +DC2(a="hi") +DC2(a="hi", b=1) +DC2("hi", b=1) + +# This should generate an error because "b" is keyword-only. +DC2("hi", 1) + + +@dataclass(kw_only=True) +class DC3: + a: str = field(kw_only=False) + b: int = 0 + + +DC3("hi") +DC3(a="hi") +DC3(a="hi", b=1) +DC3("hi", b=1) + +# This should generate an error because "b" is keyword-only. +DC3("hi", 1) + + +@dataclass +class DC4(DC3): + c: float + + +DC4("", 0.2, b=3) +DC4(a="", b=3, c=0.2) diff --git a/conformance/tests/dataclasses_order.py b/conformance/tests/dataclasses_order.py new file mode 100644 index 000000000..dce831c7e --- /dev/null +++ b/conformance/tests/dataclasses_order.py @@ -0,0 +1,55 @@ +""" +Tests the synthesized comparison methods for dataclasses. +""" + +from dataclasses import dataclass + +@dataclass(order=True) +class DC1: + a: str + b: int + + +@dataclass(order=True) +class DC2: + a: str + b: int + + +dc1_1 = DC1("", 0) +dc1_2 = DC1("", 0) + +if dc1_1 < dc1_2: + pass + +if dc1_1 <= dc1_2: + pass + +if dc1_1 > dc1_2: + pass + +if dc1_1 >= dc1_2: + pass + +if dc1_1 == dc1_2: + pass + +if dc1_1 != dc1_2: + pass + +if dc1_1 == None: + pass + +if dc1_1 != None: + pass + +dc2_1 = DC2("hi", 2) + +# This should generate an error because the types are +# incompatible. +if dc1_1 < dc2_1: + pass + +if dc1_1 != dc2_1: + pass + diff --git a/conformance/tests/dataclasses_postinit.py b/conformance/tests/dataclasses_postinit.py new file mode 100644 index 000000000..e20b26248 --- /dev/null +++ b/conformance/tests/dataclasses_postinit.py @@ -0,0 +1,55 @@ +""" +Tests type checking of the __post_init__ method in a dataclass. +""" + +# Specification: https://peps.python.org/pep-0557/#post-init-processing + +from dataclasses import InitVar, dataclass, field, replace +from typing import assert_type + + +@dataclass +class DC1: + a: int + b: int + x: InitVar[int] + c: int + y: InitVar[str] + + def __post_init__(self, x: int, y: int) -> None: # Type error: wrong type for y + pass + + +dc1 = DC1(1, 2, 3, 4, "") + +assert_type(dc1.a, int) +assert_type(dc1.b, int) +assert_type(dc1.c, int) +print(dc1.x) # Type error: cannot access InitVar +print(dc1.y) # Type error: cannot access InitVar + +@dataclass +class DC2: + x: InitVar[int] + y: InitVar[str] + + def __post_init__(self, x: int) -> None: # Type error: missing y + pass + + +@dataclass +class DC3: + _name: InitVar[str] = field() + name: str = field(init=False) + + def __post_init__(self, _name: str): + ... + + +@dataclass +class DC4(DC3): + _age: InitVar[int] = field() + age: int = field(init=False) + + def __post_init__(self, _name: str, _age: int): + ... diff --git a/conformance/tests/dataclasses_slots.py b/conformance/tests/dataclasses_slots.py new file mode 100644 index 000000000..3c8c14443 --- /dev/null +++ b/conformance/tests/dataclasses_slots.py @@ -0,0 +1,70 @@ +""" +Tests the slots functionality of dataclass added in Python 3.10. +""" + +# Specification: https://docs.python.org/3/library/dataclasses.html#module-contents + +from dataclasses import dataclass +from typing import Iterable, assert_type + +# This should generate an error because __slots__ is already defined. +@dataclass(slots=True) +class DC1: + x: int + + __slots__ = () + + +@dataclass(slots=True) +class DC2: + x: int + + def __init__(self): + self.x = 3 + + # This should generate an error because "y" is not in slots. + self.y = 3 + + +@dataclass(slots=False) +class DC3: + x: int + + __slots__ = ("x",) + + def __init__(self): + self.x = 3 + + # This should generate an error because "y" is not in slots. + self.y = 3 + + +@dataclass +class DC4: + __slots__ = ("y", "x") + x: int + y: str + + +DC4(1, "bar") + + +@dataclass(slots=True) +class DC5: + a: int + + +DC5.__slots__ +DC5(1).__slots__ + + +@dataclass +class DC6: + a: int + + +# This should generate an error because __slots__ is not defined. +DC6.__slots__ + +# This should generate an error because __slots__ is not defined. +DC6(1).__slots__ diff --git a/conformance/tests/dataclasses_transform_class.py b/conformance/tests/dataclasses_transform_class.py new file mode 100644 index 000000000..ca3278243 --- /dev/null +++ b/conformance/tests/dataclasses_transform_class.py @@ -0,0 +1,119 @@ +""" +Tests the dataclass_transform mechanism when it is applied to a base class. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/dataclasses.html#the-dataclass-transform-decorator + +from typing import Any, Generic, TypeVar, dataclass_transform + +T = TypeVar("T") + + +class ModelField: + def __init__(self, *, init: bool = True, default: Any | None = None) -> None: + ... + + +def model_field( + *, init: bool = True, default: Any | None = None, alias: str | None = None +) -> Any: + ... + + +@dataclass_transform( + kw_only_default=True, + field_specifiers=(ModelField, model_field), +) +class ModelBase: + not_a_field: str + + def __init_subclass__( + cls, + *, + frozen: bool = False, + kw_only: bool = True, + order: bool = True, + ) -> None: + ... + + +class Customer1(ModelBase, frozen=True): + id: int = model_field() + name: str = model_field() + name2: str = model_field(alias="other_name", default="None") + + +# This should generate an error because a non-frozen dataclass cannot +# derive from a frozen one. +class Customer1Subclass(Customer1): + salary: float = model_field() + + +class Customer2(ModelBase, order=True): + id: int + name: str = model_field(default="None") + + +c1_1 = Customer1(id=3, name="Sue", other_name="Susan") + +# This should generate an error because the class is frozen. +c1_1.id = 4 + +# This should generate an error because the class is kw_only. +c1_2 = Customer1(3, "Sue") + +c1_3 = Customer1(id=3, name="John") + +# This should generate an error because comparison methods are +# not synthesized. +v1 = c1_1 < c1_2 + +c2_1 = Customer2(id=0, name="John") + +c2_2 = Customer2(id=1) + +v2 = c2_1 < c2_2 + +# This should generate an error because Customer2 supports +# keyword-only parameters for its constructor. +c2_3 = Customer2(0, "John") + + +@dataclass_transform( + kw_only_default=True, + field_specifiers=(ModelField, model_field), +) +class GenericModelBase(Generic[T]): + not_a_field: T + + def __init_subclass__( + cls, + *, + frozen: bool = False, + kw_only: bool = True, + order: bool = True, + ) -> None: + ... + + +class GenericCustomer(GenericModelBase[int]): + id: int = model_field() + + +gc_1 = GenericCustomer(id=3) + + +@dataclass_transform(frozen_default=True) +class ModelBaseFrozen: + not_a_field: str + + +class Customer3(ModelBaseFrozen): + id: int + name: str + + +c3_1 = Customer3(id=2, name="hi") + +# This should generate an error because Customer3 is frozen. +c3_1.id = 4 diff --git a/conformance/tests/dataclasses_transform_field.py b/conformance/tests/dataclasses_transform_field.py new file mode 100644 index 000000000..09e4ce6a5 --- /dev/null +++ b/conformance/tests/dataclasses_transform_field.py @@ -0,0 +1,77 @@ +""" +Tests the dataclass_transform mechanism honors implicit default values +in field parameters. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/dataclasses.html#field-specifier-parameters + +from typing import Any, Callable, Literal, TypeVar, dataclass_transform, overload + +T = TypeVar("T") + +# > Field specifier functions can use overloads that implicitly specify the +# > value of init using a literal bool value type (Literal[False] or Literal[True]). + +@overload +def field1( + *, + default: str | None = None, + resolver: Callable[[], Any], + init: Literal[False] = False, +) -> Any: + ... + + +@overload +def field1( + *, + default: str | None = None, + resolver: None = None, + init: Literal[True] = True, +) -> Any: + ... + + +def field1( + *, + default: str | None = None, + resolver: Callable[[], Any] | None = None, + init: bool = True, +) -> Any: + ... + + +def field2(*, init: bool = False, kw_only: bool = True) -> Any: + ... + + +@dataclass_transform(kw_only_default=True, field_specifiers=(field1, field2)) +def create_model(*, init: bool = True) -> Callable[[type[T]], type[T]]: + ... + + +@create_model() +class CustomerModel1: + id: int = field1(resolver=lambda: 0) + name: str = field1(default="Voldemort") + + +CustomerModel1() +CustomerModel1(name="hi") + +# This should generate an error because "id" is not +# supposed to be part of the init function. +CustomerModel1(id=1, name="hi") + + +@create_model() +class CustomerModel2: + id: int = field2() + name: str = field2(init=True) + + +# This should generate an error because kw_only is True +# by default for field2. +CustomerModel2(1) + +CustomerModel2(name="Fred") diff --git a/conformance/tests/dataclasses_transform_func.py b/conformance/tests/dataclasses_transform_func.py new file mode 100644 index 000000000..0dc1b2623 --- /dev/null +++ b/conformance/tests/dataclasses_transform_func.py @@ -0,0 +1,97 @@ +""" +Tests the dataclass_transform mechanism when it is applied to a decorator function. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/dataclasses.html#the-dataclass-transform-decorator + +from typing import Any, Callable, TypeVar, dataclass_transform, overload + +T = TypeVar("T") + + +@overload +@dataclass_transform(kw_only_default=True, order_default=True) +def create_model(cls: T) -> T: + ... + + +@overload +@dataclass_transform(kw_only_default=True, order_default=True) +def create_model( + *, + frozen: bool = False, + kw_only: bool = True, + order: bool = True, +) -> Callable[[T], T]: + ... + + +def create_model(*args: Any, **kwargs: Any) -> Any: + ... + + +@create_model(kw_only=False, order=False) +class Customer1: + id: int + name: str + + +@create_model(frozen=True) +class Customer2: + id: int + name: str + + +@create_model(frozen=True) +class Customer2Subclass(Customer2): + salary: float + + +c1_1 = Customer1(id=3, name="Sue") +c1_1.id = 4 + +c1_2 = Customer1(3, "Sue") +c1_2.name = "Susan" + +# This should generate an error because of a type mismatch. +c1_2.name = 3 + +# This should generate an error because comparison methods are +# not synthesized. +v1 = c1_1 < c1_2 + +# This should generate an error because salary is not +# a defined field. +c1_3 = Customer1(id=3, name="Sue", salary=40000) + +c2_1 = Customer2(id=0, name="John") + +# This should generate an error because Customer2 supports +# keyword-only parameters for its constructor. +c2_2 = Customer2(0, "John") + +v2 = c2_1 < c2_2 + + +@dataclass_transform(kw_only_default=True, order_default=True, frozen_default=True) +def create_model_frozen(cls: T) -> T: + ... + + +@create_model_frozen +class Customer3: + id: int + name: str + + +# This should generate an error because a non-frozen class +# cannot inherit from a frozen class. +@create_model +class Customer3Subclass(Customer3): + age: int + + +c3_1 = Customer3(id=2, name="hi") + +# This should generate an error because Customer3 is frozen. +c3_1.id = 4 diff --git a/conformance/tests/dataclasses_transform_meta.py b/conformance/tests/dataclasses_transform_meta.py new file mode 100644 index 000000000..3d1fb76ca --- /dev/null +++ b/conformance/tests/dataclasses_transform_meta.py @@ -0,0 +1,100 @@ +""" +Tests the dataclass_transform mechanism when it is applied to a metaclass. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/dataclasses.html#the-dataclass-transform-decorator + + +from typing import Any, dataclass_transform + +class ModelField: + def __init__(self, *, init: bool = True, default: Any | None = None) -> None: + ... + + +def model_field( + *, init: bool = True, default: Any | None = None, alias: str | None = None +) -> Any: + ... + + +@dataclass_transform( + kw_only_default=True, + field_specifiers=(ModelField, model_field), +) +class ModelMeta(type): + not_a_field: str + + +class ModelBase(metaclass=ModelMeta): + def __init_subclass__( + cls, + *, + frozen: bool = False, + kw_only: bool = True, + order: bool = True, + ) -> None: + ... + + +class Customer1(ModelBase, frozen=True): + id: int = model_field() + name: str = model_field() + name2: str = model_field(alias="other_name", default="None") + + +# This should generate an error because a non-frozen class cannot +# derive from a frozen one. +class Customer1Subclass(Customer1, frozen=False): + salary: float = model_field() + + +class Customer2(ModelBase, order=True): + id: int + name: str = model_field(default="None") + + +c1_1 = Customer1(id=3, name="Sue", other_name="Susan") + +# This should generate an error because the class is frozen. +c1_1.id = 4 + +# This should generate an error because the class is kw_only. +c1_2 = Customer1(3, "Sue") + +# This should generate an error because other_name is missing. +c1_3 = Customer1(id=3, name="John") + +# This should generate an error because comparison methods are +# not synthesized. +v1 = c1_1 < c1_2 + +c2_1 = Customer2(id=0, name="John") + +c2_2 = Customer2(id=1) + +v2 = c2_1 < c2_2 + +# This should generate an error because Customer2 supports +# keyword-only parameters for its constructor. +c2_3 = Customer2(0, "John") + + +@dataclass_transform(frozen_default=True) +class ModelMetaFrozen(type): + pass + + +class ModelBaseFrozen(metaclass=ModelMetaFrozen): + ... + + +class Customer3(ModelBaseFrozen): + id: int + name: str + + +c3_1 = Customer3(id=2, name="hi") + +# This should generate an error because Customer3 is frozen. +c3_1.id = 4 diff --git a/conformance/tests/dataclasses_usage.py b/conformance/tests/dataclasses_usage.py new file mode 100644 index 000000000..d41a93f45 --- /dev/null +++ b/conformance/tests/dataclasses_usage.py @@ -0,0 +1,230 @@ +""" +Tests basic handling of the dataclass factory. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/dataclasses.html +# Also, see https://peps.python.org/pep-0557/ + +from dataclasses import InitVar, dataclass, field +from typing import Any, Callable, ClassVar, Generic, Protocol, TypeVar, assert_type + +T = TypeVar("T") + + +@dataclass(order=True) +class InventoryItem: + x = 0 + name: str + unit_price: float + quantity_on_hand: int = 0 + + def total_cost(self) -> float: + return self.unit_price * self.quantity_on_hand + + +v1 = InventoryItem("soap", 2.3) + + +class InventoryItemInitProto(Protocol): + def __call__( + self, name: str, unit_price: float, quantity_on_hand: int = ... + ) -> None: + ... + + +# Validate the type of the synthesized __init__ method. +x1: InventoryItemInitProto = v1.__init__ + +# Make sure the following additional methods were synthesized. +print(v1.__repr__) +print(v1.__eq__) +print(v1.__ne__) +print(v1.__lt__) +print(v1.__le__) +print(v1.__gt__) +print(v1.__ge__) + +assert_type(v1.name, str) +assert_type(v1.unit_price, float) +assert_type(v1.quantity_on_hand, int) + +v2 = InventoryItem("name") # Type error: missing unit_price +v3 = InventoryItem("name", "price") # Type error: incorrect type for unit_price +v4 = InventoryItem("name", 3.1, 3, 4) # Type error: too many arguments + + +# > TypeError will be raised if a field without a default value follows a +# > field with a default value. This is true either when this occurs in a +# > single class, or as a result of class inheritance. +@dataclass +class DC1: + a: int = 0 + b: int # Error: field with no default cannot follow field with default. + + +@dataclass +class DC2: + a: int = field(default=1) + b: int # Error: field with no default cannot follow field with default. + + +@dataclass +class DC3: + a: InitVar[int] = 0 + b: int # Error: field with no default cannot follow field with default. + + +@dataclass +class DC4: + a: int = field(init=False) + b: int + + +v5 = DC4(0) +v6 = DC4(0, 1) # Type error: too many parameters + + +@dataclass +class DC5: + a: int = field(default_factory=str) # Type error: type mismatch + + +def f(s: str) -> int: + return int(s) + + +@dataclass +class DC6: + a: ClassVar[int] = 0 + b: str + c: Callable[[str], int] = f + + +dc6 = DC6("") +assert_type(dc6.a, int) +assert_type(DC6.a, int) +assert_type(dc6.b, str) +assert_type(dc6.c, Callable[[str], int]) + + +@dataclass +class DC7: + x: int + + +@dataclass(init=False) +class DC8(DC7): + y: int + + def __init__(self, a: DC7, y: int): + self.__dict__ = a.__dict__ + + +a = DC7(3) +b = DC8(a, 5) + +# This should generate an error because there is an extra parameter +DC7(3, 4) + +# This should generate an error because there is one too few parameters +DC8(a) + + +@dataclass +class DC9: + a: str = field(init=False, default="s") + b: bool = field() + + +@dataclass +class DC10(DC9): + a: str = field() + b: bool = field() + + +@dataclass(init=False) +class DC11: + x: int + x_squared: int + + def __init__(self, x: int): + self.x = x + self.x_squared = x**2 + + +DC11(3) + + +@dataclass(init=True) +class DC12: + x: int + x_squared: int + + def __init__(self, x: int): + self.x = x + self.x_squared = x**2 + + +DC12(3) + + +@dataclass(init=False) +class DC13: + x: int + x_squared: int + + +# This should generate an error because there is no +# override __init__ method and no synthesized __init__. +DC13(3) + + +@dataclass +class DC14: + prop_1: str = field(init=False) + prop_2: str = field(default="hello") + prop_3: str = field(default_factory=lambda: "hello") + + +@dataclass +class DC15(DC14): + prop_2: str + + +dc15 = DC15(prop_2="test") + +assert_type(dc15.prop_1, str) +assert_type(dc15.prop_2, str) +assert_type(dc15.prop_3, str) + + +class DataclassProto(Protocol): + # Checking for this attribute seems to currently be + # the most reliable way to ascertain that something is a dataclass + __dataclass_fields__: dict[str, Any] + + +v1: DataclassProto = dc15 + + +@dataclass +class DC16(Generic[T]): + value: T + + +assert_type(DC16(1), DC16[int]) + + +class DC17(DC16[str]): + pass + + +assert_type(DC17(""), DC17) + + +@dataclass +class DC18: + x: int = field() + # This should generate an error because an unannotated field + # will result in a runtime exception. + y = field() diff --git a/conformance/tests/generics_self_advanced.py b/conformance/tests/generics_self_advanced.py new file mode 100644 index 000000000..9a837e40f --- /dev/null +++ b/conformance/tests/generics_self_advanced.py @@ -0,0 +1,46 @@ +""" +Tests for advanced or special-case usage of the typing.Self type. +""" + +from typing import assert_type, Self + + +class ParentA: + # Test for property that returns Self. + @property + def prop1(self) -> Self: + ... + +class ChildA(ParentA): + ... + + +assert_type(ParentA().prop1, ParentA) +assert_type(ChildA().prop1, ChildA) + + +# Test for a child that accesses an attribute within a parent +# whose type is annotated using Self. +class ParentB: + a: list[Self] + + @classmethod + def method1(cls) -> Self: + ... + +class ChildB(ParentB): + b: int = 0 + + def method2(self) -> None: + assert_type(self, Self) + assert_type(self.a, list[Self]) + assert_type(self.a[0], Self) + assert_type(self.method1(), Self) + + @classmethod + def method3(cls) -> None: + assert_type(cls, type[Self]) + assert_type(cls.a, list[Self]) + assert_type(cls.a[0], Self) + assert_type(cls.method1(), Self) + diff --git a/conformance/tests/generics_self_attributes.py b/conformance/tests/generics_self_attributes.py new file mode 100644 index 000000000..2fad31cb9 --- /dev/null +++ b/conformance/tests/generics_self_attributes.py @@ -0,0 +1,34 @@ +""" +Tests for usage of the typing.Self type with attributes. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#use-in-attribute-annotations + +from typing import TypeVar, Generic, Self +from dataclasses import dataclass + + +T = TypeVar("T") + +@dataclass +class LinkedList(Generic[T]): + value: T + next: Self | None = None + + +@dataclass +class OrdinalLinkedList(LinkedList[int]): + def ordinal_value(self) -> str: + return str(self.value) + + +# This should result in a type error. +xs = OrdinalLinkedList(value=1, next=LinkedList[int](value=2)) + +if xs.next is not None: + xs.next = OrdinalLinkedList(value=3, next=None) # OK + + # This should result in a type error. + xs.next = LinkedList[int](value=3, next=None) + + diff --git a/conformance/tests/generics_self_basic.py b/conformance/tests/generics_self_basic.py new file mode 100644 index 000000000..aea671078 --- /dev/null +++ b/conformance/tests/generics_self_basic.py @@ -0,0 +1,82 @@ +""" +Tests for basic usage of the typing.Self type. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#self. + +from typing import Callable, Generic, Self, TypeVar, assert_type + +T = TypeVar("T") + +class Shape: + def set_scale(self, scale: float) -> Self: + assert_type(self, Self) + self.scale = scale + return self + + def method2(self) -> Self: + # This should result in a type error. + return Shape() + + def method3(self) -> "Shape": + return self + + @classmethod + def from_config(cls, config: dict[str, float]) -> Self: + assert_type(cls, type[Self]) + return cls(config["scale"]) + + @classmethod + def cls_method2(cls) -> Self: + # This should result in a type error. + return Shape() + + @classmethod + def cls_method3(cls) -> "Shape": + return cls() + + def difference(self, other: Self) -> float: + assert_type(other, Self) + return 0.0 + + def apply(self, f: Callable[[Self], None]) -> None: + return f(self) + + +class Circle(Shape): + pass + + +assert_type(Shape().set_scale(1.0), Shape) +assert_type(Circle().set_scale(1.0), Circle) + +assert_type(Shape.from_config({}), Shape) +assert_type(Circle.from_config({}), Circle) + + +class Container(Generic[T]): + value: T + + def set_value(self, value: T) -> Self: + ... + + # This should generate an error because Self isn't subscriptable. + def foo(self, other: Self[int]) -> None: + pass + + +def object_with_concrete_type( + int_container: Container[int], str_container: Container[str] +) -> None: + assert_type(int_container.set_value(42), Container[int]) + assert_type(str_container.set_value("hello"), Container[str]) + + +def object_with_generic_type( + container: Container[T], + value: T, +) -> Container[T]: + val = container.set_value(value) + assert_type(val, Container[T]) + return val + diff --git a/conformance/tests/generics_self_protocols.py b/conformance/tests/generics_self_protocols.py new file mode 100644 index 000000000..6f27bf0b9 --- /dev/null +++ b/conformance/tests/generics_self_protocols.py @@ -0,0 +1,64 @@ +""" +Tests for usage of the typing.Self type with protocols. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#use-in-protocols + +from typing import Protocol, Self, assert_type + + +class ShapeProtocol(Protocol): + def set_scale(self, scale: float) -> Self: + ... + + +class ReturnSelf: + scale: float = 1.0 + + def set_scale(self, scale: float) -> Self: + self.scale = scale + return self + + +class ReturnConcreteShape: + scale: float = 1.0 + + def set_scale(self, scale: float) -> "ReturnConcreteShape": + self.scale = scale + return self + + +class BadReturnType: + scale: float = 1.0 + + def set_scale(self, scale: float) -> int: + self.scale = scale + return 42 + + +class ReturnDifferentClass: + scale: float = 1.0 + + def set_scale(self, scale: float) -> ReturnConcreteShape: + return ReturnConcreteShape() + + +def accepts_shape(shape: ShapeProtocol) -> None: + y = shape.set_scale(0.5) + assert_type(y, ShapeProtocol) + + +def main( + return_self_shape: ReturnSelf, + return_concrete_shape: ReturnConcreteShape, + bad_return_type: BadReturnType, + return_different_class: ReturnDifferentClass, +) -> None: + accepts_shape(return_self_shape) # OK + accepts_shape(return_concrete_shape) # OK + + # This should generate a type error. + accepts_shape(bad_return_type) + + # Not OK because it returns a non-subclass. + accepts_shape(return_different_class) diff --git a/conformance/tests/generics_self_usage.py b/conformance/tests/generics_self_usage.py new file mode 100644 index 000000000..657849b24 --- /dev/null +++ b/conformance/tests/generics_self_usage.py @@ -0,0 +1,126 @@ +""" +Tests for valid and invalid usage of the typing.Self type. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/generics.html#valid-locations-for-self + +from typing import Any, Callable, Generic, Self, TypeAlias, TypeVar + +class ReturnsSelf: + def foo(self) -> Self: # Accepted + return self + + @classmethod + def bar(cls) -> Self: # Accepted + return cls(1) + + def __new__(cls, value: int) -> Self: # Accepted + return cls(1) + + def explicitly_use_self(self: Self) -> Self: # Accepted + return self + + # Accepted (Self can be nested within other types) + def returns_list(self) -> list[Self]: + return [] + + # Accepted (Self can be nested within other types) + @classmethod + def return_cls(cls) -> type[Self]: + return cls + +class Child(ReturnsSelf): + # Accepted (we can override a method that uses Self annotations) + def foo(self) -> Self: + return self + +class TakesSelf: + def foo(self, other: Self) -> bool: # Accepted + return True + +class Recursive: + # Accepted (treated as an @property returning ``Self | None``) + next: Self | None + +class CallableAttribute: + def foo(self) -> int: + return 0 + + # Accepted (treated as an @property returning the Callable type) + bar: Callable[[Self], int] = foo + +class HasNestedFunction: + x: int = 42 + + def foo(self) -> None: + + # Accepted (Self is bound to HasNestedFunction). + def nested(z: int, inner_self: Self) -> Self: + print(z) + print(inner_self.x) + return inner_self + + nested(42, self) # OK + + +class Outer: + class Inner: + def foo(self) -> Self: # Accepted (Self is bound to Inner) + return self + + +# This should generate an error. +def foo(bar: Self) -> Self: ... # Rejected (not within a class) + +# This should generate an error. +bar: Self # Rejected (not within a class) + +TFoo2 = TypeVar("TFoo2", bound="Foo2") + +class Foo2: + # Rejected (Self is treated as unknown). + def has_existing_self_annotation(self: TFoo2) -> Self: ... + +class Foo3: + def return_concrete_type(self) -> Self: + return Foo3() # Rejected (see FooChild below for rationale) + +class Foo3Child(Foo3): + child_value: int = 42 + + def child_method(self) -> None: + y = self.return_concrete_type() + y.child_value + +T = TypeVar("T") + +class Bar(Generic[T]): + def bar(self) -> T: ... + +# This should generate an error. +class Baz(Bar[Self]): ... # Rejected + +class Baz2(Self): ... # Rejected + +# This should generate an error. +TupleSelf: TypeAlias = tuple[Self] # Rejected + +class Base: + @staticmethod + # This should generate an error. + def make() -> Self: # Rejected + ... + + @staticmethod + # This should generate an error. + def return_parameter(foo: Self) -> Self: # Rejected + ... + +class MyMetaclass(type): + # This should generate an error. + def __new__(cls, *args: Any) -> Self: # Rejected + ... + + # This should generate an error. + def __mul__(cls, count: int) -> list[Self]: # Rejected + ... diff --git a/conformance/tests/literals_interactions.py b/conformance/tests/literals_interactions.py new file mode 100644 index 000000000..f9782c4f1 --- /dev/null +++ b/conformance/tests/literals_interactions.py @@ -0,0 +1,116 @@ +""" +Tests interactions between Literal types and other typing features. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/literal.html#interactions-with-other-types-and-features + +from enum import Enum +from typing import IO, Any, Final, Generic, Literal, TypeVar, assert_type, overload + + +def func1(v: tuple[int, str, list[bool]], a: Literal[0], b: Literal[5], c: Literal[-5]): + assert_type(v[a], int) + assert_type(v[2], list[bool]) + + v[b] # Type error: index out of range + v[c] # Type error: index out of range + v[4] # Type error: index out of range + v[-4] # Type error: index out of range + + +_PathType = str | bytes | int + + +@overload +def open( + path: _PathType, + mode: Literal["r", "w", "a", "x", "r+", "w+", "a+", "x+"], +) -> IO[str]: + ... + + +@overload +def open( + path: _PathType, + mode: Literal["rb", "wb", "ab", "xb", "r+b", "w+b", "a+b", "x+b"], +) -> IO[bytes]: + ... + + +@overload +def open(path: _PathType, mode: str) -> IO[Any]: + ... + + +def open(path: _PathType, mode: Any) -> Any: + pass + + +assert_type(open("path", "r"), IO[str]) +assert_type(open("path", "wb"), IO[bytes]) +assert_type(open("path", "other"), IO[Any]) + + +A = TypeVar("A", bound=int) +B = TypeVar("B", bound=int) +C = TypeVar("C", bound=int) + + +class Matrix(Generic[A, B]): + def __add__(self, other: "Matrix[A, B]") -> "Matrix[A, B]": + ... + + def __matmul__(self, other: "Matrix[B, C]") -> "Matrix[A, C]": + ... + + def transpose(self) -> "Matrix[B, A]": + ... + + +def func2(a: Matrix[Literal[2], Literal[3]], b: Matrix[Literal[3], Literal[7]]): + c = a @ b + assert_type(c, Matrix[Literal[2], Literal[7]]) + + +T = TypeVar("T", Literal["a"], Literal["b"], Literal["c"]) +S = TypeVar("S", bound=Literal["foo"]) + + +class Status(Enum): + SUCCESS = 0 + INVALID_DATA = 1 + FATAL_ERROR = 2 + + +def parse_status1(s: str | Status) -> None: + if s is Status.SUCCESS: + assert_type(s, Literal[Status.SUCCESS]) + elif s is Status.INVALID_DATA: + assert_type(s, Literal[Status.INVALID_DATA]) + elif s is Status.FATAL_ERROR: + assert_type(s, Literal[Status.FATAL_ERROR]) + else: + assert_type(s, str) + + +def expects_bad_status(status: Literal["MALFORMED", "ABORTED"]): + ... + + +def expects_pending_status(status: Literal["PENDING"]): + ... + + +def parse_status2(status: str) -> None: + if status in ("MALFORMED", "ABORTED"): + return expects_bad_status(status) + + if status == "PENDING": + expects_pending_status(status) + + +final_val1: Final = 3 +assert_type(final_val1, Literal[3]) + +final_val2: Final = True +assert_type(final_val2, Literal[True]) diff --git a/conformance/tests/literals_literalstring.py b/conformance/tests/literals_literalstring.py new file mode 100644 index 000000000..10b50e080 --- /dev/null +++ b/conformance/tests/literals_literalstring.py @@ -0,0 +1,170 @@ +""" +Tests handling of the LiteralString special form. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/literal.html#literalstring + + +from typing import ( + Any, + Generic, + Literal, + LiteralString, + Sequence, + TypeVar, + assert_type, + overload, +) + + +variable_annotation: LiteralString + + +def my_function(literal_string: LiteralString) -> LiteralString: + ... + + +class Foo: + my_attribute: LiteralString = "" + + +type_argument: list[LiteralString] + +T = TypeVar("T", bound=LiteralString) + + +bad_union: Literal["hello", LiteralString] # Type error +bad_nesting: Literal[LiteralString] # Type error + + +def func1(a: Literal["one"], b: Literal["two"]): + x1: LiteralString = a + + x2: Literal[""] = b # Type error + + +def func2(a: LiteralString, b: LiteralString): + # > Addition: x + y is of type LiteralString if both x and y are compatible with LiteralString. + assert_type(a + b, LiteralString) + + # > Joining: sep.join(xs) is of type LiteralString if sep’s type is + # > compatible with LiteralString and xs’s type is compatible with Iterable[LiteralString]. + assert_type(",".join((a, b)), LiteralString) + assert_type(",".join((a, str(b))), str) + + # > In-place addition: If s has type LiteralString and x has type compatible with + # > LiteralString, then s += x preserves s’s type as LiteralString. + a += "hello" + b += a + + # > String formatting: An f-string has type LiteralString if and only if its constituent + # > expressions are literal strings. s.format(...) has type LiteralString if and only if + # > s and the arguments have types compatible with LiteralString. + assert_type(f"{a} {b}", LiteralString) + + variable = 3 + x1: LiteralString = f"{a} {str(variable)}" # Type error + + assert_type(a + str(1), str) + + # > LiteralString is compatible with the type str + x2: str = a + + # > Other literal types, such as literal integers, are not compatible with LiteralString. + x3: LiteralString = 3 # Type error + x4: LiteralString = b"test" # Type error + + +# > Conditional statements and expressions work as expected. +def condition1() -> bool: + ... + + +def return_literal_string() -> LiteralString: + return "foo" if condition1() else "bar" # OK + + +def return_literal_str2(literal_string: LiteralString) -> LiteralString: + return "foo" if condition1() else literal_string # OK + + +def return_literal_str3() -> LiteralString: + result: LiteralString + if condition1(): + result = "foo" + else: + result = "bar" + + return result # OK + + +# > TypeVars can be bound to LiteralString. +TLiteral = TypeVar("TLiteral", bound=LiteralString) + + +def literal_identity(s: TLiteral) -> TLiteral: + return s + + +def func3(s: Literal["hello"]): + y = literal_identity(s) + assert_type(y, Literal["hello"]) + + +def func4(s: LiteralString): + y2 = literal_identity(s) + assert_type(y2, LiteralString) + + +def func5(s: str): + literal_identity(s) # Type error + + +# > LiteralString can be used as a type argument for generic classes. +class Container(Generic[T]): + def __init__(self, value: T) -> None: + self.value = value + + +def func6(s: LiteralString): + x: Container[LiteralString] = Container(s) # OK + + +def func7(s: str): + x_error: Container[LiteralString] = Container(s) # Type error + + +# > Standard containers like List work as expected. +xs: list[LiteralString] = ["foo", "bar", "baz"] + + +@overload +def func8(x: Literal["foo"]) -> int: + ... + + +@overload +def func8(x: LiteralString) -> bool: + ... + + +@overload +def func8(x: str) -> str: + ... + + +def func8(x: Any) -> Any: + ... + + +assert_type(func8("foo"), int) # First overload +assert_type(func8("bar"), bool) # Second overload +assert_type(func8(str(1)), str) # Third overload + + +def func9(val: list[LiteralString]): + x1: list[str] = val # Type error + + +def func10(val: Sequence[LiteralString]): + x1: Sequence[str] = val # OK diff --git a/conformance/tests/literals_parameterizations.py b/conformance/tests/literals_parameterizations.py new file mode 100644 index 000000000..0edc1d4d8 --- /dev/null +++ b/conformance/tests/literals_parameterizations.py @@ -0,0 +1,67 @@ +""" +Tests legal and illegal parameterizations of Literal. +""" + +# > Literal must be parameterized with at least one type. + +from typing import Any, Literal, TypeVar +from enum import Enum + + +class Color(Enum): + RED = 0 + GREEN = 1 + BLUE = 2 + + +good1: Literal[26] +good2: Literal[0x1A] +good3: Literal[-4] +good4: Literal["hello world"] +good5: Literal[b"hello world"] +good6: Literal["hello world"] +good7: Literal[True] +good8: Literal[Color.RED] +good9: Literal[None] + +ReadOnlyMode = Literal["r", "r+"] +WriteAndTruncateMode = Literal["w", "w+", "wt", "w+t"] +WriteNoTruncateMode = Literal["r+", "r+t"] +AppendMode = Literal["a", "a+", "at", "a+t"] + +AllModes = Literal[ReadOnlyMode, WriteAndTruncateMode, WriteNoTruncateMode, AppendMode] + +good10: Literal[Literal[Literal[1, 2, 3], "foo"], 5, None] + +variable = 3 +T = TypeVar("T") + +# > Arbitrary expressions [are illegal] +bad1: Literal[3 + 4] # Type error +bad2: Literal["foo".replace("o", "b")] # Type error +bad3: Literal[4 + 3j] # Type error +bad4: Literal[+5] # Type error +bad5: Literal[not False] # Type error +bad6: Literal[(1, "foo", "bar")] # Type error +bad7: Literal[{"a": "b", "c": "d"}] # Type error +bad8: Literal[int] # Type error +bad9: Literal[variable] # Type error +bad10: Literal[T] # Type error +bad11: Literal[3.14] # Type error +bad12: Literal[Any] # Type error +bad13: Literal[...] # Type error + + +def my_function(x: Literal[1 + 2]) -> int: # Type error + return x * 3 + +x: Literal # Type error +y: Literal[my_function] = my_function # Type error + + +def func2(a: Literal[Color.RED]): + x1: Literal["Color.RED"] = a # Type error + + x2: "Literal[Color.RED]" = a # OK + + diff --git a/conformance/tests/literals_semantics.py b/conformance/tests/literals_semantics.py new file mode 100644 index 000000000..a75b48c5d --- /dev/null +++ b/conformance/tests/literals_semantics.py @@ -0,0 +1,42 @@ +""" +Tests the semantics of the Literal special form. +""" + +from typing import Literal +from typing import Literal as L + + +v1: Literal[3] = 3 +v2: Literal[3] = 4 # Type error + +v3: L[-3] = -3 + + +# > Literal[20] and Literal[0x14] are equivalent +def func1(a: Literal[20], b: Literal[0x14], c: Literal[0b10100]): + x1: Literal[0x14] = a + x2: Literal[0x14] = b + x3: Literal[0x14] = c + + +# > Literal[0] and Literal[False] are not equivalent +def func2(a: Literal[0], b: Literal[False]): + x1: Literal[False] = a # Type Error + x2: Literal[0] = b # Type Error + + +# > Given some value v that is a member of type T, the type Literal[v] shall +# > be treated as a subtype of T. For example, Literal[3] is a subtype of int. +def func3(a: L[3, 4, 5]): + b = a.__add__(3) + c = a + 3 + a += 3 # Type error + + +# > When a Literal is parameterized with more than one value, it’s treated +# > as exactly equivalent to the union of those types. +def func4(a: L[None, 3] | L[3, "foo", b"bar", True]): + x1: Literal[3, b"bar", True, "foo", None] = a + a = x1 + + diff --git a/conformance/tests/narrowing_typeguard.py b/conformance/tests/narrowing_typeguard.py new file mode 100644 index 000000000..fbdbca821 --- /dev/null +++ b/conformance/tests/narrowing_typeguard.py @@ -0,0 +1,108 @@ +""" +Tests TypeGuard functionality. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/narrowing.html#typeguard + +from typing import Any, Self, TypeGuard, TypeVar, assert_type + + +T = TypeVar("T") + +def is_two_element_tuple(val: tuple[T, ...]) -> TypeGuard[tuple[T, T]]: + return len(val) == 2 + +def func1(names: tuple[str, ...]): + if is_two_element_tuple(names): + assert_type(names, tuple[str, str]) + else: + assert_type(names, tuple[str, ...]) + + +def is_str_list(val: list[object], allow_empty: bool) -> TypeGuard[list[str]]: + if len(val) == 0: + return allow_empty + return all(isinstance(x, str) for x in val) + +def is_set_of(val: set[Any], type: type[T]) -> TypeGuard[set[T]]: + return all(isinstance(x, type) for x in val) + +def func2(val: set[object]): + if is_set_of(val, int): + assert_type(val, set[int]) + else: + assert_type(val, set[object]) + + +T_A = TypeVar("T_A", bound="A") + +class A: + def tg_1(self, val: object) -> TypeGuard[int]: + return isinstance(val, int) + + @classmethod + def tg_2(cls, val: object) -> TypeGuard[int]: + return isinstance(val, int) + + @staticmethod + def tg_3(val: object) -> TypeGuard[int]: + return isinstance(val, int) + + def tg4(self, val: object) -> TypeGuard[Self]: + return isinstance(val, type(self)) + + def tg5(self: T_A, val: object) -> TypeGuard[T_A]: + return isinstance(val, type(self)) + +class B(A): + pass + +# > Type checkers should assume that type narrowing should be applied to +# > the expression that is passed as the first positional argument to a +# > user-defined type guard. If the type guard function accepts more than +# > one argument, no type narrowing is applied to those additional argument +# > expressions. + +def func3() -> None: + val1 = object() + if A().tg_1(val1): + assert_type(val1, int) + + val2 = object() + if A().tg_2(val2): + assert_type(val2, int) + + val3 = object() + if A.tg_2(val3): + assert_type(val3, int) + + val4 = object() + if A().tg_3(val4): + assert_type(val4, int) + + val5 = object() + if A.tg_3(val5): + assert_type(val5, int) + + val6 = object() + if B().tg4(val6): + assert_type(val6, B) + + val7 = object() + if B().tg4(val7): + assert_type(val7, B) + + +# > If a type guard function is implemented as an instance method or class +# > method, the first positional argument maps to the second parameter +# > (after “self” or “cls”). + +class C: + # Type checker should emit error here. + def tg_1(self) -> TypeGuard[int]: + return False + + @classmethod + # Type checker should emit error here. + def tg_2(cls) -> TypeGuard[int]: + return False diff --git a/conformance/tests/typeddicts_alt_syntax.py b/conformance/tests/typeddicts_alt_syntax.py new file mode 100644 index 000000000..1baf016cb --- /dev/null +++ b/conformance/tests/typeddicts_alt_syntax.py @@ -0,0 +1,45 @@ +""" +Tests the "alternative" (non-class) syntax for defining a TypedDict. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/typeddict.html#alternative-syntax + +from typing import TypedDict + + +Movie = TypedDict("Movie", {"name": str, "year": int, "illegal key name": bool}) + +movie: Movie = {"name": "Blade Runner", "year": 1982, "illegal key name": True} + +MovieOptional = TypedDict("MovieOptional", {"name": str, "year": int}, total=False) + +movie_opt1: MovieOptional = {} +movie_opt2: MovieOptional = {"year": 1982} + +# > A type checker is only expected to accept a dictionary display expression as +# > the second argument to TypedDict. In particular, a variable that refers to a +# > dictionary object does not need to be supported, to simplify implementation. +my_dict = {"name": str} +BadTypedDict1 = TypedDict("BadTypedDict1", my_dict) + + +# This should generate an error because it uses a non-str key. +BadTypedDict2 = TypedDict("BadTypedDict2", {1: str}) + + +# This should generate an error because it uses a non-matching name. +BadTypedDict3 = TypedDict("WrongName", {"name": str}) + + +# This should generate an error because of the additional parameter. +BadTypedDict4 = TypedDict("BadTypedDict4", {"name": str}, total=False, other=False) + + +# > The keyword-argument syntax is deprecated in 3.11 and will be removed in 3.13. +# > It may also be unsupported by static type checkers. + +Movie2 = TypedDict("Movie2", name=str, year=int) + +movie2: Movie2 +movie2 = {"name": "Blade Runner", "year": 1982} +movie2 = {"name": "Blade Runner", "year": ""} # Type error: Incorrect type for year diff --git a/conformance/tests/typeddicts_class_syntax.py b/conformance/tests/typeddicts_class_syntax.py new file mode 100644 index 000000000..38ed09c0c --- /dev/null +++ b/conformance/tests/typeddicts_class_syntax.py @@ -0,0 +1,79 @@ +""" +Tests the class syntax for defining a TypedDict. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/typeddict.html#typeddict + +from typing import Generic, TypeVar, TypedDict + + +class Movie(TypedDict): + name: str + year: int + + # > String literal forward references are valid in the value types. + director: "Person" + + +class Person(TypedDict): + name: str + age: int + + +# > Methods are not allowed, since the runtime type of a TypedDict object +# > will always be just dict (it is never a subclass of dict). +class BadTypedDict1(TypedDict): + name: str + + # Methods are not allowed, so this should generate an error. + def method1(self): + pass + + # Methods are not allowed, so this should generate an error. + @classmethod + def method2(cls): + pass + + # Methods are not allowed, so this should generate an error. + @staticmethod + def method3(): + pass + + +# > Specifying a metaclass is not allowed. +class BadTypedDict2(TypedDict, metaclass=type): + name: str + + +# This should generate an error because "other" is not an allowed keyword argument. +class BadTypedDict3(TypedDict, other=True): + name: str + + +# > TypedDicts may be made generic by adding Generic[T] among the bases. +T = TypeVar("T") + + +class GenericTypedDict(Generic[T]): + name: str + value: T + + +# > An empty TypedDict can be created by only including pass in the +# > body (if there is a docstring, pass can be omitted): +class EmptyDict1(TypedDict): + pass + + +class EmptyDict2(TypedDict): + """Docstring""" + + +class MovieTotal(TypedDict, total=True): + name: str + + +class MovieOptional(TypedDict, total=False): + name: str + + diff --git a/conformance/tests/typeddicts_final.py b/conformance/tests/typeddicts_final.py new file mode 100644 index 000000000..1cd08f2f9 --- /dev/null +++ b/conformance/tests/typeddicts_final.py @@ -0,0 +1,26 @@ +""" +Tests the use of Final values when used with TypedDicts. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/typeddict.html#use-of-final-values-and-literal-types + +from typing import Final, Literal, TypedDict + + +class Movie(TypedDict): + name: str + year: int + + +# > Type checkers should allow final names (PEP 591) with string values to be +# > used instead of string literals in operations on TypedDict objects. +YEAR: Final = "year" + +m: Movie = {"name": "Alien", "year": 1979} +years_since_epoch = m[YEAR] - 1970 + + +# > An expression with a suitable literal type (PEP 586) can be used instead of +# > a literal value. +def get_value(movie: Movie, key: Literal["year", "name"]) -> int | str: + return movie[key] diff --git a/conformance/tests/typeddicts_inheritance.py b/conformance/tests/typeddicts_inheritance.py new file mode 100644 index 000000000..38b72403a --- /dev/null +++ b/conformance/tests/typeddicts_inheritance.py @@ -0,0 +1,66 @@ +""" +Tests inheritance rules for TypedDict classes. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/typeddict.html#typeddict + +from typing import TypedDict + + +class Movie(TypedDict): + name: str + year: int + +class BookBasedMovie(Movie): + based_on: str + +class BookBasedMovieAlso(TypedDict): + name: str + year: int + based_on: str + +b1: BookBasedMovie = {"name": "Little Women", "year": 2019, "based_on": "Little Women"} + +b2: BookBasedMovieAlso = b1 + + +class X(TypedDict): + x: int + +class Y(TypedDict): + y: str + +class XYZ(X, Y): + z: bool + +x1 = XYZ(x=1, y="", z=True) + +# > A TypedDict cannot inherit from both a TypedDict type and a +# > non-TypedDict base class other than Generic. + +class NonTypedDict: + pass + +class BadTypedDict(TypedDict, NonTypedDict): + pass + + +# > Changing a field type of a parent TypedDict class in a subclass is +# > not allowed. + +class X1(TypedDict): + x: str + +class Y1(X1): + x: int # Type check error: cannot overwrite TypedDict field "x" + + +# > Multiple inheritance does not allow conflict types for the same name field: +class X2(TypedDict): + x: int + +class Y2(TypedDict): + x: str + +class XYZ2(X2, Y2): # Type check error: cannot overwrite TypedDict field "x" while merging + xyz: bool diff --git a/conformance/tests/typeddicts_operations.py b/conformance/tests/typeddicts_operations.py new file mode 100644 index 000000000..11c449043 --- /dev/null +++ b/conformance/tests/typeddicts_operations.py @@ -0,0 +1,65 @@ +""" +Tests operations provided by a TypedDict object. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/typeddict.html#supported-and-unsupported-operations + + +from typing import TypedDict, assert_type + + +class Movie(TypedDict): + name: str + year: int + + +movie: Movie + +movie = {"name": "Blade Runner", "year": 1982} +movie["name"] = "Other" +movie["year"] = 1981 + +movie["name"] = 1982 # Type error: wrong type +movie["year"] = "" # Type error: wrong type +movie["other"] = "" # Type error: unknown key added + +print(movie["other"]) # Type error: unknown key referenced + +movie = {"name": "Blade Runner"} # Type error: year is missing +movie = {"name": "Blade Runner", "year": 1982.1} # Type error: year is wrong type + +# > The use of a key that is not known to exist should be reported as an error. +movie = {"name": "", "year": 1900, "other": 2} # Type error: extra key + + +def func1(variable_key: str): + # > A key that is not a literal should generally be rejected. + movie: Movie = {variable_key: "", "year": 1900} # Type error: variable key + + +# It's not clear from the spec what type this should be. +movie.get("name") + +# It's not clear from the spec what type this should be. +movie.get("other") + + +movie.clear() # Type error: clear not allowed + +del movie["name"] # Type error: del not allowed for required key + + + +class MovieOptional(TypedDict, total=False): + name: str + year: int + + +movie_optional: MovieOptional = {} + +assert_type(movie_optional.get("name"), str | None) + +movie_optional.clear() # Type error: clear not allowed + +del movie_optional["name"] + diff --git a/conformance/tests/typeddicts_required.py b/conformance/tests/typeddicts_required.py new file mode 100644 index 000000000..22485f0f1 --- /dev/null +++ b/conformance/tests/typeddicts_required.py @@ -0,0 +1,76 @@ +""" +Tests the Required and NotRequired special forms. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/typeddict.html#required-and-notrequired + +from typing import Annotated, NotRequired, Required, TypedDict + + +# Required and NotRequired are valid only within a TypedDict. +class NotTypedDict: + x: Required[int] # Type error: Required not allowed in this context + + +def func1( + x: NotRequired[int], +) -> None: # Type error: Required not allowed in this context + pass + + +class TD1(TypedDict, total=False): + a: int + + +class TD2(TD1, total=True): + b: int + + +class TD3(TypedDict): + a: NotRequired[int] + b: Required[int] + + +class TD4(TypedDict, total=False): + a: int + b: Required[int] + + +class TD5(TypedDict, total=True): + a: NotRequired[int] + b: int + + +td3: TD3 = {"b": 0} +td4: TD4 = {"b": 0} +td5: TD5 = {"b": 0} + +# These are all equivalent types, so they should be +# bidirectionally type compatible. +td3 = td4 +td3 = td5 +td4 = td3 +td4 = td5 +td5 = td3 +td5 = td4 + + +class TD6(TypedDict): + a: Required[Required[int]] # Type error: Nesting not allowed + b: Required[NotRequired[int]] # Type error: Nesting not allowed + + +class TD7(TypedDict): + # > Required[] and NotRequired[] can be used with Annotated[], in any nesting order. + x: Annotated[Required[int], ""] + y: Required[Annotated[int, ""]] + z: Annotated[Required[Annotated[int, ""]], ""] + + +RecursiveMovie = TypedDict( + "RecursiveMovie", {"title": Required[str], "predecessor": NotRequired["RecursiveMovie"]} +) + +movie: RecursiveMovie = {"title": "Beethoven 3", "predecessor": {"title": "Beethoven 2"}} + + diff --git a/conformance/tests/typeddicts_type_consistency.py b/conformance/tests/typeddicts_type_consistency.py new file mode 100644 index 000000000..c782b2cc3 --- /dev/null +++ b/conformance/tests/typeddicts_type_consistency.py @@ -0,0 +1,150 @@ +""" +Tests the type consistency rules for TypedDict objects. +""" + +# Specification: https://typing.readthedocs.io/en/latest/spec/typeddict.html#type-consistency + +from typing import Any, Literal, Mapping, TypedDict + + +class A1(TypedDict): + x: int | None + + +class B1(TypedDict): + x: int + + +b1: B1 = {"x": 0} + +# > Value types behave invariantly. +a1: A1 = b1 # Type check error: 'B1' not compatible with 'A1' + +# > any TypedDict type is consistent with Mapping[str, object] +v1: Mapping[str, object] = b1 + +# > A TypedDict type with a required key is not consistent with a TypedDict +# > type where the same key is a non-required key. + +class A2(TypedDict, total=False): + x: int + + +class B2(TypedDict): + x: int + + +b2: B2 = {"x": 0} +a2: A2 = b2 # Type check error: 'B2' not compatible with 'A2' + + +# > A TypedDict type A is consistent with TypedDict B if A is structurally +# > compatible with B. This is true if and only if both of these conditions +# > are satisfied: +# > 1. For each key in B, A has the corresponding key and the corresponding +# > value type in A is consistent with the value type in B. For each key in B, +# > the value type in B is also consistent with the corresponding value type +# > in A. +# > 2. For each required key in B, the corresponding key is required in A. For +# > each non-required key in B, the corresponding key is not required in A. + + +class A3(TypedDict): + x: int + + +class B3(TypedDict): + x: int + y: int + + +b3: B3 = {"x": 0, "y": 0} +a3: A3 = b3 + +a3 = {"x": 0} +b3 = a3 # Type checker error + + +# This should generate an error because it's a literal assignment. +a3_1: A3 = {"x": 0, "y": 0} + +# This should not generate an error. +a3_2 = b3 + +# > A TypedDict isn’t consistent with any Dict[...] type. + +d1: dict[str, int] = b3 # Type checker error +d2: dict[str, object] = b3 # Type checker error +d3: dict[Any, Any] = b3 # Type checker error + +# > A TypedDict with all int values is not consistent with Mapping[str, int]. + +m1: Mapping[str, int] = b3 # Type checker error +m2: Mapping[str, object] = b3 # OK +m3: Mapping[str, Any] = b3 # OK + + +# Test "get" method. +UserType1 = TypedDict("UserType1", {"name": str, "age": int}, total=False) +user1: UserType1 = {"name": "Bob", "age": 40} + +name1: str = user1.get("name", "n/a") +age1: int = user1.get("age", 42) + +UserType2 = TypedDict("UserType2", {"name": str, "age": int}) +user2: UserType2 = {"name": "Bob", "age": 40} + +name2: str | None = user2.get("name") + +name3: str = user2.get("name") + +age2: int = user2.get("age", 42) + +age3: int | str = user2.get("age", "42") + +age4: int = user2.get("age", "42") + +# Test nested TypedDicts. +class Inner1(TypedDict): + inner_key: str + + +class Inner2(TypedDict): + inner_key: Inner1 + + +class Outer1(TypedDict): + outer_key: Inner2 + + +o1: Outer1 = {"outer_key": {"inner_key": {"inner_key": "hi"}}} + +# This should generate an error because the inner-most value +# should be a string. +o2: Outer1 = {"outer_key": {"inner_key": {"inner_key": 1}}} + + +class Inner3(TypedDict): + x: int + + +class Inner4(TypedDict): + x: int + + +class Outer2(TypedDict): + y: str + z: Literal[""] | Inner3 + + +class Outer3(TypedDict): + y: str + z: Literal[""] | Inner4 + + +def func1(td: Outer3): + ... + + +o3: Outer2 = {"y": "", "z": {"x": 0}} +o4: Outer3 = o3 diff --git a/conformance/tests/typeddicts_usage.py b/conformance/tests/typeddicts_usage.py new file mode 100644 index 000000000..99232872d --- /dev/null +++ b/conformance/tests/typeddicts_usage.py @@ -0,0 +1,42 @@ +""" +Tests for basic usage of TypedDict. +""" + +from typing import TypeVar, TypedDict + + +class Movie(TypedDict): + name: str + year: int + + +movie: Movie = {"name": "Blade Runner", "year": 1982} + + +def record_movie(movie: Movie) -> None: + ... + + +record_movie({"name": "Blade Runner", "year": 1982}) + + +movie["director"] = "Ridley Scott" # Error: invalid key 'director' +movie["year"] = "1982" # Error: invalid value type ("int" expected) + +# The code below should be rejected, since 'title' is not a valid key, +# and the 'name' key is missing: +movie2: Movie = {"title": "Blade Runner", "year": 1982} + +m = Movie(name='Blade Runner', year=1982) + + +# > TypedDict type objects cannot be used in isinstance() tests such as +# > isinstance(d, Movie). +if isinstance(movie, Movie): + pass + + +# TypedDict should not be allowed as a bound for a TypeVar. +T = TypeVar("T", bound=TypedDict) # Type checker error + +