galtea-cli 0.0.1__py3-none-win_amd64.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 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=_DocQk3_iA2YaXDLdk71nB7piZGVtJYdxSmFJAutRRo,32435712
5
+ galtea_cli-0.0.1.dist-info/METADATA,sha256=ne8erbp86fvVa4FdhCjqcBhVsa8kC6A6jXwIXns2YJ0,4305
6
+ galtea_cli-0.0.1.dist-info/WHEEL,sha256=fip2IBhkkNvH-S_Xh3PV94_XVqHJB1nn9gTAcldDBj4,94
7
+ galtea_cli-0.0.1.dist-info/entry_points.txt,sha256=osQhcSz4pUM2EQxS5eq7xAWFUQN5Y5kcJ2DPAo15CNQ,52
8
+ galtea_cli-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-win_amd64
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ galtea = galtea_cli.__main__:main