diff --git a/src/schemas/json/ty.json b/src/schemas/json/ty.json index 7b43853bc28..f87b0b091e9 100644 --- a/src/schemas/json/ty.json +++ b/src/schemas/json/ty.json @@ -200,6 +200,16 @@ "OverrideOptions": { "type": "object", "properties": { + "analysis": { + "anyOf": [ + { + "$ref": "#/definitions/AnalysisOptions" + }, + { + "type": "null" + } + ] + }, "exclude": { "description": "A list of file and directory patterns to exclude from this override.\n\nPatterns follow a syntax similar to `.gitignore`.\nExclude patterns take precedence over include patterns within the same override.\n\nIf not specified, defaults to `[]` (excludes no files).", "anyOf": [ @@ -512,6 +522,16 @@ } ] }, + "ineffective-final": { + "title": "detects calls to `final()` that type checkers cannot interpret", + "description": "## What it does\nChecks for calls to `final()` that type checkers cannot interpret.\n\n## Why is this bad?\nThe `final()` function is designed to be used as a decorator. When called directly\nas a function (e.g., `final(type(...))`), type checkers will not understand the\napplication of `final` and will not prevent subclassing.\n\n## Example\n\n```python\nfrom typing import final\n\n# Incorrect: type checkers will not prevent subclassing\nMyClass = final(type(\"MyClass\", (), {}))\n\n# Correct: use `final` as a decorator\n@final\nclass MyClass: ...\n```", + "default": "warn", + "oneOf": [ + { + "$ref": "#/definitions/Level" + } + ] + }, "instance-layout-conflict": { "title": "detects class definitions that raise `TypeError` due to instance layout conflict", "description": "## What it does\nChecks for classes definitions which will fail at runtime due to\n\"instance memory layout conflicts\".\n\nThis error is usually caused by attempting to combine multiple classes\nthat define non-empty `__slots__` in a class's [Method Resolution Order]\n(MRO), or by attempting to combine multiple builtin classes in a class's\nMRO.\n\n## Why is this bad?\nInheriting from bases with conflicting instance memory layouts\nwill lead to a `TypeError` at runtime.\n\nAn instance memory layout conflict occurs when CPython cannot determine\nthe memory layout instances of a class should have, because the instance\nmemory layout of one of its bases conflicts with the instance memory layout\nof one or more of its other bases.\n\nFor example, if a Python class defines non-empty `__slots__`, this will\nimpact the memory layout of instances of that class. Multiple inheritance\nfrom more than one different class defining non-empty `__slots__` is not\nallowed:\n\n```python\nclass A:\n __slots__ = (\"a\", \"b\")\n\nclass B:\n __slots__ = (\"a\", \"b\") # Even if the values are the same\n\n# TypeError: multiple bases have instance lay-out conflict\nclass C(A, B): ...\n```\n\nAn instance layout conflict can also be caused by attempting to use\nmultiple inheritance with two builtin classes, due to the way that these\nclasses are implemented in a CPython C extension:\n\n```python\nclass A(int, float): ... # TypeError: multiple bases have instance lay-out conflict\n```\n\nNote that pure-Python classes with no `__slots__`, or pure-Python classes\nwith empty `__slots__`, are always compatible:\n\n```python\nclass A: ...\nclass B:\n __slots__ = ()\nclass C:\n __slots__ = (\"a\", \"b\")\n\n# fine\nclass D(A, B, C): ...\n```\n\n## Known problems\nClasses that have \"dynamic\" definitions of `__slots__` (definitions do not consist\nof string literals, or tuples of string literals) are not currently considered disjoint\nbases by ty.\n\nAdditionally, this check is not exhaustive: many C extensions (including several in\nthe standard library) define classes that use extended memory layouts and thus cannot\ncoexist in a single MRO. Since it is currently not possible to represent this fact in\nstub files, having a full knowledge of these classes is also impossible. When it comes\nto classes that do not define `__slots__` at the Python level, therefore, ty, currently\nonly hard-codes a number of cases where it knows that a class will produce instances with\nan atypical memory layout.\n\n## Further reading\n- [CPython documentation: `__slots__`](https://docs.python.org/3/reference/datamodel.html#slots)\n- [CPython documentation: Method Resolution Order](https://docs.python.org/3/glossary.html#term-method-resolution-order)\n\n[Method Resolution Order]: https://docs.python.org/3/glossary.html#term-method-resolution-order", @@ -582,6 +602,26 @@ } ] }, + "invalid-dataclass": { + "title": "detects invalid `@dataclass` applications", + "description": "## What it does\nChecks for invalid applications of the `@dataclass` decorator.\n\n## Why is this bad?\nApplying `@dataclass` to a class that inherits from `NamedTuple`, `TypedDict`,\n`Enum`, or `Protocol` is invalid:\n\n- `NamedTuple` and `TypedDict` classes will raise an exception at runtime when\n instantiating the class.\n- `Enum` classes with `@dataclass` are [explicitly not supported].\n- `Protocol` classes define interfaces and cannot be instantiated.\n\n## Examples\n```python\nfrom dataclasses import dataclass\nfrom typing import NamedTuple\n\n@dataclass # error: [invalid-dataclass]\nclass Foo(NamedTuple):\n x: int\n```\n\n[explicitly not supported]: https://docs.python.org/3/howto/enum.html#dataclass-support", + "default": "error", + "oneOf": [ + { + "$ref": "#/definitions/Level" + } + ] + }, + "invalid-dataclass-override": { + "title": "detects dataclasses with `frozen=True` that have a custom `__setattr__` or `__delattr__` implementation", + "description": "## What it does\nChecks for dataclass definitions that have both `frozen=True` and a custom `__setattr__` or\n`__delattr__` method defined.\n\n## Why is this bad?\nFrozen dataclasses synthesize `__setattr__` and `__delattr__` methods which raise a\n`FrozenInstanceError` to emulate immutability.\n\nOverriding either of these methods raises a runtime error.\n\n## Examples\n```python\nfrom dataclasses import dataclass\n\n@dataclass(frozen=True)\nclass A:\n def __setattr__(self, name: str, value: object) -> None: ...\n```", + "default": "error", + "oneOf": [ + { + "$ref": "#/definitions/Level" + } + ] + }, "invalid-declaration": { "title": "detects invalid declarations", "description": "## What it does\nChecks for declarations where the inferred type of an existing symbol\nis not [assignable to] its post-hoc declared type.\n\n## Why is this bad?\nSuch declarations break the rules of the type system and\nweaken a type checker's ability to accurately reason about your code.\n\n## Examples\n```python\na = 1\na: str\n```\n\n[assignable to]: https://typing.python.org/en/latest/spec/glossary.html#term-assignable", @@ -632,6 +672,16 @@ } ] }, + "invalid-generic-enum": { + "title": "detects generic enum classes", + "description": "## What it does\nChecks for enum classes that are also generic.\n\n## Why is this bad?\nEnum classes cannot be generic. Python does not support generic enums:\nattempting to create one will either result in an immediate `TypeError`\nat runtime, or will create a class that cannot be specialized in the way\nthat a normal generic class can.\n\n## Examples\n```python\nfrom enum import Enum\nfrom typing import Generic, TypeVar\n\nT = TypeVar(\"T\")\n\n# error: enum class cannot be generic (class creation fails with `TypeError`)\nclass E[T](Enum):\n A = 1\n\n# error: enum class cannot be generic (class creation fails with `TypeError`)\nclass F(Enum, Generic[T]):\n A = 1\n\n# error: enum class cannot be generic -- the class creation does not immediately fail...\nclass G(Generic[T], Enum):\n A = 1\n\n# ...but this raises `KeyError`:\nx: G[int]\n```\n\n## References\n- [Python documentation: Enum](https://docs.python.org/3/library/enum.html)", + "default": "error", + "oneOf": [ + { + "$ref": "#/definitions/Level" + } + ] + }, "invalid-ignore-comment": { "title": "detects ignore comments that use invalid syntax", "description": "## What it does\nChecks for `type: ignore` and `ty: ignore` comments that are syntactically incorrect.\n\n## Why is this bad?\nA syntactically incorrect ignore comment is probably a mistake and is useless.\n\n## Examples\n```py\na = 20 / 0 # type: ignoree\n```\n\nUse instead:\n\n```py\na = 20 / 0 # type: ignore\n```", @@ -1152,6 +1202,16 @@ } ] }, + "unsupported-dynamic-base": { + "title": "detects dynamic class bases that are unsupported as ty could not feasibly calculate the class's MRO", + "description": "## What it does\nChecks for dynamic class definitions (using `type()`) that have bases\nwhich are unsupported by ty.\n\nThis is equivalent to [`unsupported-base`] but applies to classes created\nvia `type()` rather than `class` statements.\n\n## Why is this bad?\nIf a dynamically created class has a base that is an unsupported type\nsuch as `type[T]`, ty will not be able to resolve the\n[method resolution order] (MRO) for the class. This may lead to an inferior\nunderstanding of your codebase and unpredictable type-checking behavior.\n\n## Default level\nThis rule is disabled by default because it will not cause a runtime error,\nand may be noisy on codebases that use `type()` in highly dynamic ways.\n\n## Examples\n```python\ndef factory(base: type[Base]) -> type:\n # `base` has type `type[Base]`, not `type[Base]` itself\n return type(\"Dynamic\", (base,), {}) # error: [unsupported-dynamic-base]\n```\n\n[method resolution order]: https://docs.python.org/3/glossary.html#term-method-resolution-order\n[`unsupported-base`]: https://docs.astral.sh/ty/rules/unsupported-base", + "default": "ignore", + "oneOf": [ + { + "$ref": "#/definitions/Level" + } + ] + }, "unsupported-operator": { "title": "detects binary, unary, or comparison expressions where the operands don't support the operator", "description": "## What it does\nChecks for binary expressions, comparisons, and unary expressions where\nthe operands don't support the operator.\n\n## Why is this bad?\nAttempting to use an unsupported operator will raise a `TypeError` at\nruntime.\n\n## Examples\n```python\nclass A: ...\n\nA() + A() # TypeError: unsupported operand type(s) for +: 'A' and 'A'\n```", @@ -1163,9 +1223,9 @@ ] }, "unused-ignore-comment": { - "title": "detects unused `type: ignore` comments", - "description": "## What it does\nChecks for `type: ignore` or `ty: ignore` directives that are no longer applicable.\n\n## Why is this bad?\nA `type: ignore` directive that no longer matches any diagnostic violations is likely\nincluded by mistake, and should be removed to avoid confusion.\n\n## Examples\n```py\na = 20 / 2 # ty: ignore[division-by-zero]\n```\n\nUse instead:\n\n```py\na = 20 / 2\n```", - "default": "ignore", + "title": "detects unused `ty: ignore` and `type: ignore` comments", + "description": "## What it does\nChecks for `ty: ignore` or `type: ignore` directives that are no longer applicable.\n\n## Why is this bad?\nA `ty: ignore` directive that no longer matches any diagnostic violations is likely\nincluded by mistake, and should be removed to avoid confusion.\n\n## Examples\n```py\na = 20 / 2 # ty: ignore[division-by-zero]\n```\n\nUse instead:\n\n```py\na = 20 / 2\n```\n\n## Options\nSet [`analysis.respect-type-ignore-comments`](https://docs.astral.sh/ty/reference/configuration/#respect-type-ignore-comments)\nto `false` to prevent this rule from reporting unused `type: ignore` comments.", + "default": "warn", "oneOf": [ { "$ref": "#/definitions/Level"