mojox-core 0.5.0__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.
@@ -0,0 +1,10 @@
1
+ # Local working docs (project context, specs, plans)
2
+ docs/
3
+ specs/
4
+ plans/
5
+
6
+ __pycache__/
7
+ *.py[cod]
8
+ dist/
9
+ *.egg-info/
10
+ .venv/
@@ -0,0 +1,178 @@
1
+ Metadata-Version: 2.5
2
+ Name: mojox-core
3
+ Version: 0.5.0
4
+ Summary: Pure model layer for mojox: manifest parsing, target discovery, policy resolution, and build planning.
5
+ Project-URL: Repository, https://github.com/Conobi/mojox
6
+ Author: Conobi
7
+ License-Expression: MIT
8
+ Requires-Python: >=3.10
9
+ Requires-Dist: packaging>=23.0
10
+ Requires-Dist: tomli>=1.1.0; python_version < '3.11'
11
+ Description-Content-Type: text/markdown
12
+
13
+ # mojox-core
14
+
15
+ Pure model layer for the [mojox](https://github.com/Conobi/mojox) build system.
16
+ No I/O, no subprocess, no filesystem access at module level.
17
+ All data types are frozen dataclasses; every transformer is a pure function
18
+ (data in, data out).
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ uv add mojox-core
24
+ ```
25
+
26
+ Requires Python 3.10+. Only runtime dependency is `packaging>=23.0`
27
+ (plus `tomli` on Python < 3.11).
28
+
29
+ ## Pipeline
30
+
31
+ The core exposes a five-stage pipeline where each step takes immutable data
32
+ and returns immutable data:
33
+
34
+ ```
35
+ parse -> discover -> resolve -> plan -> serialize
36
+ ```
37
+
38
+ I/O readers live in the separate `mojox_core.io` subpackage. Consumers can
39
+ skip them entirely and feed fixtures directly into the pipeline.
40
+
41
+ ## Quick start
42
+
43
+ ```python
44
+ from pathlib import Path
45
+
46
+ from mojox_core import (
47
+ parse_manifest,
48
+ discover,
49
+ resolve,
50
+ plan,
51
+ serialize,
52
+ LocalSettings,
53
+ )
54
+ from mojox_core.io.manifest import read as read_manifest
55
+ from mojox_core.io.toolchain import resolve as resolve_toolchain
56
+ from mojox_core.io.environment import (
57
+ read_distributions,
58
+ read_lockfile,
59
+ read_host_facts,
60
+ )
61
+ from mojox_core import build_env
62
+
63
+ # 1. Read raw TOML (I/O)
64
+ raw = read_manifest(Path("."))
65
+
66
+ # 2. Parse manifest (pure)
67
+ manifest = parse_manifest(raw)
68
+
69
+ # 3. Discover targets by convention (pure)
70
+ targets = discover(manifest, Path("."))
71
+
72
+ # 4. Resolve build policy from all precedence layers (pure)
73
+ policy = resolve(manifest, "dev", {}, LocalSettings.EMPTY)
74
+
75
+ # 5. Detect toolchain and build environment (I/O)
76
+ toolchain = resolve_toolchain()
77
+ dists = read_distributions()
78
+ lock = read_lockfile(Path("."))
79
+ env = build_env(dists, lock, toolchain.mojo_path, toolchain.version)
80
+ host = read_host_facts(Path("."))
81
+
82
+ # 6. Plan mojo invocations (pure)
83
+ commands = plan(targets, env, policy, toolchain, host)
84
+
85
+ for cmd in commands:
86
+ print(cmd.kind, cmd.argv)
87
+
88
+ # 7. Serialize to the `mojox metadata` JSON schema (pure)
89
+ metadata = serialize(targets, env, policy, commands, toolchain, diagnostics=())
90
+ ```
91
+
92
+ ## Public API
93
+
94
+ ### Types
95
+
96
+ All exported from `mojox_core`. Every type is a frozen dataclass or enum.
97
+
98
+ | Type | Description |
99
+ |------|-------------|
100
+ | `Manifest` | Parsed `[tool.mojox]` config and PEP 621 project metadata |
101
+ | `Command` | A planned mojo invocation (data, not execution) |
102
+ | `CommandKind` | Enum of command kinds |
103
+ | `Policy` | Resolved build policy (profile + defines + flags) |
104
+ | `Profile` | Build profile (`dev` or `release`) with optimization/debug settings |
105
+ | `Target` | A single build/test/example/binary target |
106
+ | `TargetKind` | Enum of target kinds |
107
+ | `TargetGraph` | The full set of discovered targets |
108
+ | `ResolvedEnv` | Resolved environment (import paths, library paths, mojo binary) |
109
+ | `Toolchain` | Detected Mojo toolchain info |
110
+ | `HostFacts` | Host platform facts |
111
+ | `LocalSettings` | Parsed `.mojox/config.toml` settings |
112
+ | `Diagnostic` | Lint diagnostic |
113
+ | `LintConfig` | Lint configuration |
114
+ | `DistEntry` | Distribution metadata entry |
115
+ | `DistKind` | Enum of distribution kinds |
116
+ | `BinaryEntry` | Binary entry in a distribution |
117
+
118
+ ### Transformers
119
+
120
+ Pure functions. No side effects, no I/O.
121
+
122
+ ```python
123
+ parse_manifest(data: dict) -> Manifest
124
+ discover(manifest: Manifest, root: Path) -> TargetGraph
125
+ resolve(manifest: Manifest, profile_name: str, cli_overrides: dict, settings: LocalSettings) -> Policy
126
+ plan(graph: TargetGraph, env: ResolvedEnv, policy: Policy, toolchain: Toolchain, host: HostFacts) -> tuple[Command, ...]
127
+ build_env(dists: list[dict], lock_data: dict | None, mojo_path: str, mojo_version: str) -> ResolvedEnv
128
+ serialize(graph: TargetGraph, env: ResolvedEnv, policy: Policy, commands: tuple[Command, ...], toolchain: Toolchain, diagnostics: tuple[Diagnostic, ...]) -> dict
129
+ parse_settings(user: dict | None, project: dict | None, env: dict[str, str]) -> LocalSettings
130
+ ```
131
+
132
+ ### I/O readers
133
+
134
+ In the `mojox_core.io` subpackage. These are the only functions that touch
135
+ the filesystem or run subprocesses.
136
+
137
+ ```python
138
+ mojox_core.io.manifest.read(path: Path) -> dict # read & parse pyproject.toml
139
+ mojox_core.io.toolchain.resolve() -> Toolchain # detect installed Mojo compiler
140
+ mojox_core.io.environment.read_distributions(platlib=None) -> list[dict] # scan installed dists
141
+ mojox_core.io.environment.read_lockfile(project_root: Path) -> dict | None
142
+ mojox_core.io.environment.read_host_facts(manifest_dir: Path) -> HostFacts
143
+ ```
144
+
145
+ ### Errors
146
+
147
+ ```python
148
+ class ConfigError(Exception):
149
+ key_path: str # dotted path to the offending key
150
+ message: str # human-readable explanation
151
+ ```
152
+
153
+ Raised on invalid manifest or settings. No `KeyError` or `TypeError` reaches
154
+ the caller -- every rejection is a `ConfigError` with a structured key path.
155
+
156
+ ## Testing without I/O
157
+
158
+ Because the pipeline is pure, you can test any stage by constructing fixtures
159
+ directly:
160
+
161
+ ```python
162
+ from mojox_core import Manifest, discover, TargetGraph
163
+
164
+ manifest = Manifest(...) # build the frozen dataclass by hand
165
+ graph = discover(manifest, some_temp_dir)
166
+ assert isinstance(graph, TargetGraph)
167
+ ```
168
+
169
+ No mojo compiler, no installed packages, no pyproject.toml required.
170
+
171
+ ## See also
172
+
173
+ - [mojox](https://github.com/Conobi/mojox) -- CLI that drives the full build
174
+ - [mojox-build](https://github.com/Conobi/mojox/tree/main/packages/mojox-build) -- PEP 517 build backend
175
+
176
+ ## License
177
+
178
+ MIT
@@ -0,0 +1,166 @@
1
+ # mojox-core
2
+
3
+ Pure model layer for the [mojox](https://github.com/Conobi/mojox) build system.
4
+ No I/O, no subprocess, no filesystem access at module level.
5
+ All data types are frozen dataclasses; every transformer is a pure function
6
+ (data in, data out).
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ uv add mojox-core
12
+ ```
13
+
14
+ Requires Python 3.10+. Only runtime dependency is `packaging>=23.0`
15
+ (plus `tomli` on Python < 3.11).
16
+
17
+ ## Pipeline
18
+
19
+ The core exposes a five-stage pipeline where each step takes immutable data
20
+ and returns immutable data:
21
+
22
+ ```
23
+ parse -> discover -> resolve -> plan -> serialize
24
+ ```
25
+
26
+ I/O readers live in the separate `mojox_core.io` subpackage. Consumers can
27
+ skip them entirely and feed fixtures directly into the pipeline.
28
+
29
+ ## Quick start
30
+
31
+ ```python
32
+ from pathlib import Path
33
+
34
+ from mojox_core import (
35
+ parse_manifest,
36
+ discover,
37
+ resolve,
38
+ plan,
39
+ serialize,
40
+ LocalSettings,
41
+ )
42
+ from mojox_core.io.manifest import read as read_manifest
43
+ from mojox_core.io.toolchain import resolve as resolve_toolchain
44
+ from mojox_core.io.environment import (
45
+ read_distributions,
46
+ read_lockfile,
47
+ read_host_facts,
48
+ )
49
+ from mojox_core import build_env
50
+
51
+ # 1. Read raw TOML (I/O)
52
+ raw = read_manifest(Path("."))
53
+
54
+ # 2. Parse manifest (pure)
55
+ manifest = parse_manifest(raw)
56
+
57
+ # 3. Discover targets by convention (pure)
58
+ targets = discover(manifest, Path("."))
59
+
60
+ # 4. Resolve build policy from all precedence layers (pure)
61
+ policy = resolve(manifest, "dev", {}, LocalSettings.EMPTY)
62
+
63
+ # 5. Detect toolchain and build environment (I/O)
64
+ toolchain = resolve_toolchain()
65
+ dists = read_distributions()
66
+ lock = read_lockfile(Path("."))
67
+ env = build_env(dists, lock, toolchain.mojo_path, toolchain.version)
68
+ host = read_host_facts(Path("."))
69
+
70
+ # 6. Plan mojo invocations (pure)
71
+ commands = plan(targets, env, policy, toolchain, host)
72
+
73
+ for cmd in commands:
74
+ print(cmd.kind, cmd.argv)
75
+
76
+ # 7. Serialize to the `mojox metadata` JSON schema (pure)
77
+ metadata = serialize(targets, env, policy, commands, toolchain, diagnostics=())
78
+ ```
79
+
80
+ ## Public API
81
+
82
+ ### Types
83
+
84
+ All exported from `mojox_core`. Every type is a frozen dataclass or enum.
85
+
86
+ | Type | Description |
87
+ |------|-------------|
88
+ | `Manifest` | Parsed `[tool.mojox]` config and PEP 621 project metadata |
89
+ | `Command` | A planned mojo invocation (data, not execution) |
90
+ | `CommandKind` | Enum of command kinds |
91
+ | `Policy` | Resolved build policy (profile + defines + flags) |
92
+ | `Profile` | Build profile (`dev` or `release`) with optimization/debug settings |
93
+ | `Target` | A single build/test/example/binary target |
94
+ | `TargetKind` | Enum of target kinds |
95
+ | `TargetGraph` | The full set of discovered targets |
96
+ | `ResolvedEnv` | Resolved environment (import paths, library paths, mojo binary) |
97
+ | `Toolchain` | Detected Mojo toolchain info |
98
+ | `HostFacts` | Host platform facts |
99
+ | `LocalSettings` | Parsed `.mojox/config.toml` settings |
100
+ | `Diagnostic` | Lint diagnostic |
101
+ | `LintConfig` | Lint configuration |
102
+ | `DistEntry` | Distribution metadata entry |
103
+ | `DistKind` | Enum of distribution kinds |
104
+ | `BinaryEntry` | Binary entry in a distribution |
105
+
106
+ ### Transformers
107
+
108
+ Pure functions. No side effects, no I/O.
109
+
110
+ ```python
111
+ parse_manifest(data: dict) -> Manifest
112
+ discover(manifest: Manifest, root: Path) -> TargetGraph
113
+ resolve(manifest: Manifest, profile_name: str, cli_overrides: dict, settings: LocalSettings) -> Policy
114
+ plan(graph: TargetGraph, env: ResolvedEnv, policy: Policy, toolchain: Toolchain, host: HostFacts) -> tuple[Command, ...]
115
+ build_env(dists: list[dict], lock_data: dict | None, mojo_path: str, mojo_version: str) -> ResolvedEnv
116
+ serialize(graph: TargetGraph, env: ResolvedEnv, policy: Policy, commands: tuple[Command, ...], toolchain: Toolchain, diagnostics: tuple[Diagnostic, ...]) -> dict
117
+ parse_settings(user: dict | None, project: dict | None, env: dict[str, str]) -> LocalSettings
118
+ ```
119
+
120
+ ### I/O readers
121
+
122
+ In the `mojox_core.io` subpackage. These are the only functions that touch
123
+ the filesystem or run subprocesses.
124
+
125
+ ```python
126
+ mojox_core.io.manifest.read(path: Path) -> dict # read & parse pyproject.toml
127
+ mojox_core.io.toolchain.resolve() -> Toolchain # detect installed Mojo compiler
128
+ mojox_core.io.environment.read_distributions(platlib=None) -> list[dict] # scan installed dists
129
+ mojox_core.io.environment.read_lockfile(project_root: Path) -> dict | None
130
+ mojox_core.io.environment.read_host_facts(manifest_dir: Path) -> HostFacts
131
+ ```
132
+
133
+ ### Errors
134
+
135
+ ```python
136
+ class ConfigError(Exception):
137
+ key_path: str # dotted path to the offending key
138
+ message: str # human-readable explanation
139
+ ```
140
+
141
+ Raised on invalid manifest or settings. No `KeyError` or `TypeError` reaches
142
+ the caller -- every rejection is a `ConfigError` with a structured key path.
143
+
144
+ ## Testing without I/O
145
+
146
+ Because the pipeline is pure, you can test any stage by constructing fixtures
147
+ directly:
148
+
149
+ ```python
150
+ from mojox_core import Manifest, discover, TargetGraph
151
+
152
+ manifest = Manifest(...) # build the frozen dataclass by hand
153
+ graph = discover(manifest, some_temp_dir)
154
+ assert isinstance(graph, TargetGraph)
155
+ ```
156
+
157
+ No mojo compiler, no installed packages, no pyproject.toml required.
158
+
159
+ ## See also
160
+
161
+ - [mojox](https://github.com/Conobi/mojox) -- CLI that drives the full build
162
+ - [mojox-build](https://github.com/Conobi/mojox/tree/main/packages/mojox-build) -- PEP 517 build backend
163
+
164
+ ## License
165
+
166
+ MIT
@@ -0,0 +1,28 @@
1
+ [project]
2
+ name = "mojox-core"
3
+ version = "0.5.0"
4
+ description = "Pure model layer for mojox: manifest parsing, target discovery, policy resolution, and build planning."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ requires-python = ">=3.10"
8
+ authors = [{ name = "Conobi" }]
9
+ dependencies = [
10
+ "packaging>=23.0",
11
+ 'tomli >= 1.1.0; python_version < "3.11"',
12
+ ]
13
+
14
+ [project.urls]
15
+ Repository = "https://github.com/Conobi/mojox"
16
+
17
+ [build-system]
18
+ requires = ["hatchling"]
19
+ build-backend = "hatchling.build"
20
+
21
+ [tool.hatch.build.targets.wheel]
22
+ packages = ["src/mojox_core"]
23
+
24
+ [tool.pytest.ini_options]
25
+ testpaths = ["tests"]
26
+
27
+ [tool.mypy]
28
+ strict = true
@@ -0,0 +1,63 @@
1
+ """mojox-core: pure model layer for Mojo build tooling.
2
+
3
+ Public API:
4
+ - Types: Manifest, Command, Policy, ResolvedEnv, TargetGraph, etc.
5
+ - Transformers: parse_manifest, build_env, discover, resolve, plan, serialize
6
+ - Errors: ConfigError
7
+ """
8
+
9
+ from ._errors import ConfigError
10
+ from ._types import (
11
+ BinaryEntry,
12
+ Command,
13
+ CommandKind,
14
+ Diagnostic,
15
+ DistEntry,
16
+ DistKind,
17
+ HostFacts,
18
+ LintConfig,
19
+ LocalSettings,
20
+ Manifest,
21
+ Policy,
22
+ Profile,
23
+ ResolvedEnv,
24
+ Target,
25
+ TargetGraph,
26
+ TargetKind,
27
+ Toolchain,
28
+ )
29
+ from .environment import build_env
30
+ from .manifest import parse_manifest
31
+ from .metadata import serialize
32
+ from .plan import plan
33
+ from .policy import resolve
34
+ from .settings import parse_settings
35
+ from .targets import discover
36
+
37
+ __all__ = [
38
+ "BinaryEntry",
39
+ "Command",
40
+ "CommandKind",
41
+ "ConfigError",
42
+ "Diagnostic",
43
+ "DistEntry",
44
+ "DistKind",
45
+ "HostFacts",
46
+ "LintConfig",
47
+ "LocalSettings",
48
+ "Manifest",
49
+ "Policy",
50
+ "Profile",
51
+ "ResolvedEnv",
52
+ "Target",
53
+ "TargetGraph",
54
+ "TargetKind",
55
+ "Toolchain",
56
+ "build_env",
57
+ "discover",
58
+ "parse_manifest",
59
+ "parse_settings",
60
+ "plan",
61
+ "resolve",
62
+ "serialize",
63
+ ]
@@ -0,0 +1,16 @@
1
+ """User-facing configuration errors with structured key paths."""
2
+
3
+ from __future__ import annotations
4
+
5
+
6
+ class ConfigError(Exception):
7
+ """A configuration error carrying the offending key path and a remediation.
8
+
9
+ No KeyError, no TypeError, no stack trace reaches the user — every
10
+ rejection produces one of these with a human-readable message.
11
+ """
12
+
13
+ def __init__(self, key_path: str, message: str) -> None:
14
+ self.key_path = key_path
15
+ self.message = message
16
+ super().__init__(f"[{key_path}] {message}")
@@ -0,0 +1,235 @@
1
+ """All frozen dataclasses for the mojox-core model layer.
2
+
3
+ Every type here is immutable (frozen=True). No type in this module imports
4
+ subprocess or performs I/O. Path-valued fields use PurePosixPath for lexical
5
+ paths (manifest-relative) and str for resolved absolute paths (from readers).
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from collections.abc import Mapping
11
+ from dataclasses import dataclass, field
12
+ from enum import Enum
13
+ from pathlib import PurePosixPath
14
+ from typing import ClassVar, Literal
15
+
16
+ # -- Enums -----------------------------------------------------------------
17
+
18
+
19
+ class CommandKind(Enum):
20
+ """The kind of mojo invocation a Command represents."""
21
+
22
+ COMPILE_PACKAGE = "compile-package"
23
+ COMPILE_BINARY = "compile-binary"
24
+ RUN_TEST = "run-test"
25
+ CHECK_EXAMPLE = "check-example"
26
+ RUN = "run"
27
+
28
+
29
+ class TargetKind(Enum):
30
+ """Discovered target kinds."""
31
+
32
+ LIB = "lib"
33
+ BIN = "bin"
34
+ TEST = "test"
35
+ EXAMPLE = "example"
36
+
37
+
38
+ class DistKind(Enum):
39
+ """How a distribution provides its Mojo packages."""
40
+
41
+ SOURCE = "source"
42
+ PRECOMPILED = "precompiled"
43
+
44
+
45
+ # -- Leaf types ------------------------------------------------------------
46
+
47
+
48
+ @dataclass(frozen=True)
49
+ class BinaryEntry:
50
+ """One executable produced by ``mojo build``."""
51
+
52
+ source: str
53
+ name: str
54
+
55
+
56
+ @dataclass(frozen=True)
57
+ class LintConfig:
58
+ """Lint settings that translate to compiler flags."""
59
+
60
+ warnings_as_errors: bool = False
61
+ check_doc_strings: bool = False
62
+ missing_doc_strings: bool = False
63
+ unstable_apis: bool = False
64
+
65
+
66
+ @dataclass(frozen=True)
67
+ class Diagnostic:
68
+ """A compiler or mojox diagnostic."""
69
+
70
+ kind: Literal["error", "warning", "note"]
71
+ message: str
72
+ file: str | None = None
73
+ line: int | None = None
74
+ column: int | None = None
75
+ source_text: str | None = None
76
+
77
+
78
+ @dataclass(frozen=True)
79
+ class Target:
80
+ """A discovered build target."""
81
+
82
+ kind: TargetKind
83
+ path: str
84
+ target_id: str
85
+
86
+
87
+ @dataclass(frozen=True)
88
+ class DistEntry:
89
+ """One installed distribution contributing to the include sequence."""
90
+
91
+ name: str
92
+ include_dir: str
93
+ kind: DistKind
94
+ packages: tuple[str, ...]
95
+ provenance: str
96
+ native_lib_dirs: tuple[str, ...] = ()
97
+
98
+
99
+ # -- Compound types --------------------------------------------------------
100
+
101
+
102
+ @dataclass(frozen=True)
103
+ class Profile:
104
+ """A named compilation profile (dev, release, or user-declared)."""
105
+
106
+ optimize: int | None = None
107
+ debug_level: str | None = None
108
+ defines: dict[str, str] = field(default_factory=dict)
109
+ flags: tuple[str, ...] = ()
110
+
111
+
112
+ @dataclass(frozen=True)
113
+ class Manifest:
114
+ """Parsed pyproject.toml -- portable, published, versioned with the code."""
115
+
116
+ # [project]
117
+ name: str
118
+ version: str
119
+ description: str | None
120
+ readme: str | None
121
+ license_expr: str | None
122
+ license_files: tuple[str, ...]
123
+ requires_python: str | None
124
+ dependencies: tuple[str, ...]
125
+ optional_dependencies: dict[str, tuple[str, ...]]
126
+ keywords: tuple[str, ...]
127
+ authors: tuple[dict[str, str], ...]
128
+ maintainers: tuple[dict[str, str], ...]
129
+ urls: dict[str, str]
130
+ classifiers: tuple[str, ...]
131
+
132
+ # [tool.mojox]
133
+ packages: tuple[str, ...] | None
134
+ package_root: str
135
+ binaries: tuple[BinaryEntry, ...]
136
+ test_roots: tuple[str, ...]
137
+ test_parallel: bool
138
+ defines: dict[str, str]
139
+ flags: tuple[str, ...]
140
+ lints: LintConfig
141
+ optimize: int | None
142
+ debug_level: str | None
143
+ pre_build: tuple[tuple[str, ...], ...]
144
+ native_libs: tuple[str, ...]
145
+ source_include: tuple[str, ...] | None
146
+ source_exclude: tuple[str, ...]
147
+ wheel_exclude: tuple[str, ...]
148
+ profiles: dict[str, Profile]
149
+ build_profile: str
150
+
151
+
152
+ @dataclass(frozen=True)
153
+ class TargetGraph:
154
+ """Discovered targets in topological order (lib targets first)."""
155
+
156
+ targets: tuple[Target, ...]
157
+ edges: tuple[tuple[str, str], ...]
158
+ unsearched_test_dirs: tuple[tuple[str, int], ...] = ()
159
+
160
+
161
+ @dataclass(frozen=True)
162
+ class ResolvedEnv:
163
+ """The resolved build environment -- include sequence, mojo binary, provenance."""
164
+
165
+ include_sequence: tuple[DistEntry, ...]
166
+ mojo_path: str
167
+ mojo_version: str
168
+ path_mojo: str | None
169
+ lock_version: int | None
170
+ diagnostics: tuple[Diagnostic, ...] = ()
171
+
172
+
173
+ @dataclass(frozen=True)
174
+ class Toolchain:
175
+ """Resolved Mojo toolchain identity."""
176
+
177
+ mojo_path: str
178
+ version: str
179
+ subcommand: str
180
+ extension: str
181
+
182
+
183
+ @dataclass(frozen=True)
184
+ class HostFacts:
185
+ """Machine-specific facts injected into the planner for determinism."""
186
+
187
+ cpu_count: int
188
+ available_memory_mb: int
189
+ manifest_dir: PurePosixPath
190
+
191
+
192
+ @dataclass(frozen=True)
193
+ class LocalSettings:
194
+ """Machine-local settings (from .mojox/config.toml + env vars)."""
195
+
196
+ jobs: int | None = None
197
+ timeout_s: int | None = None
198
+ config_paths: tuple[str, ...] = ()
199
+ env: dict[str, str] = field(default_factory=dict)
200
+
201
+ EMPTY: ClassVar[LocalSettings] # set below
202
+
203
+
204
+ # Bootstrap the EMPTY sentinel after the class is defined.
205
+ LocalSettings.EMPTY = LocalSettings()
206
+
207
+
208
+ @dataclass(frozen=True)
209
+ class Policy:
210
+ """The fully resolved flag set the planner consumes."""
211
+
212
+ optimize: int
213
+ debug_level: str
214
+ defines: dict[str, str]
215
+ flags: tuple[str, ...]
216
+ include_paths: tuple[str, ...]
217
+ lints: LintConfig
218
+ jobs: int
219
+ jobs_compile: int
220
+ jobs_tests: int
221
+ timeout_s: int
222
+
223
+
224
+ @dataclass(frozen=True)
225
+ class Command:
226
+ """One mojo invocation the planner produces."""
227
+
228
+ argv: tuple[str, ...]
229
+ cwd: PurePosixPath
230
+ env: Mapping[str, str]
231
+ kind: CommandKind
232
+ target_id: str
233
+ timeout_s: int | None
234
+ outputs: tuple[str, ...]
235
+ depends_on: tuple[str, ...]