livery-extensions-python 0.0.0__py3-none-any.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.
- livery/extensions/python/__init__.py +51 -0
- livery/extensions/python/_answers.py +127 -0
- livery/extensions/python/_backend.py +1532 -0
- livery/extensions/python/_declared.py +252 -0
- livery/extensions/python/_docs/index.md +165 -0
- livery/extensions/python/_docs/nav.toml +14 -0
- livery/extensions/python/_installed.py +219 -0
- livery/extensions/python/_parse.py +324 -0
- livery/extensions/python/_reaches.py +165 -0
- livery/extensions/python/_steps.py +71 -0
- livery/extensions/python/_terminal.py +118 -0
- livery/extensions/python/_verify.py +112 -0
- livery/extensions/python/content/templates/python-library/LICENSE.jinja +21 -0
- livery/extensions/python/content/templates/python-library/README.md.jinja +7 -0
- livery/extensions/python/content/templates/python-library/pyproject.toml.jinja +43 -0
- livery/extensions/python/content/templates/python-library/src/{{ source_path }}/__init__.py.jinja +15 -0
- livery/extensions/python/content/templates/python-library/src/{{ source_path }}/__main__.py.jinja +30 -0
- livery/extensions/python/content/templates/python-library/src/{{ source_path }}/py.typed +0 -0
- livery/extensions/python/content/templates/python-library/tests/test_{{ project_slug }}_cli.py.jinja +39 -0
- livery/extensions/python/content/templates/python-library/tests/test_{{ project_slug }}_package.py.jinja +22 -0
- livery/extensions/python/content/templates/python-library/workshop.toml.jinja +10 -0
- livery/extensions/python/extension.toml +165 -0
- livery/extensions/python/py.typed +0 -0
- livery_extensions_python-0.0.0.dist-info/METADATA +31 -0
- livery_extensions_python-0.0.0.dist-info/RECORD +28 -0
- livery_extensions_python-0.0.0.dist-info/WHEEL +4 -0
- livery_extensions_python-0.0.0.dist-info/entry_points.txt +3 -0
- livery_extensions_python-0.0.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""The python extension's names another extension reads to build and test a wheel.
|
|
2
|
+
|
|
3
|
+
The python extension builds, versions, publishes and tests a package
|
|
4
|
+
whose set holds python. An extension that builds such a package's
|
|
5
|
+
wheels with a tool of its own, as nanobind builds them with
|
|
6
|
+
cibuildwheel, reads two of its functions.
|
|
7
|
+
[livery.extensions.python.module_docs][] copies the package's ``docs/``
|
|
8
|
+
into its source tree as the wheel's embedded ``_docs`` for one build,
|
|
9
|
+
and removes the copy after it. [livery.extensions.python.run_isolated_test][]
|
|
10
|
+
installs a built wheel into a fresh venv and runs the package's tests
|
|
11
|
+
against the installed copy.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
# The literal-False spelling the checkers honour without importing
|
|
17
|
+
# `typing`: the names below are what a checker sees, and at runtime
|
|
18
|
+
# `__getattr__` serves each from its module when it is read, so importing
|
|
19
|
+
# this module loads none of the extension's modules.
|
|
20
|
+
TYPE_CHECKING = False
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from livery.extensions.python._backend import module_docs as module_docs
|
|
23
|
+
from livery.extensions.python._backend import (
|
|
24
|
+
run_isolated_test as run_isolated_test,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
__version__ = "0.0.0"
|
|
28
|
+
|
|
29
|
+
__all__ = ["__version__", "module_docs", "run_isolated_test"]
|
|
30
|
+
|
|
31
|
+
# The module each lazily served name lives in.
|
|
32
|
+
_EXPORTS: dict[str, str] = {
|
|
33
|
+
"module_docs": "livery.extensions.python._backend",
|
|
34
|
+
"run_isolated_test": "livery.extensions.python._backend",
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def __getattr__(name: str) -> object:
|
|
39
|
+
"""Serve a public name from its module, each time it is read.
|
|
40
|
+
|
|
41
|
+
The value is never kept here, so a test that patches the name in
|
|
42
|
+
its module is read through.
|
|
43
|
+
"""
|
|
44
|
+
import importlib
|
|
45
|
+
|
|
46
|
+
module = _EXPORTS.get(name)
|
|
47
|
+
if module is None:
|
|
48
|
+
raise AttributeError(
|
|
49
|
+
f"module 'livery.extensions.python' has no attribute {name!r}"
|
|
50
|
+
)
|
|
51
|
+
return getattr(importlib.import_module(module), name)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""The python extension's answers: about a package, and about the workspace.
|
|
2
|
+
|
|
3
|
+
About a package, from its manifest and sources: its version, the files
|
|
4
|
+
a version is written into, its requirements, the names its code is
|
|
5
|
+
referenced by, its public modules and what each source references.
|
|
6
|
+
About the workspace, while pytest is listed: the functions that run
|
|
7
|
+
the python packages' suites and a package's documentation examples.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
13
|
+
|
|
14
|
+
from livery.extensions.python import _backend
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from collections.abc import Callable, Mapping
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
from livery.forge import Registry
|
|
21
|
+
from livery.workshop import Package, RequirementWriter, SourceReferences
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def current_version(package: Package) -> str:
|
|
25
|
+
"""The version the package's ``pyproject.toml`` declares."""
|
|
26
|
+
return _backend.current_version(package)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def version_files(package: Package) -> tuple[Path, ...]:
|
|
30
|
+
"""``pyproject.toml``, and every ``__init__.py`` that may carry ``__version__``."""
|
|
31
|
+
return tuple(_backend.stamp_version(package).homes())
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def requirements(package: Package) -> Mapping[str, str]:
|
|
35
|
+
"""The package's ``[project.dependencies]``, each name to its constraint."""
|
|
36
|
+
return _backend.declared_requirements(package)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def requirement_writers(package: Package) -> tuple[RequirementWriter, ...]:
|
|
40
|
+
"""The pyproject's writer of a requirement on a sibling that holds python."""
|
|
41
|
+
del package
|
|
42
|
+
return (_backend.declare_requirement,)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_requirements(package: Package) -> Mapping[str, str]:
|
|
46
|
+
"""The package's ``test`` extra, each name to its constraint."""
|
|
47
|
+
return _backend.declared_test_requirements(package)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_requirement_writers(package: Package) -> tuple[RequirementWriter, ...]:
|
|
51
|
+
"""The pyproject's writer of a test requirement on a sibling that holds python."""
|
|
52
|
+
del package
|
|
53
|
+
return (_backend.declare_test_requirement,)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def module_roots(package: Package) -> tuple[str, ...]:
|
|
57
|
+
"""The import prefixes the package's code is referenced by."""
|
|
58
|
+
return tuple(_backend.module_roots(package))
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def public_modules(package: Package) -> tuple[str, ...]:
|
|
62
|
+
"""The modules that declare the package's public API."""
|
|
63
|
+
return tuple(_backend.public_modules(package))
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def references(package: Package) -> tuple[SourceReferences, ...]:
|
|
67
|
+
"""What each python source under ``src`` and ``tests`` references, one per file."""
|
|
68
|
+
return _backend.references(package)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
#: The ecosystem a python package is released to, as the ``distributions``
|
|
72
|
+
#: query names it, and the registry kind its target resolves by.
|
|
73
|
+
ECOSYSTEM = "python"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def distributions(package: Package) -> tuple[tuple[str, str], ...]:
|
|
77
|
+
"""The distribution the package releases, as its ecosystem and its name."""
|
|
78
|
+
return ((ECOSYSTEM, package.name),)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def executables(package: Package) -> tuple[str, ...]:
|
|
82
|
+
"""The scripts the package's ``pyproject.toml`` names in ``[project.scripts]``."""
|
|
83
|
+
return _backend.scripts(package)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def registry(package: Package) -> Registry:
|
|
87
|
+
"""The simple index the package is released to, as a probe of its versions.
|
|
88
|
+
|
|
89
|
+
The index is the python target the registry ladder resolves for the
|
|
90
|
+
package's workspace ([livery.workshop.registry][]), and the probe
|
|
91
|
+
reads it with the target's credential: an authenticated index, a
|
|
92
|
+
forge's own registry or a private owner's, answers only with it, and
|
|
93
|
+
an anonymous probe would wait for a version the index already
|
|
94
|
+
serves.
|
|
95
|
+
"""
|
|
96
|
+
from livery.forge import SimpleRegistry
|
|
97
|
+
from livery.workshop import registry as resolved
|
|
98
|
+
|
|
99
|
+
target = resolved(package.root, ECOSYSTEM)
|
|
100
|
+
return SimpleRegistry(target.url, token=target.token)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def suite_runner(root: Path) -> Callable[..., None]:
|
|
104
|
+
"""Answer ``python.test.runner`` with the function that runs the suites.
|
|
105
|
+
|
|
106
|
+
pytest's test step asks with the workspace root, which the answer
|
|
107
|
+
does not depend on, and calls the answer with the words for pytest,
|
|
108
|
+
the packages whose suites run in one call, the root, the test files
|
|
109
|
+
that stand for each package's suite, the CI point and whether the
|
|
110
|
+
run is measured.
|
|
111
|
+
"""
|
|
112
|
+
del root
|
|
113
|
+
return _backend.run_test
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def examples_runner(
|
|
117
|
+
root: Path,
|
|
118
|
+
) -> Callable[[Package, Path, tuple[str, ...], tuple[str, ...]], None]:
|
|
119
|
+
"""Answer ``python.examples.runner`` with the function that runs examples.
|
|
120
|
+
|
|
121
|
+
pytest's examples step asks with the workspace root, which the
|
|
122
|
+
answer does not depend on, and calls the answer once per package
|
|
123
|
+
with the package, the root, the example files the run names (empty
|
|
124
|
+
for all of them) and the words for pytest.
|
|
125
|
+
"""
|
|
126
|
+
del root
|
|
127
|
+
return _backend.run_examples
|