Docs site, PyPI packaging, duckdb (1.0.0 prep) - #8
Merged
Merged
Conversation
Prepares the first PyPI release and gives the project documentation that lives somewhere other than the repo root. Packaging: `Documentation` was "README.md", which is not a URL and PyPI rejects it. Adds license-files, Operating System and Typing classifiers, Python 3.13, py.typed, and a Changelog URL. `__version__` reads from installed metadata rather than being duplicated, and `adata --version` reports it. publish.yml publishes on a tag using PyPI trusted publishing, so there is no API token to hold. It reuses tests.yml via workflow_call, so a release cannot skip the suite, and refuses to publish when the tag does not match the version in pyproject.toml -- nothing enforced that before, and 0.3.2 was tagged against a tree declaring 0.3.1. A workflow_dispatch path targets TestPyPI first. Docs become a GitHub Pages site served from docs/ with plain Jekyll, so the files stay readable as markdown on github.com. Adds index.md, a full COMMANDS.md reference, and to each ELEMENTS doc a section on what this tool actually does with each element -- they were pure spec transcriptions saying nothing about the CLI. Documents the `null` encoding (absent from the upstream prose spec but written by anndata 0.12+) and, for Zarr, the v2/v3 differences that matter when copying between stores. csvkit is replaced by duckdb in the tutorial and the image. The tutorial now leads with `--obs-query`, which covers the example it used csvsql for, and keeps duckdb for filters that genuinely need SQL. The image drops the csvkit side-venv for a single static duckdb binary, and passes the --locked flag its comment already claimed. Verified: the wheel installs into a clean venv and runs; the image builds and the documented duckdb workflow runs inside it end to end. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
# Conflicts: # .github/workflows/tests.yml
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5d189b60d4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
publish-pypi depended on check-version, which only runs for tags. GitHub skips a job whose dependency was skipped, so a manual dispatch targeting PyPI would never have published anything. Both publish jobs now use always() with the success of build asserted explicitly, accepting check-version as either passed or not applicable. The Dockerfile sets ENTRYPOINT ["adata"], so the README and index examples were running `adata adata view ...`, which Typer rejects. Dropped the repeated executable; verified against the built image. COMMANDS.md listed `--zarr-format` among split's options, but the flag did not exist -- `adata split ... --zarr-format 2` failed with an unknown option. Implemented it rather than deleting the claim: split already inherited the source store's Zarr version, so only the override was missing. Adds tests/test_docs_are_accurate.py, which extracts every `adata ...` invocation from the README and docs and checks each command and option against the real --help. That alone would not have caught this one, since the claim lived in prose rather than a fenced example, so sentences naming an option and the commands offering it are checked too. Both checks fail if the flag is removed again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The docs test scraped `--help` output, which Rich wraps to the terminal width. It passed on a wide local terminal and failed in CI, where the width is narrower and long option names break across lines -- an assertion about rendered UI rather than about the CLI. Options now come from the Click command objects behind the Typer app, so the check is exact and width-independent. Verified passing at COLUMNS 40 through 200, and still failing at both widths when --zarr-format is removed from split again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The short name was free when this was planned but has since been claimed by an unrelated "AData CLI" project, uploaded 2026-04-04. Publishing would have failed against a project we do not own, so the distribution is now `pyadata-cli`, matching the pending publisher configured on PyPI. Only the distribution name changes. The repository, the import package, the command and the documentation all stay `adata` / `adata-cli`, so the sole user-visible difference is `pip install pyadata-cli`. That mismatch is explained where the install is documented rather than left to surprise anyone. __version__ reads its metadata under the new name, so `adata --version` keeps working; verified by installing the built wheel into a clean environment. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 3, the last of the roadmap. Stacked on #7, which is stacked on #6 — this PR's own diff is docs, packaging and the Dockerfile.
PyPI
pip install adata-cliwas not possible; several things blocked it.Documentation = "README.md"is not a URL, and PyPI rejects it. Now points at the Pages site.license-files = ["LICENSE"],Operating SystemandTyping :: Typedclassifiers, Python 3.13, apy.typedmarker, and aChangelogURL.__version__reads from installed metadata instead of being duplicated in a second place, andadata --versionreports it.New
publish.ymluses trusted publishing (OIDC), so there is no API token to store. It:tests.ymlthroughworkflow_call, so a release cannot skip the suite;pyproject.toml. Nothing enforced that before, which is how0.3.2came to be tagged against a tree declaring0.3.1;workflow_dispatchpath targeting TestPyPI, so the first publish can be rehearsed.Verified locally:
uv build→twine checkpasses, the wheel installs into a clean venv, andadata --version/adata ls/ the deprecatedh5adalias all work from that install.Docs site
GitHub Pages served from
docs/with plain Jekyll — no generator, so the files stay readable as markdown on github.com.docs/index.md— landing page with a format support matrixdocs/COMMANDS.md— full reference for all eight commands, the query language, and Zarr format selectionELEMENTS_*.mdgains a "Whatadata-clidoes with these elements" section. They were pure spec transcriptions that said nothing about the tool's own behaviour, so nothing in the repo recorded what was and wasn't supported.nullencoding, which is absent from the upstream prose spec but is what anndata 0.12+ writes forNoneinuns.ELEMENTS_zarr.mdgains a v2 vs v3 section covering the differences that actually matter when copying between stores —VLenUTF8infiltersversus the v3 string data type,compressorversuscompressors, sharding — and why text is always written as variable-length UTF-8.docs/TESTING.md.You still need to enable Pages in repo settings → Pages → Deploy from branch →
main//docs.duckdb replaces csvkit
The tutorial now leads with
--obs-query, which covers the exact examplecsvsqlwas there for, and keeps duckdb for filters that genuinely need SQL — joins, aggregates, window functions. duckdb reads the CSV in place with no import step, and-noheader -listemits exactly the one-name-per-line format--obsexpects.The Dockerfile drops the csvkit side-venv for a single static duckdb binary (no venv, so it cannot conflict with the project's dependencies), passes the
--lockedflag its comment already claimed but did not use, drops the stale "install git so we can clone the repo" step, and retargets the image toquay.io/cellgeni/adata-cli.This also folds in what
main's stranded32520d3was reaching for. Note the image is 820MB, largely the Python base — worth a separate look if that matters.Verified with a real build: the image builds, and the documented duckdb workflow runs end to end inside it:
CHANGELOG
Added, covering the whole 0.5.0 line across all three phases, with the deprecation removals called out.
Before you tag
Two things still outstanding from planning, both needing a decision rather than code:
mainanddevhave diverged.maincarries32520d3(duckdb-cli in the Dockerfile) which never reacheddev; mergingdev→mainas-is would revert it. This PR supersedes that commit's intent, so the simplest resolution is probably to take this branch's Dockerfile.0.3.2points atdev's tip, not at anything onmain. Worth reconciling beforepublish.ymlstarts firing on tags.🤖 Generated with Claude Code