diff --git a/.github/workflows/pyvolca.yml b/.github/workflows/pyvolca.yml index c363e413..b24859d8 100644 --- a/.github/workflows/pyvolca.yml +++ b/.github/workflows/pyvolca.yml @@ -49,6 +49,12 @@ jobs: - name: Install pyvolca with dev extras run: pip install -e .[dev] + - name: Type-check with pyright + # Pinned pyright (see dev extras) over src/volca; config in + # pyproject.toml [tool.pyright]. Catches type regressions the + # editor LSP would show but pytest never would. + run: pyright + - name: Download engine binary from main's latest build # Pull the linux-amd64 engine artefact from the most recent # successful build.yml run on main. test_drift.py's live_spec diff --git a/AGENTS.md b/AGENTS.md index 3236312a..bfccb653 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -89,6 +89,7 @@ A Python client lives in `pyvolca/` (own `pyproject.toml`); the MUMPS binding in - Simplicity: perfection = nothing left to remove. Avoid over-engineering and cognitive load. - **Pre-1.0 (`v0.y.z`): no backward-compatibility obligation yet** — keep wire formats and APIs clean rather than carrying cruft. Reassess at `v1.0.0`. - Use language servers for fast diagnostics: HLS for Haskell, pyright for the `pyvolca/` Python client. +- Fix a diagnostic the moment you see it, even a pre-existing one you only surfaced in passing — don't defer it to "later" or leave it because it predates your change. A separate small commit keeps it out of your feature's scope. ### Open-source boundary - This engine stands alone — keep deployment/SaaS concerns and any customer- or product-specific names out of code, comments, and PRs. diff --git a/pyvolca/pyproject.toml b/pyvolca/pyproject.toml index 0f1c0a05..1f7abb15 100644 --- a/pyvolca/pyproject.toml +++ b/pyvolca/pyproject.toml @@ -16,7 +16,7 @@ classifiers = [ ] [project.optional-dependencies] -dev = ["pytest"] +dev = ["pytest", "pyright==1.1.411"] [project.urls] Documentation = "https://volca.run/docs/guides/pyvolca/" @@ -29,3 +29,8 @@ build-backend = "setuptools.build_meta" [tool.setuptools.packages.find] where = ["src"] + +[tool.pyright] +include = ["src/volca"] +typeCheckingMode = "basic" +pythonVersion = "3.10" diff --git a/pyvolca/src/volca/client.py b/pyvolca/src/volca/client.py index b45eed14..62cd9161 100644 --- a/pyvolca/src/volca/client.py +++ b/pyvolca/src/volca/client.py @@ -422,7 +422,7 @@ def _call( self, operation_id: str, *, - substitutions: list[dict] | None = None, + substitutions: list[SubstitutionLike] | None = None, **kwargs: Any, ) -> Any: """Dispatch an OpenAPI operation by ``operationId``. diff --git a/pyvolca/src/volca/types.py b/pyvolca/src/volca/types.py index cea8eb5d..d5276b6e 100644 --- a/pyvolca/src/volca/types.py +++ b/pyvolca/src/volca/types.py @@ -654,8 +654,12 @@ def from_json( if fetch is None: inner_fetch = None else: - def inner_fetch(o: int, l: int | None) -> dict: - return fetch(o, l)["results"] + page_fetch = fetch # narrowed to non-None for the closure below + + def _fetch_results(o: int, l: int | None) -> dict: + return page_fetch(o, l)["results"] + + inner_fetch = _fetch_results return cls( consumers=SearchResults.from_raw( d["results"], parse=ConsumerResult.from_json, fetch=inner_fetch,