mirror of
https://github.com/github/spec-kit.git
synced 2026-07-03 12:28:06 +08:00
* feat(cli): add `py` script type & Python interpreter resolution (#3278) Introduce a third script variant alongside `sh`/`ps` as the foundation for unifying workflow scripts under a single Python implementation. - Add `"py": "Python"` to `SCRIPT_TYPE_CHOICES`; `VALID_SCRIPT_TYPES` consumers (init workflow step, init command, _helpers) pick it up automatically since they derive from that mapping. - Add `IntegrationBase.resolve_python_interpreter()` (project venv → `python3` → `python`, falling back to `python3`). - Prefix the resolved interpreter when `process_template()` expands `{SCRIPT}` for the `py` script type so `.py` scripts run portably (notably on Windows); thread `project_root` through callers so venv preference works. - Make `install_scripts()` mark copied `.py` files executable too. Includes positive and negative unit tests for interpreter resolution, `py` template processing, the new choice, and script installation. Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(cli): return repo-relative venv interpreter & correct docstring Address PR review feedback on #3285: - `resolve_python_interpreter()` now returns the venv interpreter as a path relative to the project root (`.venv/bin/python` / `.venv/Scripts/python.exe`) instead of an absolute/joined path, so the generated `{SCRIPT}` invocation stays portable and runnable from the repo root regardless of where the project lives. - Update `install_scripts()` docstring to note `.py` scripts are now made executable alongside `.sh`. - Update tests to assert the repo-relative interpreter path. Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(cli): fall back to sys.executable for interpreter resolution When neither python3 nor python is discoverable on PATH (and no project venv is found), resolve_python_interpreter() now returns the running interpreter (sys.executable) so the generated {SCRIPT} invocation works in the current environment, falling back to "python3" only if that is also unavailable. Update unit tests accordingly. * fix(cli): quote py interpreter path when it contains whitespace For the `py` script type, the resolved interpreter may be an absolute path containing spaces (notably `sys.executable` under Windows `Program Files`). Quote it when it contains whitespace so the `{SCRIPT}` invocation isn't split into multiple arguments. Add positive/negative tests for the quoting behavior. * test: guard executable-bit assertions from Windows chmod semantics The Windows CI job failed because `os.chmod` does not set POSIX executable bits on Windows, so `install_scripts()` cannot make `.py`/ `.sh` files executable there (nor is it needed — the interpreter is invoked explicitly). Split the install_scripts test so file-copy behavior is still verified cross-platform, and skip the executable-bit assertions on win32 (matching the repo's existing pattern). --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
53 lines
1.6 KiB
Python
53 lines
1.6 KiB
Python
"""Tests for the commands/ package structure."""
|
|
import importlib
|
|
|
|
|
|
def test_commands_package_importable():
|
|
mod = importlib.import_module("specify_cli.commands")
|
|
assert mod is not None
|
|
|
|
|
|
def test_commands_init_importable():
|
|
mod = importlib.import_module("specify_cli.commands.init")
|
|
assert hasattr(mod, "register")
|
|
assert callable(mod.register)
|
|
|
|
|
|
def test_agent_config_importable():
|
|
from specify_cli._agent_config import (
|
|
AGENT_CONFIG,
|
|
DEFAULT_INIT_INTEGRATION,
|
|
SCRIPT_TYPE_CHOICES,
|
|
)
|
|
assert isinstance(AGENT_CONFIG, dict)
|
|
assert DEFAULT_INIT_INTEGRATION == "copilot"
|
|
assert "sh" in SCRIPT_TYPE_CHOICES
|
|
|
|
|
|
def test_script_type_choices_includes_python():
|
|
from specify_cli._agent_config import SCRIPT_TYPE_CHOICES
|
|
assert SCRIPT_TYPE_CHOICES.get("py") == "Python"
|
|
# The three supported variants are sh, ps, and py.
|
|
assert {"sh", "ps", "py"} <= set(SCRIPT_TYPE_CHOICES)
|
|
|
|
|
|
def test_workflow_init_valid_script_types_includes_python():
|
|
from specify_cli.workflows.steps.init import VALID_SCRIPT_TYPES
|
|
assert "py" in VALID_SCRIPT_TYPES
|
|
# Negative: an unknown variant is not accepted.
|
|
assert "rb" not in VALID_SCRIPT_TYPES
|
|
|
|
|
|
def test_agent_config_re_exported_from_init():
|
|
from specify_cli import AGENT_CONFIG, SCRIPT_TYPE_CHOICES
|
|
assert isinstance(AGENT_CONFIG, dict)
|
|
assert "sh" in SCRIPT_TYPE_CHOICES
|
|
|
|
|
|
def test_init_command_registered():
|
|
from specify_cli import app
|
|
callback_names = [
|
|
cmd.callback.__name__ for cmd in app.registered_commands if cmd.callback
|
|
]
|
|
assert "init" in callback_names
|