-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathty.schema.json
More file actions
2587 lines (2587 loc) · 245 KB
/
Copy pathty.schema.json
File metadata and controls
2587 lines (2587 loc) · 245 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Options",
"type": "object",
"properties": {
"analysis": {
"anyOf": [
{
"$ref": "#/definitions/AnalysisOptions"
},
{
"type": "null"
}
]
},
"editor": {
"description": "Configures the parts of the editor experience that type checking does not decide.",
"anyOf": [
{
"$ref": "#/definitions/EditorOptions"
},
{
"type": "null"
}
]
},
"environment": {
"description": "Configures the type checking environment.",
"anyOf": [
{
"$ref": "#/definitions/EnvironmentOptions"
},
{
"type": "null"
}
]
},
"overrides": {
"description": "Override configurations for specific file patterns.\n\nEach override specifies include/exclude patterns and rule configurations\nthat apply to matching files. Multiple overrides can match the same file,\nwith later overrides taking precedence.",
"anyOf": [
{
"$ref": "#/definitions/OverridesOptions"
},
{
"type": "null"
}
]
},
"rules": {
"description": "Configures the enabled rules and their severity.\n\nThe keys are either rule names or `all` to set a default severity for all rules.\nSee [the rules documentation](https://ty.dev/rules) for a list of all available rules.\n\nValid severities are:\n\n* `ignore`: Disable the rule.\n* `warn`: Enable the rule and create a warning diagnostic.\n* `error`: Enable the rule and create an error diagnostic.\n\nBy default, ty exits with code 1 if it emits any warning or error diagnostics.\nSet `terminal.error-on-warning` to `false` to exit with code 0 if all diagnostics have `warning` severity.",
"anyOf": [
{
"$ref": "#/definitions/Rules"
},
{
"type": "null"
}
]
},
"run": {
"description": "Configures how `by run` executes the project.",
"anyOf": [
{
"$ref": "#/definitions/RunOptions"
},
{
"type": "null"
}
]
},
"src": {
"anyOf": [
{
"$ref": "#/definitions/SrcOptions"
},
{
"type": "null"
}
]
},
"terminal": {
"anyOf": [
{
"$ref": "#/definitions/TerminalOptions"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
"definitions": {
"AnalysisOptions": {
"type": "object",
"properties": {
"allowed-unresolved-imports": {
"description": "A list of module glob patterns for which `unresolved-import` diagnostics should be suppressed.\n\nDetails on supported glob patterns:\n- `*` matches zero or more characters except `.`. For example, `foo.*` matches `foo.bar` but\n not `foo.bar.baz`; `foo*` matches `foo` and `foobar` but not `foo.bar` or `barfoo`; and `*foo`\n matches `foo` and `barfoo` but not `foo.bar` or `foobar`.\n- `**` matches any number of module components (e.g., `foo.**` matches `foo`, `foo.bar`, etc.)\n- Prefix a pattern with `!` to exclude matching modules\n\nWhen multiple patterns match, later entries take precedence.\n\nGlob patterns can be used in combinations with each other. For example, to suppress errors for\nany module where the first component contains the substring `test`, use `*test*.**`.",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/string"
}
},
"bivariant-private-attributes": {
"description": "Whether a private attribute leaves an inferred type parameter bivariant. This is a\nbasedpython feature.\n\nA private (single-underscore or name-mangled) member is invisible to external observers, so\nit cannot be used to distinguish two specializations of its class, and therefore cannot\nconstrain the class's variance:\n\n```python\nclass A[T]:\n _t: T\n```\n\nWith this option enabled, `T` is inferred bivariant: nothing on `A`'s public surface\nmentions `T`, so `A[int]` and `A[object]` are mutually assignable. As soon as a public\nmember mentions `T`, that member drives the inference as usual.\n\nWhen set to `false`, a private attribute is instead treated as immutable-but-readable,\nwhich constrains the type parameter to covariance.\n\nDefaults to `true`.",
"type": [
"boolean",
"null"
]
},
"dependency-groups": {
"description": "The requirement groups the matching files may import from.\n\n`project` names `[project].dependencies`, an extra or a PEP 735 dependency group\nis named by its own name, and `*` names every group.\n\nWhen this is unset, a file may import from every group unless it is part of what\nthe project ships — the modules named by `shipped-modules` — in which case it may\nimport only `project` and the extras. Nothing the project ships can import a\ndependency group, because nothing installs one alongside the project.",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/string"
}
},
"disable-fluid-specializations": {
"description": "Whether to disable \"fluid specializations\", a basedpython feature that widens the\ninferred generic specialization of an unannotated binding flow-sensitively based on\nits later uses in the same scope.\n\nWhen set to `true`, each unannotated binding keeps the specialization it was inferred\nwith at its creation site; later uses no longer widen or lock it.\n\nDefaults to `false`.",
"type": [
"boolean",
"null"
]
},
"exported-dependencies": {
"description": "The dependencies this project hands to its own users.\n\nA library whose interface is partly made of another distribution's types — one that\nreturns numpy arrays, or takes a pydantic model — can say so, and then a project\nthat depends on this one may import those distributions without declaring them\nitself.\n\nOnly what the project already depends on can be exported, and the claim only\ntravels one link: exporting a distribution does not export whatever *it* depends\non, unless that distribution exports it in turn.\n\nThis is written into the `by.typed` marker when the project is built, because that\nis what its users have — a `pyproject.toml` is not installed with the package.",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/string"
}
},
"implicit-object-repr-exempt-types": {
"description": "A list of classes never reported as an\n[`implicit-object-repr`](rules.md#implicit-object-repr).\n\nA class deriving from one of these is exempt too, so listing a base opts out a whole\nhierarchy.\n\nEntries are qualified class names (`decimal.Decimal`). A class in `builtins` may also be\nspelled bare (`int`).",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/string"
}
},
"implicit-object-repr-report-types": {
"description": "A list of classes whose stub is taken at its word when looking for an\n[`implicit-object-repr`](rules.md#implicit-object-repr).\n\nA stub normally settles nothing, because it omits `__str__` and `__repr__` whether or not\nthe runtime class has them — `int` declares neither and still prints as a number. For a\nclass listed here the omission counts as real, the same way it would for a class written\nin source, so a value of that class is reported unless the stub does declare one.\n\nDefaults to the two whose bare repr is seen most often: `types.FunctionType`, which prints\n`<function f at 0x...>`, and `builtins.type`, which prints `<class 'C'>`.\n\nEntries are qualified class names (`decimal.Decimal`). A class in `builtins` may also be\nspelled bare (`int`).",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/string"
}
},
"infer-unannotated-signatures": {
"description": "Whether a function with no annotations is given the signature its body determines. This is\na basedpython feature.\n\nPython's gradual guarantee makes an unannotated `def` say nothing: its parameters accept\nanything and it returns `Unknown`. That is the largest remaining source of `Unknown` in an\notherwise typed project, and it silently swallows real mistakes. With this enabled, the\nmissing half of the signature is recovered from what the function itself already determines:\n\n- **Each unannotated parameter** opens an anonymous type parameter named after it — the same\n hole `some` spells by hand — bounded by everything the function requires of it: the\n promoted type of its default, the members its body reads and calls, the parameters it is\n forwarded into, and any `assert` at the top of the body. Naming the hole is what keeps\n what a call passes in connected to what it gets back, so `def ident(x): return x` is\n inferred as the identity function.\n- **A missing return type** is the union of what the body returns, plus `None` when control\n can also fall off the end. An empty body returns `None`, a body that always raises returns\n `Never`, and a generator returns a generator.\n\nNothing is invented from a use this analysis cannot read, so such a parameter stays gradual\nand its body keeps type-checking exactly as it did. An explicit annotation always wins, and\nso does anything an overload group or an overridden base method already supplies.\n\nDefaults to `true`.",
"type": [
"boolean",
"null"
]
},
"overlapping-condition-assume-truthy-instances": {
"description": "Whether an instance with no `__bool__` and no `__len__` counts as always truthy when\nlooking for an [`overlapping-condition`](rules.md#overlapping-condition).\n\nSuch an instance is only *ambiguously* truthy — a subclass may define `__bool__` — so by\ndefault it is a falsy member of `if not x` just as `None` is. Enabling this assumes the\nclass means what it looks like it means, which drops the reports for the very common\n`if not x` over an optional instance.\n\nDefaults to `false`.",
"type": [
"boolean",
"null"
]
},
"overlapping-condition-exempt-types": {
"description": "A list of classes whose values do not count as a distinct member of an\n[`overlapping-condition`](rules.md#overlapping-condition).\n\n`if not x` over an `int | None` selects both a falsy `int` and `None`, and is reported\nbecause the branch cannot tell them apart. Listing `int` here says that conflating a falsy\n`int` with anything else is fine, so only `None` is left and the condition is accepted.\n\nEntries are qualified class names (`decimal.Decimal`). A class in `builtins` may also be\nspelled bare (`int`), and `None` stands for the type of `None`.",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/string"
}
},
"precise-unsolved-typevars": {
"description": "Whether a type variable that a call leaves unsolved is solved to `Never`. This is a\nbasedpython feature.\n\nA call can leave a type variable entirely unsolved, because no argument mentions it:\n\n```python\ndef f[T]() -> T: ...\n\na = f()\n```\n\n`Never` is the precise answer here: no value ever reaches that position, so nothing the\ncall returns can be observed at type `T`. When set to `false`, the type variable falls back\nto the gradual `Unknown` instead, which silences any error that would follow from the call\nsite.\n\nThis applies where the type variable is an output. Where it is instead written through or\npassed back in — the element of an invariant `list[T]`, the parameter of a returned\n`Callable[[T], R]` — `Never` would say that nothing can ever be put there, so an invariant\nor contravariant occurrence keeps the gradual `Unknown`.\n\nA PEP 696 default (`def f[T = str]()`) always takes priority, and a `ParamSpec`,\n`TypeVarTuple` or keyword-variadic pack is unaffected because `Never` is not a valid\nsolution for one.\n\nDefaults to `true`.",
"type": [
"boolean",
"null"
]
},
"replace-imports-with-any": {
"description": "A list of module glob patterns whose imports should be replaced with `typing.Any`.\n\nUnlike `allowed-unresolved-imports`, this setting replaces the module's type information\nwith `typing.Any` even if the module can be resolved. Import diagnostics are\nunconditionally suppressed for matching modules.\n\n- Prefix a pattern with `!` to exclude matching modules\n\nWhen multiple patterns match, later entries take precedence.\n\nGlob patterns can be used in combinations with each other. For example, to suppress errors for\nany module where the first component contains the substring `test`, use `*test*.**`.\n\nWhen multiple patterns match, later entries take precedence.",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/string"
}
},
"respect-type-ignore-comments": {
"description": "Whether ty should respect `type: ignore` comments.\n\nWhen set to `false`, `type: ignore` comments are treated like any other normal\ncomment and can't be used to suppress ty errors (you have to use `ty: ignore` instead).\n\nSetting this option can be useful when using ty alongside other type checkers or when\nyou prefer using `ty: ignore` over `type: ignore`.\n\nDefaults to `true`.",
"type": [
"boolean",
"null"
]
},
"shipped-modules": {
"description": "The top-level modules the project ships.\n\nDefaults to the module named after `[project].name`: a project named `my-lib`\nships `my_lib`. Only a project that ships several unrelated modules, or one whose\nmodule is not named after it, needs to say.",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/string"
}
},
"sound-types": {
"description": "Whether to infer sound (non-gradual) types wherever a precise type is available. This is a\nbasedpython feature.\n\nPython's gradual guarantee requires a type checker to fall back to a gradual type whenever\nan annotation is missing, even when a precise type could be inferred. In a fully typed\nproject that is pure boilerplate: it forces an annotation to be written for something the\nchecker already knows. When set to `true`, this option deliberately breaks the gradual\nguarantee and uses the precise type instead. It affects:\n\n- **Unannotated parameters**: each one opens an anonymous type parameter named after it,\n bounded by everything the function requires of it — the promoted type of its default, the\n members its body reads and calls, the parameters it is forwarded into, and any `assert` at\n the top of the body. So `def f(a=1)` rejects a `str` at a call site, and\n `def ident(x): return x` is inferred as the identity function. A lambda parameter with a\n default takes that default's promoted type directly.\n- **Unannotated return types**: the union of what the body returns, plus `None` when control\n can fall off the end. An empty body returns `None` and a body that always raises returns\n `Never`; a generator returns a generator.\n- **Unannotated methods that override a base method**: the parameter and return types are\n inherited from the overridden method, including from `Protocol` members and\n `abstractmethod` declarations.\n- **Bare `ClassVar` annotations**: `x: ClassVar = 1` declares `int` rather than the union of\n `Unknown` and the inferred type.\n- **Empty collection literals**: `[]` has element type `Never`, so passing one to a generic\n call solves from it precisely instead of leaking `Unknown`.\n\nAn explicit annotation always takes priority over any of the above.\n\nDefaults to `false`.",
"type": [
"boolean",
"null"
]
},
"strict-equality-semantics": {
"description": "Configure ty's behavior regarding type inference and narrowing of equality\nchecks. Defaults to `false`.\n\nBy default, ty makes various assumptions about equality checks that match the\nintuitions of most Python programmers, but may not be fully sound in all situations.\nEnabling this option makes ty more conservative about these assumptions, making it\nless likely to infer `Literal[True]` or `Literal[False]` as the result of an\nequality check. This has various effects on type checking, including fewer type\nnarrowing opportunities and more conservative assumptions regarding control flow.\n\nOne way in which ty will by default make unsound assumptions is by narrowing an\nobject `x` of type `str` to `Literal[\"a\"]` after an `if x == \"a\"` check. This is\nunsound because a subclass of `str` with value `\"a\"` will (by default) compare equal\nto `\"a\"`, but will not be of type `Literal[\"a\"]`:\n\n```pycon\n>>> # `Literal[\"a\"]` can only be inhabited by instances of exactly `str`, not\n>>> # subclasses, but str subclasses compare equal by default:\n>>> class StringSubclass(str): ...\n...\n>>> StringSubclass(\"a\") == \"a\"\nTrue\n>>>\n>>> # This also applies to `StrEnum`s:\n>>> from enum import StrEnum\n>>> class MyEnum(StrEnum):\n... A = \"a\"\n...\n>>> MyEnum.A == \"a\"\nTrue\n```\n\nEnabling this option prevents the unsound narrowing of `x` to `Literal[\"a\"]`,\nand instead keeps it as `str`:\n\n```python\nfrom typing import Literal\n\ndef parse(value: str) -> Literal[\"a\"] | None:\n # with `strict-equality-semantics = true`, no narrowing will occur here,\n # and an error will be emitted on the `return` statement.\n if value == \"a\":\n return value\n return None\n```\n\nAnother assumption ty makes by default is that subclasses will never override `__eq__` or\n`__ne__`. This allows ty to narrow the following union based on an equality check, despite\nthe fact that an instance of a subclass of `Foo` could compare equal to `None`, and it's\nperfectly valid to pass an instance of a subclass into the `x` parameter of this function:\n\n```python\ndef narrow(x: Foo | None, other: Foo) -> None:\n if x == other:\n # with this option enabled, `x` will still have type `Foo | None` here,\n # since it is legal to subclass `Foo` and override its `__eq__` method.\n reveal_type(x)\n```\n\nMany operations in Python implicitly call `__eq__` under the hood; enabling this option\nwill also impact those operations. For example, this option will also impact narrowing from\n`in` checks, and narrowing in `match` statements that use value patterns:\n\n```python\ndef narrow_in(x: Foo | None, other: list[Foo]) -> None:\n if x in other:\n # with this option enabled, `x` will still have type `Foo | None` here,\n # since the `in` operator implicitly calls `__eq__` on each element of `other`.\n reveal_type(x)\n\n\ndef narrow_match(x: str) -> None:\n match x:\n case \"a\":\n # with this option enabled, `x` will still have type `str` here,\n # since this `case` branch will be taken by any object that compares\n # equal to `\"a\"`, including subclasses of `str`.\n reveal_type(x)\n```",
"type": [
"boolean",
"null"
]
},
"strict-float": {
"description": "Whether `float` and `complex` annotations mean *only* themselves. This is a\nbasedpython feature.\n\nThe typing spec's special case says an `int` is acceptable wherever a `float` is\nasked for, so `x: float` really declares `int | float`. A `.by` file opts out of\nthat already; this makes the same model available to a `.py` one, per module.\n\nIt is not only a checking question. The wider annotation is why a `.py`\n`list[float]` cannot be laid out as an unboxed buffer and a `.py` class cannot\nhave `double` fields, so `by compile` reads this to choose a representation.\n\nDefaults to `false`.",
"type": [
"boolean",
"null"
]
},
"strict-generic-narrowing": {
"description": "Whether ty should use strict narrowing for unspecialized generic classes in\n`isinstance()` and `issubclass()` checks, as well as `match` class patterns.\n\nWhen enabled, ty narrows to the top materialization of the class. For example,\n`isinstance(value, list)` narrows a value of type `object` to `Top[list[Unknown]]`,\nrepresenting the (infinite) union of all possible `list` specializations. Iterating\nover the list would yield values of type `object`.\n\nWhen disabled, ty uses gradual generic narrowing, preserving compatible type\narguments from the original type where possible. For example,\n`isinstance(value, list)` narrows a value of type `Sequence[int]` to `list[int]`.\nIf no specialization is available, the same check narrows a value of type `object`\nto `list[Unknown]`; items of any type can then be appended to the list. Class\npatterns such as `case list():` follow the same behavior.\n\nDefaults to `false`.",
"type": [
"boolean",
"null"
]
}
},
"additionalProperties": false
},
"Array_of_string": {
"type": "array",
"items": {
"$ref": "#/definitions/string"
}
},
"CommonAliases": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"EditorOptions": {
"type": "object",
"properties": {
"common-aliases": {
"description": "The modules a name is a common alias of, keyed by the alias.\n\nA file that writes `np.` before importing anything almost always means numpy, because `np`\nis what numpy is conventionally imported as. The editor completes such a name as the module\nit names, and accepting one of those completions writes the `import numpy as np` that makes\nthe name real.\n\nThis adds aliases of your own to the ones ty already knows; an entry whose alias ty knows\nreplaces it. An alias for a module the project does not have is never offered, so an entry\nfor a module nobody installed costs nothing.\n\nDefaults to `{}`, which leaves ty's own aliases as they are.",
"anyOf": [
{
"$ref": "#/definitions/CommonAliases"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"EnvironmentOptions": {
"type": "object",
"properties": {
"extra-paths": {
"description": "User-provided paths that should take first priority in module resolution.\n\nThis is an advanced option that should usually only be used for first-party or third-party\nmodules that are not installed into your Python environment in a conventional way.\nUse the `python` option to specify the location of your Python environment.\n\nThis option is similar to mypy's `MYPYPATH` environment variable and pyright's `stubPath`\nconfiguration setting.",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/RelativePathBuf"
}
},
"python": {
"description": "Path to your project's Python environment or interpreter.\n\nty uses the `site-packages` directory of your project's Python environment\nto resolve third-party (and, in some cases, first-party) imports in your code.\n\nThis can be a path to:\n\n- A Python interpreter, e.g. `.venv/bin/python3`\n- A virtual environment directory, e.g. `.venv`\n- A system Python [`sys.prefix`] directory, e.g. `/usr`\n\nIf you're using a project management tool such as uv, you should not generally need to\nspecify this option, as commands such as `uv run` will set the `VIRTUAL_ENV` environment\nvariable to point to your project's virtual environment. ty can also infer the location of\nyour environment from an activated Conda environment, and will look for a `.venv` directory\nin the project root if none of the above apply. Failing that, ty will look for a `python3`\nor `python` binary available in `PATH`.\n\n[`sys.prefix`]: https://docs.python.org/3/library/sys.html#sys.prefix",
"anyOf": [
{
"$ref": "#/definitions/RelativePathBuf"
},
{
"type": "null"
}
]
},
"python-platform": {
"description": "Specifies the target platform that will be used to analyze the source code.\nIf specified, ty will understand conditions based on comparisons with `sys.platform`, such\nas are commonly found in typeshed to reflect the differing contents of the standard library across platforms.\nIf `all` is specified, ty will assume that the source code can run on any platform.\n\nIf no platform is specified, ty will use the current platform:\n- `win32` for Windows\n- `darwin` for macOS\n- `android` for Android\n- `ios` for iOS\n- `linux` for everything else",
"anyOf": [
{
"$ref": "#/definitions/PythonPlatform"
},
{
"type": "null"
}
]
},
"python-version": {
"description": "Specifies the version of Python that will be used to analyze the source code.\nThe version should be specified as a string in the format `M.m` where `M` is the major version\nand `m` is the minor (e.g. `\"3.7\"` or `\"3.12\"`).\nIf a version is provided, ty will generate errors if the source code makes use of language features\nthat are not supported in that version.\n\nty officially supports type checking code that targets Python 3.10 and later. Python 3.7\nthrough 3.9 can still be selected, but ty may produce false positives or false negatives for\nstandard-library APIs because its bundled stubs do not fully describe those versions.\n\nIf a version is not specified, ty will try the following techniques in order of preference\nto determine a value:\n1. Check for the `project.requires-python` setting in a `pyproject.toml` file\n and use the minimum version from the specified range\n2. Check for an activated or configured Python environment\n and attempt to infer the Python version of that environment\n3. Fall back to the default value (see below)\n\nFor some language features, ty can also understand conditionals based on comparisons\nwith `sys.version_info`. These are commonly found in typeshed, for example,\nto reflect the differing contents of the standard library across Python versions.",
"anyOf": [
{
"$ref": "#/definitions/SupportedPythonVersion"
},
{
"type": "null"
}
]
},
"root": {
"description": "The root paths of the project, used for finding first-party modules.\n\nAccepts a list of directory paths searched in priority order (first has highest priority).\n\nIf left unspecified, ty will try to detect common project layouts and initialize `root` accordingly.\nThe project root (`.`) is always included. Additionally, the following directories are included\nif they exist and are not packages (i.e. they do not contain `__init__.py` or `__init__.pyi` files):\n\n* `./src`\n* `./<project-name>` (if a `./<project-name>/<project-name>` directory exists)\n* `./python`",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/RelativePathBuf"
}
},
"typeshed": {
"description": "Optional path to a \"typeshed\" directory on disk for us to use for standard-library types.\nIf this is not provided, we will fallback to our vendored typeshed stubs for the stdlib,\nbundled as a zip file in the binary",
"anyOf": [
{
"$ref": "#/definitions/RelativePathBuf"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"Level": {
"oneOf": [
{
"title": "Ignore",
"description": "The lint is disabled and should not run.",
"type": "string",
"const": "ignore"
},
{
"title": "Warn",
"description": "The lint is enabled and diagnostic should have a warning severity.",
"type": "string",
"const": "warn"
},
{
"title": "Error",
"description": "The lint is enabled and diagnostics have an error severity.",
"type": "string",
"const": "error"
}
]
},
"OutputFormat": {
"description": "The diagnostic output format.",
"oneOf": [
{
"description": "The default full mode will print \"pretty\" diagnostics.\n\nThat is, color will be used when printing to a `tty`.\nMoreover, diagnostic messages may include additional\ncontext and annotations on the input to help understand\nthe message.",
"type": "string",
"const": "full"
},
{
"description": "Print diagnostics in a concise mode.\n\nThis will guarantee that each diagnostic is printed on\na single line. Only the most important or primary aspects\nof the diagnostic are included. Contextual information is\ndropped.\n\nThis may use color when printing to a `tty`.",
"type": "string",
"const": "concise"
},
{
"description": "Print diagnostics in the JSON format expected by GitLab [Code Quality] reports.\n\n[Code Quality]: https://docs.gitlab.com/ci/testing/code_quality/#code-quality-report-format",
"type": "string",
"const": "gitlab"
},
{
"description": "Print diagnostics in the format used by [GitHub Actions] workflow error annotations.\n\n[GitHub Actions]: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-commands#setting-an-error-message",
"type": "string",
"const": "github"
},
{
"description": "Print diagnostics as a JUnit-style XML report.",
"type": "string",
"const": "junit"
}
]
},
"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": [
{
"$ref": "#/definitions/Array_of_string"
},
{
"type": "null"
}
]
},
"include": {
"description": "A list of file and directory patterns to include for this override.\n\nThe `include` option follows a similar syntax to `.gitignore` but reversed:\nIncluding a file or directory will make it so that it (and its contents)\nare affected by this override.\n\nIf not specified, defaults to `[\"**\"]` (matches all files).",
"anyOf": [
{
"$ref": "#/definitions/Array_of_string"
},
{
"type": "null"
}
]
},
"rules": {
"description": "Rule overrides for files matching the include/exclude patterns.\n\nThese rules will be merged with the global rules, with override rules\ntaking precedence for matching files. You can set rules to different\nseverity levels or disable them entirely.",
"anyOf": [
{
"$ref": "#/definitions/Rules"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"OverridesOptions": {
"description": "Configuration override that applies to specific files based on glob patterns.\n\nAn override allows you to apply different rule configurations to specific\nfiles or directories. Multiple overrides can match the same file, with\nlater overrides take precedence. Override rules take precedence over global\nrules for matching files.\n\nFor example, to relax enforcement of rules in test files:\n\n```toml\n[[tool.ty.overrides]]\ninclude = [\"tests/**\", \"**/test_*.py\"]\n\n[tool.ty.overrides.rules]\npossibly-unresolved-reference = \"warn\"\n```\n\nOr, to ignore a rule in generated files but retain enforcement in an important file:\n\n```toml\n[[tool.ty.overrides]]\ninclude = [\"generated/**\"]\nexclude = [\"generated/important.py\"]\n\n[tool.ty.overrides.rules]\npossibly-unresolved-reference = \"ignore\"\n```",
"type": "array",
"items": {
"$ref": "#/definitions/OverrideOptions"
}
},
"PythonPlatform": {
"description": "The target platform to assume when resolving types.\n",
"anyOf": [
{
"type": "string"
},
{
"description": "Do not make any assumptions about the target platform.",
"const": "all"
},
{
"description": "Darwin",
"const": "darwin"
},
{
"description": "Linux",
"const": "linux"
},
{
"description": "Windows",
"const": "win32"
}
]
},
"RelativePathBuf": {
"description": "A possibly relative path in a configuration file.\n\nRelative paths in configuration files or from CLI options\nrequire different anchoring:\n\n* CLI: The path is relative to the current working directory\n* Configuration file: The path is relative to the project's root.",
"allOf": [
{
"$ref": "#/definitions/SystemPathBuf"
}
]
},
"Rules": {
"type": "object",
"properties": {
"abstract-and-final-method": {
"title": "detects methods that are both abstract and final",
"description": "## What it does\n\nChecks for methods decorated with both `@abstractmethod` and `@final`.\n\n## Why is this bad?\n\nAn abstract method must be overridden for a subclass to become concrete, but a final\nmethod cannot be overridden. Combining the decorators therefore makes it impossible\nfor a subclass to provide a concrete implementation.\n\n## Example\n\n```python\nfrom abc import ABC, abstractmethod\nfrom typing import final\n\n\nclass Base(ABC):\n @final\n @abstractmethod\n def method(self) -> None: ... # error\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"abstract-method-in-final-class": {
"title": "detects `@final` classes with unimplemented abstract methods",
"description": "## What it does\n\nChecks for `@final` classes that have unimplemented abstract methods.\n\n## Why is this bad?\n\nA class decorated with `@final` cannot be subclassed. If such a class has abstract\nmethods that are not implemented, the class can never be properly instantiated, as\nthe abstract methods can never be implemented (since subclassing is prohibited).\n\nAt runtime, instantiation of classes with unimplemented abstract methods is only\nprevented for classes that have `ABCMeta` (or a subclass of it) as their metaclass.\nHowever, type checkers also enforce this for classes that do not use `ABCMeta`, since\nthe intent for the class to be abstract is clear from the use of `@abstractmethod`.\n\n## Example\n\n```python\nfrom abc import ABC, abstractmethod\nfrom typing import final\n\n\nclass Base(ABC):\n @abstractmethod\n def method(self) -> int: ...\n\n\n@final\n# `Derived` does not implement `method`\nclass Derived(Base): # error\n pass\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"all": {
"title": "set the default severity level for all rules",
"description": "Configure a default severity level for all rules. Individual rule settings override this default.",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"ambiguous-context-argument": {
"title": "detects calls whose `context` parameter matches several context values",
"description": "## What it does\nChecks for calls where several `context` declarations in the same scope\ncould fill one `context` parameter.\n\n## Why is this bad?\nThe implicit argument is chosen by assignability, not by name. When two\ndeclarations in the winning scope both match, either choice would be\narbitrary — the call must pass the argument explicitly (or the extra\ndeclaration must move to another scope).\n\n## Examples\n```python\ndef f(a: int, context b: str): ...\n\ncontext s1 = \"hello\"\ncontext s2 = \"world\"\nf(1) # error: `s1` and `s2` both match\nf(1, b=s1) # ok — explicit\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"ambiguous-conversion": {
"title": "detects conversion sites served by more than one conversion",
"description": "## What it does\nChecks for conversion sites where more than one conversion applies — two\ndunders, a dunder and an in-scope conformance, or two applicable\n`implementation`s of the same interface and type.\n\n## Why is this bad?\n`__from__` and `__into__` are hand-written bodies that can disagree, so\nwhich one runs must not depend on arbitrary ordering. Remove one of them,\nor write the conversion you want explicitly.\n\n## Example\n\n```by\nclass Celsius:\n def __into__(self) -> Fahrenheit: ...\n\nclass Fahrenheit:\n @classmethod\n def __from__(cls, value: Celsius) -> Self: ...\n\nreport(Celsius()) # error: two conversions apply\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"ambiguous-extension-member": {
"title": "detects attribute accesses supplied by more than one extension",
"description": "## What it does\nChecks for attribute accesses that resolve to a member supplied by more\nthan one applicable basedpython extension.\n\n## Why is this bad?\nWhen two extensions in scope both add the same member to the receiver's\ntype, the access is ambiguous — which implementation runs would depend\non arbitrary ordering. Constrain one of the extensions (or drop the\nimport that brings the second into scope) so exactly one applies.\n\n## Example\n\n```by\nextension list:\n def second(self) -> Element: ...\n\nextension list:\n def second(self) -> Element: ...\n\n[1, 2].second() # error: ambiguous extension member\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"ambiguous-protocol-member": {
"title": "detects protocol classes with ambiguous interfaces",
"description": "## What it does\n\nChecks for protocol classes with members that will lead to ambiguous interfaces.\n\n## Why is this bad?\n\nAssigning to an undeclared variable in a protocol class, or to an undeclared attribute\nthrough a protocol method's `self` or `cls` receiver, leads to an ambiguous interface\nwhich may lead to the type checker inferring unexpected things. It's recommended to\nensure that all members of a protocol class are explicitly declared.\n\n## Examples\n\n```py\nfrom typing import ClassVar, Protocol\n\n\nclass BaseProto(Protocol):\n a: int # fine (explicitly declared as `int`)\n instance_member: str\n class_member: ClassVar[str]\n\n # fine: a method definition using `def` is considered a declaration\n def method_member(self) -> int: ...\n\n def method(self) -> None:\n self.instance_member = \"value\" # fine (declared in the class body)\n self.implicit = \"value\" # error: [ambiguous-protocol-member]\n\n @classmethod\n def class_method(cls) -> None:\n cls.class_member = \"value\" # fine (declared in the class body)\n cls.implicit_class = \"value\" # error: [ambiguous-protocol-member]\n\n # no explicit declaration, leading to ambiguity\n c = \"some variable\" # error\n # no explicit declaration, leading to ambiguity\n b = method_member # error\n\n # This creates implicit assignments of `d` and `e` in the protocol class body.\n # Were they really meant to be considered protocol members?\n # error: \"`d` is not declared as a protocol member\"\n # error: \"`e` is not declared as a protocol member\"\n for d, e in enumerate(range(42)):\n pass\n\n\nclass SubProto(BaseProto, Protocol):\n a = 42 # fine (declared in superclass)\n```",
"default": "warn",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"assert-type-unspellable-subtype": {
"title": "detects failed type assertions",
"description": "## What it does\n\nChecks for `assert_type()` calls where the actual type\nis an unspellable subtype of the asserted type.\n\n## Why is this bad?\n\n`assert_type()` is intended to ensure that the inferred type of a value\nis exactly the same as the asserted type. But in some situations, ty\nhas nonstandard extensions to the type system that allow it to infer\nmore precise types than can be expressed in user annotations. ty emits a\ndifferent error code to `type-assertion-failure` in these situations so\nthat users can easily differentiate between the two cases.\n\n## Example\n\n```toml\n[environment]\npython-version = \"3.11\"\n```\n\n```python\nfrom typing import assert_type\n\n\ndef _(x: int):\n assert_type(x, int) # fine\n if x:\n # the actual type is `int & ~AlwaysFalsy`,\n # which excludes types like `Literal[0]`\n # error: [assert-type-unspellable-subtype]\n assert_type(x, int)\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"blanket-ignore-comment": {
"title": "detects blanket `ty: ignore` comments",
"description": "## What it does\n\nChecks for `ty: ignore` comments that don't specify which rules to ignore.\n\n## Why is this bad?\n\nA blanket `ty: ignore` comment suppresses every type-checking diagnostic on the\napplicable line or file. Specifying rule codes documents which diagnostics are\nexpected and prevents the comment from silencing unrelated errors.\n\n## Examples\n\n```py\n# error\nvalue = unknown # ty: ignore\n```\n\nUse instead:\n\n```py\nvalue = unknown # ty: ignore[unresolved-reference]\n```",
"default": "ignore",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"bool-as-int": {
"title": "detects a `bool` implicitly used as an `int`",
"description": "## What it does\nChecks for a `bool` value in a position that expects a number, where it is\nadmitted only because `bool` is a subclass of `int`.\n\n## Why is this bad?\nNothing is converted here — `bool` really is a subclass of `int`, and `True`\nand `False` really are `1` and `0`. That is the problem: the value satisfies\nan `int` (or `float`, or `complex`) annotation silently, so a boolean that\nreached a numeric slot by mistake type-checks exactly like one that was meant\nto. Writing `int(...)` says the number is what you meant, and widening the\nannotation to `bool` says the flag is.\n\nThe value has to be a boolean and the target a number for this to fire, so\narithmetic on booleans, a `bool` annotation, and a container of booleans are\nall left alone. Note that `int | bool` is not an escape hatch: a union of a\nclass and its subclass simplifies to the supertype, so that annotation *is*\n`int` and is reported as such.\n\n## Examples\n```python\ndef take(n: int): ...\n\na: int = True # warning: `bool` used as `int`\ntake(True) # warning: `bool` used as `int`\n\na2: int = int(True) # ok — explicit\na3: bool = True # ok\na4 = True + 1 # ok — a boolean used as a boolean\n```",
"default": "warn",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"call-abstract-method": {
"title": "detects calls to abstract methods with trivial bodies on class objects",
"description": "## What it does\n\nChecks for calls to abstract `@classmethod`s or `@staticmethod`s\nwith \"trivial bodies\" when accessed on the class object itself.\n\n\"Trivial bodies\" are bodies that solely consist of `...`, `pass`,\na docstring, and/or `raise NotImplementedError`.\n\n## Why is this bad?\n\nAn abstract method with a trivial body has no concrete implementation\nto execute, so calling such a method directly on the class will probably\nnot have the desired effect.\n\nIt is also unsound to call these methods directly on the class. Unlike\nother methods, ty permits abstract methods with trivial bodies to have\nnon-`None` return types even though they always return `None` at runtime.\nThis is because it is expected that these methods will always be\noverridden rather than being called directly. As a result of this\nexception to the normal rule, ty may infer an incorrect type if one of\nthese methods is called directly, which may then mean that type errors\nelsewhere in your code go undetected by ty.\n\nCalling abstract classmethods or staticmethods via `type[X]` is allowed,\nsince the actual runtime type could be a concrete subclass with an implementation.\n\n## Example\n\n```python\nfrom abc import ABC, abstractmethod\n\n\nclass Foo(ABC):\n @classmethod\n @abstractmethod\n def method(cls) -> int: ...\n\n\n# cannot call abstract classmethod\nFoo.method() # error\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"call-non-callable": {
"title": "detects calls to non-callable objects",
"description": "## What it does\n\nChecks for calls to non-callable objects.\n\n## Why is this bad?\n\nCalling a non-callable object will raise a `TypeError` at runtime.\n\n## Examples\n\n```python\n# TypeError: 'int' object is not callable\n4() # error\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"call-top-callable": {
"title": "detects calls to the top callable type",
"description": "## What it does\n\nChecks for calls to objects typed as `Top[Callable[..., T]]` (the infinite union of all\ncallable types with return type `T`).\n\n## Why is this bad?\n\nWhen an object is narrowed to `Top[Callable[..., object]]` (e.g., via `callable(x)` or\n`isinstance(x, Callable)`), we know the object is callable, but we don't know its\nprecise signature. This type represents the set of all possible callable types\n(including, e.g., functions that take no arguments and functions that require arguments),\nso no specific set of arguments can be guaranteed to be valid.\n\n## Examples\n\n```python\ndef f(x: object):\n if callable(x):\n # We know `x` is callable, but not what arguments it accepts\n x() # error\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"conflicting-declarations": {
"title": "detects conflicting declarations",
"description": "## What it does\n\nChecks whether a variable has been declared as two conflicting types.\n\n## Why is this bad\n\nA variable with two conflicting declarations likely indicates a mistake.\nMoreover, it could lead to incorrect or ill-defined type inference for\nother code that relies on these variables.\n\n## Examples\n\n```python\nif __name__ == \"__main__\":\n a: int\nelse:\n a: str\n\na = 1 # error\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"conflicting-metaclass": {
"title": "detects conflicting metaclasses",
"description": "## What it does\n\nChecks for class definitions where the metaclass of the class\nbeing created would not be a subclass of the metaclasses of\nall the class's bases.\n\n## Why is it bad?\n\nSuch a class definition raises a `TypeError` at runtime.\n\n## Examples\n\n```pyi\nclass M1(type): ...\nclass M2(type): ...\nclass A(metaclass=M1): ...\nclass B(metaclass=M2): ...\n\n# TypeError: metaclass conflict\nclass C(A, B): ... # error\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"cyclic-class-definition": {
"title": "detects cyclic class definitions",
"description": "## What it does\n\nChecks for class definitions in stub files that inherit\n(directly or indirectly) from themselves.\n\n## Why is it bad?\n\nAlthough forward references are natively supported in stub files,\ninheritance cycles are still disallowed, as it is impossible to\nresolve a consistent [method resolution order] for a class that\ninherits from itself.\n\n## Examples\n\n`foo.pyi`:\n\n```pyi\nclass A(B): ... # error\nclass B(A): ... # error\n```\n\n[method resolution order]: https://docs.python.org/3/glossary.html#term-method-resolution-order",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"cyclic-type-alias-definition": {
"title": "detects cyclic type alias definitions",
"description": "## What it does\n\nChecks for type alias definitions that (directly or mutually) refer to themselves.\n\n## Why is it bad?\n\nAlthough it is permitted to define a recursive type alias, it is not meaningful\nto have a type alias whose expansion can only result in itself, and is therefore not allowed.\n\n## Examples\n\n```toml\n[environment]\npython-version = \"3.12\"\n```\n\n```python\ntype Itself = Itself # error\n\ntype A = B # error\ntype B = A # error\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"dataclass-field-order": {
"title": "detects dataclass definitions with required fields after fields with default values",
"description": "## What it does\n\nChecks for dataclass definitions where required fields are defined after\nfields with default values.\n\n## Why is this bad?\n\nIn dataclasses, all required fields (fields without default values) must be\ndefined before fields with default values. This is a Python requirement that\nwill raise a `TypeError` at runtime if violated.\n\n## Example\n\n```python\nfrom dataclasses import dataclass\n\n\n@dataclass\nclass Example:\n x: int = 1 # Field with default value\n # Required field after field with default\n y: str # error\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"deprecated": {
"title": "detects uses of deprecated items",
"description": "## What it does\n\nChecks for uses of deprecated items\n\n## Why is this bad?\n\nDeprecated items should no longer be used.\n\n## Examples\n\n```toml\n[environment]\npython-version = \"3.13\"\n```\n\n```python\nimport warnings\n\n\n@warnings.deprecated(\"use new_func instead\")\ndef old_func(): ...\n\n\nold_func() # error: [deprecated]\n```",
"default": "warn",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"division-by-zero": {
"title": "detects division by zero",
"description": "## What it does\n\nIt detects division by zero.\n\n## Why is this bad?\n\nDividing by zero raises a `ZeroDivisionError` at runtime.\n\n## Rule status\n\nThis rule is currently disabled by default because of the number of\nfalse positives it can produce.\n\n## Examples\n\n```python\n5 / 0 # error\n```",
"default": "ignore",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"duplicate-base": {
"title": "detects class definitions with duplicate bases",
"description": "## What it does\n\nChecks for class definitions with duplicate bases.\n\n## Why is this bad?\n\nClass definitions with duplicate bases raise `TypeError` at runtime.\n\n## Examples\n\n```python\nclass A: ...\n\n\n# TypeError: duplicate base class\nclass B(A, A): ... # error\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"duplicate-kw-only": {
"title": "detects dataclass definitions with more than one usage of `KW_ONLY`",
"description": "## What it does\n\nChecks for dataclass definitions with more than one field\nannotated with `KW_ONLY`.\n\n## Why is this bad?\n\n`dataclasses.KW_ONLY` is a special marker used to\nemulate the `*` syntax in normal signatures.\nIt can only be used once per dataclass.\n\nAttempting to annotate two different fields with\nit will lead to a runtime error.\n\n## Examples\n\n```python\nfrom dataclasses import dataclass, KW_ONLY\n\n\n# Crash at runtime\n@dataclass\nclass A: # error\n b: int\n _1: KW_ONLY\n c: str\n _2: KW_ONLY\n d: bytes\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"empty-body": {
"title": "detects functions with empty bodies that have a non-`None` return type annotation",
"description": "## What it does\n\nDetects functions with empty bodies that have a non-`None` return type annotation.\n\nThe errors reported by this rule have the same motivation as the `invalid-return-type`\nrule. The diagnostic exists as a separate error code to allow users to disable this\nrule while prototyping code. While we strongly recommend enabling this rule if\npossible, users migrating from other type checkers may also find it useful to\ntemporarily disable this rule on some or all of their codebase if they find it\nresults in a large number of diagnostics.\n\n## Why is this bad?\n\nA function with an empty body (containing only `...`, `pass`, or a docstring) will\nimplicitly return `None` at runtime. Returning `None` when the return type is non-`None`\nis unsound, and will lead to ty inferring incorrect types elsewhere.\n\nFunctions with empty bodies are permitted in certain contexts where they serve as\ndeclarations rather than implementations:\n\n- Functions in stub files (`.pyi`)\n- Methods in Protocol classes\n- Abstract methods decorated with `@abstractmethod`\n- Overload declarations decorated with `@overload`\n- Functions in `if TYPE_CHECKING` blocks\n\n## Examples\n\n```python\ndef foo() -> int: ... # error: [empty-body]\n\n\ndef bar() -> str: # error: [empty-body]\n \"\"\"A function that does nothing.\"\"\"\n pass\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"erased-cast-argument": {
"title": "detects casts whose type arguments cannot be checked at runtime",
"description": "## What it does\nChecks for a basedpython `cast` / `cast?` whose target type carries type\narguments that are erased at runtime.\n\n## Why is this bad?\nA checked cast validates its value with `isinstance`, which can only test\na class — a builtin container erases its type arguments, so `list[int]`\nis checkable only as `list`. The cast still narrows the static type to\n`list[int]`, but nothing verifies the `int` claim at runtime, which is\nexactly the assumption a checked cast exists to rule out.\n\nThis only fires where the claim really is assumed. A *user* generic\ncarries `__orig_class__`, so `A[int]` is checked in full. A value typed by\na *reified* type parameter carries the answer in a runtime cell, so\ncasting `list[T]` to `list[int]` compares `T == int` exactly. A *protocol*\nis checked structurally against the value's reified annotations — data\nmembers against class annotations, method members against\nparameter/return annotations. Only a protocol member whose specialized\ntype has no runtime spelling (a callable attribute) leaves the cast with\nno runtime residue, so the whole cast — not just its arguments — is left\nunchecked.\n\n## Example\n\n```by\nfrom typing import Protocol\nfrom collections.abc import Callable\n\ndef f(x: object):\n a = x cast! list[int] # warning: only `list` is checked\n b = x cast! list # ok — no argument claimed\n\nclass A[T]:\n init(self, t: T)\n\ndef g(x: object):\n a = x cast! A[int] # ok — checked in full via `__orig_class__`\n\ndef r[T](data: list[T]):\n a = data cast! list[int] # ok — the reified `T` cell decides it\n\nclass HasCb[T](Protocol):\n cb: Callable[[T], T]\n\ndef h(x: object):\n a = x cast! HasCb[int] # warning: a callable member has no runtime check\n```",
"default": "warn",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"erased-type-check": {
"title": "detects parametric type tests against a protocol with no runtime residue",
"description": "## What it does\nChecks for parametric type tests (`x is P[int]`) against a protocol,\nwhich has no sound runtime residue.\n\n## Why is this bad?\nA parametric `is` test is answered from static types wherever possible\n(Rust-style). When it cannot be — the value's type is dynamic or a mixed\nunion — the last resort is a runtime probe that unwinds the value's\n`__orig_class__` and its class's generic bases across the mro. A protocol\nhas nothing to unwind: an instance's `__orig_class__` names its concrete\nclass, never the protocol, and a structural `isinstance` check sees no\ntype arguments (and raises outright unless the protocol is\n`@runtime_checkable`). So the test can never confirm the specialization.\n\n## Example\n\n```by\nfrom typing import Protocol\nclass P[T](Protocol):\n def get(self) -> T: ...\n\ndef f(x):\n return x is P[int] # error: a protocol records no specialization\n```\n\nReify the type parameter (so the test compares the reified cell), or test\nagainst a concrete class that fixes the arguments (a user generic, or a\nsubclass whose `__orig_bases__` records the specialization):\n\n```by\ndef f[T](x: T):\n return x is list[int] # ok — compares the reified `T`\n\nclass A[T]: ...\ndef g(x):\n return x is A[int] # ok — unwinds `x`'s mro\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"escape-character-in-forward-annotation": {
"title": "detects forward type annotations with escape characters",
"description": "## What it does\n\nChecks for forward annotations that contain escape characters.\n\n## Why is this bad?\n\nStatic analysis tools like ty can't analyze type annotations that contain escape characters.\n\n## Example\n\n```python\ndef foo() -> \"intt\\b\": ... # error\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"escaping-local": {
"title": "detects a `local` parameter whose value escapes its call",
"description": "## What it does\nChecks for a basedpython `local` parameter whose value escapes the call it\nis bound in — returned to the caller, stored on a parameter-rooted object,\nassigned to a `global` / `nonlocal` binding, or passed on to a parameter\nthat is not itself a borrow.\n\nA callable type may declare its own parameters `local` too\n(`(local int) -> None`), which puts the same constraint on the trailing\nlambda block filling it: the block's implicit `it` is borrowed from the\ncall.\n\n## Why is this bad?\nA `local` parameter is borrowed only for the duration of the call. Letting\nits value outlive the call defeats the borrow: the caller may release the\nunderlying resource, leaving a dangling reference behind.\n\n## Example\n\n```by\n_saved: object\n\ndef f(local fn: () -> None):\n global _saved\n _saved = fn # error: `fn` is local and cannot escape the call\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"escaping-loop-variable": {
"title": "detects a trailing-lambda block capturing a loop variable with a non-borrow callee",
"description": "## What it does\nChecks for a trailing-lambda block inside a loop that captures a loop\nvariable while its callee's callback parameter is **not** a borrow\n(`local` / `once`).\n\n## Why is this bad?\nA trailing-lambda block lowers to a closure that captures the loop variable\nby reference. If the callee is a borrow (`local` / `once`), it runs the\nblock synchronously — the variable still holds this iteration's value. But\na non-borrow callee may store the block and call it after the loop has\nadvanced, at which point every deferred call sees the loop variable's final\nvalue — the classic late-binding trap.\n\nThis is the type-aware complement to ruff's syntactic `B023`, which cannot\nresolve the callee's marker. An opaque callee (not a resolvable function or\nbound method) is left alone.\n\n## Example\n\n```by\ndef defer(fn: () -> None): # not a borrow — may keep `fn`\n _saved.append(fn)\n\nfor x in [1, 2, 3]:\n defer:\n print(x) # error: captures loop variable `x`\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"experimental-syntax": {
"title": "detects experimental syntax",
"description": "## What it does\n\nChecks for experimental syntax that is not part of the Python typing specification.\n\n## Why is this bad?\n\nExperimental syntax is specific to ty. It may be rejected by other type checkers and may never be\nstandardized, or be subject to breaking changes.\n\n## Examples\n\n```toml\n[environment]\npython-version = \"3.14\"\n```\n\n```python\nclass A: ...\n\n\nclass B: ...\n\n\ndef f(value: A & B) -> None: ... # error: [experimental-syntax]\ndef g(value: ~A) -> None: ... # error: [experimental-syntax]\n```",
"default": "warn",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"final-on-non-method": {
"title": "detects `@final` applied to non-method functions",
"description": "## What it does\n\nChecks for `@final` decorators applied to non-method functions.\n\n## Why is this bad?\n\nThe `@final` decorator is only meaningful on methods and classes.\nApplying it to a module-level function or a nested function has no\neffect and is likely a mistake.\n\n## Example\n\n```python\nfrom typing import final\n\n\n# @final is not allowed on non-method functions\n@final # error\ndef my_function() -> int:\n return 0\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"final-on-variable": {
"title": "detects the `final` modifier on a bare variable assignment",
"description": "## What it does\nChecks for the basedpython `final` modifier applied to a bare variable\nassignment outside of a class body, e.g. `final a = 1`.\n\n## Why is this bad?\n`final` is a class/method modifier. On a bare assignment it lowers to a\nplain assignment and makes the variable no more final than before, so it\nis almost certainly a mistake. A final variable is declared with `let`,\nwhich lowers to `Final`.\n\n`final override` is a legitimate assignment marker and is not flagged.\n\n## Example\n\n```by\n# Error: `final` on a variable has no effect\nfinal a = 1\n\n# Correct: `let` declares a final variable\nlet a = 1\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"final-without-value": {
"title": "detects `Final` declarations without a value",
"description": "## What it does\n\nChecks for `Final` symbols that are declared without a value and are never\nassigned a value in their scope.\n\n## Why is this bad?\n\nA `Final` symbol must be initialized with a value at the time of declaration\nor in a subsequent assignment. At module or function scope, the assignment must\noccur in the same scope. In a class body, the assignment may occur in `__init__`.\nProtocol members are declarations of an interface and do not require a value.\n\n## Examples\n\n```python\nfrom typing import Final\n\n# `Final` symbol without a value\nMY_CONSTANT: Final[int] # error\n\n# OK: `Final` symbol with a value\nINITIALIZED_CONSTANT: Final[int] = 1\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"ignore-comment-unknown-rule": {
"title": "detects `ty: ignore` comments that reference unknown rules",
"description": "## What it does\n\nChecks for `ty: ignore[code]` or `type: ignore[ty:code]` comments where `code` isn't a known lint rule.\n\n## Why is this bad?\n\nA `ty: ignore[code]` or a `type: ignore[ty:code]` directive with a `code` that doesn't match\nany known rule will not suppress any type errors, and is probably a mistake.\n\n## Examples\n\n```py\n# error\na = 20 / 1 # ty: ignore[division-by-zer]\n```\n\nUse instead:\n\n```py\na = 20 / 0 # ty: ignore[division-by-zero]\n```",
"default": "warn",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"implicit-concatenated-string-type-annotation": {
"title": "detects implicit concatenated strings in type annotations",
"description": "## What it does\n\nChecks for implicit concatenated strings in type annotation positions.\n\n## Why is this bad?\n\nStatic analysis tools like ty can't analyze type annotations that use implicit concatenated strings.\n\n## Examples\n\n<!-- fmt:off -->\n\n```python\nfrom typing import Literal\n\ndef test() -> \"Literal[\" \"5\" \"]\": # error\n return 5\n```\n\n<!-- fmt:on -->\n\nUse instead:\n\n```python\nfrom typing import Literal\n\n\ndef test() -> \"Literal[5]\":\n return 5\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"implicit-object-repr": {
"title": "detects a value printed through `object.__repr__`",
"description": "## What it does\nChecks for a value rendered as text when its class says nothing about\nhow it should look.\n\n## Why is this bad?\nA class that defines nothing the site can use falls back to the\ninterpreter's own default, which prints the class name and the address\nthe object happens to sit at — `<__main__.A object at 0x102bcc6a0>`.\nThat is never what the message was meant to say, and the address makes\nthe output differ on every run.\n\nWhich dunders count depends on what the site asks for, because the\nfallbacks run one way only: `object.__str__` calls `__repr__`, and\n`object.__format__` calls `str`, but nothing falls back to `__str__`.\n\n- `repr(x)`, `ascii(x)`, `f\"{x!r}\"` — only `__repr__`\n- `str(x)`, `print(x)`, `f\"{x!s}\"` — `__str__` or `__repr__`\n- `format(x)`, `f\"{x}\"` — `__format__`, `__str__` or `__repr__`\n\nOnly a class written in source is judged. A stub leaves these dunders\nout whether or not the runtime class has them — `int` declares none of\nthe three and still prints as a number — so a class that comes from a\nstub, or that inherits from one, is not reported. The exception is a\nstub named in `analysis.implicit-object-repr-report-types`, which\ndefaults to `types.FunctionType` and `builtins.type`: printing a bare\nfunction or class object is the same mistake, and neither stub is\nhiding a rendering.\n\n## Options\n- `analysis.implicit-object-repr-exempt-types`\n- `analysis.implicit-object-repr-report-types`\n\n## Examples\n```python\nclass Point:\n def __init__(self, x: int):\n self.x = x\n\nprint(Point(1)) # warning: prints `<__main__.Point object at 0x...>`\nf\"at {Point(1)}\" # warning\n\nclass Spoken:\n def __str__(self) -> str:\n return \"Spoken()\"\n\nprint(Spoken()) # ok\nrepr(Spoken()) # warning: `__str__` is not what `repr` asks for\n\nclass Labelled:\n def __repr__(self) -> str:\n return \"Labelled()\"\n\nprint(Labelled()) # ok — `str` falls back to `__repr__`\nrepr(Labelled()) # ok\n\ndef helper() -> None: ...\n\nprint(helper) # warning: prints `<function helper at 0x...>`\nprint(Labelled) # warning: prints `<class '__main__.Labelled'>`\n```",
"default": "warn",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"inconsistent-mro": {
"title": "detects class definitions with an inconsistent MRO",
"description": "## What it does\n\nChecks for classes with an inconsistent [method resolution order] (MRO).\n\n## Why is this bad?\n\nClasses with an inconsistent MRO will raise a `TypeError` at runtime.\n\n## Examples\n\n```python\nclass A: ...\n\n\nclass B(A): ...\n\n\n# TypeError: Cannot create a consistent method resolution order\nclass C(A, B): ... # error\n```\n\n[method resolution order]: https://docs.python.org/3/glossary.html#term-method-resolution-order",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"index-out-of-bounds": {
"title": "detects index out of bounds errors",
"description": "## What it does\n\nChecks for attempts to use an out of bounds index to get an item from\na container.\n\n## Why is this bad?\n\nUsing an out of bounds index will raise an `IndexError` at runtime.\n\n## Examples\n\n```python\nt = (0, 1, 2)\n# IndexError: tuple index out of range\nt[3] # error\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"ineffective-final": {
"title": "detects calls to `final()` that type checkers cannot interpret",
"description": "## What it does\n\nChecks for calls to `final()` that type checkers cannot interpret.\n\n## Why is this bad?\n\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\", (), {})) # error\n\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\n\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][method-resolution-order]\n(MRO), or by attempting to combine multiple builtin classes in a class's\nMRO.\n\n## Why is this bad?\n\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\n\nclass B:\n __slots__ = (\"a\", \"b\") # Even if the values are the same\n\n\n# TypeError: multiple bases have instance lay-out conflict\nclass C(A, B): ... # error\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\n# TypeError: multiple bases have instance lay-out conflict\nclass A(int, float): ... # error\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: ...\n\n\nclass B:\n __slots__ = ()\n\n\nclass C:\n __slots__ = (\"a\", \"b\")\n\n\n# fine\nclass D(A, B, C): ...\n```\n\n## Known problems\n\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\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",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"invalid-argument-type": {
"title": "detects call arguments whose type is not assignable to the corresponding typed parameter",
"description": "## What it does\n\nDetects call arguments whose type is not assignable to the corresponding typed parameter.\n\n## Why is this bad?\n\nPassing an argument of a type the function (or callable object) does not accept violates\nthe expectations of the function author and may cause unexpected runtime errors within the\nbody of the function.\n\n## Examples\n\n```python\ndef func(x: int): ...\n\n\nfunc(\"foo\") # error: [invalid-argument-type]\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"invalid-assignment": {
"title": "detects invalid assignments",
"description": "## What it does\n\nChecks for assignments where the type of the value\nis not [assignable to] the type of the assignee.\n\n## Why is this bad?\n\nSuch assignments break the rules of the type system and\nweaken a type checker's ability to accurately reason about your code.\n\n## Examples\n\n```python\na: int = \"\" # error\n```\n\n[assignable to]: https://typing.python.org/en/latest/spec/glossary.html#term-assignable",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"invalid-attribute-access": {
"title": "Invalid attribute access",
"description": "## What it does\n\nChecks for assignments to class variables from instances\nand assignments to instance-only attributes from their class.\n\nAn \"instance-only\" variable is one which is only ever assigned to or declared\nwhen accessed via `self` in an instance method.\n\n## Why is this bad?\n\nIncorrect assignments break the rules of the type system and\nweaken a type checker's ability to accurately reason about your code.\n\n## Examples\n\n```python\nfrom typing import ClassVar\n\n\nclass C:\n instance_var: int\n class_var: ClassVar[int] = 1\n\n def __init__(self):\n # instance variable declared in the class body\n self.instance_var = 42\n\n # instance-only variable not declared in the class body\n self.instance_only_var: int = 42\n\n\nC.class_var = 3 # okay\n\nC.instance_var = 56 # okay\nC().instance_var = 72 # okay\n\nC().instance_only_var = 100 # okay\n\n# Cannot assign to class variable from instance\nC().class_var = 3 # error\n\n# Cannot assign to instance-only variable from class\nC.instance_only_var = 56 # error\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"invalid-attribute-override": {
"title": "detects attribute overrides that change class-variable or instance-variable behavior",
"description": "## What it does\n\nDetects attribute overrides that change whether an inherited attribute\nis a class variable or an instance variable.\n\nThis rule currently only covers class-variable and instance-variable\ncategory changes.\n\n## Why is this bad?\n\nPure class variables and instance variables have different access and\nassignment behavior. Overriding one with the other violates the\n[Liskov Substitution Principle][liskov-substitution-principle] (\"LSP\"), because code that is valid for\nthe superclass may no longer be valid for the subclass.\n\n## Example\n\n```python\nfrom typing import ClassVar\n\n\nclass Base:\n instance_attr: int\n class_attr: ClassVar[int]\n\n\nclass Sub(Base):\n instance_attr: ClassVar[int] # error: [invalid-attribute-override]\n class_attr: int # error: [invalid-attribute-override]\n```\n\n[liskov-substitution-principle]: https://en.wikipedia.org/wiki/Liskov_substitution_principle",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"invalid-await": {
"title": "detects awaiting on types that don't support it",
"description": "## What it does\n\nChecks for `await` being used with types that are not [Awaitable][awaitable-abc].\n\n## Why is this bad?\n\nSuch expressions will lead to `TypeError` being raised at runtime.\n\n## Examples\n\n```python\nimport asyncio\n\n\nclass InvalidAwait:\n def __await__(self) -> int:\n return 5\n\n\nasync def main() -> None:\n await InvalidAwait() # error: [invalid-await]\n await 42 # error: [invalid-await]\n\n\nasyncio.run(main())\n```\n\n[awaitable-abc]: https://docs.python.org/3/library/collections.abc.html#collections.abc.Awaitable",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"invalid-base": {
"title": "detects class bases that will cause the class definition to raise an exception at runtime",
"description": "## What it does\n\nChecks for class definitions that have bases which are not instances of `type`.\n\n## Why is this bad?\n\nClass definitions with bases like this will lead to `TypeError` being raised at runtime.\n\n## Examples\n\n```python\nclass A(42): ... # error: [invalid-base]\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"invalid-conformance": {
"title": "detects invalid basedpython conformance declarations",
"description": "## What it does\nChecks for invalid basedpython conformance declarations\n(`extension str(A):`): an interface that is neither a protocol nor an\nabstract class, or a requirement nothing answers.\n\n## Why is this bad?\nA conformance states that an existing type satisfies an existing\ninterface, and registers a witness table so that a call through an\ninterface-typed receiver reaches it. Conforming to a concrete class would\nmean promising its fields, which a conformance has nowhere to store; and a\nrequirement neither the block, a default on the interface's own extension,\nnor the type itself answers is an `AttributeError` the first time anything\ndispatches through the conformance.\n\n## Example\n\n```by\nprotocol A:\n def bar(self)\n\nextension str(A): # error: `str` does not answer every member of `A`\n ...\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"invalid-context-manager": {
"title": "detects expressions used in with statements that don't implement the context manager protocol",
"description": "## What it does\n\nChecks for expressions used in `with` statements\nthat do not implement the context manager protocol.\n\n## Why is this bad?\n\nSuch a statement will raise `TypeError` at runtime.\n\n## Examples\n\n```python\n# TypeError: 'int' object does not support the context manager protocol\nwith 1: # error\n print(2)\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"invalid-conversion": {
"title": "detects malformed basedpython conversion dunders",
"description": "## What it does\nChecks that the basedpython conversion dunders have the shape their\nlowered call needs: `__from__` and `__of__` are classmethods on the target\ntaking one value and returning it, and `__into__` is a plain instance\nmethod on the source taking nothing.\n\n## Why is this bad?\nA conversion site lowers to `Target.__from__(value)` or `value.__into__()`.\nA `__from__` that is not a classmethod would bind the value to its first\nparameter, and an overloaded `__into__` would have nothing to dispatch on —\nso a malformed dunder converts nothing, silently, wherever it was meant to.\n\n## Example\n\n```by\nclass Fahrenheit:\n def __from__(cls, value: Celsius) -> Self: # error: not a classmethod\n ...\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"invalid-dataclass": {
"title": "detects invalid `@dataclass` applications",
"description": "## What it does\n\nChecks for invalid applications of the `@dataclass` decorator.\n\n## Why is this bad?\n\nApplying `@dataclass` with incompatible arguments raises an exception while creating the\nclass:\n\n- `order=True` with `eq=False`\n- `weakref_slot=True` with `slots=False`\n\nApplying `@dataclass` to a class that inherits from `NamedTuple`, `TypedDict`,\n`Enum`, or `Protocol` is also 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\n```python\nfrom dataclasses import dataclass\nfrom typing import NamedTuple\n\n\n@dataclass(order=True, eq=False) # error: [invalid-dataclass]\nclass Ordered: ...\n\n\n@dataclass\nclass Foo(NamedTuple): # error: [invalid-dataclass]\n x: int\n```\n\nSee: <https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass>\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\n\nChecks for dataclass definitions that have both `frozen=True` and a custom `__setattr__` or\n`__delattr__` method defined.\n\n## Why is this bad?\n\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\n```python\nfrom dataclasses import dataclass\n\n\n@dataclass(frozen=True)\nclass A:\n def __setattr__(self, name: str, value: object) -> None: ... # error\n```",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},
"invalid-declaration": {
"title": "detects invalid declarations",
"description": "## What it does\n\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?\n\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\n```python\na = 1\na: str # error\n```\n\n[assignable to]: https://typing.python.org/en/latest/spec/glossary.html#term-assignable",
"default": "error",
"oneOf": [
{
"$ref": "#/definitions/Level"
}
]
},