diff --git a/AGENTS.md b/AGENTS.md index 52b13e9..a02a0ca 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,7 +6,7 @@ Use `.venv/bin/python` and `.venv/bin/pip` (repo root) for all Python commands. Invoke the `.venv/bin` executables directly — never system `python`/`pip`. Editable install only. If `jrag`/`java-codebase-rag` serve stale behavior -while pytest passes, run `.venv/bin/pip install -e .` — don't report it. +while pytest passes, run `.venv/bin/pip install -e ".[dev]"` — don't report it. `tests/conftest.py` enforces this. ## Tests diff --git a/docs/JAVA-CODEBASE-RAG-CLI.md b/docs/JAVA-CODEBASE-RAG-CLI.md index 70a29e3..e28df25 100644 --- a/docs/JAVA-CODEBASE-RAG-CLI.md +++ b/docs/JAVA-CODEBASE-RAG-CLI.md @@ -7,7 +7,7 @@ The **`java-codebase-rag`** command is the **operator surface** for this bundle: After installing the package (e.g. editable install from the repo root), the console script is on your `PATH`: ```bash -.venv/bin/pip install -e . +.venv/bin/pip install -e ".[dev]" java-codebase-rag --help ``` diff --git a/tests/conftest.py b/tests/conftest.py index 622b508..2db5d99 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -35,6 +35,7 @@ def pytest_configure(config) -> None: "markers", "lance_e2e: end-to-end cocoindex + Lance (optional; also gate with JAVA_CODEBASE_RAG_RUN_HEAVY).", ) + _enforce_dev_deps() _enforce_editable_install() @@ -67,11 +68,35 @@ def _enforce_editable_install() -> None: where = resolved or f"import failed (rc={res.returncode}): {res.stderr.strip()}" pytest.exit( f"\n[install] `jrag`/`java-codebase-rag` resolve to a stale/non-editable copy " - f"({where}).\n Fix once: .venv/bin/pip install -e . then re-run pytest.\n", + f'({where}).\n Fix once: .venv/bin/pip install -e ".[dev]" then re-run pytest.\n', returncode=4, ) +def _enforce_dev_deps() -> None: + """Fail collection if ``pytest-asyncio`` (a ``[dev]`` extra) is missing. + + ``pytest.ini`` sets ``asyncio_mode = auto``, which is a silent no-op + without the plugin: every ``async def test_*`` is collected and then + fails instantly (~0.01s, coroutine-never-awaited) instead of running. + That signature is indistinguishable from a real regression and has + produced false "pre-existing failures on master" baselines. CI installs + ``[dev]`` (``.github/workflows/test.yml``); this catches a local + ``pip install -e .`` that omitted it. Checked via direct import (not + pluginmanager) so the message clearly names the missing package. + """ + try: + import pytest_asyncio # noqa: F401 + except ImportError: + pytest.exit( + "\n[dev-deps] pytest-asyncio is missing. With pytest.ini's " + "`asyncio_mode = auto`, every async test fails instantly and " + "looks like a real regression.\n" + ' Fix once: .venv/bin/pip install -e ".[dev]" then re-run pytest.\n', + returncode=4, + ) + + @pytest.fixture(scope="session") def corpus_root() -> Path: assert CORPUS_ROOT.is_dir(), f"corpus missing: {CORPUS_ROOT}"