dryv-compiler 0.0.1__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 (30) hide show
  1. dryv_compiler-0.0.1/.gitignore +28 -0
  2. dryv_compiler-0.0.1/PKG-INFO +120 -0
  3. dryv_compiler-0.0.1/README.md +110 -0
  4. dryv_compiler-0.0.1/pyproject.toml +69 -0
  5. dryv_compiler-0.0.1/src/dryv_compiler/__init__.py +21 -0
  6. dryv_compiler-0.0.1/src/dryv_compiler/__main__.py +3 -0
  7. dryv_compiler-0.0.1/src/dryv_compiler/cli.py +159 -0
  8. dryv_compiler-0.0.1/src/dryv_compiler/compatibility.py +64 -0
  9. dryv_compiler-0.0.1/src/dryv_compiler/execution/__init__.py +23 -0
  10. dryv_compiler-0.0.1/src/dryv_compiler/execution/bootstrap.py +106 -0
  11. dryv_compiler-0.0.1/src/dryv_compiler/execution/entrypoint.py +63 -0
  12. dryv_compiler-0.0.1/src/dryv_compiler/execution/environment.py +123 -0
  13. dryv_compiler-0.0.1/src/dryv_compiler/execution/project.py +245 -0
  14. dryv_compiler-0.0.1/src/dryv_compiler/mapping/__init__.py +4 -0
  15. dryv_compiler-0.0.1/src/dryv_compiler/mapping/compile.py +90 -0
  16. dryv_compiler-0.0.1/src/dryv_compiler/mapping/encode.py +277 -0
  17. dryv_compiler-0.0.1/src/dryv_compiler/mapping/index.py +174 -0
  18. dryv_compiler-0.0.1/src/dryv_compiler/protocol/__init__.py +42 -0
  19. dryv_compiler-0.0.1/src/dryv_compiler/protocol/contracts.py +180 -0
  20. dryv_compiler-0.0.1/src/dryv_compiler/protocol/encoding.py +127 -0
  21. dryv_compiler-0.0.1/src/dryv_compiler/protocol/parsing.py +81 -0
  22. dryv_compiler-0.0.1/src/dryv_compiler/protocol/records.py +102 -0
  23. dryv_compiler-0.0.1/src/dryv_compiler/protocol/session.py +237 -0
  24. dryv_compiler-0.0.1/src/dryv_compiler/version.py +18 -0
  25. dryv_compiler-0.0.1/tests/fixtures/faidibiz_app.py +511 -0
  26. dryv_compiler-0.0.1/tests/test_compatibility.py +27 -0
  27. dryv_compiler-0.0.1/tests/test_compiler.py +283 -0
  28. dryv_compiler-0.0.1/tests/test_execution.py +102 -0
  29. dryv_compiler-0.0.1/tests/test_protocol.py +151 -0
  30. dryv_compiler-0.0.1/uv.lock +623 -0
@@ -0,0 +1,28 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .pytest_cache/
6
+ .mypy_cache/
7
+ .ruff_cache/
8
+ .venv/
9
+ venv/
10
+ build/
11
+ dist/
12
+ generated/
13
+ # Node / editors
14
+ node_modules/
15
+ .vscode-test/
16
+ .idea
17
+
18
+ # Environment
19
+ .env
20
+ .env.*
21
+ !.env.example
22
+
23
+ # OS
24
+ .DS_Store
25
+ Thumbs.db
26
+
27
+ # Dryv local cache and materialized resources
28
+ .dryv/
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.5
2
+ Name: dryv-compiler
3
+ Version: 0.0.1
4
+ Summary: Runnable Python authoring compiler/provider for Dryv
5
+ License: Apache-2.0
6
+ Requires-Python: >=3.11
7
+ Requires-Dist: dryv-author<0.1,>=0.0.1
8
+ Requires-Dist: packaging<26,>=24
9
+ Description-Content-Type: text/markdown
10
+
11
+ # dryv-compiler
12
+
13
+ `dryv-compiler` is the Python Author compiler/provider for Dryv.
14
+
15
+ It captures the typed `AuthorState` snapshot from the project's `dryv.app(...)` (in the project's own Python, via `execution/bootstrap.py`), resolves author handles to canonical JSON Pointers, and lowers the states into `dryv.ir/v1alpha1`. The engine's contract models and `validate_runtime_ir` are the final authority; the compiler never accepts IR the engine rejects.
16
+
17
+ ## Commands
18
+
19
+ ```bash
20
+ dryv-py doctor ./dryv.py
21
+ dryv-py compile ./dryv.py
22
+ dryv-py stdio
23
+ ```
24
+
25
+ `stdio` uses the canonical Dryv Authoring Protocol.
26
+
27
+ Request example:
28
+
29
+ ```json
30
+ {"type":"compile-request","session_id":"build-1","entrypoint":"./dryv.py","protocol_versions":["dryv.authoring/v1alpha1"],"runtime_ir_versions":["dryv.ir/v1alpha1"],"batch_size":64}
31
+ ```
32
+
33
+ Provider messages use canonical types such as:
34
+
35
+ ```text
36
+ provider-hello
37
+ begin
38
+ batch
39
+ diagnostic
40
+ end
41
+ error
42
+ cancelled
43
+ ```
44
+
45
+ ## How lowering works
46
+
47
+ ```text
48
+ dryv.app(...).snapshot() typed AuthorState (dryv_author.state)
49
+ ↓ mapping/index.py identities → canonical names and pointers
50
+ ↓ mapping/encode.py states → canonical JSON; query "*" expansion;
51
+ projection selections → canonical projection fields
52
+ ↓ mapping/compile.py DryvIR.model_validate + validate_runtime_ir
53
+ ↓ protocol/records.py one record per registry entry, with author origins
54
+ ```
55
+
56
+ Author states mirror canonical shapes, so lowering is structural. Registry names are group-qualified (`group.Name`). The app itself is emitted as the application named by its key.
57
+
58
+ Parity: `tests/test_compiler.py` compiles `tests/fixtures/faidibiz_app.py` (a port of the TypeScript faidibiz example) and, when `bun` is available, asserts the same semantic digest as the TypeScript compiler.
59
+
60
+ ## Canonical naming
61
+
62
+ The compiler must normalize Dryv-owned wire vocabulary regardless of Python Author implementation details:
63
+
64
+ ```text
65
+ Dryv-owned object keys -> lower_snake_case
66
+ Dryv-owned fixed values -> lower-kebab-case
67
+ Authored identifiers -> preserve exactly
68
+ Reserved/external tokens -> preserve governing spelling
69
+ ```
70
+
71
+ Canonical examples include:
72
+
73
+ ```text
74
+ session_id
75
+ runtime_ir_version
76
+ property-primitive
77
+ property-generic
78
+ provider-hello
79
+ $ref
80
+ ```
81
+
82
+ The compiler must never apply a blind recursive case converter because authored names and standards-owned values are opaque.
83
+
84
+ See `.docs/reference/ir/naming.md` and `.docs/reference/ir/properties.md`.
85
+
86
+ ## Responsibility boundary
87
+
88
+ The compiler may:
89
+
90
+ - validate Author/compiler compatibility;
91
+ - inspect and execute the Python authoring environment;
92
+ - validate Python Author state;
93
+ - resolve symbolic relationships;
94
+ - classify implementation-specific declarations into canonical concepts;
95
+ - normalize canonical key/value spelling;
96
+ - compile to Runtime-owned IR contracts;
97
+ - stream deterministic Authoring Protocol records;
98
+ - preserve source/provenance diagnostics.
99
+
100
+ It must not:
101
+
102
+ - create a competing semantic model;
103
+ - generate application source code;
104
+ - select template packs;
105
+ - choose output paths;
106
+ - write generated project files;
107
+ - own persisted Runtime serialization.
108
+
109
+ Equivalent Python and TypeScript authored meaning must converge on equivalent canonical Runtime IR.
110
+
111
+ ## Development
112
+
113
+ ```bash
114
+ uv sync
115
+ uv run ruff format .
116
+ uv run ruff check --fix .
117
+ uv run mypy
118
+ uv run pytest
119
+ uv build
120
+ ```
@@ -0,0 +1,110 @@
1
+ # dryv-compiler
2
+
3
+ `dryv-compiler` is the Python Author compiler/provider for Dryv.
4
+
5
+ It captures the typed `AuthorState` snapshot from the project's `dryv.app(...)` (in the project's own Python, via `execution/bootstrap.py`), resolves author handles to canonical JSON Pointers, and lowers the states into `dryv.ir/v1alpha1`. The engine's contract models and `validate_runtime_ir` are the final authority; the compiler never accepts IR the engine rejects.
6
+
7
+ ## Commands
8
+
9
+ ```bash
10
+ dryv-py doctor ./dryv.py
11
+ dryv-py compile ./dryv.py
12
+ dryv-py stdio
13
+ ```
14
+
15
+ `stdio` uses the canonical Dryv Authoring Protocol.
16
+
17
+ Request example:
18
+
19
+ ```json
20
+ {"type":"compile-request","session_id":"build-1","entrypoint":"./dryv.py","protocol_versions":["dryv.authoring/v1alpha1"],"runtime_ir_versions":["dryv.ir/v1alpha1"],"batch_size":64}
21
+ ```
22
+
23
+ Provider messages use canonical types such as:
24
+
25
+ ```text
26
+ provider-hello
27
+ begin
28
+ batch
29
+ diagnostic
30
+ end
31
+ error
32
+ cancelled
33
+ ```
34
+
35
+ ## How lowering works
36
+
37
+ ```text
38
+ dryv.app(...).snapshot() typed AuthorState (dryv_author.state)
39
+ ↓ mapping/index.py identities → canonical names and pointers
40
+ ↓ mapping/encode.py states → canonical JSON; query "*" expansion;
41
+ projection selections → canonical projection fields
42
+ ↓ mapping/compile.py DryvIR.model_validate + validate_runtime_ir
43
+ ↓ protocol/records.py one record per registry entry, with author origins
44
+ ```
45
+
46
+ Author states mirror canonical shapes, so lowering is structural. Registry names are group-qualified (`group.Name`). The app itself is emitted as the application named by its key.
47
+
48
+ Parity: `tests/test_compiler.py` compiles `tests/fixtures/faidibiz_app.py` (a port of the TypeScript faidibiz example) and, when `bun` is available, asserts the same semantic digest as the TypeScript compiler.
49
+
50
+ ## Canonical naming
51
+
52
+ The compiler must normalize Dryv-owned wire vocabulary regardless of Python Author implementation details:
53
+
54
+ ```text
55
+ Dryv-owned object keys -> lower_snake_case
56
+ Dryv-owned fixed values -> lower-kebab-case
57
+ Authored identifiers -> preserve exactly
58
+ Reserved/external tokens -> preserve governing spelling
59
+ ```
60
+
61
+ Canonical examples include:
62
+
63
+ ```text
64
+ session_id
65
+ runtime_ir_version
66
+ property-primitive
67
+ property-generic
68
+ provider-hello
69
+ $ref
70
+ ```
71
+
72
+ The compiler must never apply a blind recursive case converter because authored names and standards-owned values are opaque.
73
+
74
+ See `.docs/reference/ir/naming.md` and `.docs/reference/ir/properties.md`.
75
+
76
+ ## Responsibility boundary
77
+
78
+ The compiler may:
79
+
80
+ - validate Author/compiler compatibility;
81
+ - inspect and execute the Python authoring environment;
82
+ - validate Python Author state;
83
+ - resolve symbolic relationships;
84
+ - classify implementation-specific declarations into canonical concepts;
85
+ - normalize canonical key/value spelling;
86
+ - compile to Runtime-owned IR contracts;
87
+ - stream deterministic Authoring Protocol records;
88
+ - preserve source/provenance diagnostics.
89
+
90
+ It must not:
91
+
92
+ - create a competing semantic model;
93
+ - generate application source code;
94
+ - select template packs;
95
+ - choose output paths;
96
+ - write generated project files;
97
+ - own persisted Runtime serialization.
98
+
99
+ Equivalent Python and TypeScript authored meaning must converge on equivalent canonical Runtime IR.
100
+
101
+ ## Development
102
+
103
+ ```bash
104
+ uv sync
105
+ uv run ruff format .
106
+ uv run ruff check --fix .
107
+ uv run mypy
108
+ uv run pytest
109
+ uv build
110
+ ```
@@ -0,0 +1,69 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "dryv-compiler"
7
+ version = "0.0.1"
8
+ description = "Runnable Python authoring compiler/provider for Dryv"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = { text = "Apache-2.0" }
12
+ dependencies = [
13
+ "dryv-author>=0.0.1,<0.1",
14
+ "packaging>=24,<26",
15
+ ]
16
+
17
+ [project.scripts]
18
+ dryv-py = "dryv_compiler.cli:main"
19
+
20
+ [dependency-groups]
21
+ dev = [
22
+ # The engine validates compiled IR in tests only; the published compiler doesn't need it.
23
+ "dryv",
24
+ "mypy>=1.17",
25
+ "pytest>=8.4",
26
+ "ruff>=0.12",
27
+ ]
28
+
29
+ [tool.uv.sources]
30
+ dryv-author = { path = "../author", editable = true }
31
+ dryv = { path = "../../../../engine/python/engine", editable = true }
32
+
33
+ [tool.hatch.build.targets.wheel]
34
+ packages = ["src/dryv_compiler"]
35
+
36
+ [tool.ruff]
37
+ target-version = "py311"
38
+ line-length = 100
39
+ src = ["src", "tests"]
40
+
41
+ [tool.ruff.lint]
42
+ select = ["E4", "E7", "E9", "F", "I", "UP", "B", "SIM", "RUF"]
43
+
44
+ [tool.ruff.format]
45
+ quote-style = "double"
46
+ indent-style = "space"
47
+ line-ending = "lf"
48
+ docstring-code-format = true
49
+
50
+ [tool.mypy]
51
+ python_version = "3.11"
52
+ strict = true
53
+ plugins = ["pydantic.mypy"]
54
+ mypy_path = "../../../../engine/python/engine/src:../author/src"
55
+ files = ["src", "tests"]
56
+ pretty = true
57
+ show_error_codes = true
58
+ warn_unreachable = true
59
+
60
+ [tool.pydantic-mypy]
61
+ init_forbid_extra = true
62
+ init_typed = true
63
+ warn_required_dynamic_aliases = true
64
+ warn_untyped_fields = true
65
+
66
+ [tool.pytest.ini_options]
67
+ pythonpath = ["src", "../author/src", "../../../../engine/python/engine/src"]
68
+ testpaths = ["tests"]
69
+ addopts = ["--strict-config", "--strict-markers", "-ra"]
@@ -0,0 +1,21 @@
1
+ from .compatibility import AuthorCompatibilityError, validate_author_compatibility
2
+ from .mapping import compile_app, compile_ir
3
+ from .version import (
4
+ AUTHOR_COMPATIBILITY,
5
+ COMPILER_VERSION,
6
+ SUPPORTED_AUTHORING_PROTOCOLS,
7
+ SUPPORTED_RUNTIME_IR_VERSIONS,
8
+ __version__,
9
+ )
10
+
11
+ __all__ = [
12
+ "AUTHOR_COMPATIBILITY",
13
+ "COMPILER_VERSION",
14
+ "SUPPORTED_AUTHORING_PROTOCOLS",
15
+ "SUPPORTED_RUNTIME_IR_VERSIONS",
16
+ "AuthorCompatibilityError",
17
+ "__version__",
18
+ "compile_app",
19
+ "compile_ir",
20
+ "validate_author_compatibility",
21
+ ]
@@ -0,0 +1,3 @@
1
+ from .cli import main
2
+
3
+ raise SystemExit(main())
@@ -0,0 +1,159 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ import signal
6
+ import sys
7
+ from collections.abc import Sequence
8
+ from threading import Thread
9
+
10
+ from .execution import inspect_python_environment
11
+ from .protocol import (
12
+ AuthoringServerMessage,
13
+ CancellationToken,
14
+ CancelRequest,
15
+ CompileRequest,
16
+ ErrorMessage,
17
+ encode_message,
18
+ parse_client_message_text,
19
+ stream_compile,
20
+ )
21
+ from .version import (
22
+ COMPILER_VERSION,
23
+ SUPPORTED_AUTHORING_PROTOCOLS,
24
+ SUPPORTED_RUNTIME_IR_VERSIONS,
25
+ )
26
+
27
+
28
+ def _emit(message: AuthoringServerMessage) -> None:
29
+ sys.stdout.write(encode_message(message))
30
+ sys.stdout.write("\n")
31
+ sys.stdout.flush()
32
+
33
+
34
+ def _install_signal_cancellation(token: CancellationToken) -> None:
35
+ def cancel(_signum: int, _frame: object) -> None:
36
+ token.cancel()
37
+
38
+ signal.signal(signal.SIGINT, cancel)
39
+ signal.signal(signal.SIGTERM, cancel)
40
+
41
+
42
+ def _watch_stdin_cancellation(session_id: str, token: CancellationToken) -> None:
43
+ for raw in sys.stdin:
44
+ if not raw.strip():
45
+ continue
46
+ try:
47
+ message = parse_client_message_text(raw)
48
+ except ValueError:
49
+ continue
50
+ if isinstance(message, CancelRequest) and message.session_id == session_id:
51
+ token.cancel()
52
+ return
53
+
54
+
55
+ def _run_request(request: CompileRequest, *, watch_stdin: bool) -> int:
56
+ token = CancellationToken()
57
+ _install_signal_cancellation(token)
58
+ if watch_stdin:
59
+ Thread(
60
+ target=_watch_stdin_cancellation,
61
+ args=(request.session_id, token),
62
+ daemon=True,
63
+ ).start()
64
+ return 0 if stream_compile(request, _emit, cancellation=token) else 1
65
+
66
+
67
+ def _stdio() -> int:
68
+ first = sys.stdin.readline()
69
+ if not first:
70
+ sys.stderr.write("dryv-py stdio expected a compile.request JSONL message\n")
71
+ return 2
72
+ try:
73
+ message = parse_client_message_text(first)
74
+ except ValueError as exc:
75
+ _emit(ErrorMessage(session_id="unknown", code="PROTOCOL_ERROR", message=str(exc)))
76
+ return 2
77
+ if not isinstance(message, CompileRequest):
78
+ _emit(
79
+ ErrorMessage(
80
+ session_id=message.session_id,
81
+ code="PROTOCOL_ERROR",
82
+ message="first stdio message must be compile.request",
83
+ )
84
+ )
85
+ return 2
86
+ return _run_request(message, watch_stdin=True)
87
+
88
+
89
+ def _compile(
90
+ *,
91
+ entrypoint: str,
92
+ session_id: str,
93
+ batch_size: int,
94
+ protocol: str,
95
+ runtime_ir: str,
96
+ ) -> int:
97
+ request = CompileRequest(
98
+ session_id=session_id,
99
+ entrypoint=entrypoint,
100
+ protocol_versions=(protocol,),
101
+ runtime_ir_versions=(runtime_ir,),
102
+ batch_size=batch_size,
103
+ )
104
+ return _run_request(request, watch_stdin=False)
105
+
106
+
107
+ def _doctor(entrypoint: str) -> int:
108
+ report = inspect_python_environment(entrypoint)
109
+ value: dict[str, object] = {
110
+ "status": report.status.value,
111
+ "pythonExecutable": report.python_executable,
112
+ "pythonVersion": report.python_version,
113
+ "projectRoot": report.project_root,
114
+ "entrypoint": report.entrypoint,
115
+ "virtualEnvironment": report.virtual_environment,
116
+ "authorVersion": report.author_version,
117
+ }
118
+ if report.message is not None:
119
+ value["message"] = report.message
120
+ sys.stdout.write(json.dumps(value, sort_keys=True, separators=(",", ":")))
121
+ sys.stdout.write("\n")
122
+ return 0 if report.status.value == "READY" else 1
123
+
124
+
125
+ def build_parser() -> argparse.ArgumentParser:
126
+ parser = argparse.ArgumentParser(prog="dryv-py")
127
+ parser.add_argument("--version", action="version", version=COMPILER_VERSION)
128
+ commands = parser.add_subparsers(dest="command", required=True)
129
+
130
+ compile_parser = commands.add_parser("compile", help="compile one Python authoring entrypoint")
131
+ compile_parser.add_argument("entrypoint")
132
+ compile_parser.add_argument("--session-id", default="standalone")
133
+ compile_parser.add_argument("--batch-size", type=int, default=64)
134
+ compile_parser.add_argument("--protocol", default=SUPPORTED_AUTHORING_PROTOCOLS[0])
135
+ compile_parser.add_argument("--runtime-ir", default=SUPPORTED_RUNTIME_IR_VERSIONS[0])
136
+
137
+ commands.add_parser("stdio", help="serve one machine-readable JSONL compile session on stdio")
138
+ doctor_parser = commands.add_parser("doctor", help="inspect the Python authoring environment")
139
+ doctor_parser.add_argument("entrypoint")
140
+ return parser
141
+
142
+
143
+ def main(argv: Sequence[str] | None = None) -> int:
144
+ parser = build_parser()
145
+ args = parser.parse_args(argv)
146
+ command = str(args.command)
147
+ if command == "compile":
148
+ return _compile(
149
+ entrypoint=str(args.entrypoint),
150
+ session_id=str(args.session_id),
151
+ batch_size=int(args.batch_size),
152
+ protocol=str(args.protocol),
153
+ runtime_ir=str(args.runtime_ir),
154
+ )
155
+ if command == "stdio":
156
+ return _stdio()
157
+ if command == "doctor":
158
+ return _doctor(str(args.entrypoint))
159
+ parser.error(f"unsupported command: {command}")
@@ -0,0 +1,64 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from dryv_author import AUTHOR_REPRESENTATION_VERSION
6
+ from dryv_author import __version__ as author_version
7
+ from packaging.specifiers import SpecifierSet
8
+ from packaging.version import InvalidVersion, Version
9
+
10
+ from .version import AUTHOR_COMPATIBILITY, AUTHOR_REPRESENTATION
11
+
12
+
13
+ class AuthorCompatibilityError(RuntimeError):
14
+ """Raised when an author SDK cannot be consumed by this compiler."""
15
+
16
+
17
+ @dataclass(frozen=True, slots=True)
18
+ class AuthorCompatibility:
19
+ author_version: str
20
+ supported_versions: str
21
+ representation: str
22
+
23
+
24
+ def current_author_compatibility() -> AuthorCompatibility:
25
+ return AuthorCompatibility(
26
+ author_version=author_version,
27
+ supported_versions=AUTHOR_COMPATIBILITY,
28
+ representation=AUTHOR_REPRESENTATION_VERSION,
29
+ )
30
+
31
+
32
+ def validate_author_details(author_version_value: str, representation: str) -> AuthorCompatibility:
33
+ compatibility = AuthorCompatibility(
34
+ author_version=author_version_value,
35
+ supported_versions=AUTHOR_COMPATIBILITY,
36
+ representation=representation,
37
+ )
38
+ try:
39
+ parsed = Version(compatibility.author_version)
40
+ except InvalidVersion as exc:
41
+ raise AuthorCompatibilityError(
42
+ f"installed dryv-author version {compatibility.author_version!r} is invalid"
43
+ ) from exc
44
+
45
+ if parsed not in SpecifierSet(compatibility.supported_versions):
46
+ raise AuthorCompatibilityError(
47
+ "installed dryv-author version "
48
+ f"{compatibility.author_version!r} is incompatible with compiler requirement "
49
+ f"{compatibility.supported_versions!r}"
50
+ )
51
+ if compatibility.representation != AUTHOR_REPRESENTATION:
52
+ raise AuthorCompatibilityError(
53
+ "installed dryv-author compiler-facing representation "
54
+ f"{compatibility.representation!r} is incompatible with {AUTHOR_REPRESENTATION!r}"
55
+ )
56
+ return compatibility
57
+
58
+
59
+ def validate_author_compatibility() -> AuthorCompatibility:
60
+ compatibility = current_author_compatibility()
61
+ return validate_author_details(
62
+ compatibility.author_version,
63
+ compatibility.representation,
64
+ )
@@ -0,0 +1,23 @@
1
+ from .entrypoint import AuthorEntrypointError, LoadedAuthor, load_author_entrypoint
2
+ from .environment import EnvironmentStatus, PythonEnvironmentReport, inspect_python_environment
3
+ from .project import (
4
+ CapturedAuthor,
5
+ ProjectPythonError,
6
+ capture_author_entrypoint,
7
+ discover_project_python,
8
+ inspect_project_python,
9
+ )
10
+
11
+ __all__ = [
12
+ "AuthorEntrypointError",
13
+ "CapturedAuthor",
14
+ "EnvironmentStatus",
15
+ "LoadedAuthor",
16
+ "ProjectPythonError",
17
+ "PythonEnvironmentReport",
18
+ "capture_author_entrypoint",
19
+ "discover_project_python",
20
+ "inspect_project_python",
21
+ "inspect_python_environment",
22
+ "load_author_entrypoint",
23
+ ]