Skip to content

refactor(census): promote BaseCatalogue + convert store.py to CensusStore#153

Merged
VortexUK merged 1 commit into
mainfrom
refactor/census-store-catalogue
Jul 11, 2026
Merged

refactor(census): promote BaseCatalogue + convert store.py to CensusStore#153
VortexUK merged 1 commit into
mainfrom
refactor/census-store-catalogue

Conversation

@VortexUK

Copy link
Copy Markdown
Owner

Summary

First of three PRs extending the catalogue architecture (#141#152) beyond eq2db, per the survey: census store → parses db → users.db family.

  • BaseCatalogue promoted from backend/eq2db/_catalogue.py to backend/db_catalogue.py — once non-eq2db modules adopt it, the eq2db namespace stops being the right home. Seven eq2db imports, the base test, and CLAUDE.md re-pointed; no behaviour change.
  • backend/census/store.pyCensusStore(BaseCatalogue): init_db becomes the template-method hook (_create_schema with the three tables + migrations loop; FOREIGN_KEYS=True, CREATE_META=False since census.db predates the shared _meta table); the conn-taking get/upsert helpers (including the keep-best-known character merge, untouched) become staticmethods. Shared store = CensusStore() instance.
  • Consumers (aa, character views, favorites, guild, parses ingest, census_refresh, guild_cache) import the instance as census_store, so call sites read identically — and the 14 redundant census_store.init_db(census_store.DB_PATH) explicit-default calls collapse to census_store.init_db().
  • Tests: CensusStore(tmp).init_db() construction, statics via the class, monkeypatch.setattr(census_store, "DB_PATH", …)setattr(census_store.store, "path", …) (the instance is what routes read now). conftest re-points store.path alongside DB_PATH.

CensusStore gets the full inherited surface for free: log-friendly repr (path + ready/missing), bool = provisioned, context-manager close-on-exit, and the narrowed unbuilt-schema read-error handling.

Verification

Full suite 1524 green, ruff + pyright clean. Live /api/character/{name} (store-first read path) and /api/character/{name}/aas verified on the dev backend.

🤖 Generated with Claude Code

…onvert store.py to CensusStore

First step of extending the catalogue architecture beyond eq2db:

- backend/eq2db/_catalogue.py moves to backend/db_catalogue.py — the
  base is no longer eq2db-specific; the seven eq2db imports, the base
  test and CLAUDE.md re-point.
- backend/census/store.py: init_db moves onto a CensusStore class
  (FOREIGN_KEYS=True, CREATE_META=False — census.db predates _meta);
  the conn-taking get/upsert helpers become staticmethods. Shared
  `store = CensusStore()` instance; consumers alias it census_store so
  call sites read the same, and the redundant
  `census_store.init_db(census_store.DB_PATH)` explicit-default calls
  collapse to `census_store.init_db()`.
- conftest re-points store.path alongside DB_PATH; tests construct
  CensusStore(tmp) / call the statics via the class, and DB_PATH
  monkeypatches become instance `path` patches.

CensusStore inherits the full base surface: template init_db, dunder
repr/bool/eq/fspath/context-manager, and the narrowed unbuilt-schema
read handling.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@VortexUK
VortexUK merged commit ef589a0 into main Jul 11, 2026
6 checks passed
@VortexUK
VortexUK deleted the refactor/census-store-catalogue branch July 11, 2026 10:25
VortexUK added a commit that referenced this pull request Jul 11, 2026
…154)

Second PR extending the catalogue architecture beyond eq2db (after
CensusStore #153):

- backend/server/parses/db.py: init_db collapses into the base template
  method (_create_schema hosts the six table schemas, the _MIGRATIONS
  loop, the three named migrations and indexes; FOREIGN_KEYS=True,
  CREATE_META=False). The 28 conn-taking helpers become staticmethods;
  invalidate_is_player_cache becomes an instance method over self.path.
  SwingType + the swing-type constants stay module-level. Shared
  `store = ParsesStore()` instance.
- The hand-rolled :memory: special-case is gone (BaseCatalogue dropped
  it in #152 for silently-broken reads); tests that used
  init_db(":memory:") now use tmp_path files. The unused pragma_* SQL
  blocks are removed (base owns the connection pragmas); the
  world-migration's own FK toggle blocks stay.
- Consumers (admin, parses delete/ingest/list/tamper, rankings, app
  startup, cleanup) import the instance as parses_db — call sites read
  the same, and the parses_db.init_db(parses_db.DB_PATH)
  explicit-default calls collapse to parses_db.init_db().
- conftest + the shared parses_db_path fixture re-point store.path
  alongside DB_PATH; test monkeypatches move from module DB_PATH to
  instance path; static calls route through the store.

1524 tests green, ruff + pyright clean.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
VortexUK added a commit that referenced this pull request Jul 11, 2026
…e classes (#155)

Final PR extending the catalogue architecture (CensusStore #153,
ParsesStore #154):

- backend/db_catalogue.py: the path-bound identity + dunder surface
  (repr/bool/eq/hash/fspath) extracts into PathBound; BaseCatalogue
  inherits it, and a new AsyncStoreBase(PathBound) is the base for the
  aiosqlite-backed users.db domains (which do NOT own schema — the
  package-level backend.server.db.init_db orchestrator is unchanged).
- Seven domain modules become store classes sharing one users.db:
  UsersStore, ClaimsStore, FavoritesStore, ItemWatchStore, TokensStore,
  ServersStore (sync), RaidScheduleStore — each with a shared `store`
  instance. The 58 `path: Path = DB_PATH` kwargs threaded through every
  public function are gone; pure helpers (generate_token, hash_token,
  _server_row, _teams_with_slots) are staticmethods.
- backend/server/db/__init__.py facade re-exports each store's BOUND
  METHODS under the original names, so the `users_db.get_active_claims(...)`
  API shape (and every from-package import) is preserved with zero route
  churn. ALL_STORES tuple lets conftest re-point every store in one loop.
- Direct domain-module importers (favorites API, raid_schedule API,
  raid_live, character views pre-warm, server_context.load_registry —
  which passed DB_PATH positionally) migrate to store instances.
- Tests: explicit path= kwargs stripped where they were the redirected
  default; genuinely-injected temp paths become XStore(tmp) constructions
  or autouse store-repoint fixtures; DB_PATH monkeypatches gain the
  instance-path repoint; stale patch strings move onto the store bindings.

1524 tests green, ruff + pyright clean. Live-verified /api/server
(registry), raid-schedule and raiding-live endpoints.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
VortexUK added a commit that referenced this pull request Jul 11, 2026
Follow-up review of #153-#155 (same 8-angle adversarial pipeline as
#152); this fixes everything it found:

Correctness hazards:
- backend/server/db/__init__.py init_db now reads DB_PATH at call time
  (was `path: Path = DB_PATH` — the default-arg-captured-at-import
  pattern the arc eliminated everywhere else; under the documented
  early-import race, conftest's argless call would have run schema +
  migrations against the developer's real users.db).
- backend/server/api/zones.py drops the import-time PARSES_DB_PATH
  value copy for the store's dynamic `parses_db.path` — the last
  consumer that a per-test store.path re-point couldn't reach.
- tests/fixtures/parses_db.py: de-duplicated setattr (the second line
  now re-points DB_PATH as the docstring promised), docstring honest.

Structure / dedup:
- AsyncStoreBase gains the shared `_db()` asynccontextmanager — the 46
  hand-rolled `aiosqlite.connect(self.path)` (+19 row_factory) sites in
  the six async domain stores collapse onto it; future connection-level
  policy (busy_timeout, FK pragma) has one home.
- ServersStore (sync) moves off the async-named base onto PathBound.
- BaseCatalogue._apply_migrations replaces the four drifted per-store
  migration loops (census logged, parses/recipes/zones swallowed
  silently) — skips now log at DEBUG uniformly.
- CensusStore aligns with the .sql convention (new store.sql; inline
  schema/DML constants removed), FOREIGN_KEYS corrected to False (the
  schema declares no FKs), and sql_loader's stale "DDL stays embedded
  in the .py" docstring bullet updated to reality.
- backend/db_catalogue.py log prefix [eq2db] → [db-catalogue].

Docs & tests:
- The seven users.db domain docstrings + parses/db.py no longer teach
  the removed `path: Path = DB_PATH` convention; the inverted
  "CRITICAL: pass the explicit path" comments in two test files now
  describe the store model; orphaned test constants removed.
- New tests/fixtures/users_db.py point_users_db_at() replaces the ~9
  pasted (and already-forked) ALL_STORES re-point loops.
- New tests/server/test_db_facade.py: facade completeness guard (a
  public store method with no alias fails the build with the name
  spelled out; intentional omissions live in _FACADE_EXEMPT, itself
  checked for staleness) + alias-integrity guard (every facade alias
  must be bound to an ALL_STORES instance). Three dead aliases
  (get_server_by_subdomain_sync, generate_token, hash_token) removed.

1527 tests green (3 new), ruff + pyright clean; /api/server,
raid-schedule and character read paths live-verified.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant