python-constricter 0.4.1__cp312-cp312-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.
- constricter/__init__.py +55 -0
- constricter/__main__.py +26 -0
- constricter/_version.py +4 -0
- constricter/cli/__init__.py +2 -0
- constricter/cli/baseline.py +107 -0
- constricter/cli/collecting.py +54 -0
- constricter/cli/command.py +547 -0
- constricter/cli/config.py +322 -0
- constricter/cli/explain.py +104 -0
- constricter/cli/lsp/__init__.py +2 -0
- constricter/cli/lsp/connection.py +475 -0
- constricter/cli/lsp/edits.py +188 -0
- constricter/cli/lsp/guard.py +133 -0
- constricter/cli/lsp/hints.py +391 -0
- constricter/cli/lsp/protocol.py +192 -0
- constricter/cli/lsp/remembered.py +81 -0
- constricter/cli/lsp/stored.py +200 -0
- constricter/cli/options.py +799 -0
- constricter/cli/paths.py +151 -0
- constricter/cli/reading.py +36 -0
- constricter/cli/report.py +397 -0
- constricter/cli/rounds.py +328 -0
- constricter/cli/runs.py +90 -0
- constricter/cli/schedule.py +463 -0
- constricter/cli/traced.py +401 -0
- constricter/cli/workers.py +286 -0
- constricter/empty.py +66 -0
- constricter/fix/__init__.cp312-win32.pyd +0 -0
- constricter/fix/__init__.py +2 -0
- constricter/fix/core/__init__.cp312-win32.pyd +0 -0
- constricter/fix/core/__init__.py +2 -0
- constricter/fix/core/asked.cp312-win32.pyd +0 -0
- constricter/fix/core/asked.py +56 -0
- constricter/fix/core/fixes.cp312-win32.pyd +0 -0
- constricter/fix/core/fixes.py +317 -0
- constricter/fix/core/imports.cp312-win32.pyd +0 -0
- constricter/fix/core/imports.py +580 -0
- constricter/fix/core/inherited.cp312-win32.pyd +0 -0
- constricter/fix/core/inherited.py +311 -0
- constricter/fix/core/known.cp312-win32.pyd +0 -0
- constricter/fix/core/known.py +730 -0
- constricter/fix/core/signatures.cp312-win32.pyd +0 -0
- constricter/fix/core/signatures.py +132 -0
- constricter/fix/index/__init__.cp312-win32.pyd +0 -0
- constricter/fix/index/__init__.py +2 -0
- constricter/fix/index/awaits.cp312-win32.pyd +0 -0
- constricter/fix/index/awaits.py +90 -0
- constricter/fix/index/beyond.cp312-win32.pyd +0 -0
- constricter/fix/index/beyond.py +149 -0
- constricter/fix/index/callers.cp312-win32.pyd +0 -0
- constricter/fix/index/callers.py +155 -0
- constricter/fix/index/crossed.cp312-win32.pyd +0 -0
- constricter/fix/index/crossed.py +327 -0
- constricter/fix/index/decorated.cp312-win32.pyd +0 -0
- constricter/fix/index/decorated.py +140 -0
- constricter/fix/index/fixtures.cp312-win32.pyd +0 -0
- constricter/fix/index/fixtures.py +176 -0
- constricter/fix/index/linked.cp312-win32.pyd +0 -0
- constricter/fix/index/linked.py +142 -0
- constricter/fix/index/loose.cp312-win32.pyd +0 -0
- constricter/fix/index/loose.py +103 -0
- constricter/fix/index/managed.cp312-win32.pyd +0 -0
- constricter/fix/index/managed.py +63 -0
- constricter/fix/index/modules.cp312-win32.pyd +0 -0
- constricter/fix/index/modules.py +741 -0
- constricter/fix/index/offers.cp312-win32.pyd +0 -0
- constricter/fix/index/offers.py +252 -0
- constricter/fix/index/order.cp312-win32.pyd +0 -0
- constricter/fix/index/order.py +155 -0
- constricter/fix/index/origins.cp312-win32.pyd +0 -0
- constricter/fix/index/origins.py +238 -0
- constricter/fix/index/own_methods.cp312-win32.pyd +0 -0
- constricter/fix/index/own_methods.py +91 -0
- constricter/fix/index/own_overloads.cp312-win32.pyd +0 -0
- constricter/fix/index/own_overloads.py +70 -0
- constricter/fix/index/own_types.cp312-win32.pyd +0 -0
- constricter/fix/index/own_types.py +330 -0
- constricter/fix/index/params.cp312-win32.pyd +0 -0
- constricter/fix/index/params.py +81 -0
- constricter/fix/index/plain.cp312-win32.pyd +0 -0
- constricter/fix/index/plain.py +221 -0
- constricter/fix/index/project.cp312-win32.pyd +0 -0
- constricter/fix/index/project.py +797 -0
- constricter/fix/index/sides.cp312-win32.pyd +0 -0
- constricter/fix/index/sides.py +160 -0
- constricter/fix/index/strings.cp312-win32.pyd +0 -0
- constricter/fix/index/strings.py +46 -0
- constricter/fix/index/stubs/__init__.cp312-win32.pyd +0 -0
- constricter/fix/index/stubs/__init__.py +2 -0
- constricter/fix/index/stubs/atoms.cp312-win32.pyd +0 -0
- constricter/fix/index/stubs/atoms.py +425 -0
- constricter/fix/index/stubs/chained.cp312-win32.pyd +0 -0
- constricter/fix/index/stubs/chained.py +69 -0
- constricter/fix/index/stubs/classnames.cp312-win32.pyd +0 -0
- constricter/fix/index/stubs/classnames.py +124 -0
- constricter/fix/index/stubs/declared.cp312-win32.pyd +0 -0
- constricter/fix/index/stubs/declared.py +508 -0
- constricter/fix/index/stubs/installed.cp312-win32.pyd +0 -0
- constricter/fix/index/stubs/installed.py +425 -0
- constricter/fix/index/stubs/names.cp312-win32.pyd +0 -0
- constricter/fix/index/stubs/names.py +200 -0
- constricter/fix/index/stubs/read.cp312-win32.pyd +0 -0
- constricter/fix/index/stubs/read.py +70 -0
- constricter/fix/index/stubs/signatures.cp312-win32.pyd +0 -0
- constricter/fix/index/stubs/signatures.py +656 -0
- constricter/fix/index/stubs/stubbed.cp312-win32.pyd +0 -0
- constricter/fix/index/stubs/stubbed.py +208 -0
- constricter/fix/index/taken.cp312-win32.pyd +0 -0
- constricter/fix/index/taken.py +45 -0
- constricter/fix/index/tuples.cp312-win32.pyd +0 -0
- constricter/fix/index/tuples.py +112 -0
- constricter/fix/libraries/__init__.cp312-win32.pyd +0 -0
- constricter/fix/libraries/__init__.py +2 -0
- constricter/fix/libraries/library.cp312-win32.pyd +0 -0
- constricter/fix/libraries/library.py +420 -0
- constricter/fix/libraries/opened.cp312-win32.pyd +0 -0
- constricter/fix/libraries/opened.py +147 -0
- constricter/fix/libraries/overloads.cp312-win32.pyd +0 -0
- constricter/fix/libraries/overloads.py +960 -0
- constricter/fix/libraries/receivers.cp312-win32.pyd +0 -0
- constricter/fix/libraries/receivers.py +274 -0
- constricter/fix/libraries/stdlib.cp312-win32.pyd +0 -0
- constricter/fix/libraries/stdlib.py +752 -0
- constricter/fix/libraries/walks.cp312-win32.pyd +0 -0
- constricter/fix/libraries/walks.py +49 -0
- constricter/fix/tables/aliases.json +147 -0
- constricter/fix/tables/attributes.json +700 -0
- constricter/fix/tables/awaited.json +69 -0
- constricter/fix/tables/awaited_overloads.json +14 -0
- constricter/fix/tables/bases.json +888 -0
- constricter/fix/tables/classes.json +1941 -0
- constricter/fix/tables/elements.json +156 -0
- constricter/fix/tables/functions.json +58 -0
- constricter/fix/tables/generic_attributes.json +254 -0
- constricter/fix/tables/method_overloads.json +461 -0
- constricter/fix/tables/method_signatures.json +954 -0
- constricter/fix/tables/methods.json +954 -0
- constricter/fix/tables/overloads.json +540 -0
- constricter/fix/tables/platform.json +37 -0
- constricter/fix/tables/returns.json +1362 -0
- constricter/fix/tables/scalar_members.json +16 -0
- constricter/fix/tables/scalars.json +2707 -0
- constricter/fix/tables/source.json +28 -0
- constricter/fix/tables/subscriptable.json +77 -0
- constricter/fix/tables/type_parameters.json +178 -0
- constricter/fix/tables/variables.json +2962 -0
- constricter/fix/values/__init__.cp312-win32.pyd +0 -0
- constricter/fix/values/__init__.py +2 -0
- constricter/fix/values/aliased.cp312-win32.pyd +0 -0
- constricter/fix/values/aliased.py +195 -0
- constricter/fix/values/bodies.cp312-win32.pyd +0 -0
- constricter/fix/values/bodies.py +76 -0
- constricter/fix/values/callables.cp312-win32.pyd +0 -0
- constricter/fix/values/callables.py +323 -0
- constricter/fix/values/called.cp312-win32.pyd +0 -0
- constricter/fix/values/called.py +194 -0
- constricter/fix/values/classvars.cp312-win32.pyd +0 -0
- constricter/fix/values/classvars.py +629 -0
- constricter/fix/values/decided.cp312-win32.pyd +0 -0
- constricter/fix/values/decided.py +429 -0
- constricter/fix/values/displays.cp312-win32.pyd +0 -0
- constricter/fix/values/displays.py +101 -0
- constricter/fix/values/doubts.cp312-win32.pyd +0 -0
- constricter/fix/values/doubts.py +677 -0
- constricter/fix/values/entered.cp312-win32.pyd +0 -0
- constricter/fix/values/entered.py +332 -0
- constricter/fix/values/fills.cp312-win32.pyd +0 -0
- constricter/fix/values/fills.py +446 -0
- constricter/fix/values/guesses.cp312-win32.pyd +0 -0
- constricter/fix/values/guesses.py +376 -0
- constricter/fix/values/hinted.cp312-win32.pyd +0 -0
- constricter/fix/values/hinted.py +811 -0
- constricter/fix/values/inference.cp312-win32.pyd +0 -0
- constricter/fix/values/inference.py +698 -0
- constricter/fix/values/loops.cp312-win32.pyd +0 -0
- constricter/fix/values/loops.py +335 -0
- constricter/fix/values/members.cp312-win32.pyd +0 -0
- constricter/fix/values/members.py +578 -0
- constricter/fix/values/narrowed.cp312-win32.pyd +0 -0
- constricter/fix/values/narrowed.py +220 -0
- constricter/fix/values/operated.cp312-win32.pyd +0 -0
- constricter/fix/values/operated.py +202 -0
- constricter/fix/values/ordered.cp312-win32.pyd +0 -0
- constricter/fix/values/ordered.py +74 -0
- constricter/fix/values/returned.cp312-win32.pyd +0 -0
- constricter/fix/values/returned.py +479 -0
- constricter/fix/values/returns.cp312-win32.pyd +0 -0
- constricter/fix/values/returns.py +237 -0
- constricter/fix/values/shapes.cp312-win32.pyd +0 -0
- constricter/fix/values/shapes.py +654 -0
- constricter/fix/values/stored.cp312-win32.pyd +0 -0
- constricter/fix/values/stored.py +564 -0
- constricter/fix/values/targets.cp312-win32.pyd +0 -0
- constricter/fix/values/targets.py +419 -0
- constricter/fix/values/unchecked.cp312-win32.pyd +0 -0
- constricter/fix/values/unchecked.py +278 -0
- constricter/jsonc.py +50 -0
- constricter/noqa.py +47 -0
- constricter/notebook.py +115 -0
- constricter/offences.py +436 -0
- constricter/overrides.py +24 -0
- constricter/plugins/__init__.py +2 -0
- constricter/plugins/flake8.py +133 -0
- constricter/plugins/pylint.py +186 -0
- constricter/py.typed +0 -0
- constricter/recording.py +660 -0
- constricter/rules/__init__.cp312-win32.pyd +0 -0
- constricter/rules/__init__.py +2 -0
- constricter/rules/annotations.cp312-win32.pyd +0 -0
- constricter/rules/annotations.py +296 -0
- constricter/rules/binding.cp312-win32.pyd +0 -0
- constricter/rules/binding.py +652 -0
- constricter/rules/calls.cp312-win32.pyd +0 -0
- constricter/rules/calls.py +460 -0
- constricter/rules/checker.cp312-win32.pyd +0 -0
- constricter/rules/checker.py +536 -0
- constricter/rules/declarations.cp312-win32.pyd +0 -0
- constricter/rules/declarations.py +730 -0
- constricter/rules/decorators.cp312-win32.pyd +0 -0
- constricter/rules/decorators.py +351 -0
- constricter/rules/flow.cp312-win32.pyd +0 -0
- constricter/rules/flow.py +502 -0
- constricter/rules/keys.cp312-win32.pyd +0 -0
- constricter/rules/keys.py +79 -0
- constricter/rules/late.cp312-win32.pyd +0 -0
- constricter/rules/late.py +969 -0
- constricter/rules/narrowing.cp312-win32.pyd +0 -0
- constricter/rules/narrowing.py +98 -0
- constricter/rules/parsed.cp312-win32.pyd +0 -0
- constricter/rules/parsed.py +136 -0
- constricter/rules/quoted.cp312-win32.pyd +0 -0
- constricter/rules/quoted.py +141 -0
- constricter/rules/rebinding.cp312-win32.pyd +0 -0
- constricter/rules/rebinding.py +169 -0
- constricter/rules/recorded.cp312-win32.pyd +0 -0
- constricter/rules/recorded.py +168 -0
- constricter/rules/redundant.cp312-win32.pyd +0 -0
- constricter/rules/redundant.py +160 -0
- constricter/rules/scope.cp312-win32.pyd +0 -0
- constricter/rules/scope.py +802 -0
- constricter/rules/scoped.cp312-win32.pyd +0 -0
- constricter/rules/scoped.py +232 -0
- constricter/rules/scoping.cp312-win32.pyd +0 -0
- constricter/rules/scoping.py +346 -0
- constricter/rules/settings.cp312-win32.pyd +0 -0
- constricter/rules/settings.py +189 -0
- constricter/rules/syntax.cp312-win32.pyd +0 -0
- constricter/rules/syntax.py +472 -0
- constricter/rules/tables.cp312-win32.pyd +0 -0
- constricter/rules/tables.py +169 -0
- constricter/rules/walked.cp312-win32.pyd +0 -0
- constricter/rules/walked.py +127 -0
- constricter/rules/widened.cp312-win32.pyd +0 -0
- constricter/rules/widened.py +322 -0
- constricter/trace.py +374 -0
- e45ce06b2fdd5c43f782__mypyc.cp312-win32.pyd +0 -0
- python_constricter-0.4.1.dist-info/METADATA +400 -0
- python_constricter-0.4.1.dist-info/RECORD +261 -0
- python_constricter-0.4.1.dist-info/WHEEL +4 -0
- python_constricter-0.4.1.dist-info/entry_points.txt +5 -0
- python_constricter-0.4.1.dist-info/licenses/LICENSE.md +21 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
"""An attribute of what an installed class's method returns, read off the call: `capsys.readouterr().out`.
|
|
3
|
+
|
|
4
|
+
The returned class may be one no file can name (pytest's `CaptureResult`, private to `_pytest`), so
|
|
5
|
+
the call alone has no type to write; its attribute's is the method's own return, as far as the
|
|
6
|
+
receiver's type arguments bind it: a signature of the method's, returning the attribute's type.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import ast
|
|
10
|
+
import re
|
|
11
|
+
from typing import TYPE_CHECKING, Final
|
|
12
|
+
|
|
13
|
+
from constricter.fix.index.stubs.atoms import parse_text
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from collections.abc import Mapping
|
|
17
|
+
|
|
18
|
+
from constricter.fix.index.modules import Module
|
|
19
|
+
from constricter.fix.index.stubs.declared import Class, Signature
|
|
20
|
+
|
|
21
|
+
_WORD: Final = re.compile(r"\b\w+\b")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def key(method: str, attribute: str) -> str:
|
|
25
|
+
"""Name the entry of an attribute of a method's return, beside the method's own.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
It.
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
return f"{method}().{attribute}"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def attributes(
|
|
35
|
+
module: "Module",
|
|
36
|
+
klass: "Class",
|
|
37
|
+
method: str,
|
|
38
|
+
wanted: frozenset[str],
|
|
39
|
+
) -> dict[str, tuple["Signature", ...]]:
|
|
40
|
+
"""Read the attributes (of `wanted`) of what `klass`'s own `method` returns, as signatures of its.
|
|
41
|
+
|
|
42
|
+
For a method of one signature returning an instance of a class its own module declares, that
|
|
43
|
+
class's type parameters bound as the return writes them (`CaptureResult[AnyStr]`'s `out`: an
|
|
44
|
+
`AnyStr`, the receiver's).
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Each attribute's, by name: the method's signature, returning the attribute's type.
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
written: tuple[Signature, ...] | None = klass.methods.get(method)
|
|
51
|
+
if written is None or len(written) != 1 or written[0].returns is None or module.declared is None:
|
|
52
|
+
return {}
|
|
53
|
+
returned: ast.expr = parse_text(written[0].returns)
|
|
54
|
+
base: ast.expr = returned.value if isinstance(returned, ast.Subscript) else returned
|
|
55
|
+
# By its name there: one defined under an `if` isn't among the module's names.
|
|
56
|
+
result: Class | None = module.declared.classes.get(base.id) if isinstance(base, ast.Name) else None
|
|
57
|
+
given: list[ast.expr] = []
|
|
58
|
+
if isinstance(returned, ast.Subscript):
|
|
59
|
+
given = list(returned.slice.elts) if isinstance(returned.slice, ast.Tuple) else [returned.slice]
|
|
60
|
+
if result is None or len(given) != len(result.params):
|
|
61
|
+
return {}
|
|
62
|
+
bound: Mapping[str, str] = {
|
|
63
|
+
name: ast.unparse(arg) for (name, _), arg in zip(result.params, given, strict=True)
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
name: (written[0]._replace(returns=_WORD.sub(lambda word: bound.get(word[0], word[0]), text)),)
|
|
67
|
+
for name, text in result.attributes.items()
|
|
68
|
+
if name in wanted
|
|
69
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
"""The installed classes and aliases a module names, and the methods a class's lineage declares.
|
|
3
|
+
|
|
4
|
+
For `constricter.fix.index.stubs.stubbed`, which reads their methods' signatures.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from collections.abc import Iterator, Mapping, Sequence
|
|
8
|
+
from typing import TYPE_CHECKING, TypeAlias
|
|
9
|
+
|
|
10
|
+
from constricter.fix.core.known import Origin
|
|
11
|
+
from constricter.fix.index import project
|
|
12
|
+
from constricter.fix.index.modules import Module
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from constricter.fix.index.stubs.declared import Class, Declarations
|
|
16
|
+
|
|
17
|
+
# A package's classes (or aliases): each as written after the package's name, and where it's defined.
|
|
18
|
+
Packaged: TypeAlias = tuple[tuple[str, Origin], ...]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def method_names(modules: Mapping[str, Module], lineage: Sequence[str]) -> frozenset[str]:
|
|
22
|
+
"""Name the methods a class or any of its installed ancestors (its lineage) declares.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Them.
|
|
26
|
+
|
|
27
|
+
"""
|
|
28
|
+
found: set[str] = set()
|
|
29
|
+
path: str
|
|
30
|
+
for path in lineage:
|
|
31
|
+
module: str
|
|
32
|
+
name: str
|
|
33
|
+
module, _, name = path.rpartition(".")
|
|
34
|
+
declared: Declarations | None = None if module not in modules else modules[module].declared
|
|
35
|
+
klass: Class | None = None if declared is None else declared.classes.get(name)
|
|
36
|
+
found.update(() if klass is None else klass.methods)
|
|
37
|
+
return frozenset(found)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def classes(
|
|
41
|
+
modules: Mapping[str, Module],
|
|
42
|
+
names: Mapping[str, Origin],
|
|
43
|
+
packaged: dict[tuple[str, bool], "Packaged"],
|
|
44
|
+
*,
|
|
45
|
+
aliases: bool = False,
|
|
46
|
+
) -> Iterator[tuple[str, Origin]]:
|
|
47
|
+
"""Find the installed classes `names` (a module's) name: imported (`ndarray`), or through a package.
|
|
48
|
+
|
|
49
|
+
Through a package, what any of its modules defines or re-exports (`numpy.ndarray`), the package
|
|
50
|
+
imported from another module too (`from pandas._typing import npt`). With
|
|
51
|
+
`aliases`, the installed aliases it names instead (`npt.NDArray`). `packaged`: each package's, as
|
|
52
|
+
read so far.
|
|
53
|
+
|
|
54
|
+
Yields:
|
|
55
|
+
Each as the module writes it, and where it's defined.
|
|
56
|
+
|
|
57
|
+
"""
|
|
58
|
+
local: str
|
|
59
|
+
origin: Origin
|
|
60
|
+
for local, origin in names.items():
|
|
61
|
+
where: Origin = project.canonical_origin(modules, origin)
|
|
62
|
+
if where[1] is not None:
|
|
63
|
+
if declares(modules, where, aliases=aliases):
|
|
64
|
+
yield local, where
|
|
65
|
+
continue
|
|
66
|
+
if (where[0], aliases) not in packaged:
|
|
67
|
+
packaged[where[0], aliases] = tuple(_package_classes(modules, where[0], aliases=aliases))
|
|
68
|
+
suffix: str
|
|
69
|
+
found: Origin
|
|
70
|
+
for suffix, found in packaged[where[0], aliases]:
|
|
71
|
+
yield f"{local}{suffix}", found
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _package_classes(
|
|
75
|
+
modules: Mapping[str, Module],
|
|
76
|
+
package: str,
|
|
77
|
+
*,
|
|
78
|
+
aliases: bool,
|
|
79
|
+
) -> Iterator[tuple[str, Origin]]:
|
|
80
|
+
"""Find the installed classes (or aliases) a package's modules define or re-export.
|
|
81
|
+
|
|
82
|
+
Yields:
|
|
83
|
+
Each as written after the package's name (`.ndarray`, `.linalg.LinAlgError`), and where it's defined.
|
|
84
|
+
|
|
85
|
+
"""
|
|
86
|
+
name: str
|
|
87
|
+
other: Module
|
|
88
|
+
for name, other in modules.items():
|
|
89
|
+
if other.installed and (name == package or name.startswith(f"{package}.")):
|
|
90
|
+
bound: str
|
|
91
|
+
found: Origin
|
|
92
|
+
for bound, found in other.names.items():
|
|
93
|
+
where: Origin = project.canonical_origin(modules, found)
|
|
94
|
+
if declares(modules, where, aliases=aliases):
|
|
95
|
+
yield f"{name.removeprefix(package)}.{bound}", where
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def declares(modules: Mapping[str, Module], origin: Origin, *, aliases: bool = False) -> bool:
|
|
99
|
+
"""Check whether an installed module declares a class (or an alias) under `origin`'s name.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Whether it does.
|
|
103
|
+
|
|
104
|
+
"""
|
|
105
|
+
module: Module | None = modules.get(origin[0])
|
|
106
|
+
declared: Declarations | None = None if module is None or not module.installed else module.declared
|
|
107
|
+
return declared is not None and origin[1] in (declared.aliases if aliases else declared.classes)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def as_module(modules: Mapping[str, Module], origin: Origin | None) -> Origin | None:
|
|
111
|
+
"""Take a name imported from a package that is its submodule (`from pkg import util`) as that module.
|
|
112
|
+
|
|
113
|
+
Unless the package itself binds the name another way.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
The module (`(name, None)`), or `origin` as it is.
|
|
117
|
+
|
|
118
|
+
"""
|
|
119
|
+
if origin is None or origin[1] is None:
|
|
120
|
+
return origin
|
|
121
|
+
submodule: str = f"{origin[0]}.{origin[1]}"
|
|
122
|
+
package: Module | None = modules.get(origin[0])
|
|
123
|
+
bound: bool = package is not None and package.names.get(origin[1], (submodule, None)) != (submodule, None)
|
|
124
|
+
return (submodule, None) if submodule in modules and not bound else origin
|
|
Binary file
|