galtea-cli 0.0.1__py3-none-win_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.
- galtea_cli/__init__.py +27 -0
- galtea_cli/__main__.py +70 -0
- galtea_cli/_locate.py +67 -0
- galtea_cli/bin/galtea.exe +0 -0
- galtea_cli-0.0.1.dist-info/METADATA +106 -0
- galtea_cli-0.0.1.dist-info/RECORD +8 -0
- galtea_cli-0.0.1.dist-info/WHEEL +5 -0
- galtea_cli-0.0.1.dist-info/entry_points.txt +2 -0
galtea_cli/__init__.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""galtea-cli — Python wrapper around the native galtea binary.
|
|
2
|
+
|
|
3
|
+
This package is a thin shim that locates the platform-specific
|
|
4
|
+
`galtea` executable bundled inside the wheel and forwards stdin /
|
|
5
|
+
stdout / stderr / signals / exit codes to it.
|
|
6
|
+
|
|
7
|
+
The version string is sourced from the installed distribution metadata
|
|
8
|
+
via `importlib.metadata.version("galtea-cli")` — the single
|
|
9
|
+
authoritative source. cli.yml sed-replaces the placeholder in
|
|
10
|
+
pyproject.toml at build time, and that value flows through here without
|
|
11
|
+
a parallel placeholder to keep in sync.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
__version__: str = version("galtea-cli")
|
|
20
|
+
except PackageNotFoundError:
|
|
21
|
+
# Source-tree / editable / uninstalled scenarios (e.g. running tests
|
|
22
|
+
# from cli/python/ without a prior `pip install`). Fall through to a
|
|
23
|
+
# sentinel rather than raising — `import galtea_cli` should not break
|
|
24
|
+
# before the package is installed.
|
|
25
|
+
__version__ = "0.0.0+unknown"
|
|
26
|
+
|
|
27
|
+
__all__: list[str] = ["__version__"]
|
galtea_cli/__main__.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""Console-script entry point for the galtea wheel.
|
|
2
|
+
|
|
3
|
+
`pip install galtea-cli` registers this module under the `galtea`
|
|
4
|
+
name (see `[project.scripts]` in pyproject.toml). At runtime we
|
|
5
|
+
locate the bundled native binary, invoke it as a subprocess, and
|
|
6
|
+
propagate its exit code.
|
|
7
|
+
|
|
8
|
+
We use subprocess.run + sys.exit (NOT os.execv) on purpose:
|
|
9
|
+
|
|
10
|
+
- os.execv replaces the current process image with the binary, which
|
|
11
|
+
on POSIX is fine but on Windows is emulated via subprocess +
|
|
12
|
+
exit-code copying with subtle semantics (signal handling, console
|
|
13
|
+
attach, exit-code truncation to 16 bits in some shells). Running
|
|
14
|
+
the binary as a subprocess and forwarding its return code is
|
|
15
|
+
identical on every platform we ship.
|
|
16
|
+
- subprocess.run with default stdio inheritance forwards stdin,
|
|
17
|
+
stdout, stderr to the child without buffering, so interactive
|
|
18
|
+
prompts (`galtea login` no-echo password input) and TTY detection
|
|
19
|
+
work the same way they do when the binary is invoked directly.
|
|
20
|
+
- KeyboardInterrupt is forwarded as SIGINT to the child on POSIX and
|
|
21
|
+
as the equivalent on Windows; we exit with the child's return code
|
|
22
|
+
rather than 130 so existing CI harnesses that key off galtea's
|
|
23
|
+
documented exit codes (e.g. exit 10 = version-gate hard-block, see
|
|
24
|
+
`cli-go.md` Versioning section) keep working.
|
|
25
|
+
|
|
26
|
+
Pattern reference: astral-sh/ruff (`ruff/__main__.py`), astral-sh/uv
|
|
27
|
+
(`uv/__main__.py`).
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
import subprocess
|
|
33
|
+
import sys
|
|
34
|
+
|
|
35
|
+
from galtea_cli._locate import find_binary
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def main() -> None:
|
|
39
|
+
"""Locate the bundled galtea binary and forward control to it."""
|
|
40
|
+
try:
|
|
41
|
+
binary: str = find_binary()
|
|
42
|
+
except FileNotFoundError as exc:
|
|
43
|
+
print(f"galtea-cli: {exc}", file=sys.stderr)
|
|
44
|
+
sys.exit(1)
|
|
45
|
+
|
|
46
|
+
# subprocess.run with the original argv tail; check=False so we
|
|
47
|
+
# propagate non-zero exit codes ourselves rather than raising
|
|
48
|
+
# CalledProcessError. close_fds defaults are fine on every
|
|
49
|
+
# platform we ship.
|
|
50
|
+
try:
|
|
51
|
+
completed: subprocess.CompletedProcess[bytes] = subprocess.run(
|
|
52
|
+
[binary, *sys.argv[1:]],
|
|
53
|
+
check=False,
|
|
54
|
+
)
|
|
55
|
+
except OSError as exc:
|
|
56
|
+
# Triggered by e.g. a wrong-platform wheel force-installed via
|
|
57
|
+
# `pip install --platform=...`, missing exec bit, or a virus
|
|
58
|
+
# scanner briefly locking the binary on Windows. Surface a
|
|
59
|
+
# clear remediation hint instead of a Python traceback.
|
|
60
|
+
print(
|
|
61
|
+
f"galtea-cli: failed to execute bundled binary at {binary}: {exc}\n"
|
|
62
|
+
"Try `pip install --upgrade --force-reinstall galtea-cli`.",
|
|
63
|
+
file=sys.stderr,
|
|
64
|
+
)
|
|
65
|
+
sys.exit(1)
|
|
66
|
+
sys.exit(completed.returncode)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
if __name__ == "__main__":
|
|
70
|
+
main()
|
galtea_cli/_locate.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Locate the bundled galtea binary inside the installed wheel.
|
|
2
|
+
|
|
3
|
+
Each per-platform wheel embeds exactly one binary under
|
|
4
|
+
`galtea_cli/bin/`:
|
|
5
|
+
- POSIX wheels (linux / macOS): `galtea_cli/bin/galtea`
|
|
6
|
+
- Windows wheels: `galtea_cli/bin/galtea.exe`
|
|
7
|
+
|
|
8
|
+
We deliberately don't fall through to a `PATH` lookup or a downloader:
|
|
9
|
+
the contract of this wheel is that the binary it advertises is the
|
|
10
|
+
binary it ships. If the binary is missing, that's a packaging bug we
|
|
11
|
+
want to surface loudly rather than silently substitute a different
|
|
12
|
+
version installed elsewhere on the system.
|
|
13
|
+
|
|
14
|
+
Pattern reference: astral-sh/ruff (`ruff/_find_ruff.py`),
|
|
15
|
+
astral-sh/uv (`uv/_find_uv.py`).
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import os
|
|
21
|
+
import sys
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _binary_filename() -> str:
|
|
26
|
+
"""Return the bundled binary's filename for the current platform.
|
|
27
|
+
|
|
28
|
+
Windows ships `galtea.exe`; everything else ships `galtea`. This
|
|
29
|
+
matches GoReleaser's per-target output and the `format_overrides`
|
|
30
|
+
in `cli/.goreleaser.yaml`.
|
|
31
|
+
"""
|
|
32
|
+
if sys.platform == "win32":
|
|
33
|
+
return "galtea.exe"
|
|
34
|
+
return "galtea"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def find_binary() -> str:
|
|
38
|
+
"""Return the absolute path to the bundled galtea binary.
|
|
39
|
+
|
|
40
|
+
Raises FileNotFoundError with a clear, actionable message when the
|
|
41
|
+
binary is missing — almost always means the wheel was built
|
|
42
|
+
without running `build_wheels.py` (or `cli/dist/` was empty when
|
|
43
|
+
the wheel was assembled), not a runtime configuration issue. The
|
|
44
|
+
message names the expected path so packagers and SREs can confirm
|
|
45
|
+
the failure mode without spelunking the wheel.
|
|
46
|
+
"""
|
|
47
|
+
bin_dir: Path = Path(__file__).resolve().parent / "bin"
|
|
48
|
+
binary_path: Path = bin_dir / _binary_filename()
|
|
49
|
+
if not binary_path.is_file():
|
|
50
|
+
raise FileNotFoundError(
|
|
51
|
+
f"galtea binary not found at {binary_path}. "
|
|
52
|
+
"This usually means the wheel was built without bundling a "
|
|
53
|
+
"platform-specific binary. Reinstall galtea-cli, or download "
|
|
54
|
+
"the binary directly from "
|
|
55
|
+
"https://github.com/Galtea-AI/monorepo/releases."
|
|
56
|
+
)
|
|
57
|
+
# Defensive: ensure executable bit on POSIX. Wheels preserve the
|
|
58
|
+
# mode field, but a hand-extracted wheel on a hostile filesystem
|
|
59
|
+
# can lose it. OR with 0o111 (just the execute bits) instead of
|
|
60
|
+
# 0o755 — a binary the user explicitly chmod'd 0o600 should not
|
|
61
|
+
# silently become world-readable as a side effect of running it.
|
|
62
|
+
# No-op on Windows where the .exe extension governs executability.
|
|
63
|
+
if sys.platform != "win32":
|
|
64
|
+
mode: int = binary_path.stat().st_mode
|
|
65
|
+
if not mode & 0o111:
|
|
66
|
+
os.chmod(binary_path, mode | 0o111)
|
|
67
|
+
return str(binary_path)
|
|
Binary file
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: galtea-cli
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Galtea CLI — terminal-native client for the Galtea AI testing & evaluation platform
|
|
5
|
+
Project-URL: Homepage, https://galtea.ai/
|
|
6
|
+
Project-URL: Documentation, https://docs.galtea.ai/
|
|
7
|
+
Project-URL: Repository, https://github.com/Galtea-AI/monorepo
|
|
8
|
+
Project-URL: Issues, https://github.com/Galtea-AI/monorepo/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/Galtea-AI/monorepo/releases
|
|
10
|
+
Author-email: Galtea AI <info@galtea.ai>
|
|
11
|
+
License-Expression: Apache-2.0
|
|
12
|
+
Keywords: ai-testing,cli,galtea,llm-evaluation,mlops
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
18
|
+
Classifier: Operating System :: MacOS
|
|
19
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
20
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
21
|
+
Classifier: Programming Language :: Python
|
|
22
|
+
Classifier: Programming Language :: Python :: 3
|
|
23
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
27
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
28
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
29
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
30
|
+
Classifier: Topic :: Software Development
|
|
31
|
+
Classifier: Topic :: Utilities
|
|
32
|
+
Requires-Python: >=3.9
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# galtea-cli
|
|
36
|
+
|
|
37
|
+
<p align="center">
|
|
38
|
+
<img src="https://galtea.ai/img/galtea_mod.png" alt="Galtea" width="500" height="auto"/>
|
|
39
|
+
</p>
|
|
40
|
+
|
|
41
|
+
<p align="center">
|
|
42
|
+
<strong>Terminal-native client for the Galtea AI Testing & Evaluation Platform</strong>
|
|
43
|
+
</p>
|
|
44
|
+
|
|
45
|
+
<p align="center">
|
|
46
|
+
<a href="https://pypi.org/project/galtea-cli/">
|
|
47
|
+
<img src="https://img.shields.io/pypi/v/galtea-cli.svg" alt="PyPI version">
|
|
48
|
+
</a>
|
|
49
|
+
<a href="https://github.com/Galtea-AI/monorepo/releases">
|
|
50
|
+
<img src="https://img.shields.io/badge/platform-linux%20%7C%20macOS%20%7C%20windows-lightgrey" alt="Platform support: Linux, macOS, Windows">
|
|
51
|
+
</a>
|
|
52
|
+
<a href="https://www.apache.org/licenses/LICENSE-2.0">
|
|
53
|
+
<img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg" alt="License">
|
|
54
|
+
</a>
|
|
55
|
+
</p>
|
|
56
|
+
|
|
57
|
+
The official command-line client for the [Galtea AI testing & evaluation
|
|
58
|
+
platform](https://galtea.ai/), distributed as a Python package for
|
|
59
|
+
zero-friction install on machines that already have Python.
|
|
60
|
+
|
|
61
|
+
## Install
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install galtea-cli
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
That's it. The wheel ships the matching native `galtea` binary inside
|
|
68
|
+
the package and registers a `galtea` console script on your `PATH`:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
galtea --version
|
|
72
|
+
galtea login
|
|
73
|
+
galtea products list
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Other install channels
|
|
77
|
+
|
|
78
|
+
`galtea-cli` is one of several first-class distribution channels for the
|
|
79
|
+
same single binary. Pick whichever fits your environment:
|
|
80
|
+
|
|
81
|
+
| Channel | Install gesture |
|
|
82
|
+
|---------|-----------------|
|
|
83
|
+
| PyPI (this package) | `pip install galtea-cli` |
|
|
84
|
+
| Homebrew | `brew install galtea-ai/tap/galtea` |
|
|
85
|
+
| Scoop | `scoop bucket add galtea https://github.com/Galtea-AI/scoop-bucket && scoop install galtea` |
|
|
86
|
+
| Winget | `winget install galtea` |
|
|
87
|
+
| Debian / Ubuntu (apt) | `apt install galtea` — see [pkgs.galtea.ai](https://pkgs.galtea.ai) for the one-time `apt` source setup |
|
|
88
|
+
| Fedora / RHEL (dnf) | `dnf install galtea` — see [pkgs.galtea.ai](https://pkgs.galtea.ai) for the one-time `dnf` repo setup |
|
|
89
|
+
| Direct `.deb` / `.rpm` | Download from the [latest GitHub Release](https://github.com/Galtea-AI/monorepo/releases) and `dpkg -i` / `rpm -i` |
|
|
90
|
+
| Direct download | [GitHub Releases](https://github.com/Galtea-AI/monorepo/releases) `tar.gz` / `zip` |
|
|
91
|
+
|
|
92
|
+
The same binary ships through every channel — nothing is rebuilt per
|
|
93
|
+
channel. See
|
|
94
|
+
[`cli/adr/0005-pypi-distribution-and-monorepo-train.md`](https://github.com/Galtea-AI/monorepo/blob/main/cli/adr/0005-pypi-distribution-and-monorepo-train.md)
|
|
95
|
+
for the rationale.
|
|
96
|
+
|
|
97
|
+
## Documentation
|
|
98
|
+
|
|
99
|
+
📖 **Full CLI documentation:** [docs.galtea.ai](https://docs.galtea.ai/) — command reference, tutorials, and authentication guides.
|
|
100
|
+
|
|
101
|
+
For source code, issues, and release notes see the
|
|
102
|
+
[monorepo](https://github.com/Galtea-AI/monorepo).
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
Apache License 2.0.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
galtea_cli/__init__.py,sha256=_aDHGW46-lUZ6gOACX8Dc_HOIhz03361kYueqqcQ60k,1065
|
|
2
|
+
galtea_cli/__main__.py,sha256=FDuocsYBNaqsETWSXkta8HwX7JvHmP1oJDYlj5cjgOk,2712
|
|
3
|
+
galtea_cli/_locate.py,sha256=BBvjt385Luju00gEoUoyHciipfzTd_l89hay_nYAXYA,2694
|
|
4
|
+
galtea_cli/bin/galtea.exe,sha256=vqh4Ye9H9HJfjQeXTlHiX5Kb4kUJNJx2a2Dq3PoToKI,29803520
|
|
5
|
+
galtea_cli-0.0.1.dist-info/METADATA,sha256=ne8erbp86fvVa4FdhCjqcBhVsa8kC6A6jXwIXns2YJ0,4305
|
|
6
|
+
galtea_cli-0.0.1.dist-info/WHEEL,sha256=6DgTJ2Z0I5W7TD8VEgEN7txkKKsPwKeQ2XjbAD8fboY,94
|
|
7
|
+
galtea_cli-0.0.1.dist-info/entry_points.txt,sha256=osQhcSz4pUM2EQxS5eq7xAWFUQN5Y5kcJ2DPAo15CNQ,52
|
|
8
|
+
galtea_cli-0.0.1.dist-info/RECORD,,
|