From 41fd65af5b22543eb0b9b68b9e28f9ed97686992 Mon Sep 17 00:00:00 2001 From: FZ2000 Date: Fri, 31 Jul 2026 03:10:58 -0700 Subject: [PATCH] docs: document the PyPI install path in the guides, not just the README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 0.1.0 went to PyPI as `da-sync` and the README was updated, but the getting-started guide — the page the README sends new users to — still documented only `git clone` + `./install.sh`. The one file aimed at people who have never used the tool was the one file that never mentioned the published package. Verified against the real thing rather than by reading: * Installed `da-sync` 0.1.0 from PyPI into a throwaway venv and ran the documented commands with `XDG_CONFIG_HOME`/`XDG_STATE_HOME` pointed at a scratch directory. All 29 README quick-tour commands resolve. * Replayed the `docs/commands/config.md` transcripts in the sandbox the page documents (`/tmp/da-demo`, `client_id=12345`). `config show`, `config path`, `--config`, every `config get` example, the masking rule and the exit codes reproduce byte-for-byte — including `--unmask` writing to stderr, so `2>/dev/null` prints nothing. * Ran `./install.sh` with `DA_INSTALL_PREFIX` redirected. Its output carries a `(N modules)` suffix the transcript had dropped. Three fixes: 1. Getting-started gains the PyPI path, with the clone kept as the option that also carries the scheduling script. 2. `install_schedule.sh` is in the sdist but not the wheel, so `pipx` users cannot run `./install_schedule.sh` as the guides instruct. Both pages now say where to get it; the script's "not found on PATH" error names both install paths. 3. The `(N modules)` count is asserted by `check_doc_references` against `dacli/`. Watched it fail on a wrong number before keeping it. `docs/commands/` examples are executed by `tests/test_docs_examples.py`; `getting-started.md` is not, which is how the stale transcript survived. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 17 ++++++++++++ docs/getting-started.md | 52 +++++++++++++++++++++++++++++++++-- docs/guides/scheduling.md | 12 ++++++++ install_schedule.sh | 3 +- tools/check_doc_references.py | 32 ++++++++++++++++++++- 5 files changed, 111 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 845c9ff..dea57a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,23 @@ that disagrees with it, and PyPI therefore always matches the tag. - README documents the real `pipx install da-sync` path now that 0.1.0 is published, replacing the placeholder that said it was unavailable. +- The getting-started guide now offers the PyPI install as well. It had + only ever documented `git clone` + `./install.sh`, so the tutorial a new + user is pointed at was the one place that never mentioned the published + package. +- `install_schedule.sh` ships in the repository but not in the wheel, so + the scheduling guide and the tutorial's scheduling step now say where to + get it rather than assuming a checkout. Its "not found on PATH" error + names both install paths instead of only `./install.sh`. + +### Fixed + +- The getting-started transcript of `./install.sh` omitted the + `(N modules)` suffix the script actually prints. `check_doc_references` + now asserts any documented module count against `dacli/`, so the number + cannot drift again — `docs/commands/` examples are executed by + `tests/test_docs_examples.py`, but `getting-started.md` is not, which is + how this survived. ## 0.1.0 — 2026-07-30 diff --git a/docs/getting-started.md b/docs/getting-started.md index 0f0afd5..c3e283f 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -49,9 +49,41 @@ Check again with `python3 --version` to confirm it's 3.10 or higher. --- -## Step 2: Download and install da-cli +## Step 2: Install da-cli -In your Terminal, run these three commands one at a time: +There are two ways. Read both first — they suit different people. + +### Option A — install from PyPI (simplest) + +The package is published under the name **`da-sync`**, and the command it +installs is called `da`. In your Terminal: + +```bash +pipx install da-sync +``` + +If you don't have `pipx`, `python3 -m pip install --user da-sync` also +works. `pipx` is worth the extra step, because it gives the tool its own +private environment instead of mixing it into your system Python. + +Check that it worked: + +```bash +da --version +``` + +```text +da-cli 0.1.0 +``` + +### Option B — clone the repository + +Pick this one if you also want the optional macOS scheduling script from +[Daily automatic downloads](#optional-daily-automatic-downloads-macos) +below. That script lives in the repository and is **not** part of the +PyPI package, so Option A cannot give it to you. + +Run these three commands one at a time: ```bash git clone https://github.com/FZ2000/da-cli.git ~/da-cli @@ -70,12 +102,15 @@ You should see output like: ```text installed: ~/.local/share/da-cli/da - ~/.local/share/da-cli/dacli/ + ~/.local/share/da-cli/dacli/ (17 modules) ~/.local/bin/da -> ~/.local/share/da-cli/da da-cli 0.1.0 ``` +The module count reflects however many files the package currently has, +so don't worry if it isn't exactly 17. + **If you see a version number** — installation worked. Move to Step 3. **If you see "da: command not found"** — your system doesn't know @@ -351,6 +386,17 @@ da diagnose # health check (config, auth, disk space) Want art downloaded automatically every day at 3 AM? +This step uses `install_schedule.sh`, which ships in the repository but +not in the PyPI package. If you installed with Option A, get it first: + +```bash +git clone https://github.com/FZ2000/da-cli.git ~/da-cli +cd ~/da-cli +``` + +If you installed with Option B you are already in that directory. Either +way, then run: + ```bash ./install_schedule.sh ``` diff --git a/docs/guides/scheduling.md b/docs/guides/scheduling.md index e7b3db9..421bef7 100644 --- a/docs/guides/scheduling.md +++ b/docs/guides/scheduling.md @@ -6,6 +6,18 @@ watched artists posted. ## macOS +`install_schedule.sh` is part of the repository, not of the `da-sync` +package on PyPI. If you installed with `pipx`, clone the repository to +get it — the script drives whatever `da` is already on your `PATH`, so +you do not need to reinstall: + +```bash +git clone https://github.com/FZ2000/da-cli.git ~/da-cli +cd ~/da-cli +``` + +Then, from that directory: + ```bash ./install_schedule.sh # daily at 03:00 ./install_schedule.sh uninstall # remove it diff --git a/install_schedule.sh b/install_schedule.sh index 69cb5cd..aa5f184 100755 --- a/install_schedule.sh +++ b/install_schedule.sh @@ -111,7 +111,8 @@ fi DA_BIN="$(command -v da || true)" if [[ -z "$DA_BIN" ]]; then - echo "error: 'da' not found on PATH. Run ./install.sh first." >&2 + echo "error: 'da' not found on PATH. Install it first — either" >&2 + echo " './install.sh' from this repository, or 'pipx install da-sync'." >&2 exit 1 fi diff --git a/tools/check_doc_references.py b/tools/check_doc_references.py index 1c249cb..63f3c59 100755 --- a/tools/check_doc_references.py +++ b/tools/check_doc_references.py @@ -118,11 +118,38 @@ def _source_text() -> str: return "\n".join(parts) +def _check_module_count(problems: list[tuple[str, str, int, str]]) -> int: + """`install.sh` prints a live module count; the docs quote a number. + + A quoted count is a claim about the package, and it went stale the + moment it was written: the getting-started transcript omitted the + `(N modules)` suffix entirely while `install.sh` had been printing it + for some time. Nothing noticed, because prose is not executed. + """ + real = sum(1 for _ in (REPO / "dacli").rglob("*.py")) + found = 0 + for doc in sorted(REPO.rglob("*.md")): + rel = str(doc.relative_to(REPO)) + if any(x in rel for x in SKIP_DIRS): + continue + for lineno, line in enumerate(doc.read_text().splitlines(), 1): + m = re.search(r"\((\d+) modules\)", line) + if not m: + continue + found += 1 + if int(m.group(1)) != real: + problems.append( + ("module count is stale", rel, lineno, f"says {m.group(1)}, dacli/ has {real}") + ) + return found + + def main() -> int: paths, by_name = _repo_files() commands, flags = _cli_surface() source = _source_text() problems: list[tuple[str, str, int, str]] = [] + module_counts = _check_module_count(problems) checked = 0 for doc in sorted(REPO.rglob("*.md")): @@ -199,7 +226,10 @@ def main() -> int: # `checked`, not a fresh rglob: the summary must describe the files this # run actually looked at, or a skipped tree inflates the number and the # message quietly overstates the coverage. - print(f"all code references in {checked} markdown files resolve") + print( + f"all code references in {checked} markdown files resolve " + f"({module_counts} module-count claim(s) match dacli/)" + ) return 0