From b73aab4d91c40650f353a53b2f4add2bd06bd68e Mon Sep 17 00:00:00 2001
From: Zanie Blue warn ·
-Added in 0.0.1-alpha.22 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for imports of symbols that may be missing.
-
-**Why is this bad?**
-
-Importing a missing module or name will raise a `ModuleNotFoundError`
-or `ImportError` at runtime.
-
-**Examples**
-
-```python
-# module.py
-import datetime
-
-if datetime.date.today().weekday() != 6:
- a = 1
-
-# main.py
-from module import a # ImportError: cannot import name 'a' from 'module'
-```
-
## `redundant-cast`
@@ -2778,6 +2746,38 @@ Dividing by zero raises a `ZeroDivisionError` at runtime.
5 / 0
```
+## `possibly-missing-import`
+
+
+Default level: ignore ·
+Added in 0.0.1-alpha.22 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for imports of symbols that may be missing.
+
+**Why is this bad?**
+
+Importing a missing module or name will raise a `ModuleNotFoundError`
+or `ImportError` at runtime.
+
+**Examples**
+
+```python
+# module.py
+import datetime
+
+if datetime.date.today().weekday() != 6:
+ a = 1
+
+# main.py
+from module import a # ImportError: cannot import name 'a' from 'module'
+```
+
## `possibly-unresolved-reference`
diff --git a/pyproject.toml b/pyproject.toml
index 8aa37ab..b9e96cc 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "ty"
-version = "0.0.3"
+version = "0.0.4"
requires-python = ">=3.8"
dependencies = []
description = "An extremely fast Python type checker, written in Rust."
diff --git a/ruff b/ruff
index 9cc132f..fa57253 160000
--- a/ruff
+++ b/ruff
@@ -1 +1 @@
-Subproject commit 9cc132f098c601a2a60c488f50134dbfa4c87c5f
+Subproject commit fa57253980c317cce7ff1f35691e3d850c0fb58b
diff --git a/uv.lock b/uv.lock
index 0e60ac2..03f4494 100644
--- a/uv.lock
+++ b/uv.lock
@@ -624,7 +624,7 @@ wheels = [
[[package]]
name = "ty"
-version = "0.0.3"
+version = "0.0.4"
source = { editable = "." }
[package.dev-dependencies]
From 06b98384044927abd6f9b897f2802d93e65e5b95 Mon Sep 17 00:00:00 2001
From: Carl Meyer
--exit-zeroAlways use exit code 0, even when there are error-level diagnostics
--extra-search-path pathAdditional path to use as a module-resolution source (can be passed multiple times).
This is an advanced option that should usually only be used for first-party or third-party modules that are not installed into your Python environment in a conventional way. Use --python to point ty to your Python environment if it is in an unusual location.
--force-excludeEnforce exclusions, even for paths passed to ty directly on the command-line. Use --no-force-exclude to disable
--help, -hPrint help (see a summary with '-h')
--ignore ruleDisables the rule. Can be specified multiple times.
--no-progressHide all progress outputs.
diff --git a/docs/reference/rules.md b/docs/reference/rules.md index 6eba48d..db57225 100644 --- a/docs/reference/rules.md +++ b/docs/reference/rules.md @@ -2,10 +2,51 @@ # Rules +## `ambiguous-protocol-member` + + +Default level:warn ·
+Added in 0.0.1-alpha.20 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for protocol classes with members that will lead to ambiguous interfaces.
+
+**Why is this bad?**
+
+Assigning to an undeclared variable in a protocol class leads to an ambiguous
+interface which may lead to the type checker inferring unexpected things. It's
+recommended to ensure that all members of a protocol class are explicitly declared.
+
+**Examples**
+
+
+```py
+from typing import Protocol
+
+class BaseProto(Protocol):
+ a: int # fine (explicitly declared as `int`)
+ def method_member(self) -> int: ... # fine: a method definition using `def` is considered a declaration
+ c = "some variable" # error: no explicit declaration, leading to ambiguity
+ b = method_member # error: no explicit declaration, leading to ambiguity
+
+ # error: this creates implicit assignments of `d` and `e` in the protocol class body.
+ # Were they really meant to be considered protocol members?
+ for d, e in enumerate(range(42)):
+ pass
+
+class SubProto(BaseProto, Protocol):
+ a = 42 # fine (declared in superclass)
+```
+
## `byte-string-type-annotation`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
View source
@@ -36,7 +77,7 @@ def test(): -> "int":
## `call-non-callable`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
View source
@@ -60,7 +101,7 @@ Calling a non-callable object will raise a `TypeError` at runtime.
## `conflicting-argument-forms`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
View source
@@ -92,7 +133,7 @@ f(int) # error
## `conflicting-declarations`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
View source
@@ -123,7 +164,7 @@ a = 1
## `conflicting-metaclass`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
View source
@@ -155,7 +196,7 @@ class C(A, B): ...
## `cyclic-class-definition`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
View source
@@ -187,7 +228,7 @@ class B(A): ...
## `cyclic-type-alias-definition`
-Default level: error ·
+Default level: error ·
Preview (since 1.0.0) ·
Related issues ·
View source
@@ -212,13 +253,69 @@ type A = B
type B = A
```
+## `deprecated`
+
+
+Default level: warn ·
+Added in 0.0.1-alpha.16 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for uses of deprecated items
+
+**Why is this bad?**
+
+Deprecated items should no longer be used.
+
+**Examples**
+
+```python
+@warnings.deprecated("use new_func instead")
+def old_func(): ...
+
+old_func() # emits [deprecated] diagnostic
+```
+
+## `division-by-zero`
+
+
+Default level: ignore ·
+Preview (since 0.0.1-alpha.1) ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+It detects division by zero.
+
+**Why is this bad?**
+
+Dividing by zero raises a `ZeroDivisionError` at runtime.
+
+**Rule status**
+
+This rule is currently disabled by default because of the number of
+false positives it can produce.
+
+**Examples**
+
+```python
+5 / 0
+```
+
## `duplicate-base`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -242,10 +339,10 @@ class B(A, A): ...
## `duplicate-kw-only`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.12 ·
Related issues ·
-View source
+View source
@@ -280,7 +377,7 @@ class A: # Crash at runtime
## `escape-character-in-forward-annotation`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
View source
@@ -292,7 +389,7 @@ TODO #14889
## `fstring-type-annotation`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
View source
@@ -320,10 +417,41 @@ def test(): -> "int":
...
```
+## `ignore-comment-unknown-rule`
+
+
+Default level: warn ·
+Added in 0.0.1-alpha.1 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for `ty: ignore[code]` where `code` isn't a known lint rule.
+
+**Why is this bad?**
+
+A `ty: ignore[code]` directive with a `code` that doesn't match
+any known rule will not suppress any type errors, and is probably a mistake.
+
+**Examples**
+
+```py
+a = 20 / 0 # ty: ignore[division-by-zer]
+```
+
+Use instead:
+
+```py
+a = 20 / 0 # ty: ignore[division-by-zero]
+```
+
## `implicit-concatenated-string-type-annotation`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
View source
@@ -354,10 +482,10 @@ def test(): -> "Literal[5]":
## `inconsistent-mro`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -384,10 +512,10 @@ class C(A, B): ...
## `index-out-of-bounds`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -410,10 +538,10 @@ t[3] # IndexError: tuple index out of range
## `instance-layout-conflict`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.12 ·
Related issues ·
-View source
+View source
@@ -499,10 +627,10 @@ an atypical memory layout.
## `invalid-argument-type`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -526,10 +654,10 @@ func("foo") # error: [invalid-argument-type]
## `invalid-assignment`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -554,10 +682,10 @@ a: int = ''
## `invalid-attribute-access`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -588,10 +716,10 @@ C.instance_var = 3 # error: Cannot assign to instance variable
## `invalid-await`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.19 ·
Related issues ·
-View source
+View source
@@ -624,10 +752,10 @@ asyncio.run(main())
## `invalid-base`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -648,10 +776,10 @@ class A(42): ... # error: [invalid-base]
## `invalid-context-manager`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -675,10 +803,10 @@ with 1:
## `invalid-declaration`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -704,10 +832,10 @@ a: str
## `invalid-exception-caught`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -748,10 +876,10 @@ except ZeroDivisionError:
## `invalid-explicit-override`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.28 ·
Related issues ·
-View source
+View source
@@ -790,10 +918,10 @@ class D(A):
## `invalid-frozen-dataclass-subclass`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.35 ·
Related issues ·
-View source
+View source
@@ -834,10 +962,10 @@ class NonFrozenChild(FrozenBase): # Error raised here
## `invalid-generic-class`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -869,13 +997,43 @@ class D(Generic[U, T]): ...
- [Typing spec: Generics](https://typing.python.org/en/latest/spec/generics.html#introduction)
+## `invalid-ignore-comment`
+
+
+Default level: warn ·
+Added in 0.0.1-alpha.1 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for `type: ignore` and `ty: ignore` comments that are syntactically incorrect.
+
+**Why is this bad?**
+
+A syntactically incorrect ignore comment is probably a mistake and is useless.
+
+**Examples**
+
+```py
+a = 20 / 0 # type: ignoree
+```
+
+Use instead:
+
+```py
+a = 20 / 0 # type: ignore
+```
+
## `invalid-key`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.17 ·
Related issues ·
-View source
+View source
@@ -911,10 +1069,10 @@ carol = Person(name="Carol", age=25) # typo!
## `invalid-legacy-type-variable`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -946,10 +1104,10 @@ def f(t: TypeVar("U")): ...
## `invalid-metaclass`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -980,10 +1138,10 @@ class B(metaclass=f): ...
## `invalid-method-override`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.20 ·
Related issues ·
-View source
+View source
@@ -1087,10 +1245,10 @@ Correct use of `@override` is enforced by ty's `invalid-explicit-override` rule.
## `invalid-named-tuple`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.19 ·
Related issues ·
-View source
+View source
@@ -1141,10 +1299,10 @@ AttributeError: Cannot overwrite NamedTuple attribute _asdict
## `invalid-newtype`
-Default level: error ·
+Default level: error ·
Preview (since 1.0.0) ·
Related issues ·
-View source
+View source
@@ -1171,10 +1329,10 @@ Baz = NewType("Baz", int | str) # error: invalid base for `typing.NewType`
## `invalid-overload`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1221,10 +1379,10 @@ def foo(x: int) -> int: ...
## `invalid-parameter-default`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1247,10 +1405,10 @@ def f(a: int = ''): ...
## `invalid-paramspec`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1278,10 +1436,10 @@ P2 = ParamSpec("S2") # error: ParamSpec name must match the variable it's assig
## `invalid-protocol`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1312,10 +1470,10 @@ TypeError: Protocols can only inherit from other protocols, got error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1361,10 +1519,10 @@ def g():
## `invalid-return-type`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1386,10 +1544,10 @@ def func() -> int:
## `invalid-super-argument`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1432,7 +1590,7 @@ super(B, A) # error: `A` does not satisfy `issubclass(A, B)`
## `invalid-syntax-in-forward-annotation`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
View source
@@ -1444,10 +1602,10 @@ TODO #14889
## `invalid-type-alias-type`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.6 ·
Related issues ·
-View source
+View source
@@ -1471,10 +1629,10 @@ NewAlias = TypeAliasType(get_name(), int) # error: TypeAliasType name mus
## `invalid-type-arguments`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.29 ·
Related issues ·
-View source
+View source
@@ -1518,10 +1676,10 @@ Bar[int] # error: too few arguments
## `invalid-type-checking-constant`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1548,10 +1706,10 @@ TYPE_CHECKING = ''
## `invalid-type-form`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1578,10 +1736,10 @@ b: Annotated[int] # `Annotated` expects at least two arguments
## `invalid-type-guard-call`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.11 ·
Related issues ·
-View source
+View source
@@ -1612,10 +1770,10 @@ f(10) # Error
## `invalid-type-guard-definition`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.11 ·
Related issues ·
-View source
+View source
@@ -1646,10 +1804,10 @@ class C:
## `invalid-type-variable-constraints`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1681,10 +1839,10 @@ T = TypeVar('T', bound=str) # valid bound TypeVar
## `missing-argument`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1706,10 +1864,10 @@ func() # TypeError: func() missing 1 required positional argument: 'x'
## `missing-typed-dict-key`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.20 ·
Related issues ·
-View source
+View source
@@ -1739,10 +1897,10 @@ alice["age"] # KeyError
## `no-matching-overload`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1768,10 +1926,10 @@ func("string") # error: [no-matching-overload]
## `non-subscriptable`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1792,10 +1950,10 @@ Subscripting an object that does not support it will raise a `TypeError` at runt
## `not-iterable`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1818,10 +1976,10 @@ for i in 34: # TypeError: 'int' object is not iterable
## `override-of-final-method`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.29 ·
Related issues ·
-View source
+View source
@@ -1851,10 +2009,10 @@ class B(A):
## `parameter-already-assigned`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1878,10 +2036,10 @@ f(1, x=2) # Error raised here
## `positional-only-parameter-as-kwarg`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.22 ·
Related issues ·
-View source
+View source
@@ -1902,10 +2060,140 @@ def f(x: int, /) -> int: ...
f(x=1) # Error raised here
```
+## `possibly-missing-attribute`
+
+
+Default level: warn ·
+Added in 0.0.1-alpha.22 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for possibly missing attributes.
+
+**Why is this bad?**
+
+Attempting to access a missing attribute will raise an `AttributeError` at runtime.
+
+**Examples**
+
+```python
+class A:
+ if b:
+ c = 0
+
+A.c # AttributeError: type object 'A' has no attribute 'c'
+```
+
+## `possibly-missing-implicit-call`
+
+
+Default level: warn ·
+Added in 0.0.1-alpha.22 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for implicit calls to possibly missing methods.
+
+**Why is this bad?**
+
+Expressions such as `x[y]` and `x * y` call methods
+under the hood (`__getitem__` and `__mul__` respectively).
+Calling a missing method will raise an `AttributeError` at runtime.
+
+**Examples**
+
+```python
+import datetime
+
+class A:
+ if datetime.date.today().weekday() != 6:
+ def __getitem__(self, v): ...
+
+A()[0] # TypeError: 'A' object is not subscriptable
+```
+
+## `possibly-missing-import`
+
+
+Default level: ignore ·
+Added in 0.0.1-alpha.22 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for imports of symbols that may be missing.
+
+**Why is this bad?**
+
+Importing a missing module or name will raise a `ModuleNotFoundError`
+or `ImportError` at runtime.
+
+**Rule status**
+
+This rule is currently disabled by default because of the number of
+false positives it can produce.
+
+**Examples**
+
+```python
+# module.py
+import datetime
+
+if datetime.date.today().weekday() != 6:
+ a = 1
+
+# main.py
+from module import a # ImportError: cannot import name 'a' from 'module'
+```
+
+## `possibly-unresolved-reference`
+
+
+Default level: ignore ·
+Added in 0.0.1-alpha.1 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for references to names that are possibly not defined.
+
+**Why is this bad?**
+
+Using an undefined variable will raise a `NameError` at runtime.
+
+**Rule status**
+
+This rule is currently disabled by default because of the number of
+false positives it can produce.
+
+**Example**
+
+
+```python
+for i in range(0):
+ x = i
+
+print(x) # NameError: name 'x' is not defined
+```
+
## `raw-string-type-annotation`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
View source
@@ -1933,13 +2221,40 @@ def test(): -> "int":
...
```
+## `redundant-cast`
+
+
+Default level: warn ·
+Added in 0.0.1-alpha.1 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Detects redundant `cast` calls where the value already has the target type.
+
+**Why is this bad?**
+
+These casts have no effect and can be removed.
+
+**Example**
+
+```python
+def f() -> int:
+ return 10
+
+cast(int, f()) # Redundant
+```
+
## `static-assert-error`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1966,10 +2281,10 @@ static_assert(int(2.0 * 3.0) == 6) # error: does not have a statically known tr
## `subclass-of-final-class`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -1995,10 +2310,10 @@ class B(A): ... # Error raised here
## `super-call-in-named-tuple-method`
-Default level: error ·
+Default level: error ·
Preview (since 0.0.1-alpha.30) ·
Related issues ·
-View source
+View source
@@ -2029,10 +2344,10 @@ class F(NamedTuple):
## `too-many-positional-arguments`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -2056,10 +2371,10 @@ f("foo") # Error raised here
## `type-assertion-failure`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -2084,10 +2399,10 @@ def _(x: int):
## `unavailable-implicit-super-arguments`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -2127,13 +2442,37 @@ class A:
- [Python documentation: super()](https://docs.python.org/3/library/functions.html#super)
+## `undefined-reveal`
+
+
+Default level: warn ·
+Added in 0.0.1-alpha.1 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for calls to `reveal_type` without importing it.
+
+**Why is this bad?**
+
+Using `reveal_type` without importing it will raise a `NameError` at runtime.
+
+**Examples**
+
+```python
+reveal_type(1) # NameError: name 'reveal_type' is not defined
+```
+
## `unknown-argument`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -2157,10 +2496,10 @@ f(x=1, y=2) # Error raised here
## `unresolved-attribute`
-Default level: error ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
Related issues ·
-View source
+View source
@@ -2182,393 +2521,13 @@ class A: ...
A().foo # AttributeError: 'A' object has no attribute 'foo'
```
-## `unresolved-import`
-
-
-Default level: error ·
-Added in 0.0.1-alpha.1 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for import statements for which the module cannot be resolved.
-
-**Why is this bad?**
-
-Importing a module that cannot be resolved will raise a `ModuleNotFoundError`
-at runtime.
-
-**Examples**
-
-```python
-import foo # ModuleNotFoundError: No module named 'foo'
-```
-
-## `unresolved-reference`
-
-
-Default level: error ·
-Added in 0.0.1-alpha.1 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for references to names that are not defined.
-
-**Why is this bad?**
-
-Using an undefined variable will raise a `NameError` at runtime.
-
-**Example**
-
-
-```python
-print(x) # NameError: name 'x' is not defined
-```
-
-## `unsupported-bool-conversion`
-
-
-Default level: error ·
-Added in 0.0.1-alpha.1 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for bool conversions where the object doesn't correctly implement `__bool__`.
-
-**Why is this bad?**
-
-If an exception is raised when you attempt to evaluate the truthiness of an object,
-using the object in a boolean context will fail at runtime.
-
-**Examples**
-
-
-```python
-class NotBoolable:
- __bool__ = None
-
-b1 = NotBoolable()
-b2 = NotBoolable()
-
-if b1: # exception raised here
- pass
-
-b1 and b2 # exception raised here
-not b1 # exception raised here
-b1 < b2 < b1 # exception raised here
-```
-
-## `unsupported-operator`
-
-
-Default level: error ·
-Added in 0.0.1-alpha.1 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for binary expressions, comparisons, and unary expressions where
-the operands don't support the operator.
-
-**Why is this bad?**
-
-Attempting to use an unsupported operator will raise a `TypeError` at
-runtime.
-
-**Examples**
-
-```python
-class A: ...
-
-A() + A() # TypeError: unsupported operand type(s) for +: 'A' and 'A'
-```
-
-## `zero-stepsize-in-slice`
-
-
-Default level: error ·
-Added in 0.0.1-alpha.1 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for step size 0 in slices.
-
-**Why is this bad?**
-
-A slice with a step size of zero will raise a `ValueError` at runtime.
-
-**Examples**
-
-```python
-l = list(range(10))
-l[1:10:0] # ValueError: slice step cannot be zero
-```
-
-## `ambiguous-protocol-member`
-
-
-Default level: warn ·
-Added in 0.0.1-alpha.20 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for protocol classes with members that will lead to ambiguous interfaces.
-
-**Why is this bad?**
-
-Assigning to an undeclared variable in a protocol class leads to an ambiguous
-interface which may lead to the type checker inferring unexpected things. It's
-recommended to ensure that all members of a protocol class are explicitly declared.
-
-**Examples**
-
-
-```py
-from typing import Protocol
-
-class BaseProto(Protocol):
- a: int # fine (explicitly declared as `int`)
- def method_member(self) -> int: ... # fine: a method definition using `def` is considered a declaration
- c = "some variable" # error: no explicit declaration, leading to ambiguity
- b = method_member # error: no explicit declaration, leading to ambiguity
-
- # error: this creates implicit assignments of `d` and `e` in the protocol class body.
- # Were they really meant to be considered protocol members?
- for d, e in enumerate(range(42)):
- pass
-
-class SubProto(BaseProto, Protocol):
- a = 42 # fine (declared in superclass)
-```
-
-## `deprecated`
-
-
-Default level: warn ·
-Added in 0.0.1-alpha.16 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for uses of deprecated items
-
-**Why is this bad?**
-
-Deprecated items should no longer be used.
-
-**Examples**
-
-```python
-@warnings.deprecated("use new_func instead")
-def old_func(): ...
-
-old_func() # emits [deprecated] diagnostic
-```
-
-## `ignore-comment-unknown-rule`
-
-
-Default level: warn ·
-Added in 0.0.1-alpha.1 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for `ty: ignore[code]` where `code` isn't a known lint rule.
-
-**Why is this bad?**
-
-A `ty: ignore[code]` directive with a `code` that doesn't match
-any known rule will not suppress any type errors, and is probably a mistake.
-
-**Examples**
-
-```py
-a = 20 / 0 # ty: ignore[division-by-zer]
-```
-
-Use instead:
-
-```py
-a = 20 / 0 # ty: ignore[division-by-zero]
-```
-
-## `invalid-ignore-comment`
-
-
-Default level: warn ·
-Added in 0.0.1-alpha.1 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for `type: ignore` and `ty: ignore` comments that are syntactically incorrect.
-
-**Why is this bad?**
-
-A syntactically incorrect ignore comment is probably a mistake and is useless.
-
-**Examples**
-
-```py
-a = 20 / 0 # type: ignoree
-```
-
-Use instead:
-
-```py
-a = 20 / 0 # type: ignore
-```
-
-## `possibly-missing-attribute`
-
-
-Default level: warn ·
-Added in 0.0.1-alpha.22 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for possibly missing attributes.
-
-**Why is this bad?**
-
-Attempting to access a missing attribute will raise an `AttributeError` at runtime.
-
-**Examples**
-
-```python
-class A:
- if b:
- c = 0
-
-A.c # AttributeError: type object 'A' has no attribute 'c'
-```
-
-## `possibly-missing-implicit-call`
-
-
-Default level: warn ·
-Added in 0.0.1-alpha.22 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for implicit calls to possibly missing methods.
-
-**Why is this bad?**
-
-Expressions such as `x[y]` and `x * y` call methods
-under the hood (`__getitem__` and `__mul__` respectively).
-Calling a missing method will raise an `AttributeError` at runtime.
-
-**Examples**
-
-```python
-import datetime
-
-class A:
- if datetime.date.today().weekday() != 6:
- def __getitem__(self, v): ...
-
-A()[0] # TypeError: 'A' object is not subscriptable
-```
-
-## `redundant-cast`
-
-
-Default level: warn ·
-Added in 0.0.1-alpha.1 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Detects redundant `cast` calls where the value already has the target type.
-
-**Why is this bad?**
-
-These casts have no effect and can be removed.
-
-**Example**
-
-```python
-def f() -> int:
- return 10
-
-cast(int, f()) # Redundant
-```
-
-## `undefined-reveal`
-
-
-Default level: warn ·
-Added in 0.0.1-alpha.1 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for calls to `reveal_type` without importing it.
-
-**Why is this bad?**
-
-Using `reveal_type` without importing it will raise a `NameError` at runtime.
-
-**Examples**
-
-```python
-reveal_type(1) # NameError: name 'reveal_type' is not defined
-```
-
## `unresolved-global`
-Default level: warn ·
+Default level: warn ·
Added in 0.0.1-alpha.15 ·
Related issues ·
-View source
+View source
@@ -2620,13 +2579,63 @@ def g():
print(x)
```
+## `unresolved-import`
+
+
+Default level: error ·
+Added in 0.0.1-alpha.1 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for import statements for which the module cannot be resolved.
+
+**Why is this bad?**
+
+Importing a module that cannot be resolved will raise a `ModuleNotFoundError`
+at runtime.
+
+**Examples**
+
+```python
+import foo # ModuleNotFoundError: No module named 'foo'
+```
+
+## `unresolved-reference`
+
+
+Default level: error ·
+Added in 0.0.1-alpha.1 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for references to names that are not defined.
+
+**Why is this bad?**
+
+Using an undefined variable will raise a `NameError` at runtime.
+
+**Example**
+
+
+```python
+print(x) # NameError: name 'x' is not defined
+```
+
## `unsupported-base`
-Default level: warn ·
+Default level: warn ·
Added in 0.0.1-alpha.7 ·
Related issues ·
-View source
+View source
@@ -2659,13 +2668,109 @@ class D(C): ... # error: [unsupported-base]
[method resolution order]: https://docs.python.org/3/glossary.html#term-method-resolution-order
+## `unsupported-bool-conversion`
+
+
+Default level: error ·
+Added in 0.0.1-alpha.1 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for bool conversions where the object doesn't correctly implement `__bool__`.
+
+**Why is this bad?**
+
+If an exception is raised when you attempt to evaluate the truthiness of an object,
+using the object in a boolean context will fail at runtime.
+
+**Examples**
+
+
+```python
+class NotBoolable:
+ __bool__ = None
+
+b1 = NotBoolable()
+b2 = NotBoolable()
+
+if b1: # exception raised here
+ pass
+
+b1 and b2 # exception raised here
+not b1 # exception raised here
+b1 < b2 < b1 # exception raised here
+```
+
+## `unsupported-operator`
+
+
+Default level: error ·
+Added in 0.0.1-alpha.1 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for binary expressions, comparisons, and unary expressions where
+the operands don't support the operator.
+
+**Why is this bad?**
+
+Attempting to use an unsupported operator will raise a `TypeError` at
+runtime.
+
+**Examples**
+
+```python
+class A: ...
+
+A() + A() # TypeError: unsupported operand type(s) for +: 'A' and 'A'
+```
+
+## `unused-ignore-comment`
+
+
+Default level: ignore ·
+Added in 0.0.1-alpha.1 ·
+Related issues ·
+View source
+
+
+
+**What it does**
+
+Checks for `type: ignore` or `ty: ignore` directives that are no longer applicable.
+
+**Why is this bad?**
+
+A `type: ignore` directive that no longer matches any diagnostic violations is likely
+included by mistake, and should be removed to avoid confusion.
+
+**Examples**
+
+```py
+a = 20 / 2 # ty: ignore[division-by-zero]
+```
+
+Use instead:
+
+```py
+a = 20 / 2
+```
+
## `useless-overload-body`
-Default level: warn ·
+Default level: warn ·
Added in 0.0.1-alpha.22 ·
Related issues ·
-View source
+View source
@@ -2722,118 +2827,28 @@ def foo(x: int | str) -> int | str:
- [Python documentation: `@overload`](https://docs.python.org/3/library/typing.html#typing.overload)
-## `division-by-zero`
+## `zero-stepsize-in-slice`
-Default level: ignore ·
-Preview (since 0.0.1-alpha.1) ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-It detects division by zero.
-
-**Why is this bad?**
-
-Dividing by zero raises a `ZeroDivisionError` at runtime.
-
-**Examples**
-
-```python
-5 / 0
-```
-
-## `possibly-missing-import`
-
-
-Default level: ignore ·
-Added in 0.0.1-alpha.22 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for imports of symbols that may be missing.
-
-**Why is this bad?**
-
-Importing a missing module or name will raise a `ModuleNotFoundError`
-or `ImportError` at runtime.
-
-**Examples**
-
-```python
-# module.py
-import datetime
-
-if datetime.date.today().weekday() != 6:
- a = 1
-
-# main.py
-from module import a # ImportError: cannot import name 'a' from 'module'
-```
-
-## `possibly-unresolved-reference`
-
-
-Default level: ignore ·
+Default level: error ·
Added in 0.0.1-alpha.1 ·
-Related issues ·
-View source
+Related issues ·
+View source
**What it does**
-Checks for references to names that are possibly not defined.
+Checks for step size 0 in slices.
**Why is this bad?**
-Using an undefined variable will raise a `NameError` at runtime.
-
-**Example**
-
-
-```python
-for i in range(0):
- x = i
-
-print(x) # NameError: name 'x' is not defined
-```
-
-## `unused-ignore-comment`
-
-
-Default level: ignore ·
-Added in 0.0.1-alpha.1 ·
-Related issues ·
-View source
-
-
-
-**What it does**
-
-Checks for `type: ignore` or `ty: ignore` directives that are no longer applicable.
-
-**Why is this bad?**
-
-A `type: ignore` directive that no longer matches any diagnostic violations is likely
-included by mistake, and should be removed to avoid confusion.
+A slice with a step size of zero will raise a `ValueError` at runtime.
**Examples**
-```py
-a = 20 / 2 # ty: ignore[division-by-zero]
-```
-
-Use instead:
-
-```py
-a = 20 / 2
+```python
+l = list(range(10))
+l[1:10:0] # ValueError: slice step cannot be zero
```
diff --git a/pyproject.toml b/pyproject.toml
index b9e96cc..57b7ed7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "ty"
-version = "0.0.4"
+version = "0.0.5"
requires-python = ">=3.8"
dependencies = []
description = "An extremely fast Python type checker, written in Rust."
diff --git a/ruff b/ruff
index fa57253..ad41728 160000
--- a/ruff
+++ b/ruff
@@ -1 +1 @@
-Subproject commit fa57253980c317cce7ff1f35691e3d850c0fb58b
+Subproject commit ad41728204681a60e6d9761857b000cb6bfe732b
diff --git a/uv.lock b/uv.lock
index 03f4494..0de1e2b 100644
--- a/uv.lock
+++ b/uv.lock
@@ -624,7 +624,7 @@ wheels = [
[[package]]
name = "ty"
-version = "0.0.4"
+version = "0.0.5"
source = { editable = "." }
[package.dev-dependencies]
From 02351f9fa98debe8bbb615317932d2405fe760d4 Mon Sep 17 00:00:00 2001
From: Matthew Mckee