Skip to content

Port: Pulsarr watchlist database and API (issue #1) - #3

Merged
spin-drift merged 6 commits into
mainfrom
port-pulsarr-watchlist
Jun 14, 2026
Merged

Port: Pulsarr watchlist database and API (issue #1)#3
spin-drift merged 6 commits into
mainfrom
port-pulsarr-watchlist

Conversation

@spin-drift

@spin-drift spin-drift commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Port Pulsarr's watchlist DB schema, API, and tests (excluding rebrand)

Ports 1 feature commit from SloppyTurtle/pulsarr, preserving original authorship via git cherry-pick. Pulsarr is a community fork of calibrain/shelfmark; this PR pulls in the substantive new work while leaving the Pulsarr rebranding out. Also updates the README to call out that this fork is a meta-fork tracking selected community work.

New features

  • Author watchlist DB — new shelfmark/watchlist/db.py with watchlist_authors and watchlist_releases SQLite tables, indexes, and a thread-safe WatchlistDB wrapper. Follows the existing UserDB migration pattern (CREATE IF NOT EXISTS + PRAGMA guards) and uses cascade-on-delete for user removal.
  • Watchlist REST API — new Flask blueprint at shelfmark/watchlist/routes.py with five endpoints for author-watch CRUD and release listing.
  • WiringWatchlistDB initialized at startup alongside UserDB in shelfmark/main.py; routes registered via blueprint.
  • 35 tests in tests/watchlist/test_watchlist_db.py covering schema, CRUD, validation, idempotency, and cascade behavior.

Deliberately not ported

  • Pulsarr rebranding (bca048e) — touches only the README; rewriting the project name is out of scope for a fork keeping the Shelfmark name. Two docstrings that referenced "Pulsarr" in the feature commit have been reverted to "Shelfmark" as part of the cleanup commit.
  • Merge commit (1ca6a85) — the squashed feature commit (5f39921) is what's ported; the merge commit itself adds nothing on top.

README change

Adds an [!IMPORTANT] block near the top of the README that:

  • Identifies this fork as a meta-fork of calibrain/shelfmark
  • Lists the community forks currently being tracked, with brief summaries of what's been ported from each
  • Points readers to git log --grep="Cherry-picked from" for full attribution

Verification

  • Backend: 1977 passed, 96 skipped (35 new tests from this port; 1 preexisting seleniumbase-dependent failure in local venv, unrelated to this port)
  • Lint, format, and dead-code checks all clean against this repo's existing ruff config

Cleanups in this branch

  • ruff --fix handled import sorting in main.py, an unused # noqa: PLW0603 directive, and one unused json import in the tests
  • Manual fix for TRY300 (return moved to else block in WatchlistDB.add_author)
  • ruff format on the three new/touched files to bring them into this repo's style
  • Two module docstrings rewritten from "Pulsarr" → "Shelfmark"

Credit

Per-commit authorship preserved by cherry-pick. The single ported commit (5f39921) is unmodified from upstream apart from the two docstring reverts noted above (recorded in the cleanup commit body). Thanks to @SloppyTurtle for the work.

SloppyTurtle and others added 3 commits June 14, 2026 00:53
- Add WatchlistDB class with watchlist_authors and watchlist_releases tables
- Follows existing UserDB migration pattern (CREATE IF NOT EXISTS + PRAGMA guards)
- Add Flask blueprint with 5 API endpoints for author watch CRUD and release listing
- Wire WatchlistDB into main.py startup alongside UserDB
- 35 tests covering schema, CRUD, validation, idempotency, and cascade behavior
… port

Auto-fixed: import sorting in main.py, unused noqa in routes.py, unused
json import in test_watchlist_db.py. Manual fixes: TRY300 (return moved
to else-branch in db.py add_author), and ruff format on the three files
that drifted from this repo's config.

Also reverted "Pulsarr" → "Shelfmark" in two module docstrings to keep
this fork's naming consistent.

All 1977 backend tests pass (35 new from this port).
Calls out that this fork integrates noteworthy work from community forks
while keeping Shelfmark's identity, license, and naming intact. Lists
the forks currently tracked (litfinder, pulsarr) with a brief summary of
what's been ported from each.


def _error(message: str, status: int = 400) -> Any:
return jsonify({"error": message}), status
Updated the note about the fork to include new original features being added.
The raw sqlite3.IntegrityError message can reveal internal index and
constraint names (e.g. 'uq_watchlist_authors_hardcover') to the API
caller, which is unnecessary info disclosure. Log the underlying error
server-side and return a generic "Watch entry already exists" message
to the caller instead.

Addresses the one CodeQL py/stack-trace-exposure finding from the
initial scan of this PR. Tests still pass (they match on "already
exists", which the new message preserves).
@spin-drift
spin-drift merged commit 9e3e545 into main Jun 14, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants