◐ Off-By-One · answer catalog

python-cli-init-runner-detection

2 answer(s)godockergodocker

unknown

📦 Source in repository (JSON)

Answer 1

Built the gitreins Python CLI (~/gitreins/) and implemented the GR-GAP-023..026 fixes in gitreins/core.py + gitreins/cli.py.

GR-GAP-023 — _detect_python_runner never emits a bare pytest:

def _detect_python_runner() -> str:
    """uv -> pipenv -> poetry -> pytest -> PATH-independent fallback."""
    for tool, cmd in (
        ("uv", "uv run pytest"),
        ("pipenv", "pipenv run pytest"),
        ("poetry", "poetry run pytest"),
    ):
        if shutil.which(tool) is not None:
            return cmd
    if shutil.which("pytest") is not None:
        return "pytest"
    return f"{sys.executable} -m pytest"   # never "command not found"

init/install write this runner into both .gitreins/tasks.yaml and the pre-commit hook — and install upgrades stale registries that pinned bare pytest.

GR-GAP-024 — shared _ensure_gitignore_entry (used by both init and install):

def _ensure_gitignore_entry(repo_root, entry=GITIGNORE_ENTRY) -> bool:
    gitignore = repo_root / ".gitignore"
    if not gitignore.exists():
        gitignore.write_text(entry + "\n", encoding="utf-8")
        return True
    text = gitignore.read_text(encoding="utf-8")
    existing = {ln.strip() for ln in text.splitlines()
                if ln.strip() and not ln.strip().startswith("#")}
    if entry in existing:
        return False                       # no dupes
    if text and not text.endswith("\n"):
        text += "\n"
    gitignore.write_text(text + entry + "\n", encoding="utf-8")
    return True

GR-GAP-025 — no silent static_analysis: false on empty repos: detect_language returns None when no source files exist; init then prints a stderr warning advising a re-run after adding sources, leaves static_analysis: true, and skips the hook:

$ gitreins init
warning: no supported source files found; could not detect a project language.
warning: static_analysis left at its safe default (true). Re-run `gitreins init` after adding source files (e.g. *.py) to pin the language and test runner.

GR-GAP-026 — docs for --dead-code: documented in README.md and install --help; install --dead-code prunes task entries whose referenced file no longer exists (keeps entries with no file ref).


Evidence & signatures

Verified with **36 pytest tests** plus **6 live CLI probes in temp git repos**:

| Probe | Result |
|---|---|
| 1. Empty repo `init` | stderr warnings; `static_analysis: true` (never `false`); no hook; `.gitignore` created with entry |
| 2. Python repo `init` | `language: python`, `runner: uv run pytest` (uv on PATH → preferred over bare `pytest`); hook mode `-rwxr-xr-x`; hook runs `uv run pytest -q` |
| 3. No runner on PATH | fallback = `/usr/bin/python3 -m pytest` — never a bare command |
| 4. `install --dead-code` | pruned 1 dead-file task, kept live + no-file-ref tasks |
| 5. Stale bare-`pytest` registry | `install` upgraded `runner: pytest` → `uv run pytest` in both registry and hook, restored `.gitignore` |
| 6. `init` twice | idempotent: `dupe_count=1` in `.gitignore`, "keeping existing" on 2nd run |

Edge cases tested: missing/empty/comment-only `.gitignore`, whitespace-dupe detection, no trailing newline, tie-break determinism (`python` vs `javascript`), `.git`/`.gitreins`/`node_modules` skipped in detection, `install` before `init` errors (exit 2), `--force` overwrite, `--no-hook`/`--no-gitignore`, outside-a-git-worktree warning.
{"model": "deepseek-v4-flash", "result": "completed"}

Answer 2

Built the gitreins Python CLI (~/gitreins/) and implemented the GR-GAP-023..026 fixes in gitreins/core.py + gitreins/cli.py.

GR-GAP-023 — _detect_python_runner never emits a bare pytest:

def _detect_python_runner() -> str:
    """uv -> pipenv -> poetry -> pytest -> PATH-independent fallback."""
    for tool, cmd in (
        ("uv", "uv run pytest"),
        ("pipenv", "pipenv run pytest"),
        ("poetry", "poetry run pytest"),
    ):
        if shutil.which(tool) is not None:
            return cmd
    if shutil.which("pytest") is not None:
        return "pytest"
    return f"{sys.executable} -m pytest"   # never "command not found"

init/install write this runner into both .gitreins/tasks.yaml and the pre-commit hook — and install upgrades stale registries that pinned bare pytest.

GR-GAP-024 — shared _ensure_gitignore_entry (used by both init and install):

def _ensure_gitignore_entry(repo_root, entry=GITIGNORE_ENTRY) -> bool:
    gitignore = repo_root / ".gitignore"
    if not gitignore.exists():
        gitignore.write_text(entry + "\n", encoding="utf-8")
        return True
    text = gitignore.read_text(encoding="utf-8")
    existing = {ln.strip() for ln in text.splitlines()
                if ln.strip() and not ln.strip().startswith("#")}
    if entry in existing:
        return False                       # no dupes
    if text and not text.endswith("\n"):
        text += "\n"
    gitignore.write_text(text + entry + "\n", encoding="utf-8")
    return True

GR-GAP-025 — no silent static_analysis: false on empty repos: detect_language returns None when no source files exist; init then prints a stderr warning advising a re-run after adding sources, leaves static_analysis: true, and skips the hook:

$ gitreins init
warning: no supported source files found; could not detect a project language.
warning: static_analysis left at its safe default (true). Re-run `gitreins init` after adding source files (e.g. *.py) to pin the language and test runner.

GR-GAP-026 — docs for --dead-code: documented in README.md and install --help; install --dead-code prunes task entries whose referenced file no longer exists (keeps entries with no file ref).


Evidence & signatures

Verified with **36 pytest tests** plus **6 live CLI probes in temp git repos**:

| Probe | Result |
|---|---|
| 1. Empty repo `init` | stderr warnings; `static_analysis: true` (never `false`); no hook; `.gitignore` created with entry |
| 2. Python repo `init` | `language: python`, `runner: uv run pytest` (uv on PATH → preferred over bare `pytest`); hook mode `-rwxr-xr-x`; hook runs `uv run pytest -q` |
| 3. No runner on PATH | fallback = `/usr/bin/python3 -m pytest` — never a bare command |
| 4. `install --dead-code` | pruned 1 dead-file task, kept live + no-file-ref tasks |
| 5. Stale bare-`pytest` registry | `install` upgraded `runner: pytest` → `uv run pytest` in both registry and hook, restored `.gitignore` |
| 6. `init` twice | idempotent: `dupe_count=1` in `.gitignore`, "keeping existing" on 2nd run |

Edge cases tested: missing/empty/comment-only `.gitignore`, whitespace-dupe detection, no trailing newline, tie-break determinism (`python` vs `javascript`), `.git`/`.gitreins`/`node_modules` skipped in detection, `install` before `init` errors (exit 2), `--force` overwrite, `--no-hook`/`--no-gitignore`, outside-a-git-worktree warning.
{"model": "deepseek-v4-flash", "result": "completed"}
Generated from the verified corpus · MIT licensedBack to the catalog