python-constricter 0.4.1__cp311-cp311-win32.whl

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 (261) hide show
  1. constricter/__init__.py +55 -0
  2. constricter/__main__.py +26 -0
  3. constricter/_version.py +4 -0
  4. constricter/cli/__init__.py +2 -0
  5. constricter/cli/baseline.py +107 -0
  6. constricter/cli/collecting.py +54 -0
  7. constricter/cli/command.py +547 -0
  8. constricter/cli/config.py +322 -0
  9. constricter/cli/explain.py +104 -0
  10. constricter/cli/lsp/__init__.py +2 -0
  11. constricter/cli/lsp/connection.py +475 -0
  12. constricter/cli/lsp/edits.py +188 -0
  13. constricter/cli/lsp/guard.py +133 -0
  14. constricter/cli/lsp/hints.py +391 -0
  15. constricter/cli/lsp/protocol.py +192 -0
  16. constricter/cli/lsp/remembered.py +81 -0
  17. constricter/cli/lsp/stored.py +200 -0
  18. constricter/cli/options.py +799 -0
  19. constricter/cli/paths.py +151 -0
  20. constricter/cli/reading.py +36 -0
  21. constricter/cli/report.py +397 -0
  22. constricter/cli/rounds.py +328 -0
  23. constricter/cli/runs.py +90 -0
  24. constricter/cli/schedule.py +463 -0
  25. constricter/cli/traced.py +401 -0
  26. constricter/cli/workers.py +286 -0
  27. constricter/empty.py +66 -0
  28. constricter/fix/__init__.cp311-win32.pyd +0 -0
  29. constricter/fix/__init__.py +2 -0
  30. constricter/fix/core/__init__.cp311-win32.pyd +0 -0
  31. constricter/fix/core/__init__.py +2 -0
  32. constricter/fix/core/asked.cp311-win32.pyd +0 -0
  33. constricter/fix/core/asked.py +56 -0
  34. constricter/fix/core/fixes.cp311-win32.pyd +0 -0
  35. constricter/fix/core/fixes.py +317 -0
  36. constricter/fix/core/imports.cp311-win32.pyd +0 -0
  37. constricter/fix/core/imports.py +580 -0
  38. constricter/fix/core/inherited.cp311-win32.pyd +0 -0
  39. constricter/fix/core/inherited.py +311 -0
  40. constricter/fix/core/known.cp311-win32.pyd +0 -0
  41. constricter/fix/core/known.py +730 -0
  42. constricter/fix/core/signatures.cp311-win32.pyd +0 -0
  43. constricter/fix/core/signatures.py +132 -0
  44. constricter/fix/index/__init__.cp311-win32.pyd +0 -0
  45. constricter/fix/index/__init__.py +2 -0
  46. constricter/fix/index/awaits.cp311-win32.pyd +0 -0
  47. constricter/fix/index/awaits.py +90 -0
  48. constricter/fix/index/beyond.cp311-win32.pyd +0 -0
  49. constricter/fix/index/beyond.py +149 -0
  50. constricter/fix/index/callers.cp311-win32.pyd +0 -0
  51. constricter/fix/index/callers.py +155 -0
  52. constricter/fix/index/crossed.cp311-win32.pyd +0 -0
  53. constricter/fix/index/crossed.py +327 -0
  54. constricter/fix/index/decorated.cp311-win32.pyd +0 -0
  55. constricter/fix/index/decorated.py +140 -0
  56. constricter/fix/index/fixtures.cp311-win32.pyd +0 -0
  57. constricter/fix/index/fixtures.py +176 -0
  58. constricter/fix/index/linked.cp311-win32.pyd +0 -0
  59. constricter/fix/index/linked.py +142 -0
  60. constricter/fix/index/loose.cp311-win32.pyd +0 -0
  61. constricter/fix/index/loose.py +103 -0
  62. constricter/fix/index/managed.cp311-win32.pyd +0 -0
  63. constricter/fix/index/managed.py +63 -0
  64. constricter/fix/index/modules.cp311-win32.pyd +0 -0
  65. constricter/fix/index/modules.py +741 -0
  66. constricter/fix/index/offers.cp311-win32.pyd +0 -0
  67. constricter/fix/index/offers.py +252 -0
  68. constricter/fix/index/order.cp311-win32.pyd +0 -0
  69. constricter/fix/index/order.py +155 -0
  70. constricter/fix/index/origins.cp311-win32.pyd +0 -0
  71. constricter/fix/index/origins.py +238 -0
  72. constricter/fix/index/own_methods.cp311-win32.pyd +0 -0
  73. constricter/fix/index/own_methods.py +91 -0
  74. constricter/fix/index/own_overloads.cp311-win32.pyd +0 -0
  75. constricter/fix/index/own_overloads.py +70 -0
  76. constricter/fix/index/own_types.cp311-win32.pyd +0 -0
  77. constricter/fix/index/own_types.py +330 -0
  78. constricter/fix/index/params.cp311-win32.pyd +0 -0
  79. constricter/fix/index/params.py +81 -0
  80. constricter/fix/index/plain.cp311-win32.pyd +0 -0
  81. constricter/fix/index/plain.py +221 -0
  82. constricter/fix/index/project.cp311-win32.pyd +0 -0
  83. constricter/fix/index/project.py +797 -0
  84. constricter/fix/index/sides.cp311-win32.pyd +0 -0
  85. constricter/fix/index/sides.py +160 -0
  86. constricter/fix/index/strings.cp311-win32.pyd +0 -0
  87. constricter/fix/index/strings.py +46 -0
  88. constricter/fix/index/stubs/__init__.cp311-win32.pyd +0 -0
  89. constricter/fix/index/stubs/__init__.py +2 -0
  90. constricter/fix/index/stubs/atoms.cp311-win32.pyd +0 -0
  91. constricter/fix/index/stubs/atoms.py +425 -0
  92. constricter/fix/index/stubs/chained.cp311-win32.pyd +0 -0
  93. constricter/fix/index/stubs/chained.py +69 -0
  94. constricter/fix/index/stubs/classnames.cp311-win32.pyd +0 -0
  95. constricter/fix/index/stubs/classnames.py +124 -0
  96. constricter/fix/index/stubs/declared.cp311-win32.pyd +0 -0
  97. constricter/fix/index/stubs/declared.py +508 -0
  98. constricter/fix/index/stubs/installed.cp311-win32.pyd +0 -0
  99. constricter/fix/index/stubs/installed.py +425 -0
  100. constricter/fix/index/stubs/names.cp311-win32.pyd +0 -0
  101. constricter/fix/index/stubs/names.py +200 -0
  102. constricter/fix/index/stubs/read.cp311-win32.pyd +0 -0
  103. constricter/fix/index/stubs/read.py +70 -0
  104. constricter/fix/index/stubs/signatures.cp311-win32.pyd +0 -0
  105. constricter/fix/index/stubs/signatures.py +656 -0
  106. constricter/fix/index/stubs/stubbed.cp311-win32.pyd +0 -0
  107. constricter/fix/index/stubs/stubbed.py +208 -0
  108. constricter/fix/index/taken.cp311-win32.pyd +0 -0
  109. constricter/fix/index/taken.py +45 -0
  110. constricter/fix/index/tuples.cp311-win32.pyd +0 -0
  111. constricter/fix/index/tuples.py +112 -0
  112. constricter/fix/libraries/__init__.cp311-win32.pyd +0 -0
  113. constricter/fix/libraries/__init__.py +2 -0
  114. constricter/fix/libraries/library.cp311-win32.pyd +0 -0
  115. constricter/fix/libraries/library.py +420 -0
  116. constricter/fix/libraries/opened.cp311-win32.pyd +0 -0
  117. constricter/fix/libraries/opened.py +147 -0
  118. constricter/fix/libraries/overloads.cp311-win32.pyd +0 -0
  119. constricter/fix/libraries/overloads.py +960 -0
  120. constricter/fix/libraries/receivers.cp311-win32.pyd +0 -0
  121. constricter/fix/libraries/receivers.py +274 -0
  122. constricter/fix/libraries/stdlib.cp311-win32.pyd +0 -0
  123. constricter/fix/libraries/stdlib.py +752 -0
  124. constricter/fix/libraries/walks.cp311-win32.pyd +0 -0
  125. constricter/fix/libraries/walks.py +49 -0
  126. constricter/fix/tables/aliases.json +147 -0
  127. constricter/fix/tables/attributes.json +700 -0
  128. constricter/fix/tables/awaited.json +69 -0
  129. constricter/fix/tables/awaited_overloads.json +14 -0
  130. constricter/fix/tables/bases.json +888 -0
  131. constricter/fix/tables/classes.json +1941 -0
  132. constricter/fix/tables/elements.json +156 -0
  133. constricter/fix/tables/functions.json +58 -0
  134. constricter/fix/tables/generic_attributes.json +254 -0
  135. constricter/fix/tables/method_overloads.json +461 -0
  136. constricter/fix/tables/method_signatures.json +954 -0
  137. constricter/fix/tables/methods.json +954 -0
  138. constricter/fix/tables/overloads.json +540 -0
  139. constricter/fix/tables/platform.json +37 -0
  140. constricter/fix/tables/returns.json +1362 -0
  141. constricter/fix/tables/scalar_members.json +16 -0
  142. constricter/fix/tables/scalars.json +2707 -0
  143. constricter/fix/tables/source.json +28 -0
  144. constricter/fix/tables/subscriptable.json +77 -0
  145. constricter/fix/tables/type_parameters.json +178 -0
  146. constricter/fix/tables/variables.json +2962 -0
  147. constricter/fix/values/__init__.cp311-win32.pyd +0 -0
  148. constricter/fix/values/__init__.py +2 -0
  149. constricter/fix/values/aliased.cp311-win32.pyd +0 -0
  150. constricter/fix/values/aliased.py +195 -0
  151. constricter/fix/values/bodies.cp311-win32.pyd +0 -0
  152. constricter/fix/values/bodies.py +76 -0
  153. constricter/fix/values/callables.cp311-win32.pyd +0 -0
  154. constricter/fix/values/callables.py +323 -0
  155. constricter/fix/values/called.cp311-win32.pyd +0 -0
  156. constricter/fix/values/called.py +194 -0
  157. constricter/fix/values/classvars.cp311-win32.pyd +0 -0
  158. constricter/fix/values/classvars.py +629 -0
  159. constricter/fix/values/decided.cp311-win32.pyd +0 -0
  160. constricter/fix/values/decided.py +429 -0
  161. constricter/fix/values/displays.cp311-win32.pyd +0 -0
  162. constricter/fix/values/displays.py +101 -0
  163. constricter/fix/values/doubts.cp311-win32.pyd +0 -0
  164. constricter/fix/values/doubts.py +677 -0
  165. constricter/fix/values/entered.cp311-win32.pyd +0 -0
  166. constricter/fix/values/entered.py +332 -0
  167. constricter/fix/values/fills.cp311-win32.pyd +0 -0
  168. constricter/fix/values/fills.py +446 -0
  169. constricter/fix/values/guesses.cp311-win32.pyd +0 -0
  170. constricter/fix/values/guesses.py +376 -0
  171. constricter/fix/values/hinted.cp311-win32.pyd +0 -0
  172. constricter/fix/values/hinted.py +811 -0
  173. constricter/fix/values/inference.cp311-win32.pyd +0 -0
  174. constricter/fix/values/inference.py +698 -0
  175. constricter/fix/values/loops.cp311-win32.pyd +0 -0
  176. constricter/fix/values/loops.py +335 -0
  177. constricter/fix/values/members.cp311-win32.pyd +0 -0
  178. constricter/fix/values/members.py +578 -0
  179. constricter/fix/values/narrowed.cp311-win32.pyd +0 -0
  180. constricter/fix/values/narrowed.py +220 -0
  181. constricter/fix/values/operated.cp311-win32.pyd +0 -0
  182. constricter/fix/values/operated.py +202 -0
  183. constricter/fix/values/ordered.cp311-win32.pyd +0 -0
  184. constricter/fix/values/ordered.py +74 -0
  185. constricter/fix/values/returned.cp311-win32.pyd +0 -0
  186. constricter/fix/values/returned.py +479 -0
  187. constricter/fix/values/returns.cp311-win32.pyd +0 -0
  188. constricter/fix/values/returns.py +237 -0
  189. constricter/fix/values/shapes.cp311-win32.pyd +0 -0
  190. constricter/fix/values/shapes.py +654 -0
  191. constricter/fix/values/stored.cp311-win32.pyd +0 -0
  192. constricter/fix/values/stored.py +564 -0
  193. constricter/fix/values/targets.cp311-win32.pyd +0 -0
  194. constricter/fix/values/targets.py +419 -0
  195. constricter/fix/values/unchecked.cp311-win32.pyd +0 -0
  196. constricter/fix/values/unchecked.py +278 -0
  197. constricter/jsonc.py +50 -0
  198. constricter/noqa.py +47 -0
  199. constricter/notebook.py +115 -0
  200. constricter/offences.py +436 -0
  201. constricter/overrides.py +24 -0
  202. constricter/plugins/__init__.py +2 -0
  203. constricter/plugins/flake8.py +133 -0
  204. constricter/plugins/pylint.py +186 -0
  205. constricter/py.typed +0 -0
  206. constricter/recording.py +660 -0
  207. constricter/rules/__init__.cp311-win32.pyd +0 -0
  208. constricter/rules/__init__.py +2 -0
  209. constricter/rules/annotations.cp311-win32.pyd +0 -0
  210. constricter/rules/annotations.py +296 -0
  211. constricter/rules/binding.cp311-win32.pyd +0 -0
  212. constricter/rules/binding.py +652 -0
  213. constricter/rules/calls.cp311-win32.pyd +0 -0
  214. constricter/rules/calls.py +460 -0
  215. constricter/rules/checker.cp311-win32.pyd +0 -0
  216. constricter/rules/checker.py +536 -0
  217. constricter/rules/declarations.cp311-win32.pyd +0 -0
  218. constricter/rules/declarations.py +730 -0
  219. constricter/rules/decorators.cp311-win32.pyd +0 -0
  220. constricter/rules/decorators.py +351 -0
  221. constricter/rules/flow.cp311-win32.pyd +0 -0
  222. constricter/rules/flow.py +502 -0
  223. constricter/rules/keys.cp311-win32.pyd +0 -0
  224. constricter/rules/keys.py +79 -0
  225. constricter/rules/late.cp311-win32.pyd +0 -0
  226. constricter/rules/late.py +969 -0
  227. constricter/rules/narrowing.cp311-win32.pyd +0 -0
  228. constricter/rules/narrowing.py +98 -0
  229. constricter/rules/parsed.cp311-win32.pyd +0 -0
  230. constricter/rules/parsed.py +136 -0
  231. constricter/rules/quoted.cp311-win32.pyd +0 -0
  232. constricter/rules/quoted.py +141 -0
  233. constricter/rules/rebinding.cp311-win32.pyd +0 -0
  234. constricter/rules/rebinding.py +169 -0
  235. constricter/rules/recorded.cp311-win32.pyd +0 -0
  236. constricter/rules/recorded.py +168 -0
  237. constricter/rules/redundant.cp311-win32.pyd +0 -0
  238. constricter/rules/redundant.py +160 -0
  239. constricter/rules/scope.cp311-win32.pyd +0 -0
  240. constricter/rules/scope.py +802 -0
  241. constricter/rules/scoped.cp311-win32.pyd +0 -0
  242. constricter/rules/scoped.py +232 -0
  243. constricter/rules/scoping.cp311-win32.pyd +0 -0
  244. constricter/rules/scoping.py +346 -0
  245. constricter/rules/settings.cp311-win32.pyd +0 -0
  246. constricter/rules/settings.py +189 -0
  247. constricter/rules/syntax.cp311-win32.pyd +0 -0
  248. constricter/rules/syntax.py +472 -0
  249. constricter/rules/tables.cp311-win32.pyd +0 -0
  250. constricter/rules/tables.py +169 -0
  251. constricter/rules/walked.cp311-win32.pyd +0 -0
  252. constricter/rules/walked.py +127 -0
  253. constricter/rules/widened.cp311-win32.pyd +0 -0
  254. constricter/rules/widened.py +322 -0
  255. constricter/trace.py +374 -0
  256. e45ce06b2fdd5c43f782__mypyc.cp311-win32.pyd +0 -0
  257. python_constricter-0.4.1.dist-info/METADATA +400 -0
  258. python_constricter-0.4.1.dist-info/RECORD +261 -0
  259. python_constricter-0.4.1.dist-info/WHEEL +4 -0
  260. python_constricter-0.4.1.dist-info/entry_points.txt +5 -0
  261. python_constricter-0.4.1.dist-info/licenses/LICENSE.md +21 -0
@@ -0,0 +1,221 @@
1
+ # SPDX-License-Identifier: MIT
2
+ """Which of the checked files' classes are plain, settled across them all.
3
+
4
+ See `constricter.fix.values.classvars`, which settles one module's.
5
+
6
+ A module alone can't see past a base another file defines: the index can, through imports and
7
+ re-exports, to what that base inherits from and what it declares.
8
+ """
9
+
10
+ from collections.abc import Mapping, Sequence
11
+ from dataclasses import replace
12
+ from pathlib import Path
13
+ from typing import TYPE_CHECKING, Final
14
+
15
+ from constricter.fix.index.modules import SUFFIX, Index, Module, module_name
16
+ from constricter.fix.index.project import CLASS, definition
17
+ from constricter.fix.values import classvars
18
+
19
+ if TYPE_CHECKING:
20
+ from constricter.fix.core.known import Origin
21
+
22
+ _DOT: Final = "."
23
+ # The bases no class's binding of a name can hide: one a class above another binds is in sight.
24
+ _ROOTS: Final = frozenset({classvars.OBJECT, *classvars.BUILTIN_BASES, *classvars.PASSED_OVER})
25
+
26
+
27
+ def settled(catalog: Index, entries: Sequence[str] = ()) -> Index:
28
+ """Settle which of the checked files' classes are plain, across them all.
29
+
30
+ As `constricter.fix.values.classvars` has it for one module, a base another checked file defines
31
+ followed there: a class under another file's plain class is plain, and a class that isn't
32
+ makes what it inherits from, in any file, not plain either. A base `entries` list
33
+ (`classvars.listed`) is one a plain class may have even where a checked file defines it, plain
34
+ or not: the framework's own files, checked. So is one passed over (`classvars.PASSED_OVER`).
35
+
36
+ Returns:
37
+ The index, each checked module with its plain classes.
38
+
39
+ """
40
+ found: dict[str, tuple[str, ...]] = {
41
+ f"{module.name}.{name}": tuple(resolved(catalog.modules, module, base) for base in bases)
42
+ for module in catalog.modules.values()
43
+ for name, bases in module.bases.items()
44
+ }
45
+ if not found:
46
+ return catalog
47
+ unlisted: dict[str, tuple[str, ...]] = {
48
+ name: tuple(
49
+ base
50
+ for base in bases
51
+ if base not in classvars.PASSED_OVER and not classvars.listed(base, entries)
52
+ )
53
+ for name, bases in found.items()
54
+ }
55
+ plain: frozenset[str] = classvars.settled(unlisted, classvars.allowed)
56
+ declared: dict[str, Mapping[str, str]] = {
57
+ f"{module.name}.{name}": module.classes.get(name, {})
58
+ for module in catalog.modules.values()
59
+ for name in module.bases
60
+ }
61
+ return _named(
62
+ catalog._replace(
63
+ modules={
64
+ name: replace(
65
+ module,
66
+ plain=frozenset(
67
+ each
68
+ for each in module.bases
69
+ if f"{name}.{each}" in plain and _unheld(f"{name}.{each}", module, found, declared)
70
+ ),
71
+ )
72
+ for name, module in catalog.modules.items()
73
+ },
74
+ ),
75
+ found,
76
+ )
77
+
78
+
79
+ def _named(catalog: Index, found: Mapping[str, tuple[str, ...]]) -> Index:
80
+ """Type a plain class's variables bound to a checked file's class by name (see `classvars.named`).
81
+
82
+ `type[Name]`, where no class above or under it in the checked files binds the variable: a type
83
+ checker holds an override to its base's type once both are declared. Only where every class
84
+ above it is a checked file's, or a builtin or `object`: a framework's base, or one only a star
85
+ import re-exports, may bind it out of sight. `found`: each checked class's bases, resolved.
86
+
87
+ Returns:
88
+ The index, each such module with them among its `members`.
89
+
90
+ """
91
+ binds: dict[str, frozenset[str]] = {
92
+ f"{module.name}.{name}": names
93
+ for module in catalog.modules.values()
94
+ for name, names in module.bound.items()
95
+ }
96
+ under: dict[str, set[str]] | None = None
97
+ modules: dict[str, Module] = dict(catalog.modules)
98
+ module: Module
99
+ for module in catalog.modules.values():
100
+ added: dict[str, dict[str, str]] = {}
101
+ owner: str
102
+ bound: Mapping[str, str]
103
+ for owner, bound in module.named.items():
104
+ key: str = f"{module.name}.{owner}"
105
+ variable: str
106
+ value: str
107
+ for variable, value in bound.items() if owner in module.plain else ():
108
+ if resolved(catalog.modules, module, value) not in found or not _closed(key, found):
109
+ continue
110
+ under = _under(found) if under is None else under
111
+ if not any(
112
+ variable in binds.get(other, ())
113
+ for other in (*classvars.ancestors(key, found), *under[key])
114
+ ):
115
+ added.setdefault(owner, {})[variable] = f"type[{value}]"
116
+ if added:
117
+ typed: dict[str, Mapping[str, str]] = dict(module.members)
118
+ typed.update({owner: {**typed.get(owner, {}), **each} for owner, each in added.items()})
119
+ modules[module.name] = replace(module, members=typed)
120
+ return catalog._replace(modules=modules) if under is not None else catalog
121
+
122
+
123
+ def _closed(key: str, found: Mapping[str, tuple[str, ...]]) -> bool:
124
+ """Check that every class above `key` is in sight: a checked file's, or a builtin or `object`.
125
+
126
+ Returns:
127
+ Whether it is.
128
+
129
+ """
130
+ return all(
131
+ base in found or base in _ROOTS
132
+ for owner in (key, *classvars.ancestors(key, found))
133
+ for base in found[owner]
134
+ )
135
+
136
+
137
+ def _under(found: Mapping[str, tuple[str, ...]]) -> dict[str, set[str]]:
138
+ """Name every checked class under each one, however far.
139
+
140
+ Returns:
141
+ Them, by the class above.
142
+
143
+ """
144
+ under: dict[str, set[str]] = {name: set() for name in found}
145
+ name: str
146
+ for name in found:
147
+ above: str
148
+ for above in classvars.ancestors(name, found):
149
+ under[above].add(name)
150
+ return under
151
+
152
+
153
+ def _unheld(
154
+ key: str,
155
+ module: Module,
156
+ found: Mapping[str, tuple[str, ...]],
157
+ declared: Mapping[str, Mapping[str, str]],
158
+ ) -> bool:
159
+ """Check that a class's variables are its own to type, whatever other files' classes it inherits from.
160
+
161
+ None hides what a builtin above it has itself, nor what a class above it annotates as another
162
+ type (see `constricter.fix.values.classvars`), which the class's own module can't see past its file.
163
+
164
+ Returns:
165
+ Whether they are.
166
+
167
+ """
168
+ typed: Mapping[str, str] = module.members.get(key.rpartition(_DOT)[2], {})
169
+ above: list[Mapping[str, str]] = [declared[each] for each in classvars.ancestors(key, found)]
170
+ return not typed.keys() & classvars.reserved(key, found) and classvars.agreeing(typed, above) == typed
171
+
172
+
173
+ def resolved(modules: Mapping[str, Module], module: Module, base: str) -> str:
174
+ """Resolve a class's base, as `module` writes it, to where it's defined (`pkg.models.Row`).
175
+
176
+ Returns:
177
+ The defining module and the class, dotted, through imports and re-exports; as far as it's
178
+ known, for one no indexed module defines (`unittest.TestCase`).
179
+
180
+ """
181
+ first: str
182
+ rest: str
183
+ first, _, rest = base.partition(_DOT)
184
+ if not rest and first in module.bases:
185
+ return f"{module.name}.{first}"
186
+ origin: Origin | None
187
+ if (origin := module.names.get(first)) is None:
188
+ return base
189
+ path: list[str] = [*([origin[0]] if origin[0] else []), *([origin[1]] if origin[1] else [])]
190
+ path += rest.split(_DOT) if rest else []
191
+ where: Origin = (_DOT.join(path[:-1]), path[-1])
192
+ defined: tuple[Module, str] | None = definition(modules, where, CLASS)
193
+ return _DOT.join(path) if defined is None else f"{defined[0].name}.{defined[1]}"
194
+
195
+
196
+ def members(catalog: Index, path: Path) -> dict[str, Mapping[str, str]]:
197
+ """Find what the index types the variables of the plain classes of the file at `path` as.
198
+
199
+ What the file alone types them as, and those bound to a checked file's class by name (`_named`).
200
+
201
+ Returns:
202
+ Each class's, by its name; none for a file `catalog` doesn't have.
203
+
204
+ """
205
+ target: Module | None = catalog.modules.get(module_name(path)) if path.suffix == SUFFIX else None
206
+ return (
207
+ {}
208
+ if target is None
209
+ else {name: target.members[name] for name in target.plain if name in target.members}
210
+ )
211
+
212
+
213
+ def classes(catalog: Index, path: Path) -> frozenset[str] | None:
214
+ """Find which classes of the file at `path` the index settled as plain (see `settled`).
215
+
216
+ Returns:
217
+ Their names; `None` for a file `catalog` doesn't have, whose own classes say.
218
+
219
+ """
220
+ target: Module | None = catalog.modules.get(module_name(path)) if path.suffix == SUFFIX else None
221
+ return None if target is None else target.plain