mirror of
https://github.com/kuhyx/signal-bot.git
synced 2026-11-10 19:37:03 +01:00
fix: the tagger sets up its own venv instead of failing on a missing one
"python tool/tagger.py --untagged" died with ModuleNotFoundError: fastapi. The dependencies live in .venv and nothing said so. run.sh had the same hole and answered it by printing the two commands to type and exiting 1 -- which is the same rule broken one step further along: a script owns its dependencies, and making the user be the installer is not owning them. scripts/ensure_venv.sh creates .venv and installs the project editable if the interpreter cannot already import fastapi and signal_bot. Idempotent and cheap: the normal case is two file tests and one import check, 0.17s, so entry points call it unconditionally. tag.sh is the tagger's entry point and run.sh now uses the same helper. Verified on a clone with no .venv at all: ./tag.sh --help created the environment, installed the project and printed the usage. Editable on purpose -- a later git pull updates what the tagger runs, which is the same reason install.sh does it that way in the sibling repos. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBrE1b9HvFw3xvG9bJiDFt
This commit is contained in:
parent
9d546fef9a
commit
99aa194ad8
@ -178,12 +178,16 @@ the album format itself: **`DOCS-add-photo.md`**.
|
||||
## Filling it in: tool/tagger.py
|
||||
|
||||
```sh
|
||||
python tool/tagger.py --import ~/photos # dedup, strip, import, tag
|
||||
python tool/tagger.py --import ~/photos --dry-run # the report only
|
||||
python tool/tagger.py --untagged # only items with no tags
|
||||
python tool/tagger.py # carry on where you left off
|
||||
./tag.sh --import ~/photos # dedup, strip, import, then tag
|
||||
./tag.sh --import ~/photos --dry-run # the report only
|
||||
./tag.sh --untagged # only items with no tags yet
|
||||
./tag.sh # carry on where you left off
|
||||
```
|
||||
|
||||
`tag.sh` sets up `.venv` on first use, so this works on a fresh clone with
|
||||
nothing installed. Same for `run.sh`, which used to print the two commands to
|
||||
type and exit 1.
|
||||
|
||||
It serves one page on `127.0.0.1:8140`: the item, a labelled button per
|
||||
person, `1`–`0` then `q`–`p` to toggle, `→`/`←` to move. Every toggle rewrites
|
||||
`tags.json` atomically, so closing the tab loses nothing. Names are typed
|
||||
|
||||
49
scripts/ensure_venv.sh
Executable file
49
scripts/ensure_venv.sh
Executable file
@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ============================================================================
|
||||
# Make sure .venv exists and has this project installed in it.
|
||||
#
|
||||
# run.sh used to answer a missing venv with a message telling you to type
|
||||
# "uv venv .venv && uv pip install -e '.[dev]'" yourself, and tool/tagger.py
|
||||
# did not even do that -- it failed with ModuleNotFoundError: fastapi. Both
|
||||
# are the same rule broken: a script owns its dependencies.
|
||||
#
|
||||
# Sourced or executed. Idempotent: the common case is two file tests and no
|
||||
# subprocess at all, so entry points can call it unconditionally.
|
||||
# ============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ensure_venv() {
|
||||
local repo_root="$1"
|
||||
local venv="${repo_root}/.venv"
|
||||
local python="${venv}/bin/python"
|
||||
|
||||
# Already good: the interpreter exists and the project imports from it.
|
||||
if [[ -x "$python" ]] && "$python" -c 'import fastapi, signal_bot' 2>/dev/null; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "== setting up ${venv} (one-off)" >&2
|
||||
if [[ ! -x "$python" ]]; then
|
||||
if command -v uv >/dev/null; then
|
||||
uv venv "$venv"
|
||||
elif ! python3 -m venv "$venv"; then
|
||||
echo "Error: could not create a virtualenv at ${venv}" >&2
|
||||
echo " python3 -m venv failed; on Arch: sudo pacman -S python" >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Editable, so a later git pull updates what the tagger actually runs.
|
||||
if command -v uv >/dev/null; then
|
||||
VIRTUAL_ENV="$venv" uv pip install -e "${repo_root}[dev]"
|
||||
else
|
||||
"$python" -m pip install -e "${repo_root}[dev]"
|
||||
fi
|
||||
}
|
||||
|
||||
# Executed rather than sourced: do the thing, for callers that are not bash.
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
ensure_venv "$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
fi
|
||||
26
tag.sh
Executable file
26
tag.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ============================================================================
|
||||
# Tag the photo album, in a browser.
|
||||
#
|
||||
# ./tag.sh --untagged # only items with no tags yet
|
||||
# ./tag.sh --import ~/photos --untagged # import that folder first
|
||||
# ./tag.sh --import ~/photos --dry-run # the report, changing nothing
|
||||
#
|
||||
# Sets up .venv on first run, so this works on a clone with nothing installed.
|
||||
# ============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
readonly REPO_ROOT
|
||||
|
||||
# shellcheck source=scripts/ensure_venv.sh
|
||||
source "${REPO_ROOT}/scripts/ensure_venv.sh"
|
||||
|
||||
main() {
|
||||
ensure_venv "$REPO_ROOT"
|
||||
exec "${REPO_ROOT}/.venv/bin/python" "${REPO_ROOT}/tool/tagger.py" "$@"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@ -10,11 +10,15 @@ Names are typed *into the page*, never as arguments: an argument lands in the
|
||||
shell history, and the whole design of the pack is that the names exist in
|
||||
one directory and nowhere else.
|
||||
|
||||
python tool/tagger.py # the configured pack
|
||||
python tool/tagger.py --dir ~/pack --port 8140
|
||||
python tool/tagger.py --import ~/photos # dedup, strip and import, then tag
|
||||
python tool/tagger.py --import ~/photos --dry-run # report only
|
||||
python tool/tagger.py --untagged # only items with no tags yet
|
||||
Run it through ``./tag.sh``, which sets up ``.venv`` on first use -- the
|
||||
dependencies are not in the system interpreter, and a script that tells you to
|
||||
go and install them yourself is a script that does not own its dependencies.
|
||||
|
||||
./tag.sh # the configured pack
|
||||
./tag.sh --dir ~/pack --port 8140
|
||||
./tag.sh --import ~/photos # dedup, strip and import, then tag
|
||||
./tag.sh --import ~/photos --dry-run # the report, changing nothing
|
||||
./tag.sh --untagged # only items with no tags yet
|
||||
|
||||
It prints a summary when it stops: how many items are untagged, and how many
|
||||
photos each command would have. A command with zero is dead on arrival, and
|
||||
|
||||
Loading…
Reference in New Issue
Block a user