python-constricter 0.3.2__tar.gz → 0.3.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. {python_constricter-0.3.2 → python_constricter-0.3.5}/.gitignore +1 -0
  2. {python_constricter-0.3.2 → python_constricter-0.3.5}/PKG-INFO +42 -38
  3. {python_constricter-0.3.2 → python_constricter-0.3.5}/README.md +41 -37
  4. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/__init__.py +1 -1
  5. python_constricter-0.3.5/constricter/__main__.py +26 -0
  6. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/cli/command.py +111 -56
  7. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/cli/config.py +30 -2
  8. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/cli/hints.py +18 -12
  9. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/cli/options.py +57 -3
  10. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/cli/protocol.py +25 -5
  11. python_constricter-0.3.5/constricter/cli/remembered.py +52 -0
  12. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/cli/report.py +7 -5
  13. python_constricter-0.3.5/constricter/cli/runs.py +90 -0
  14. python_constricter-0.3.5/constricter/cli/schedule.py +415 -0
  15. python_constricter-0.3.5/constricter/cli/traced.py +401 -0
  16. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/cli/workers.py +85 -23
  17. python_constricter-0.3.5/constricter/fix/core/asked.py +56 -0
  18. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/core/fixes.py +63 -9
  19. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/core/imports.py +196 -10
  20. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/core/inherited.py +128 -15
  21. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/core/known.py +271 -55
  22. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/core/signatures.py +29 -6
  23. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/index/atoms.py +22 -4
  24. python_constricter-0.3.5/constricter/fix/index/awaits.py +90 -0
  25. python_constricter-0.3.5/constricter/fix/index/beyond.py +148 -0
  26. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/index/callers.py +3 -2
  27. python_constricter-0.3.5/constricter/fix/index/chained.py +69 -0
  28. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/index/classnames.py +17 -0
  29. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/index/declared.py +83 -3
  30. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/index/decorated.py +4 -2
  31. python_constricter-0.3.5/constricter/fix/index/fixtures.py +176 -0
  32. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/index/installed.py +68 -15
  33. python_constricter-0.3.5/constricter/fix/index/linked.py +142 -0
  34. python_constricter-0.3.5/constricter/fix/index/loose.py +98 -0
  35. python_constricter-0.3.5/constricter/fix/index/managed.py +63 -0
  36. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/index/modules.py +368 -46
  37. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/index/offers.py +4 -1
  38. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/index/order.py +13 -3
  39. python_constricter-0.3.5/constricter/fix/index/own_methods.py +67 -0
  40. python_constricter-0.3.5/constricter/fix/index/own_overloads.py +70 -0
  41. python_constricter-0.3.5/constricter/fix/index/own_types.py +161 -0
  42. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/index/plain.py +13 -8
  43. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/index/project.py +222 -180
  44. python_constricter-0.3.5/constricter/fix/index/read.py +70 -0
  45. python_constricter-0.3.5/constricter/fix/index/sides.py +160 -0
  46. python_constricter-0.3.5/constricter/fix/index/strings.py +46 -0
  47. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/index/stubbed.py +86 -80
  48. python_constricter-0.3.5/constricter/fix/index/taken.py +45 -0
  49. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/index/tuples.py +54 -28
  50. python_constricter-0.3.5/constricter/fix/libraries/library.py +374 -0
  51. python_constricter-0.3.5/constricter/fix/libraries/opened.py +147 -0
  52. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/libraries/overloads.py +155 -14
  53. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/libraries/stdlib.py +278 -24
  54. python_constricter-0.3.5/constricter/fix/libraries/walks.py +49 -0
  55. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/attributes.json +25 -0
  56. python_constricter-0.3.5/constricter/fix/tables/awaited.json +69 -0
  57. python_constricter-0.3.5/constricter/fix/tables/awaited_overloads.json +14 -0
  58. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/classes.json +3 -1
  59. python_constricter-0.3.5/constricter/fix/tables/elements.json +156 -0
  60. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/functions.json +0 -1
  61. python_constricter-0.3.5/constricter/fix/tables/generic_attributes.json +254 -0
  62. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/method_overloads.json +146 -99
  63. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/method_signatures.json +229 -40
  64. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/methods.json +35 -10
  65. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/overloads.json +88 -63
  66. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/scalars.json +5 -0
  67. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/source.json +4 -1
  68. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/subscriptable.json +1 -0
  69. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/type_parameters.json +3 -0
  70. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/variables.json +21 -0
  71. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/values/aliased.py +9 -1
  72. python_constricter-0.3.5/constricter/fix/values/bodies.py +76 -0
  73. python_constricter-0.3.5/constricter/fix/values/callables.py +321 -0
  74. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/values/called.py +10 -12
  75. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/values/classvars.py +216 -40
  76. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/values/decided.py +74 -11
  77. python_constricter-0.3.5/constricter/fix/values/displays.py +87 -0
  78. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/values/doubts.py +152 -28
  79. python_constricter-0.3.5/constricter/fix/values/entered.py +331 -0
  80. python_constricter-0.3.5/constricter/fix/values/fills.py +434 -0
  81. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/values/guesses.py +80 -21
  82. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/values/hinted.py +94 -7
  83. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/values/inference.py +145 -146
  84. python_constricter-0.3.5/constricter/fix/values/members.py +564 -0
  85. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/values/narrowed.py +60 -4
  86. python_constricter-0.3.5/constricter/fix/values/operated.py +200 -0
  87. python_constricter-0.3.5/constricter/fix/values/ordered.py +74 -0
  88. python_constricter-0.3.5/constricter/fix/values/returned.py +967 -0
  89. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/values/returns.py +45 -1
  90. python_constricter-0.3.5/constricter/fix/values/shapes.py +494 -0
  91. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/values/targets.py +51 -18
  92. python_constricter-0.3.5/constricter/fix/values/unchecked.py +162 -0
  93. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/offences.py +48 -6
  94. python_constricter-0.3.5/constricter/recording.py +571 -0
  95. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/annotations.py +52 -13
  96. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/binding.py +237 -48
  97. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/calls.py +222 -26
  98. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/checker.py +301 -77
  99. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/decorators.py +12 -0
  100. python_constricter-0.3.5/constricter/rules/keys.py +79 -0
  101. python_constricter-0.3.5/constricter/rules/late.py +663 -0
  102. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/parsed.py +42 -3
  103. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/quoted.py +32 -0
  104. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/rebinding.py +38 -11
  105. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/recorded.py +53 -10
  106. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/scope.py +291 -88
  107. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/syntax.py +20 -0
  108. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/tables.py +79 -9
  109. python_constricter-0.3.5/constricter/rules/widened.py +322 -0
  110. python_constricter-0.3.5/constricter/trace.py +378 -0
  111. {python_constricter-0.3.2 → python_constricter-0.3.5}/pyproject.toml +56 -8
  112. python_constricter-0.3.5/stdlib_tables/elements.py +101 -0
  113. {python_constricter-0.3.2 → python_constricter-0.3.5}/stdlib_tables/generate.py +176 -16
  114. {python_constricter-0.3.2 → python_constricter-0.3.5}/stdlib_tables/overloads.py +123 -34
  115. {python_constricter-0.3.2 → python_constricter-0.3.5}/stdlib_tables/reading.py +57 -11
  116. {python_constricter-0.3.2 → python_constricter-0.3.5}/stdlib_tables/templates.py +6 -1
  117. python_constricter-0.3.2/constricter/__main__.py +0 -9
  118. python_constricter-0.3.2/constricter/cli/runs.py +0 -43
  119. python_constricter-0.3.2/constricter/cli/schedule.py +0 -242
  120. python_constricter-0.3.2/constricter/fix/index/sides.py +0 -65
  121. python_constricter-0.3.2/constricter/fix/libraries/library.py +0 -172
  122. python_constricter-0.3.2/constricter/fix/libraries/opened.py +0 -74
  123. python_constricter-0.3.2/constricter/fix/tables/generic_attributes.json +0 -55
  124. python_constricter-0.3.2/constricter/fix/values/entered.py +0 -152
  125. python_constricter-0.3.2/constricter/fix/values/fills.py +0 -256
  126. python_constricter-0.3.2/constricter/fix/values/members.py +0 -277
  127. python_constricter-0.3.2/constricter/fix/values/returned.py +0 -706
  128. python_constricter-0.3.2/constricter/fix/values/shapes.py +0 -279
  129. python_constricter-0.3.2/constricter/rules/late.py +0 -324
  130. {python_constricter-0.3.2 → python_constricter-0.3.5}/LICENSE.md +0 -0
  131. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/cli/__init__.py +0 -0
  132. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/cli/baseline.py +0 -0
  133. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/cli/collecting.py +0 -0
  134. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/cli/edits.py +0 -0
  135. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/cli/explain.py +0 -0
  136. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/cli/guard.py +0 -0
  137. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/cli/paths.py +0 -0
  138. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/__init__.py +0 -0
  139. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/core/__init__.py +0 -0
  140. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/index/__init__.py +0 -0
  141. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/libraries/__init__.py +0 -0
  142. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/aliases.json +0 -0
  143. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/bases.json +0 -0
  144. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/returns.json +0 -0
  145. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/tables/scalar_members.json +0 -0
  146. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/fix/values/__init__.py +0 -0
  147. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/jsonc.py +0 -0
  148. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/noqa.py +0 -0
  149. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/notebook.py +0 -0
  150. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/plugins/__init__.py +0 -0
  151. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/plugins/flake8.py +0 -0
  152. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/plugins/pylint.py +0 -0
  153. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/py.typed +0 -0
  154. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/__init__.py +0 -0
  155. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/flow.py +0 -0
  156. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/narrowing.py +0 -0
  157. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/redundant.py +0 -0
  158. {python_constricter-0.3.2 → python_constricter-0.3.5}/constricter/rules/walked.py +0 -0
  159. {python_constricter-0.3.2 → python_constricter-0.3.5}/hatch_build.py +0 -0
  160. {python_constricter-0.3.2 → python_constricter-0.3.5}/stdlib_tables/__init__.py +0 -0
  161. {python_constricter-0.3.2 → python_constricter-0.3.5}/stdlib_tables/__main__.py +0 -0
  162. {python_constricter-0.3.2 → python_constricter-0.3.5}/stdlib_tables/partial.json +0 -0
  163. {python_constricter-0.3.2 → python_constricter-0.3.5}/stdlib_tables/stubs.py +0 -0
@@ -42,6 +42,7 @@ stdlib_tables/partial.json
42
42
  /.claude/skills
43
43
  /.claude/workflows
44
44
  /.claude/.cc-writes
45
+ /.vscode
45
46
 
46
47
  # Backups merge tools leave next to a conflicted file.
47
48
  *.orig
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: python-constricter
3
- Version: 0.3.2
3
+ Version: 0.3.5
4
4
  Import-Name: constricter
5
5
  Summary: Lint rules: every local variable is typed where it's first bound. A flake8 plugin, a pylint plugin and a standalone CLI.
6
6
  Author: Ivy Duggan
@@ -173,37 +173,39 @@ enabled).
173
173
 
174
174
  Options:
175
175
 
176
- | Option | CLI | `[tool.constricter]` | flake8 (CLI or config) | pylint |
177
- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ------------------------------- | --------------------------------- |
178
- | level | `--level` | `level` | `--constricter-level` | `constricter-level` |
179
- | strictest | `--max`: `--level=suffocate` for every path, `--all-scopes`, and the opt-in `LVA012` | — | — | — |
180
- | every fix | `--max-fix`: `--max`, `--fix --unsafe-fixes`, and `--infer-with` each of basedpyright, ty and pyrefly that's installed and runs | — | — | — |
181
- | type comments | `--type-comments` | `type-comments` | `--constricter-type-comments` | `constricter-type-comments = yes` |
182
- | all scopes | `--all-scopes` | `all-scopes` | `--constricter-all-scopes` | `constricter-all-scopes = yes` |
183
- | nesting | `--nesting N` | `nesting` | `--constricter-nesting` | `constricter-nesting` |
184
- | max length | `--max-length N` (LVA011) | `max-length` | `--constricter-max-length` | `constricter-max-length` |
185
- | vague | `--vague LEVEL` (LVA005, and the fixes offered): -1 none (the default), 0 one `Any` inside a type that says the rest (`tuple[str, Any]`), N from 1 N + 1, or one alone | `vague` | `--constricter-vague` | `constricter-vague` |
186
- | min python | `--min-python VERSION` (the oldest Python the code runs on, whose syntax `--fix` writes; default: `requires-python`'s) | `min-python` | - | - |
187
- | type hierarchy | - | `narrower` (a table) | `--constricter-narrower` | `constricter-narrower` |
188
- | fix | `--fix` (`--unsafe-fixes` for guesses), `--diff` to preview | - | - | - |
189
- | infer with | `--infer-with CHECKERS` (`basedpyright`, `ty`, `pyrefly`, several: inferred types, as guesses) | `infer-with` | - | - |
190
- | show fixes | `--show-fixes` (each fix and how it was decided, text) | - | - | - |
191
- | fix levels | `--fix-select`, `--fix-ignore`, `--unsafe-fix-select` (mechanisms: [docs/FIXES.md](https://github.com/ivylikethevine/python-constricter/blob/main/docs/FIXES.md#fix-levels)) | `fix-select`, `fix-ignore`, `unsafe-fix-select` | - | - |
192
- | fix plain bases | `--fix-plain-bases BASES` (frameworks' classes whose subclasses' bodies `--fix` annotates; django's are built in) | `fix-plain-bases` | - | - |
193
- | select | `--select CODES` (codes or prefixes) | `select` | flake8's own `select` | pylint's own `enable` |
194
- | extend select | `--extend-select CODES` (also report these; an opt-in code by its full code) | `extend-select` | flake8's own `extend-select` | pylint's own `enable` |
195
- | ignore | `--ignore CODES` | `ignore` | flake8's own `extend-ignore` | pylint's own `disable` |
196
- | exclude | `--exclude GLOB` (repeatable) | `exclude` | flake8's own `exclude` | pylint's own `ignore-paths` |
197
- | format | `--format`: `text`, `full` (with source), `json`, `github`, `sarif`, `gitlab`, `junit`, `rdjson` | - | - | - |
198
- | statistics | `--statistics` (counts per code, text format) | - | - | - |
199
- | jobs | `--jobs N` (`-j`; 0: one per CPU) | `jobs` | flake8's own `--jobs` | pylint's own `--jobs` |
200
- | baseline | `--baseline FILE`; `--write-baseline` records it | `baseline` | - | - |
201
- | coverage | `--coverage`, `--fail-under PCT` | - | - | - |
202
- | per-path levels | - | `per-path-levels` | - | - |
203
- | per-file ignores | - | `per-file-ignores` | flake8's own `per-file-ignores` | - |
204
- | stdin | `-` as the path, `--stdin-filename PATH` | - | flake8's own `-` | - |
205
- | exit status | `--exit-zero` | - | flake8's own `--exit-zero` | pylint's own `--exit-zero` |
206
- | output file | `--output-file FILE` | - | flake8's own `--output-file` | pylint's own `--output` |
176
+ | Option | CLI | `[tool.constricter]` | flake8 (CLI or config) | pylint |
177
+ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ------------------------------- | --------------------------------- |
178
+ | level | `--level` | `level` | `--constricter-level` | `constricter-level` |
179
+ | strictest | `--max`: `--level=suffocate` for every path, `--all-scopes`, and the opt-in `LVA012` | — | — | — |
180
+ | every fix | `--max-fix`: `--max`, `--fix --unsafe-fixes`, and `--infer-with` each of basedpyright, ty and pyrefly that's installed and runs | — | — | — |
181
+ | type comments | `--type-comments` | `type-comments` | `--constricter-type-comments` | `constricter-type-comments = yes` |
182
+ | all scopes | `--all-scopes` | `all-scopes` | `--constricter-all-scopes` | `constricter-all-scopes = yes` |
183
+ | nesting | `--nesting N` | `nesting` | `--constricter-nesting` | `constricter-nesting` |
184
+ | max length | `--max-length N` (LVA011) | `max-length` | `--constricter-max-length` | `constricter-max-length` |
185
+ | vague | `--vague LEVEL` (LVA005, and the fixes offered): -1 none (the default), 0 one `Any` inside a type that says the rest (`tuple[str, Any]`), N from 1 N + 1, or one alone | `vague` | `--constricter-vague` | `constricter-vague` |
186
+ | min python | `--min-python VERSION` (the oldest Python the code runs on, whose syntax `--fix` writes; default: `requires-python`'s) | `min-python` | - | - |
187
+ | type hierarchy | - | `narrower` (a table) | `--constricter-narrower` | `constricter-narrower` |
188
+ | fix | `--fix` (`--unsafe-fixes` for guesses), `--diff` to preview | - | - | - |
189
+ | infer with | `--infer-with CHECKERS` (`basedpyright`, `ty`, `pyrefly`, several: inferred types, as guesses) | `infer-with` | - | - |
190
+ | infer from | `--infer-from FILE` (the types `python -m constricter.trace -m pytest` recorded from a run, as guesses) | `infer-from` | - | - |
191
+ | show fixes | `--show-fixes` (each fix and how it was decided; with `--fix`, those made too) | - | - | - |
192
+ | fix levels | `--fix-select`, `--fix-ignore`, `--unsafe-fix-select` (mechanisms: [docs/FIXES.md](https://github.com/ivylikethevine/python-constricter/blob/main/docs/FIXES.md#fix-levels)) | `fix-select`, `fix-ignore`, `unsafe-fix-select` | - | - |
193
+ | fix plain bases | `--fix-plain-bases BASES` (frameworks' classes whose subclasses' bodies `--fix` annotates; django's are built in) | `fix-plain-bases` | - | - |
194
+ | fix widen | `--fix-widen KINDS` (wider types `--fix` may write, each marked: `untyped-parameters`, `empty-containers`, `mixed-containers`, `unions`, `vague`, `untyped-calls`, `unknown-calls`; `all`: every one; [docs/FIXES.md](https://github.com/ivylikethevine/python-constricter/blob/main/docs/FIXES.md#wider-types-fix-widen)) | `fix-widen` | - | - |
195
+ | select | `--select CODES` (codes or prefixes) | `select` | flake8's own `select` | pylint's own `enable` |
196
+ | extend select | `--extend-select CODES` (also report these; an opt-in code by its full code) | `extend-select` | flake8's own `extend-select` | pylint's own `enable` |
197
+ | ignore | `--ignore CODES` | `ignore` | flake8's own `extend-ignore` | pylint's own `disable` |
198
+ | exclude | `--exclude GLOB` (repeatable) | `exclude` | flake8's own `exclude` | pylint's own `ignore-paths` |
199
+ | format | `--format`: `text`, `full` (with source), `json`, `github`, `sarif`, `gitlab`, `junit`, `rdjson` | - | - | - |
200
+ | statistics | `--statistics` (counts per code, text format) | - | - | - |
201
+ | jobs | `--jobs N` (`-j`; 0: one per CPU) | `jobs` | flake8's own `--jobs` | pylint's own `--jobs` |
202
+ | baseline | `--baseline FILE`; `--write-baseline` records it | `baseline` | - | - |
203
+ | coverage | `--coverage`, `--fail-under PCT` | - | - | - |
204
+ | per-path levels | - | `per-path-levels` | - | - |
205
+ | per-file ignores | - | `per-file-ignores` | flake8's own `per-file-ignores` | - |
206
+ | stdin | `-` as the path, `--stdin-filename PATH` | - | flake8's own `-` | - |
207
+ | exit status | `--exit-zero` | - | flake8's own `--exit-zero` | pylint's own `--exit-zero` |
208
+ | output file | `--output-file FILE` | - | flake8's own `--output-file` | pylint's own `--output` |
207
209
 
208
210
  `constricter --explain LVA002` prints a code's rationale, its fix, and the levels that report it.
209
211
 
@@ -244,9 +246,11 @@ ignore = ["LVA003"]
244
246
  return type or whose `return`s agree (in another checked file too), a copy, subscript, attribute or
245
247
  method call of a local whose type is known, and values computed from those; a loop's target or an
246
248
  unpacking's names get a declaration on the line before. `--unsafe-fixes` adds guesses, and
247
- `--show-fixes` lists each fix and how its value decided it. `--infer-with basedpyright` (or `ty`, or
248
- `pyrefly`, or several: `basedpyright,ty`; each installed alongside) asks those type checkers for
249
- what `--fix` can't type itself, as guesses. The full list is in
249
+ `--show-fixes` lists each fix and how its value decided it, and after `--fix` each one made.
250
+ `--infer-with basedpyright` (or `ty`, or `pyrefly`, or several: `basedpyright,ty`; each installed
251
+ alongside) asks those type checkers for what `--fix` can't type itself, as guesses;
252
+ `--infer-from FILE` takes the types a run bound each name to, recorded by
253
+ `python -m constricter.trace -m pytest`, the same way. The full list is in
250
254
  [docs/FIXES.md](https://github.com/ivylikethevine/python-constricter/blob/main/docs/FIXES.md).
251
255
 
252
256
  ### Installing and running
@@ -272,7 +276,7 @@ pre-commit, after ruff's hooks (or `constricter-fix`, which runs `--fix` first):
272
276
 
273
277
  ```yaml
274
278
  - repo: https://github.com/ivylikethevine/python-constricter
275
- rev: v0.3.2
279
+ rev: v0.3.5
276
280
  hooks:
277
281
  - id: constricter
278
282
  ```
@@ -305,8 +309,8 @@ default one is used only if it exists.
305
309
  total; the bindings are the ones the rules cover (with `--all-scopes`, module and class bodies too),
306
310
  and `# noqa` doesn't make one typed. `--fail-under PCT` (which implies `--coverage`) exits 1 below
307
311
  PCT, so CI can hold a codebase to a share. With `--format=json` it prints
308
- `{"typed", "total", "percent", "files"}`, which a badge can read: publish that JSON somewhere (a
309
- gist, a release asset) and point
312
+ `{"typed", "total", "widened", "percent", "files"}`, which a badge can read: publish that JSON
313
+ somewhere (a gist, a release asset) and point
310
314
  [shields.io's dynamic JSON badge](https://shields.io/badges/dynamic-json-badge) at it with the query
311
315
  `$.percent`. This project keeps its own share at 100% in CI, so its badge is static.
312
316
 
@@ -146,37 +146,39 @@ enabled).
146
146
 
147
147
  Options:
148
148
 
149
- | Option | CLI | `[tool.constricter]` | flake8 (CLI or config) | pylint |
150
- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ------------------------------- | --------------------------------- |
151
- | level | `--level` | `level` | `--constricter-level` | `constricter-level` |
152
- | strictest | `--max`: `--level=suffocate` for every path, `--all-scopes`, and the opt-in `LVA012` | — | — | — |
153
- | every fix | `--max-fix`: `--max`, `--fix --unsafe-fixes`, and `--infer-with` each of basedpyright, ty and pyrefly that's installed and runs | — | — | — |
154
- | type comments | `--type-comments` | `type-comments` | `--constricter-type-comments` | `constricter-type-comments = yes` |
155
- | all scopes | `--all-scopes` | `all-scopes` | `--constricter-all-scopes` | `constricter-all-scopes = yes` |
156
- | nesting | `--nesting N` | `nesting` | `--constricter-nesting` | `constricter-nesting` |
157
- | max length | `--max-length N` (LVA011) | `max-length` | `--constricter-max-length` | `constricter-max-length` |
158
- | vague | `--vague LEVEL` (LVA005, and the fixes offered): -1 none (the default), 0 one `Any` inside a type that says the rest (`tuple[str, Any]`), N from 1 N + 1, or one alone | `vague` | `--constricter-vague` | `constricter-vague` |
159
- | min python | `--min-python VERSION` (the oldest Python the code runs on, whose syntax `--fix` writes; default: `requires-python`'s) | `min-python` | - | - |
160
- | type hierarchy | - | `narrower` (a table) | `--constricter-narrower` | `constricter-narrower` |
161
- | fix | `--fix` (`--unsafe-fixes` for guesses), `--diff` to preview | - | - | - |
162
- | infer with | `--infer-with CHECKERS` (`basedpyright`, `ty`, `pyrefly`, several: inferred types, as guesses) | `infer-with` | - | - |
163
- | show fixes | `--show-fixes` (each fix and how it was decided, text) | - | - | - |
164
- | fix levels | `--fix-select`, `--fix-ignore`, `--unsafe-fix-select` (mechanisms: [docs/FIXES.md](https://github.com/ivylikethevine/python-constricter/blob/main/docs/FIXES.md#fix-levels)) | `fix-select`, `fix-ignore`, `unsafe-fix-select` | - | - |
165
- | fix plain bases | `--fix-plain-bases BASES` (frameworks' classes whose subclasses' bodies `--fix` annotates; django's are built in) | `fix-plain-bases` | - | - |
166
- | select | `--select CODES` (codes or prefixes) | `select` | flake8's own `select` | pylint's own `enable` |
167
- | extend select | `--extend-select CODES` (also report these; an opt-in code by its full code) | `extend-select` | flake8's own `extend-select` | pylint's own `enable` |
168
- | ignore | `--ignore CODES` | `ignore` | flake8's own `extend-ignore` | pylint's own `disable` |
169
- | exclude | `--exclude GLOB` (repeatable) | `exclude` | flake8's own `exclude` | pylint's own `ignore-paths` |
170
- | format | `--format`: `text`, `full` (with source), `json`, `github`, `sarif`, `gitlab`, `junit`, `rdjson` | - | - | - |
171
- | statistics | `--statistics` (counts per code, text format) | - | - | - |
172
- | jobs | `--jobs N` (`-j`; 0: one per CPU) | `jobs` | flake8's own `--jobs` | pylint's own `--jobs` |
173
- | baseline | `--baseline FILE`; `--write-baseline` records it | `baseline` | - | - |
174
- | coverage | `--coverage`, `--fail-under PCT` | - | - | - |
175
- | per-path levels | - | `per-path-levels` | - | - |
176
- | per-file ignores | - | `per-file-ignores` | flake8's own `per-file-ignores` | - |
177
- | stdin | `-` as the path, `--stdin-filename PATH` | - | flake8's own `-` | - |
178
- | exit status | `--exit-zero` | - | flake8's own `--exit-zero` | pylint's own `--exit-zero` |
179
- | output file | `--output-file FILE` | - | flake8's own `--output-file` | pylint's own `--output` |
149
+ | Option | CLI | `[tool.constricter]` | flake8 (CLI or config) | pylint |
150
+ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ------------------------------- | --------------------------------- |
151
+ | level | `--level` | `level` | `--constricter-level` | `constricter-level` |
152
+ | strictest | `--max`: `--level=suffocate` for every path, `--all-scopes`, and the opt-in `LVA012` | — | — | — |
153
+ | every fix | `--max-fix`: `--max`, `--fix --unsafe-fixes`, and `--infer-with` each of basedpyright, ty and pyrefly that's installed and runs | — | — | — |
154
+ | type comments | `--type-comments` | `type-comments` | `--constricter-type-comments` | `constricter-type-comments = yes` |
155
+ | all scopes | `--all-scopes` | `all-scopes` | `--constricter-all-scopes` | `constricter-all-scopes = yes` |
156
+ | nesting | `--nesting N` | `nesting` | `--constricter-nesting` | `constricter-nesting` |
157
+ | max length | `--max-length N` (LVA011) | `max-length` | `--constricter-max-length` | `constricter-max-length` |
158
+ | vague | `--vague LEVEL` (LVA005, and the fixes offered): -1 none (the default), 0 one `Any` inside a type that says the rest (`tuple[str, Any]`), N from 1 N + 1, or one alone | `vague` | `--constricter-vague` | `constricter-vague` |
159
+ | min python | `--min-python VERSION` (the oldest Python the code runs on, whose syntax `--fix` writes; default: `requires-python`'s) | `min-python` | - | - |
160
+ | type hierarchy | - | `narrower` (a table) | `--constricter-narrower` | `constricter-narrower` |
161
+ | fix | `--fix` (`--unsafe-fixes` for guesses), `--diff` to preview | - | - | - |
162
+ | infer with | `--infer-with CHECKERS` (`basedpyright`, `ty`, `pyrefly`, several: inferred types, as guesses) | `infer-with` | - | - |
163
+ | infer from | `--infer-from FILE` (the types `python -m constricter.trace -m pytest` recorded from a run, as guesses) | `infer-from` | - | - |
164
+ | show fixes | `--show-fixes` (each fix and how it was decided; with `--fix`, those made too) | - | - | - |
165
+ | fix levels | `--fix-select`, `--fix-ignore`, `--unsafe-fix-select` (mechanisms: [docs/FIXES.md](https://github.com/ivylikethevine/python-constricter/blob/main/docs/FIXES.md#fix-levels)) | `fix-select`, `fix-ignore`, `unsafe-fix-select` | - | - |
166
+ | fix plain bases | `--fix-plain-bases BASES` (frameworks' classes whose subclasses' bodies `--fix` annotates; django's are built in) | `fix-plain-bases` | - | - |
167
+ | fix widen | `--fix-widen KINDS` (wider types `--fix` may write, each marked: `untyped-parameters`, `empty-containers`, `mixed-containers`, `unions`, `vague`, `untyped-calls`, `unknown-calls`; `all`: every one; [docs/FIXES.md](https://github.com/ivylikethevine/python-constricter/blob/main/docs/FIXES.md#wider-types-fix-widen)) | `fix-widen` | - | - |
168
+ | select | `--select CODES` (codes or prefixes) | `select` | flake8's own `select` | pylint's own `enable` |
169
+ | extend select | `--extend-select CODES` (also report these; an opt-in code by its full code) | `extend-select` | flake8's own `extend-select` | pylint's own `enable` |
170
+ | ignore | `--ignore CODES` | `ignore` | flake8's own `extend-ignore` | pylint's own `disable` |
171
+ | exclude | `--exclude GLOB` (repeatable) | `exclude` | flake8's own `exclude` | pylint's own `ignore-paths` |
172
+ | format | `--format`: `text`, `full` (with source), `json`, `github`, `sarif`, `gitlab`, `junit`, `rdjson` | - | - | - |
173
+ | statistics | `--statistics` (counts per code, text format) | - | - | - |
174
+ | jobs | `--jobs N` (`-j`; 0: one per CPU) | `jobs` | flake8's own `--jobs` | pylint's own `--jobs` |
175
+ | baseline | `--baseline FILE`; `--write-baseline` records it | `baseline` | - | - |
176
+ | coverage | `--coverage`, `--fail-under PCT` | - | - | - |
177
+ | per-path levels | - | `per-path-levels` | - | - |
178
+ | per-file ignores | - | `per-file-ignores` | flake8's own `per-file-ignores` | - |
179
+ | stdin | `-` as the path, `--stdin-filename PATH` | - | flake8's own `-` | - |
180
+ | exit status | `--exit-zero` | - | flake8's own `--exit-zero` | pylint's own `--exit-zero` |
181
+ | output file | `--output-file FILE` | - | flake8's own `--output-file` | pylint's own `--output` |
180
182
 
181
183
  `constricter --explain LVA002` prints a code's rationale, its fix, and the levels that report it.
182
184
 
@@ -217,9 +219,11 @@ ignore = ["LVA003"]
217
219
  return type or whose `return`s agree (in another checked file too), a copy, subscript, attribute or
218
220
  method call of a local whose type is known, and values computed from those; a loop's target or an
219
221
  unpacking's names get a declaration on the line before. `--unsafe-fixes` adds guesses, and
220
- `--show-fixes` lists each fix and how its value decided it. `--infer-with basedpyright` (or `ty`, or
221
- `pyrefly`, or several: `basedpyright,ty`; each installed alongside) asks those type checkers for
222
- what `--fix` can't type itself, as guesses. The full list is in
222
+ `--show-fixes` lists each fix and how its value decided it, and after `--fix` each one made.
223
+ `--infer-with basedpyright` (or `ty`, or `pyrefly`, or several: `basedpyright,ty`; each installed
224
+ alongside) asks those type checkers for what `--fix` can't type itself, as guesses;
225
+ `--infer-from FILE` takes the types a run bound each name to, recorded by
226
+ `python -m constricter.trace -m pytest`, the same way. The full list is in
223
227
  [docs/FIXES.md](https://github.com/ivylikethevine/python-constricter/blob/main/docs/FIXES.md).
224
228
 
225
229
  ### Installing and running
@@ -245,7 +249,7 @@ pre-commit, after ruff's hooks (or `constricter-fix`, which runs `--fix` first):
245
249
 
246
250
  ```yaml
247
251
  - repo: https://github.com/ivylikethevine/python-constricter
248
- rev: v0.3.2
252
+ rev: v0.3.5
249
253
  hooks:
250
254
  - id: constricter
251
255
  ```
@@ -278,8 +282,8 @@ default one is used only if it exists.
278
282
  total; the bindings are the ones the rules cover (with `--all-scopes`, module and class bodies too),
279
283
  and `# noqa` doesn't make one typed. `--fail-under PCT` (which implies `--coverage`) exits 1 below
280
284
  PCT, so CI can hold a codebase to a share. With `--format=json` it prints
281
- `{"typed", "total", "percent", "files"}`, which a badge can read: publish that JSON somewhere (a
282
- gist, a release asset) and point
285
+ `{"typed", "total", "widened", "percent", "files"}`, which a badge can read: publish that JSON
286
+ somewhere (a gist, a release asset) and point
283
287
  [shields.io's dynamic JSON badge](https://shields.io/badges/dynamic-json-badge) at it with the query
284
288
  `$.percent`. This project keeps its own share at 100% in CI, so its badge is static.
285
289
 
@@ -25,7 +25,7 @@ from constricter.offences import (
25
25
  )
26
26
  from constricter.rules.checker import Coverage, annotation_coverage, check_source, check_tree
27
27
 
28
- __version__ = "0.3.2"
28
+ __version__ = "0.3.5"
29
29
  __all__ = [
30
30
  "COMMENT_TYPED_TARGET",
31
31
  "DEFAULT_CHECKS",
@@ -0,0 +1,26 @@
1
+ # SPDX-License-Identifier: MIT
2
+ """`python -m constricter`, and the `constricter` script."""
3
+
4
+ import contextlib
5
+ import os
6
+ import sys
7
+
8
+ from constricter.cli.command import main
9
+
10
+
11
+ def run() -> None:
12
+ """Run the command, and leave with its status at once.
13
+
14
+ Not by the interpreter's own exit, which frees every parsed file and the index an object at a
15
+ time: a fifth of a check of a thousand files. What the command wrote is flushed first; nothing
16
+ else waits on the exit (its workers have ended, its output file is closed).
17
+ """
18
+ status: int = main()
19
+ with contextlib.suppress(OSError, ValueError): # a reader that left, a stream closed already
20
+ _ = sys.stdout.flush()
21
+ _ = sys.stderr.flush()
22
+ os._exit(status)
23
+
24
+
25
+ if __name__ == "__main__": # not when `--jobs` workers import it
26
+ run()