headlamp 0.1.60__py3-none-macosx_11_0_arm64.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.
- headlamp/__init__.py +6 -0
- headlamp/_bin.py +66 -0
- headlamp/_cli.py +25 -0
- headlamp/bin/headlamp +0 -0
- headlamp-0.1.60.dist-info/METADATA +241 -0
- headlamp-0.1.60.dist-info/RECORD +9 -0
- headlamp-0.1.60.dist-info/WHEEL +6 -0
- headlamp-0.1.60.dist-info/entry_points.txt +2 -0
- headlamp-0.1.60.dist-info/top_level.txt +1 -0
headlamp/__init__.py
ADDED
headlamp/_bin.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import platform
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
# Python 3.9+
|
|
9
|
+
from importlib import resources as importlib_resources # type: ignore
|
|
10
|
+
except Exception: # pragma: no cover
|
|
11
|
+
import importlib_resources # type: ignore
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
_OVERRIDE_ENV = "HEADLAMP_PYPI_BIN_OVERRIDE"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _default_binary_resource_name() -> str:
|
|
18
|
+
return "headlamp.exe" if platform.system().lower().startswith("win") else "headlamp"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_binary_path() -> Path:
|
|
22
|
+
"""
|
|
23
|
+
Returns the absolute path to the bundled `headlamp` binary.
|
|
24
|
+
|
|
25
|
+
Test override:
|
|
26
|
+
- If `HEADLAMP_PYPI_BIN_OVERRIDE` is set, that path is used (if it exists).
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
override = os.environ.get(_OVERRIDE_ENV, "").strip()
|
|
30
|
+
if override:
|
|
31
|
+
p = Path(override).expanduser()
|
|
32
|
+
if not p.is_absolute():
|
|
33
|
+
p = (Path.cwd() / p).resolve()
|
|
34
|
+
if not p.exists():
|
|
35
|
+
raise FileNotFoundError(
|
|
36
|
+
f"headlamp (PyPI): override binary not found at {_OVERRIDE_ENV}={p}"
|
|
37
|
+
)
|
|
38
|
+
return p
|
|
39
|
+
|
|
40
|
+
resource_name = _default_binary_resource_name()
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
# pkg is headlamp.bin (a namespace for resources)
|
|
44
|
+
bin_dir = importlib_resources.files("headlamp").joinpath("bin")
|
|
45
|
+
candidate = bin_dir.joinpath(resource_name)
|
|
46
|
+
candidate_path = Path(str(candidate))
|
|
47
|
+
except Exception as e: # pragma: no cover
|
|
48
|
+
raise FileNotFoundError(
|
|
49
|
+
"headlamp (PyPI): could not resolve bundled binary resources"
|
|
50
|
+
) from e
|
|
51
|
+
|
|
52
|
+
if not candidate_path.exists():
|
|
53
|
+
raise FileNotFoundError(_missing_binary_message(candidate_path))
|
|
54
|
+
return candidate_path
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _missing_binary_message(expected_path: Path) -> str:
|
|
58
|
+
return (
|
|
59
|
+
"headlamp (PyPI): bundled headlamp binary not found.\n"
|
|
60
|
+
f"Expected at: {expected_path}\n\n"
|
|
61
|
+
"This usually means you installed an sdist (source distribution) or a wheel for a\n"
|
|
62
|
+
"different platform.\n\n"
|
|
63
|
+
"Fix:\n"
|
|
64
|
+
" - Reinstall wheels only: pip install --only-binary :all: headlamp\n"
|
|
65
|
+
)
|
|
66
|
+
|
headlamp/_cli.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
from ._bin import get_binary_path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main() -> None:
|
|
11
|
+
try:
|
|
12
|
+
bin_path = get_binary_path()
|
|
13
|
+
except FileNotFoundError as e:
|
|
14
|
+
sys.stderr.write(str(e).rstrip() + os.linesep)
|
|
15
|
+
raise SystemExit(1)
|
|
16
|
+
|
|
17
|
+
argv = [str(bin_path), *sys.argv[1:]]
|
|
18
|
+
try:
|
|
19
|
+
completed = subprocess.run(argv)
|
|
20
|
+
except FileNotFoundError:
|
|
21
|
+
sys.stderr.write(f"headlamp (PyPI): failed to execute: {bin_path}{os.linesep}")
|
|
22
|
+
raise SystemExit(1)
|
|
23
|
+
|
|
24
|
+
raise SystemExit(completed.returncode)
|
|
25
|
+
|
headlamp/bin/headlamp
ADDED
|
Binary file
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: headlamp
|
|
3
|
+
Version: 0.1.60
|
|
4
|
+
Summary: Dependency-graph based test runner in Rust that supports Rust, Python, and JavaScript.
|
|
5
|
+
Author: David Piper
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/dbpiper/headlamp
|
|
8
|
+
Project-URL: Repository, https://github.com/dbpiper/headlamp
|
|
9
|
+
Keywords: testing,cli,pytest,jest,nextest
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# Headlamp
|
|
16
|
+
|
|
17
|
+
Headlamp is a **Rust-powered test UX CLI**: smarter test selection, cleaner output, and a unified workflow across **jest**, **Rust tests (headlamp runner)**, **cargo test**, **cargo nextest**, and **pytest**.
|
|
18
|
+
|
|
19
|
+
Headlamp is useful when you want a consistent way to run tests across different projects and keep feedback fast as your repo grows. It can select tests based on what changed, surface failures in a readable format, and keep common defaults (like runner args and coverage settings) in a single config file so your team doesn’t have to remember a long list of flags.
|
|
20
|
+
|
|
21
|
+
## Why Headlamp
|
|
22
|
+
|
|
23
|
+
- **One CLI, many runners**: `--runner=headlamp|jest|cargo-nextest|cargo-test|pytest`
|
|
24
|
+
- **Selection that scales**: run what changed (`--changed`) and what’s related (dependency-graph driven)
|
|
25
|
+
- **Coverage-first UX**: coverage output you can actually read
|
|
26
|
+
- **Fast**: Rust core + caching
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
### npm (Node.js projects)
|
|
31
|
+
|
|
32
|
+
Requirements:
|
|
33
|
+
|
|
34
|
+
- Node **>= 18**
|
|
35
|
+
|
|
36
|
+
Install:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm i -D headlamp
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Run:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npx headlamp --help
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Cargo (Rust projects)
|
|
49
|
+
|
|
50
|
+
Install from crates.io:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cargo install headlamp
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Python (pytest projects)
|
|
57
|
+
|
|
58
|
+
Install:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install headlamp
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
headlamp --runner=pytest
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Peer dependencies (system requirements)
|
|
69
|
+
|
|
70
|
+
Headlamp is a wrapper around your project’s runners. It does **not** vendor the runners themselves, so you need the runner executables available in your environment for the features you’re using.
|
|
71
|
+
|
|
72
|
+
### Common (all runners)
|
|
73
|
+
|
|
74
|
+
- **Git**: required for `--changed=...` modes (e.g. `--changed=branch`).
|
|
75
|
+
|
|
76
|
+
### Jest runner (`--runner=jest`)
|
|
77
|
+
|
|
78
|
+
- **Node.js**: required.
|
|
79
|
+
- **Jest installed in the repo**: Headlamp expects Jest to be runnable from your project (typically `./node_modules/.bin/jest`).
|
|
80
|
+
- **Coverage** (`--coverage`): requires Jest coverage support (standard Jest `--coverage` + reporters). Headlamp formats/prints coverage from generated reports.
|
|
81
|
+
|
|
82
|
+
### Pytest runner (`--runner=pytest`)
|
|
83
|
+
|
|
84
|
+
- **Python 3**: required.
|
|
85
|
+
- **pytest**: must be on `PATH` (`pytest` / `pytest.exe`).
|
|
86
|
+
- **Coverage** (`--coverage`): requires `pytest-cov` (Headlamp enables coverage and passes `--cov` flags; branch coverage uses `--cov-branch`).
|
|
87
|
+
|
|
88
|
+
### Headlamp (native Rust runner) (`--runner=headlamp`)
|
|
89
|
+
|
|
90
|
+
- **Rust toolchain**: `cargo` + `rustc`.
|
|
91
|
+
- **Per-test timings**: requires a preinstalled nightly toolchain (Headlamp enables libtest JSON + `--report-time` only when nightly is available).
|
|
92
|
+
- Install via: `rustup toolchain install nightly`
|
|
93
|
+
|
|
94
|
+
### Cargo test runner (`--runner=cargo-test`)
|
|
95
|
+
|
|
96
|
+
- **Rust toolchain**: `cargo` + `rustc`.
|
|
97
|
+
- **Coverage** (`--coverage`): collected via LLVM tools from `rustup` (**no `cargo-llvm-cov` dependency**).
|
|
98
|
+
- Install via: `rustup component add llvm-tools-preview`
|
|
99
|
+
|
|
100
|
+
### Cargo nextest runner (`--runner=cargo-nextest`)
|
|
101
|
+
|
|
102
|
+
- **Rust toolchain**: `cargo` + `rustc`.
|
|
103
|
+
- **nextest**: requires **`cargo-nextest`** (`cargo install cargo-nextest`).
|
|
104
|
+
- **Coverage** (`--coverage`): collected via LLVM tools from `rustup` (**no `cargo-llvm-cov` dependency**).
|
|
105
|
+
- Install via: `rustup component add llvm-tools-preview`
|
|
106
|
+
|
|
107
|
+
## Quickstart
|
|
108
|
+
|
|
109
|
+
### Jest
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
npx headlamp --runner=jest
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Forward runner args after `--` (unknown args are forwarded):
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npx headlamp --runner=jest -- --runInBand
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Cargo nextest / cargo test
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
headlamp --runner=cargo-nextest
|
|
125
|
+
headlamp --runner=cargo-test
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Requirements:
|
|
129
|
+
|
|
130
|
+
- `--runner=cargo-nextest`: requires `cargo-nextest` to be installed.
|
|
131
|
+
- Install via: `cargo install cargo-nextest` (or your preferred installer)
|
|
132
|
+
|
|
133
|
+
## CLI
|
|
134
|
+
|
|
135
|
+
Run `headlamp --help` to see the up-to-date flags list.
|
|
136
|
+
|
|
137
|
+
Highlights:
|
|
138
|
+
|
|
139
|
+
- **runners**: `--runner=headlamp|jest|pytest|cargo-nextest|cargo-test`
|
|
140
|
+
- **changed selection**: `--changed=all|staged|unstaged|branch|lastCommit|lastRelease`
|
|
141
|
+
- `lastRelease` selects changes since the previous stable SemVer release tag
|
|
142
|
+
- **coverage**: `--coverage` plus `--coverage-ui`, `--coverage-detail`, thresholds, etc.
|
|
143
|
+
- **artifacts** (default: none): `--keep-artifacts` to keep runner artifacts on disk
|
|
144
|
+
|
|
145
|
+
Legacy aliases (still accepted, but not recommended):
|
|
146
|
+
|
|
147
|
+
- `--keepArtifacts`
|
|
148
|
+
- `--coverage.detail`
|
|
149
|
+
|
|
150
|
+
## Configuration
|
|
151
|
+
|
|
152
|
+
Headlamp discovers config from your repo root. Supported file names:
|
|
153
|
+
|
|
154
|
+
- `headlamp.toml` (highest precedence)
|
|
155
|
+
- `headlamp.config.ts`
|
|
156
|
+
- `headlamp.config.js`
|
|
157
|
+
- `headlamp.config.mjs`
|
|
158
|
+
- `headlamp.config.cjs`
|
|
159
|
+
- `headlamp.config.json`
|
|
160
|
+
- `headlamp.config.json5`
|
|
161
|
+
- `headlamp.config.jsonc`
|
|
162
|
+
- `headlamp.config.yaml`
|
|
163
|
+
- `headlamp.config.yml`
|
|
164
|
+
- `.headlamprc` plus `.headlamprc.*` variants (`.json`, `.json5`, `.jsonc`, `.yaml`, `.yml`, `.js`, `.cjs`, `.mjs`, `.ts`)
|
|
165
|
+
|
|
166
|
+
Headlamp also supports embedded TOML config (lower precedence than explicit config files):
|
|
167
|
+
|
|
168
|
+
- `pyproject.toml` under `[tool.headlamp]`
|
|
169
|
+
- `Cargo.toml` under `[package.metadata.headlamp]`
|
|
170
|
+
|
|
171
|
+
### Example: `headlamp.toml` (recommended for Rust + Python)
|
|
172
|
+
|
|
173
|
+
```toml
|
|
174
|
+
# Run tests sequentially (useful for very heavy integration tests)
|
|
175
|
+
sequential = true
|
|
176
|
+
|
|
177
|
+
[coverage]
|
|
178
|
+
abort_on_failure = true
|
|
179
|
+
mode = "auto"
|
|
180
|
+
page_fit = true
|
|
181
|
+
keep_artifacts = false
|
|
182
|
+
|
|
183
|
+
[changed]
|
|
184
|
+
depth = 20
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Example: `headlamp.config.ts`
|
|
188
|
+
|
|
189
|
+
Rules:
|
|
190
|
+
|
|
191
|
+
- Must have a **default export**
|
|
192
|
+
- Only **relative imports** are supported inside the config file (`./` and `../`)
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
export default {
|
|
196
|
+
// Runner defaults
|
|
197
|
+
jestArgs: ["--runInBand"],
|
|
198
|
+
|
|
199
|
+
// Run once before tests (npm script name or a shell command)
|
|
200
|
+
bootstrapCommand: "test:jest:bootstrap",
|
|
201
|
+
|
|
202
|
+
// Global toggles
|
|
203
|
+
ci: false,
|
|
204
|
+
verbose: false,
|
|
205
|
+
noCache: false,
|
|
206
|
+
keepArtifacts: false,
|
|
207
|
+
|
|
208
|
+
// Coverage defaults
|
|
209
|
+
coverage: true,
|
|
210
|
+
coverageUi: "both",
|
|
211
|
+
coverage: {
|
|
212
|
+
abortOnFailure: true,
|
|
213
|
+
mode: "auto",
|
|
214
|
+
pageFit: true,
|
|
215
|
+
},
|
|
216
|
+
|
|
217
|
+
// Changed selection defaults
|
|
218
|
+
changed: { depth: 2 },
|
|
219
|
+
};
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Artifacts (coverage, caches, temp files)
|
|
223
|
+
|
|
224
|
+
By default, headlamp runs **artifact-free**: it uses an ephemeral per-run workspace and **does not leave files behind** in your repo (e.g. `coverage/`, `.coverage`, `.pytest_cache`, `target/`) or OS temp.
|
|
225
|
+
|
|
226
|
+
If you need artifacts on disk (for example, to upload coverage reports in CI), opt out:
|
|
227
|
+
|
|
228
|
+
- CLI: `--keep-artifacts`
|
|
229
|
+
- Config: `keepArtifacts: true`
|
|
230
|
+
|
|
231
|
+
## Contributing
|
|
232
|
+
|
|
233
|
+
Pull requests are welcome. For large changes, open an issue first to align on direction.
|
|
234
|
+
|
|
235
|
+
## Support
|
|
236
|
+
|
|
237
|
+
- Bug reports and feature requests: GitHub Issues
|
|
238
|
+
|
|
239
|
+
## License
|
|
240
|
+
|
|
241
|
+
MIT — see `LICENSE`.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
headlamp-0.1.60.dist-info/RECORD,,
|
|
2
|
+
headlamp-0.1.60.dist-info/WHEEL,sha256=0wJZkrMXhHamlhyeyzwHZC6TVoCduvm5-sXAkwO3M0I,133
|
|
3
|
+
headlamp-0.1.60.dist-info/entry_points.txt,sha256=LGS3na55nE6Ut1Es24pTJn6KNgz3UOiNTYZRE2urwgU,48
|
|
4
|
+
headlamp-0.1.60.dist-info/top_level.txt,sha256=eRZTjDhtIwmMCPa_qwcrLUl5OgT0gNtzjq58QS569K0,9
|
|
5
|
+
headlamp-0.1.60.dist-info/METADATA,sha256=36AzlYrRL-TTYNJMPbdWqsk5ccsUYQ-BSFY8wZfqElU,6843
|
|
6
|
+
headlamp/_cli.py,sha256=q9ihu8IP0E5aNjgS4l4TRaP7GNhzpkiRPn8E-Ye9iQM,580
|
|
7
|
+
headlamp/__init__.py,sha256=it3ellGUCNveQ94VrupKnDtN-5KiThF3eIhCO27V14U,181
|
|
8
|
+
headlamp/_bin.py,sha256=IaqveR8dNiphXcQcsR5DeS0h4O8X-8TN_062qNZIo_o,2045
|
|
9
|
+
headlamp/bin/headlamp,sha256=hHdDgMRSHc-xi9cP-v1FEOU1SLlLyEt5711gGBGwbYM,5082672
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
headlamp
|