mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 06:11:21 +00:00
[ty] Split invalid-base
error code into two error codes (#18245)
Some checks are pending
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / benchmarks (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
Some checks are pending
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / benchmarks (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
This commit is contained in:
parent
02394b8049
commit
cb04343b3b
9 changed files with 568 additions and 130 deletions
157
crates/ty/docs/rules.md
generated
157
crates/ty/docs/rules.md
generated
|
@ -50,7 +50,7 @@ Calling a non-callable object will raise a `TypeError` at runtime.
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20call-non-callable)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20call-non-callable)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L88)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L90)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `conflicting-argument-forms`
|
## `conflicting-argument-forms`
|
||||||
|
@ -81,7 +81,7 @@ f(int) # error
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-argument-forms)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-argument-forms)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L119)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L121)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `conflicting-declarations`
|
## `conflicting-declarations`
|
||||||
|
@ -111,7 +111,7 @@ a = 1
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-declarations)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-declarations)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L145)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L147)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `conflicting-metaclass`
|
## `conflicting-metaclass`
|
||||||
|
@ -142,7 +142,7 @@ class C(A, B): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-metaclass)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-metaclass)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L170)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L172)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `cyclic-class-definition`
|
## `cyclic-class-definition`
|
||||||
|
@ -173,7 +173,7 @@ class B(A): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20cyclic-class-definition)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20cyclic-class-definition)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L196)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L198)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `duplicate-base`
|
## `duplicate-base`
|
||||||
|
@ -199,7 +199,7 @@ class B(A, A): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20duplicate-base)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20duplicate-base)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L240)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L242)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `escape-character-in-forward-annotation`
|
## `escape-character-in-forward-annotation`
|
||||||
|
@ -336,7 +336,7 @@ TypeError: multiple bases have instance lay-out conflict
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20incompatible-slots)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20incompatible-slots)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L261)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L263)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `inconsistent-mro`
|
## `inconsistent-mro`
|
||||||
|
@ -365,7 +365,7 @@ class C(A, B): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20inconsistent-mro)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20inconsistent-mro)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L347)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L349)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `index-out-of-bounds`
|
## `index-out-of-bounds`
|
||||||
|
@ -390,7 +390,7 @@ t[3] # IndexError: tuple index out of range
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20index-out-of-bounds)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20index-out-of-bounds)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L371)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L373)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-argument-type`
|
## `invalid-argument-type`
|
||||||
|
@ -416,7 +416,7 @@ func("foo") # error: [invalid-argument-type]
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-argument-type)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-argument-type)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L391)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L393)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-assignment`
|
## `invalid-assignment`
|
||||||
|
@ -443,7 +443,7 @@ a: int = ''
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-assignment)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-assignment)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L431)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L433)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-attribute-access`
|
## `invalid-attribute-access`
|
||||||
|
@ -476,7 +476,7 @@ C.instance_var = 3 # error: Cannot assign to instance variable
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-attribute-access)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-attribute-access)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1337)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1381)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-base`
|
## `invalid-base`
|
||||||
|
@ -484,13 +484,22 @@ C.instance_var = 3 # error: Cannot assign to instance variable
|
||||||
**Default level**: error
|
**Default level**: error
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>detects invalid bases in class definitions</summary>
|
<summary>detects class bases that will cause the class definition to raise an exception at runtime</summary>
|
||||||
|
|
||||||
TODO #14889
|
### What it does
|
||||||
|
Checks for class definitions that have bases which are not instances of `type`.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
Class definitions with bases like this will lead to `TypeError` being raised at runtime.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
```python
|
||||||
|
class A(42): ... # error: [invalid-base]
|
||||||
|
```
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-base)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-base)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L453)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L455)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-context-manager`
|
## `invalid-context-manager`
|
||||||
|
@ -516,7 +525,7 @@ with 1:
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-context-manager)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-context-manager)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L462)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L506)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-declaration`
|
## `invalid-declaration`
|
||||||
|
@ -544,7 +553,7 @@ a: str
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-declaration)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-declaration)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L483)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L527)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-exception-caught`
|
## `invalid-exception-caught`
|
||||||
|
@ -585,7 +594,7 @@ except ZeroDivisionError:
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-exception-caught)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-exception-caught)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L506)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L550)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-generic-class`
|
## `invalid-generic-class`
|
||||||
|
@ -616,7 +625,7 @@ class C[U](Generic[T]): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-generic-class)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-generic-class)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L542)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L586)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-legacy-type-variable`
|
## `invalid-legacy-type-variable`
|
||||||
|
@ -649,7 +658,7 @@ def f(t: TypeVar("U")): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-legacy-type-variable)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-legacy-type-variable)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L568)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L612)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-metaclass`
|
## `invalid-metaclass`
|
||||||
|
@ -681,7 +690,7 @@ class B(metaclass=f): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-metaclass)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-metaclass)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L617)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L661)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-overload`
|
## `invalid-overload`
|
||||||
|
@ -729,7 +738,7 @@ def foo(x: int) -> int: ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-overload)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-overload)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L644)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L688)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-parameter-default`
|
## `invalid-parameter-default`
|
||||||
|
@ -754,7 +763,7 @@ def f(a: int = ''): ...
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-parameter-default)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-parameter-default)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L687)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L731)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-protocol`
|
## `invalid-protocol`
|
||||||
|
@ -787,7 +796,7 @@ TypeError: Protocols can only inherit from other protocols, got <class 'int'>
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-protocol)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-protocol)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L319)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L321)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-raise`
|
## `invalid-raise`
|
||||||
|
@ -835,7 +844,7 @@ def g():
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-raise)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-raise)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L707)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L751)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-return-type`
|
## `invalid-return-type`
|
||||||
|
@ -859,7 +868,7 @@ def func() -> int:
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-return-type)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-return-type)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L412)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L414)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-super-argument`
|
## `invalid-super-argument`
|
||||||
|
@ -903,7 +912,7 @@ super(B, A) # error: `A` does not satisfy `issubclass(A, B)`
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-super-argument)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-super-argument)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L750)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L794)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-syntax-in-forward-annotation`
|
## `invalid-syntax-in-forward-annotation`
|
||||||
|
@ -943,7 +952,7 @@ NewAlias = TypeAliasType(get_name(), int) # error: TypeAliasType name mus
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-alias-type)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-alias-type)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L596)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L640)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-type-checking-constant`
|
## `invalid-type-checking-constant`
|
||||||
|
@ -972,7 +981,7 @@ TYPE_CHECKING = ''
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-checking-constant)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-checking-constant)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L789)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L833)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-type-form`
|
## `invalid-type-form`
|
||||||
|
@ -1001,7 +1010,7 @@ b: Annotated[int] # `Annotated` expects at least two arguments
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-form)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-form)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L813)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L857)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-type-variable-constraints`
|
## `invalid-type-variable-constraints`
|
||||||
|
@ -1035,7 +1044,7 @@ T = TypeVar('T', bound=str) # valid bound TypeVar
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-variable-constraints)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-variable-constraints)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L837)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L881)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `missing-argument`
|
## `missing-argument`
|
||||||
|
@ -1059,7 +1068,7 @@ func() # TypeError: func() missing 1 required positional argument: 'x'
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20missing-argument)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20missing-argument)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L866)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L910)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `no-matching-overload`
|
## `no-matching-overload`
|
||||||
|
@ -1087,7 +1096,7 @@ func("string") # error: [no-matching-overload]
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20no-matching-overload)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20no-matching-overload)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L885)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L929)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `non-subscriptable`
|
## `non-subscriptable`
|
||||||
|
@ -1110,7 +1119,7 @@ Subscripting an object that does not support it will raise a `TypeError` at runt
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20non-subscriptable)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20non-subscriptable)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L908)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L952)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `not-iterable`
|
## `not-iterable`
|
||||||
|
@ -1135,7 +1144,7 @@ for i in 34: # TypeError: 'int' object is not iterable
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20not-iterable)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20not-iterable)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L926)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L970)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `parameter-already-assigned`
|
## `parameter-already-assigned`
|
||||||
|
@ -1161,7 +1170,7 @@ f(1, x=2) # Error raised here
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20parameter-already-assigned)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20parameter-already-assigned)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L977)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1021)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `raw-string-type-annotation`
|
## `raw-string-type-annotation`
|
||||||
|
@ -1220,7 +1229,7 @@ static_assert(int(2.0 * 3.0) == 6) # error: does not have a statically known tr
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20static-assert-error)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20static-assert-error)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1313)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1357)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `subclass-of-final-class`
|
## `subclass-of-final-class`
|
||||||
|
@ -1248,7 +1257,7 @@ class B(A): ... # Error raised here
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20subclass-of-final-class)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20subclass-of-final-class)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1068)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1112)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `too-many-positional-arguments`
|
## `too-many-positional-arguments`
|
||||||
|
@ -1274,7 +1283,7 @@ f("foo") # Error raised here
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20too-many-positional-arguments)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20too-many-positional-arguments)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1113)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1157)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `type-assertion-failure`
|
## `type-assertion-failure`
|
||||||
|
@ -1301,7 +1310,7 @@ def _(x: int):
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20type-assertion-failure)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20type-assertion-failure)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1091)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1135)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unavailable-implicit-super-arguments`
|
## `unavailable-implicit-super-arguments`
|
||||||
|
@ -1345,7 +1354,7 @@ class A:
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unavailable-implicit-super-arguments)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unavailable-implicit-super-arguments)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1134)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1178)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unknown-argument`
|
## `unknown-argument`
|
||||||
|
@ -1371,7 +1380,7 @@ f(x=1, y=2) # Error raised here
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unknown-argument)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unknown-argument)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1191)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1235)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unresolved-attribute`
|
## `unresolved-attribute`
|
||||||
|
@ -1398,7 +1407,7 @@ A().foo # AttributeError: 'A' object has no attribute 'foo'
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-attribute)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-attribute)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1212)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1256)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unresolved-import`
|
## `unresolved-import`
|
||||||
|
@ -1422,7 +1431,7 @@ import foo # ModuleNotFoundError: No module named 'foo'
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-import)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-import)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1234)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1278)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unresolved-reference`
|
## `unresolved-reference`
|
||||||
|
@ -1446,7 +1455,7 @@ print(x) # NameError: name 'x' is not defined
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-reference)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-reference)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1253)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1297)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unsupported-bool-conversion`
|
## `unsupported-bool-conversion`
|
||||||
|
@ -1482,7 +1491,7 @@ b1 < b2 < b1 # exception raised here
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-bool-conversion)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-bool-conversion)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L946)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L990)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unsupported-operator`
|
## `unsupported-operator`
|
||||||
|
@ -1509,7 +1518,7 @@ A() + A() # TypeError: unsupported operand type(s) for +: 'A' and 'A'
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-operator)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-operator)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1272)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1316)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `zero-stepsize-in-slice`
|
## `zero-stepsize-in-slice`
|
||||||
|
@ -1533,7 +1542,7 @@ l[1:10:0] # ValueError: slice step cannot be zero
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20zero-stepsize-in-slice)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20zero-stepsize-in-slice)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1294)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1338)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `call-possibly-unbound-method`
|
## `call-possibly-unbound-method`
|
||||||
|
@ -1551,7 +1560,7 @@ Calling an unbound method will raise an `AttributeError` at runtime.
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20call-possibly-unbound-method)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20call-possibly-unbound-method)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L106)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L108)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `invalid-ignore-comment`
|
## `invalid-ignore-comment`
|
||||||
|
@ -1607,7 +1616,7 @@ A.c # AttributeError: type object 'A' has no attribute 'c'
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unbound-attribute)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unbound-attribute)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L998)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1042)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `possibly-unbound-import`
|
## `possibly-unbound-import`
|
||||||
|
@ -1638,7 +1647,7 @@ from module import a # ImportError: cannot import name 'a' from 'module'
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unbound-import)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unbound-import)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1020)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1064)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `redundant-cast`
|
## `redundant-cast`
|
||||||
|
@ -1664,7 +1673,7 @@ cast(int, f()) # Redundant
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20redundant-cast)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20redundant-cast)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1365)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1409)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `undefined-reveal`
|
## `undefined-reveal`
|
||||||
|
@ -1687,7 +1696,7 @@ reveal_type(1) # NameError: name 'reveal_type' is not defined
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20undefined-reveal)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20undefined-reveal)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1173)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1217)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unknown-rule`
|
## `unknown-rule`
|
||||||
|
@ -1720,6 +1729,44 @@ a = 20 / 0 # ty: ignore[division-by-zero]
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Fsuppression.rs#L40)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Fsuppression.rs#L40)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
## `unsupported-base`
|
||||||
|
|
||||||
|
**Default level**: warn
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>detects class bases that are unsupported as ty could not feasibly calculate the class's MRO</summary>
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
Checks for class definitions that have bases which are unsupported by ty.
|
||||||
|
|
||||||
|
### Why is this bad?
|
||||||
|
If a class has a base that is an instance of a complex type such as a union type,
|
||||||
|
ty will not be able to resolve the [method resolution order] (MRO) for the class.
|
||||||
|
This will lead to an inferior understanding of your codebase and unpredictable
|
||||||
|
type-checking behavior.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
```python
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
class A: ...
|
||||||
|
class B: ...
|
||||||
|
|
||||||
|
if datetime.date.today().weekday() != 6:
|
||||||
|
C = A
|
||||||
|
else:
|
||||||
|
C = B
|
||||||
|
|
||||||
|
class D(C): ... # error: [unsupported-base]
|
||||||
|
```
|
||||||
|
|
||||||
|
[method resolution order]: https://docs.python.org/3/glossary.html#term-method-resolution-order
|
||||||
|
|
||||||
|
### Links
|
||||||
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-base)
|
||||||
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L473)
|
||||||
|
</details>
|
||||||
|
|
||||||
## `division-by-zero`
|
## `division-by-zero`
|
||||||
|
|
||||||
**Default level**: ignore
|
**Default level**: ignore
|
||||||
|
@ -1740,7 +1787,7 @@ Dividing by zero raises a `ZeroDivisionError` at runtime.
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20division-by-zero)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20division-by-zero)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L222)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L224)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `possibly-unresolved-reference`
|
## `possibly-unresolved-reference`
|
||||||
|
@ -1767,7 +1814,7 @@ print(x) # NameError: name 'x' is not defined
|
||||||
|
|
||||||
### Links
|
### Links
|
||||||
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unresolved-reference)
|
* [Related issues](https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unresolved-reference)
|
||||||
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1046)
|
* [View source](https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1090)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## `unused-ignore-comment`
|
## `unused-ignore-comment`
|
||||||
|
|
|
@ -173,7 +173,7 @@ if hasattr(DoesNotExist, "__mro__"):
|
||||||
if not isinstance(DoesNotExist, type):
|
if not isinstance(DoesNotExist, type):
|
||||||
reveal_type(DoesNotExist) # revealed: Unknown & ~type
|
reveal_type(DoesNotExist) # revealed: Unknown & ~type
|
||||||
|
|
||||||
class Foo(DoesNotExist): ... # error: [invalid-base]
|
class Foo(DoesNotExist): ... # error: [unsupported-base]
|
||||||
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -232,11 +232,15 @@ reveal_type(AA.__mro__) # revealed: tuple[<class 'AA'>, <class 'Z'>, Unknown, <
|
||||||
|
|
||||||
## `__bases__` includes a `Union`
|
## `__bases__` includes a `Union`
|
||||||
|
|
||||||
|
<!-- snapshot-diagnostics -->
|
||||||
|
|
||||||
We don't support union types in a class's bases; a base must resolve to a single `ClassType`. If we
|
We don't support union types in a class's bases; a base must resolve to a single `ClassType`. If we
|
||||||
find a union type in a class's bases, we infer the class's `__mro__` as being
|
find a union type in a class's bases, we infer the class's `__mro__` as being
|
||||||
`[<class>, Unknown, object]`, the same as for MROs that cause errors at runtime.
|
`[<class>, Unknown, object]`, the same as for MROs that cause errors at runtime.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
|
from typing_extensions import reveal_type
|
||||||
|
|
||||||
def returns_bool() -> bool:
|
def returns_bool() -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -250,7 +254,7 @@ else:
|
||||||
|
|
||||||
reveal_type(x) # revealed: <class 'A'> | <class 'B'>
|
reveal_type(x) # revealed: <class 'A'> | <class 'B'>
|
||||||
|
|
||||||
# error: 11 [invalid-base] "Invalid class base with type `<class 'A'> | <class 'B'>` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
# error: 11 [unsupported-base] "Unsupported class base with type `<class 'A'> | <class 'B'>`"
|
||||||
class Foo(x): ...
|
class Foo(x): ...
|
||||||
|
|
||||||
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||||
|
@ -259,8 +263,8 @@ reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'obje
|
||||||
## `__bases__` is a union of a dynamic type and valid bases
|
## `__bases__` is a union of a dynamic type and valid bases
|
||||||
|
|
||||||
If a dynamic type such as `Any` or `Unknown` is one of the elements in the union, and all other
|
If a dynamic type such as `Any` or `Unknown` is one of the elements in the union, and all other
|
||||||
types *would be* valid class bases, we do not emit an `invalid-base` diagnostic and use the dynamic
|
types *would be* valid class bases, we do not emit an `invalid-base` or `unsupported-base`
|
||||||
type as a base to prevent further downstream errors.
|
diagnostic, and we use the dynamic type as a base to prevent further downstream errors.
|
||||||
|
|
||||||
```py
|
```py
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
@ -299,8 +303,8 @@ else:
|
||||||
reveal_type(x) # revealed: <class 'A'> | <class 'B'>
|
reveal_type(x) # revealed: <class 'A'> | <class 'B'>
|
||||||
reveal_type(y) # revealed: <class 'C'> | <class 'D'>
|
reveal_type(y) # revealed: <class 'C'> | <class 'D'>
|
||||||
|
|
||||||
# error: 11 [invalid-base] "Invalid class base with type `<class 'A'> | <class 'B'>` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
# error: 11 [unsupported-base] "Unsupported class base with type `<class 'A'> | <class 'B'>`"
|
||||||
# error: 14 [invalid-base] "Invalid class base with type `<class 'C'> | <class 'D'>` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
# error: 14 [unsupported-base] "Unsupported class base with type `<class 'C'> | <class 'D'>`"
|
||||||
class Foo(x, y): ...
|
class Foo(x, y): ...
|
||||||
|
|
||||||
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||||
|
@ -321,7 +325,7 @@ if returns_bool():
|
||||||
else:
|
else:
|
||||||
foo = object
|
foo = object
|
||||||
|
|
||||||
# error: 21 [invalid-base] "Invalid class base with type `<class 'Y'> | <class 'object'>` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
# error: 21 [unsupported-base] "Unsupported class base with type `<class 'Y'> | <class 'object'>`"
|
||||||
class PossibleError(foo, X): ...
|
class PossibleError(foo, X): ...
|
||||||
|
|
||||||
reveal_type(PossibleError.__mro__) # revealed: tuple[<class 'PossibleError'>, Unknown, <class 'object'>]
|
reveal_type(PossibleError.__mro__) # revealed: tuple[<class 'PossibleError'>, Unknown, <class 'object'>]
|
||||||
|
@ -339,12 +343,47 @@ else:
|
||||||
# revealed: tuple[<class 'B'>, <class 'X'>, <class 'Y'>, <class 'O'>, <class 'object'>] | tuple[<class 'B'>, <class 'Y'>, <class 'X'>, <class 'O'>, <class 'object'>]
|
# revealed: tuple[<class 'B'>, <class 'X'>, <class 'Y'>, <class 'O'>, <class 'object'>] | tuple[<class 'B'>, <class 'Y'>, <class 'X'>, <class 'O'>, <class 'object'>]
|
||||||
reveal_type(B.__mro__)
|
reveal_type(B.__mro__)
|
||||||
|
|
||||||
# error: 12 [invalid-base] "Invalid class base with type `<class 'B'> | <class 'B'>` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
|
# error: 12 [unsupported-base] "Unsupported class base with type `<class 'B'> | <class 'B'>`"
|
||||||
class Z(A, B): ...
|
class Z(A, B): ...
|
||||||
|
|
||||||
reveal_type(Z.__mro__) # revealed: tuple[<class 'Z'>, Unknown, <class 'object'>]
|
reveal_type(Z.__mro__) # revealed: tuple[<class 'Z'>, Unknown, <class 'object'>]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## `__bases__` lists that include objects that are not instances of `type`
|
||||||
|
|
||||||
|
<!-- snapshot-diagnostics -->
|
||||||
|
|
||||||
|
```py
|
||||||
|
class Foo(2): ... # error: [invalid-base]
|
||||||
|
```
|
||||||
|
|
||||||
|
A base that is not an instance of `type` but does have an `__mro_entries__` method will not raise an
|
||||||
|
exception at runtime, so we issue `unsupported-base` rather than `invalid-base`:
|
||||||
|
|
||||||
|
```py
|
||||||
|
class Foo:
|
||||||
|
def __mro_entries__(self, bases: tuple[type, ...]) -> tuple[type, ...]:
|
||||||
|
return ()
|
||||||
|
|
||||||
|
class Bar(Foo()): ... # error: [unsupported-base]
|
||||||
|
```
|
||||||
|
|
||||||
|
But for objects that have badly defined `__mro_entries__`, `invalid-base` is emitted rather than
|
||||||
|
`unsupported-base`:
|
||||||
|
|
||||||
|
```py
|
||||||
|
class Bad1:
|
||||||
|
def __mro_entries__(self, bases, extra_arg):
|
||||||
|
return ()
|
||||||
|
|
||||||
|
class Bad2:
|
||||||
|
def __mro_entries__(self, bases) -> int:
|
||||||
|
return 42
|
||||||
|
|
||||||
|
class BadSub1(Bad1()): ... # error: [invalid-base]
|
||||||
|
class BadSub2(Bad2()): ... # error: [invalid-base]
|
||||||
|
```
|
||||||
|
|
||||||
## `__bases__` lists with duplicate bases
|
## `__bases__` lists with duplicate bases
|
||||||
|
|
||||||
<!-- snapshot-diagnostics -->
|
<!-- snapshot-diagnostics -->
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
---
|
||||||
|
source: crates/ty_test/src/lib.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
---
|
||||||
|
mdtest name: mro.md - Method Resolution Order tests - `__bases__` includes a `Union`
|
||||||
|
mdtest path: crates/ty_python_semantic/resources/mdtest/mro.md
|
||||||
|
---
|
||||||
|
|
||||||
|
# Python source files
|
||||||
|
|
||||||
|
## mdtest_snippet.py
|
||||||
|
|
||||||
|
```
|
||||||
|
1 | from typing_extensions import reveal_type
|
||||||
|
2 |
|
||||||
|
3 | def returns_bool() -> bool:
|
||||||
|
4 | return True
|
||||||
|
5 |
|
||||||
|
6 | class A: ...
|
||||||
|
7 | class B: ...
|
||||||
|
8 |
|
||||||
|
9 | if returns_bool():
|
||||||
|
10 | x = A
|
||||||
|
11 | else:
|
||||||
|
12 | x = B
|
||||||
|
13 |
|
||||||
|
14 | reveal_type(x) # revealed: <class 'A'> | <class 'B'>
|
||||||
|
15 |
|
||||||
|
16 | # error: 11 [unsupported-base] "Unsupported class base with type `<class 'A'> | <class 'B'>`"
|
||||||
|
17 | class Foo(x): ...
|
||||||
|
18 |
|
||||||
|
19 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||||
|
```
|
||||||
|
|
||||||
|
# Diagnostics
|
||||||
|
|
||||||
|
```
|
||||||
|
info[revealed-type]: Revealed type
|
||||||
|
--> src/mdtest_snippet.py:14:13
|
||||||
|
|
|
||||||
|
12 | x = B
|
||||||
|
13 |
|
||||||
|
14 | reveal_type(x) # revealed: <class 'A'> | <class 'B'>
|
||||||
|
| ^ `<class 'A'> | <class 'B'>`
|
||||||
|
15 |
|
||||||
|
16 | # error: 11 [unsupported-base] "Unsupported class base with type `<class 'A'> | <class 'B'>`"
|
||||||
|
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
warning[unsupported-base]: Unsupported class base with type `<class 'A'> | <class 'B'>`
|
||||||
|
--> src/mdtest_snippet.py:17:11
|
||||||
|
|
|
||||||
|
16 | # error: 11 [unsupported-base] "Unsupported class base with type `<class 'A'> | <class 'B'>`"
|
||||||
|
17 | class Foo(x): ...
|
||||||
|
| ^
|
||||||
|
18 |
|
||||||
|
19 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||||
|
|
|
||||||
|
info: ty cannot resolve a consistent MRO for class `Foo` due to this base
|
||||||
|
info: Only class objects or `Any` are supported as class bases
|
||||||
|
info: rule `unsupported-base` is enabled by default
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
info[revealed-type]: Revealed type
|
||||||
|
--> src/mdtest_snippet.py:19:13
|
||||||
|
|
|
||||||
|
17 | class Foo(x): ...
|
||||||
|
18 |
|
||||||
|
19 | reveal_type(Foo.__mro__) # revealed: tuple[<class 'Foo'>, Unknown, <class 'object'>]
|
||||||
|
| ^^^^^^^^^^^ `tuple[<class 'Foo'>, Unknown, <class 'object'>]`
|
||||||
|
|
|
||||||
|
|
||||||
|
```
|
|
@ -0,0 +1,97 @@
|
||||||
|
---
|
||||||
|
source: crates/ty_test/src/lib.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
---
|
||||||
|
mdtest name: mro.md - Method Resolution Order tests - `__bases__` lists that include objects that are not instances of `type`
|
||||||
|
mdtest path: crates/ty_python_semantic/resources/mdtest/mro.md
|
||||||
|
---
|
||||||
|
|
||||||
|
# Python source files
|
||||||
|
|
||||||
|
## mdtest_snippet.py
|
||||||
|
|
||||||
|
```
|
||||||
|
1 | class Foo(2): ... # error: [invalid-base]
|
||||||
|
2 | class Foo:
|
||||||
|
3 | def __mro_entries__(self, bases: tuple[type, ...]) -> tuple[type, ...]:
|
||||||
|
4 | return ()
|
||||||
|
5 |
|
||||||
|
6 | class Bar(Foo()): ... # error: [unsupported-base]
|
||||||
|
7 | class Bad1:
|
||||||
|
8 | def __mro_entries__(self, bases, extra_arg):
|
||||||
|
9 | return ()
|
||||||
|
10 |
|
||||||
|
11 | class Bad2:
|
||||||
|
12 | def __mro_entries__(self, bases) -> int:
|
||||||
|
13 | return 42
|
||||||
|
14 |
|
||||||
|
15 | class BadSub1(Bad1()): ... # error: [invalid-base]
|
||||||
|
16 | class BadSub2(Bad2()): ... # error: [invalid-base]
|
||||||
|
```
|
||||||
|
|
||||||
|
# Diagnostics
|
||||||
|
|
||||||
|
```
|
||||||
|
error[invalid-base]: Invalid class base with type `Literal[2]`
|
||||||
|
--> src/mdtest_snippet.py:1:11
|
||||||
|
|
|
||||||
|
1 | class Foo(2): ... # error: [invalid-base]
|
||||||
|
| ^
|
||||||
|
2 | class Foo:
|
||||||
|
3 | def __mro_entries__(self, bases: tuple[type, ...]) -> tuple[type, ...]:
|
||||||
|
|
|
||||||
|
info: Definition of class `Foo` will raise `TypeError` at runtime
|
||||||
|
info: rule `invalid-base` is enabled by default
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
warning[unsupported-base]: Unsupported class base with type `Foo`
|
||||||
|
--> src/mdtest_snippet.py:6:11
|
||||||
|
|
|
||||||
|
4 | return ()
|
||||||
|
5 |
|
||||||
|
6 | class Bar(Foo()): ... # error: [unsupported-base]
|
||||||
|
| ^^^^^
|
||||||
|
7 | class Bad1:
|
||||||
|
8 | def __mro_entries__(self, bases, extra_arg):
|
||||||
|
|
|
||||||
|
info: ty cannot resolve a consistent MRO for class `Bar` due to this base
|
||||||
|
info: Only class objects or `Any` are supported as class bases
|
||||||
|
info: rule `unsupported-base` is enabled by default
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
error[invalid-base]: Invalid class base with type `Bad1`
|
||||||
|
--> src/mdtest_snippet.py:15:15
|
||||||
|
|
|
||||||
|
13 | return 42
|
||||||
|
14 |
|
||||||
|
15 | class BadSub1(Bad1()): ... # error: [invalid-base]
|
||||||
|
| ^^^^^^
|
||||||
|
16 | class BadSub2(Bad2()): ... # error: [invalid-base]
|
||||||
|
|
|
||||||
|
info: Definition of class `BadSub1` will raise `TypeError` at runtime
|
||||||
|
info: An instance type is only a valid class base if it has a valid `__mro_entries__` method
|
||||||
|
info: Type `Bad1` has an `__mro_entries__` method, but it cannot be called with the expected arguments
|
||||||
|
info: Expected a signature at least as permissive as `def __mro_entries__(self, bases: tuple[type, ...], /) -> tuple[type, ...]`
|
||||||
|
info: rule `invalid-base` is enabled by default
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
error[invalid-base]: Invalid class base with type `Bad2`
|
||||||
|
--> src/mdtest_snippet.py:16:15
|
||||||
|
|
|
||||||
|
15 | class BadSub1(Bad1()): ... # error: [invalid-base]
|
||||||
|
16 | class BadSub2(Bad2()): ... # error: [invalid-base]
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
info: Definition of class `BadSub2` will raise `TypeError` at runtime
|
||||||
|
info: An instance type is only a valid class base if it has a valid `__mro_entries__` method
|
||||||
|
info: Type `Bad2` has an `__mro_entries__` method, but it does not return a tuple of types
|
||||||
|
info: rule `invalid-base` is enabled by default
|
||||||
|
|
||||||
|
```
|
|
@ -164,8 +164,12 @@ impl<'db> ClassBase<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::NominalInstance(_) => None, // TODO -- handle `__mro_entries__`?
|
Type::NominalInstance(_) => None, // TODO -- handle `__mro_entries__`?
|
||||||
Type::PropertyInstance(_) => None,
|
|
||||||
Type::Never
|
// This likely means that we're in unreachable code,
|
||||||
|
// in which case we want to treat `Never` in a forgiving way and silence diagnostics
|
||||||
|
Type::Never => Some(ClassBase::unknown()),
|
||||||
|
|
||||||
|
Type::PropertyInstance(_)
|
||||||
| Type::BooleanLiteral(_)
|
| Type::BooleanLiteral(_)
|
||||||
| Type::FunctionLiteral(_)
|
| Type::FunctionLiteral(_)
|
||||||
| Type::Callable(..)
|
| Type::Callable(..)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
use super::call::CallErrorKind;
|
||||||
use super::context::InferContext;
|
use super::context::InferContext;
|
||||||
use super::mro::DuplicateBaseError;
|
use super::mro::DuplicateBaseError;
|
||||||
use super::{ClassBase, ClassLiteral, KnownClass};
|
use super::{CallArgumentTypes, CallDunderError, ClassBase, ClassLiteral, KnownClass};
|
||||||
use crate::db::Db;
|
use crate::db::Db;
|
||||||
use crate::lint::{Level, LintRegistryBuilder, LintStatus};
|
use crate::lint::{Level, LintRegistryBuilder, LintStatus};
|
||||||
use crate::suppression::FileSuppressionId;
|
use crate::suppression::FileSuppressionId;
|
||||||
|
@ -70,6 +71,7 @@ pub(crate) fn register_lints(registry: &mut LintRegistryBuilder) {
|
||||||
registry.register_lint(&UNRESOLVED_ATTRIBUTE);
|
registry.register_lint(&UNRESOLVED_ATTRIBUTE);
|
||||||
registry.register_lint(&UNRESOLVED_IMPORT);
|
registry.register_lint(&UNRESOLVED_IMPORT);
|
||||||
registry.register_lint(&UNRESOLVED_REFERENCE);
|
registry.register_lint(&UNRESOLVED_REFERENCE);
|
||||||
|
registry.register_lint(&UNSUPPORTED_BASE);
|
||||||
registry.register_lint(&UNSUPPORTED_OPERATOR);
|
registry.register_lint(&UNSUPPORTED_OPERATOR);
|
||||||
registry.register_lint(&ZERO_STEPSIZE_IN_SLICE);
|
registry.register_lint(&ZERO_STEPSIZE_IN_SLICE);
|
||||||
registry.register_lint(&STATIC_ASSERT_ERROR);
|
registry.register_lint(&STATIC_ASSERT_ERROR);
|
||||||
|
@ -451,14 +453,56 @@ declare_lint! {
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
/// TODO #14889
|
/// ## What it does
|
||||||
|
/// Checks for class definitions that have bases which are not instances of `type`.
|
||||||
|
///
|
||||||
|
/// ## Why is this bad?
|
||||||
|
/// Class definitions with bases like this will lead to `TypeError` being raised at runtime.
|
||||||
|
///
|
||||||
|
/// ## Examples
|
||||||
|
/// ```python
|
||||||
|
/// class A(42): ... # error: [invalid-base]
|
||||||
|
/// ```
|
||||||
pub(crate) static INVALID_BASE = {
|
pub(crate) static INVALID_BASE = {
|
||||||
summary: "detects invalid bases in class definitions",
|
summary: "detects class bases that will cause the class definition to raise an exception at runtime",
|
||||||
status: LintStatus::preview("1.0.0"),
|
status: LintStatus::preview("1.0.0"),
|
||||||
default_level: Level::Error,
|
default_level: Level::Error,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_lint! {
|
||||||
|
/// ## What it does
|
||||||
|
/// Checks for class definitions that have bases which are unsupported by ty.
|
||||||
|
///
|
||||||
|
/// ## Why is this bad?
|
||||||
|
/// If a class has a base that is an instance of a complex type such as a union type,
|
||||||
|
/// ty will not be able to resolve the [method resolution order] (MRO) for the class.
|
||||||
|
/// This will lead to an inferior understanding of your codebase and unpredictable
|
||||||
|
/// type-checking behavior.
|
||||||
|
///
|
||||||
|
/// ## Examples
|
||||||
|
/// ```python
|
||||||
|
/// import datetime
|
||||||
|
///
|
||||||
|
/// class A: ...
|
||||||
|
/// class B: ...
|
||||||
|
///
|
||||||
|
/// if datetime.date.today().weekday() != 6:
|
||||||
|
/// C = A
|
||||||
|
/// else:
|
||||||
|
/// C = B
|
||||||
|
///
|
||||||
|
/// class D(C): ... # error: [unsupported-base]
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [method resolution order]: https://docs.python.org/3/glossary.html#term-method-resolution-order
|
||||||
|
pub(crate) static UNSUPPORTED_BASE = {
|
||||||
|
summary: "detects class bases that are unsupported as ty could not feasibly calculate the class's MRO",
|
||||||
|
status: LintStatus::preview("1.0.0"),
|
||||||
|
default_level: Level::Warn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
/// ## What it does
|
/// ## What it does
|
||||||
/// Checks for expressions used in `with` statements
|
/// Checks for expressions used in `with` statements
|
||||||
|
@ -1976,3 +2020,132 @@ pub(crate) fn report_duplicate_bases(
|
||||||
|
|
||||||
diagnostic.sub(sub_diagnostic);
|
diagnostic.sub(sub_diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn report_invalid_or_unsupported_base(
|
||||||
|
context: &InferContext,
|
||||||
|
base_node: &ast::Expr,
|
||||||
|
base_type: Type,
|
||||||
|
class: ClassLiteral,
|
||||||
|
) {
|
||||||
|
let db = context.db();
|
||||||
|
let instance_of_type = KnownClass::Type.to_instance(db);
|
||||||
|
|
||||||
|
if base_type.is_assignable_to(db, instance_of_type) {
|
||||||
|
report_unsupported_base(context, base_node, base_type, class);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tuple_of_types = KnownClass::Tuple.to_specialized_instance(db, [instance_of_type]);
|
||||||
|
|
||||||
|
let explain_mro_entries = |diagnostic: &mut LintDiagnosticGuard| {
|
||||||
|
diagnostic.info(
|
||||||
|
"An instance type is only a valid class base \
|
||||||
|
if it has a valid `__mro_entries__` method",
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
match base_type.try_call_dunder(
|
||||||
|
db,
|
||||||
|
"__mro_entries__",
|
||||||
|
CallArgumentTypes::positional([tuple_of_types]),
|
||||||
|
) {
|
||||||
|
Ok(ret) => {
|
||||||
|
if ret.return_type(db).is_assignable_to(db, tuple_of_types) {
|
||||||
|
report_unsupported_base(context, base_node, base_type, class);
|
||||||
|
} else {
|
||||||
|
let Some(mut diagnostic) =
|
||||||
|
report_invalid_base(context, base_node, base_type, class)
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
explain_mro_entries(&mut diagnostic);
|
||||||
|
diagnostic.info(format_args!(
|
||||||
|
"Type `{}` has an `__mro_entries__` method, but it does not return a tuple of types",
|
||||||
|
base_type.display(db)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(mro_entries_call_error) => {
|
||||||
|
let Some(mut diagnostic) = report_invalid_base(context, base_node, base_type, class)
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
match mro_entries_call_error {
|
||||||
|
CallDunderError::MethodNotAvailable => {}
|
||||||
|
CallDunderError::PossiblyUnbound(_) => {
|
||||||
|
explain_mro_entries(&mut diagnostic);
|
||||||
|
diagnostic.info(format_args!(
|
||||||
|
"Type `{}` has an `__mro_entries__` attribute, but it is possibly unbound",
|
||||||
|
base_type.display(db)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
CallDunderError::CallError(CallErrorKind::NotCallable, _) => {
|
||||||
|
explain_mro_entries(&mut diagnostic);
|
||||||
|
diagnostic.info(format_args!(
|
||||||
|
"Type `{}` has an `__mro_entries__` attribute, but it is not callable",
|
||||||
|
base_type.display(db)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
CallDunderError::CallError(CallErrorKind::BindingError, _) => {
|
||||||
|
explain_mro_entries(&mut diagnostic);
|
||||||
|
diagnostic.info(format_args!(
|
||||||
|
"Type `{}` has an `__mro_entries__` method, \
|
||||||
|
but it cannot be called with the expected arguments",
|
||||||
|
base_type.display(db)
|
||||||
|
));
|
||||||
|
diagnostic.info(
|
||||||
|
"Expected a signature at least as permissive as \
|
||||||
|
`def __mro_entries__(self, bases: tuple[type, ...], /) -> tuple[type, ...]`"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
CallDunderError::CallError(CallErrorKind::PossiblyNotCallable, _) => {
|
||||||
|
explain_mro_entries(&mut diagnostic);
|
||||||
|
diagnostic.info(format_args!(
|
||||||
|
"Type `{}` has an `__mro_entries__` method, \
|
||||||
|
but it may not be callable",
|
||||||
|
base_type.display(db)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn report_unsupported_base(
|
||||||
|
context: &InferContext,
|
||||||
|
base_node: &ast::Expr,
|
||||||
|
base_type: Type,
|
||||||
|
class: ClassLiteral,
|
||||||
|
) {
|
||||||
|
let Some(builder) = context.report_lint(&UNSUPPORTED_BASE, base_node) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let mut diagnostic = builder.into_diagnostic(format_args!(
|
||||||
|
"Unsupported class base with type `{}`",
|
||||||
|
base_type.display(context.db())
|
||||||
|
));
|
||||||
|
diagnostic.info(format_args!(
|
||||||
|
"ty cannot resolve a consistent MRO for class `{}` due to this base",
|
||||||
|
class.name(context.db())
|
||||||
|
));
|
||||||
|
diagnostic.info("Only class objects or `Any` are supported as class bases");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn report_invalid_base<'ctx, 'db>(
|
||||||
|
context: &'ctx InferContext<'db>,
|
||||||
|
base_node: &ast::Expr,
|
||||||
|
base_type: Type<'db>,
|
||||||
|
class: ClassLiteral<'db>,
|
||||||
|
) -> Option<LintDiagnosticGuard<'ctx, 'db>> {
|
||||||
|
let builder = context.report_lint(&INVALID_BASE, base_node)?;
|
||||||
|
let mut diagnostic = builder.into_diagnostic(format_args!(
|
||||||
|
"Invalid class base with type `{}`",
|
||||||
|
base_type.display(context.db())
|
||||||
|
));
|
||||||
|
diagnostic.info(format_args!(
|
||||||
|
"Definition of class `{}` will raise `TypeError` at runtime",
|
||||||
|
class.name(context.db())
|
||||||
|
));
|
||||||
|
Some(diagnostic)
|
||||||
|
}
|
||||||
|
|
|
@ -102,8 +102,9 @@ use super::diagnostic::{
|
||||||
SUBCLASS_OF_FINAL_CLASS, TYPE_ASSERTION_FAILURE, report_attempted_protocol_instantiation,
|
SUBCLASS_OF_FINAL_CLASS, TYPE_ASSERTION_FAILURE, report_attempted_protocol_instantiation,
|
||||||
report_bad_argument_to_get_protocol_members, report_duplicate_bases,
|
report_bad_argument_to_get_protocol_members, report_duplicate_bases,
|
||||||
report_index_out_of_bounds, report_invalid_exception_caught, report_invalid_exception_cause,
|
report_index_out_of_bounds, report_invalid_exception_caught, report_invalid_exception_cause,
|
||||||
report_invalid_exception_raised, report_invalid_type_checking_constant,
|
report_invalid_exception_raised, report_invalid_or_unsupported_base,
|
||||||
report_non_subscriptable, report_possibly_unresolved_reference,
|
report_invalid_type_checking_constant, report_non_subscriptable,
|
||||||
|
report_possibly_unresolved_reference,
|
||||||
report_runtime_check_against_non_runtime_checkable_protocol, report_slice_step_size_zero,
|
report_runtime_check_against_non_runtime_checkable_protocol, report_slice_step_size_zero,
|
||||||
report_unresolved_reference,
|
report_unresolved_reference,
|
||||||
};
|
};
|
||||||
|
@ -892,63 +893,51 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
|
|
||||||
// (3) Check that the class's MRO is resolvable
|
// (3) Check that the class's MRO is resolvable
|
||||||
match class.try_mro(self.db(), None) {
|
match class.try_mro(self.db(), None) {
|
||||||
Err(mro_error) => {
|
Err(mro_error) => match mro_error.reason() {
|
||||||
match mro_error.reason() {
|
MroErrorKind::DuplicateBases(duplicates) => {
|
||||||
MroErrorKind::DuplicateBases(duplicates) => {
|
let base_nodes = class_node.bases();
|
||||||
let base_nodes = class_node.bases();
|
for duplicate in duplicates {
|
||||||
for duplicate in duplicates {
|
report_duplicate_bases(&self.context, class, duplicate, base_nodes);
|
||||||
report_duplicate_bases(&self.context, class, duplicate, base_nodes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MroErrorKind::InvalidBases(bases) => {
|
|
||||||
let base_nodes = class_node.bases();
|
|
||||||
for (index, base_ty) in bases {
|
|
||||||
if base_ty.is_never() {
|
|
||||||
// A class base of type `Never` can appear in unreachable code. It
|
|
||||||
// does not indicate a problem, since the actual construction of the
|
|
||||||
// class will never happen.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let Some(builder) =
|
|
||||||
self.context.report_lint(&INVALID_BASE, &base_nodes[*index])
|
|
||||||
else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
builder.into_diagnostic(format_args!(
|
|
||||||
"Invalid class base with type `{}` \
|
|
||||||
(all bases must be a class, `Any`, `Unknown` or `Todo`)",
|
|
||||||
base_ty.display(self.db())
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MroErrorKind::UnresolvableMro { bases_list } => {
|
|
||||||
if let Some(builder) =
|
|
||||||
self.context.report_lint(&INCONSISTENT_MRO, class_node)
|
|
||||||
{
|
|
||||||
builder.into_diagnostic(format_args!(
|
|
||||||
"Cannot create a consistent method resolution order (MRO) \
|
|
||||||
for class `{}` with bases list `[{}]`",
|
|
||||||
class.name(self.db()),
|
|
||||||
bases_list
|
|
||||||
.iter()
|
|
||||||
.map(|base| base.display(self.db()))
|
|
||||||
.join(", ")
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MroErrorKind::InheritanceCycle => {
|
|
||||||
if let Some(builder) = self
|
|
||||||
.context
|
|
||||||
.report_lint(&CYCLIC_CLASS_DEFINITION, class_node)
|
|
||||||
{
|
|
||||||
builder.into_diagnostic(format_args!(
|
|
||||||
"Cyclic definition of `{}` (class cannot inherit from itself)",
|
|
||||||
class.name(self.db())
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
MroErrorKind::InvalidBases(bases) => {
|
||||||
|
let base_nodes = class_node.bases();
|
||||||
|
for (index, base_ty) in bases {
|
||||||
|
report_invalid_or_unsupported_base(
|
||||||
|
&self.context,
|
||||||
|
&base_nodes[*index],
|
||||||
|
*base_ty,
|
||||||
|
class,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MroErrorKind::UnresolvableMro { bases_list } => {
|
||||||
|
if let Some(builder) =
|
||||||
|
self.context.report_lint(&INCONSISTENT_MRO, class_node)
|
||||||
|
{
|
||||||
|
builder.into_diagnostic(format_args!(
|
||||||
|
"Cannot create a consistent method resolution order (MRO) \
|
||||||
|
for class `{}` with bases list `[{}]`",
|
||||||
|
class.name(self.db()),
|
||||||
|
bases_list
|
||||||
|
.iter()
|
||||||
|
.map(|base| base.display(self.db()))
|
||||||
|
.join(", ")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MroErrorKind::InheritanceCycle => {
|
||||||
|
if let Some(builder) = self
|
||||||
|
.context
|
||||||
|
.report_lint(&CYCLIC_CLASS_DEFINITION, class_node)
|
||||||
|
{
|
||||||
|
builder.into_diagnostic(format_args!(
|
||||||
|
"Cyclic definition of `{}` (class cannot inherit from itself)",
|
||||||
|
class.name(self.db())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
Ok(_) => check_class_slots(&self.context, class, class_node),
|
Ok(_) => check_class_slots(&self.context, class, class_node),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use rustc_hash::FxHashMap;
|
use indexmap::IndexMap;
|
||||||
|
use rustc_hash::FxBuildHasher;
|
||||||
|
|
||||||
use crate::Db;
|
use crate::Db;
|
||||||
use crate::types::class_base::ClassBase;
|
use crate::types::class_base::ClassBase;
|
||||||
|
@ -157,8 +158,8 @@ impl<'db> Mro<'db> {
|
||||||
let mut duplicate_dynamic_bases = false;
|
let mut duplicate_dynamic_bases = false;
|
||||||
|
|
||||||
let duplicate_bases: Vec<DuplicateBaseError<'db>> = {
|
let duplicate_bases: Vec<DuplicateBaseError<'db>> = {
|
||||||
let mut base_to_indices: FxHashMap<ClassBase<'db>, Vec<usize>> =
|
let mut base_to_indices: IndexMap<ClassBase<'db>, Vec<usize>, FxBuildHasher> =
|
||||||
FxHashMap::default();
|
IndexMap::default();
|
||||||
|
|
||||||
for (index, base) in valid_bases.iter().enumerate() {
|
for (index, base) in valid_bases.iter().enumerate() {
|
||||||
base_to_indices.entry(*base).or_default().push(index);
|
base_to_indices.entry(*base).or_default().push(index);
|
||||||
|
|
14
ty.schema.json
generated
14
ty.schema.json
generated
|
@ -401,8 +401,8 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"invalid-base": {
|
"invalid-base": {
|
||||||
"title": "detects invalid bases in class definitions",
|
"title": "detects class bases that will cause the class definition to raise an exception at runtime",
|
||||||
"description": "TODO #14889",
|
"description": "## What it does\nChecks for class definitions that have bases which are not instances of `type`.\n\n## Why is this bad?\nClass definitions with bases like this will lead to `TypeError` being raised at runtime.\n\n## Examples\n```python\nclass A(42): ... # error: [invalid-base]\n```",
|
||||||
"default": "error",
|
"default": "error",
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
|
@ -800,6 +800,16 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"unsupported-base": {
|
||||||
|
"title": "detects class bases that are unsupported as ty could not feasibly calculate the class's MRO",
|
||||||
|
"description": "## What it does\nChecks for class definitions that have bases which are unsupported by ty.\n\n## Why is this bad?\nIf a class has a base that is an instance of a complex type such as a union type,\nty will not be able to resolve the [method resolution order] (MRO) for the class.\nThis will lead to an inferior understanding of your codebase and unpredictable\ntype-checking behavior.\n\n## Examples\n```python\nimport datetime\n\nclass A: ...\nclass B: ...\n\nif datetime.date.today().weekday() != 6:\n C = A\nelse:\n C = B\n\nclass D(C): ... # error: [unsupported-base]\n```\n\n[method resolution order]: https://docs.python.org/3/glossary.html#term-method-resolution-order",
|
||||||
|
"default": "warn",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/Level"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"unsupported-bool-conversion": {
|
"unsupported-bool-conversion": {
|
||||||
"title": "detects boolean conversion where the object incorrectly implements `__bool__`",
|
"title": "detects boolean conversion where the object incorrectly implements `__bool__`",
|
||||||
"description": "## What it does\nChecks for bool conversions where the object doesn't correctly implement `__bool__`.\n\n## Why is this bad?\nIf an exception is raised when you attempt to evaluate the truthiness of an object,\nusing the object in a boolean context will fail at runtime.\n\n## Examples\n\n```python\nclass NotBoolable:\n __bool__ = None\n\nb1 = NotBoolable()\nb2 = NotBoolable()\n\nif b1: # exception raised here\n pass\n\nb1 and b2 # exception raised here\nnot b1 # exception raised here\nb1 < b2 < b1 # exception raised here\n```",
|
"description": "## What it does\nChecks for bool conversions where the object doesn't correctly implement `__bool__`.\n\n## Why is this bad?\nIf an exception is raised when you attempt to evaluate the truthiness of an object,\nusing the object in a boolean context will fail at runtime.\n\n## Examples\n\n```python\nclass NotBoolable:\n __bool__ = None\n\nb1 = NotBoolable()\nb2 = NotBoolable()\n\nif b1: # exception raised here\n pass\n\nb1 and b2 # exception raised here\nnot b1 # exception raised here\nb1 < b2 < b1 # exception raised here\n```",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue