Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions .github/scripts/tests/test_docs_lint.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,10 +449,17 @@ def test_roster_derivation_sees_the_real_calculators(self):
# tether is keyed on the CURRENT identity, version suffix included.
"stage-d-illustration-v2",
"local-name-frequency-v1",
# Declared in `management/commands/`, which the pre-2026-07-29
# non-recursive glob never read. If this scan ever narrows
# again, this is the assertion that says so.
"scryfall-tagger-v1",
# `scryfall-tagger-v1` stood here from 2026-07-29 as the one
# identity declared under `management/commands/` — the subtree the
# pre-2026-07-29 non-recursive glob never read. It retired together
# with `PrintingTagVote` on 2026-07-30, and no live identity is
# declared under `management/commands/` any more, so this list
# cannot carry a real-repo witness for the recursion. The recursion
# itself stays covered — on fixtures rather than on the real tree —
# by `test_scan_is_recursive_but_bounded`, which is the assertion
# that fails if the scan ever narrows again. If an identity is ever
# declared under `management/commands/` again, add it here and this
# list becomes a real-repo witness once more.
):
self.assertIn(identity, found)

Expand Down
9 changes: 0 additions & 9 deletions MPCAutofill/cardpicker/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
ImageEvidence,
LandsAmbiguousResidue,
PilotRunLedger,
PrintingTagVote,
Project,
ProjectMember,
SavedDeck,
Expand Down Expand Up @@ -234,14 +233,6 @@ class AdminCardTagVote(admin.ModelAdmin[CardTagVote]):
raw_id_fields = ["card", "tag"]


@admin.register(PrintingTagVote)
class AdminPrintingTagVote(admin.ModelAdmin[PrintingTagVote]):
list_display = ("printing", "tag", "polarity", "source", "confidence", "anonymous_id", "created_at")
list_filter = ("source", "polarity")
search_fields = ("printing__name", "tag__name")
raw_id_fields = ["printing", "tag"]


@admin.register(CardReport)
class AdminCardReport(admin.ModelAdmin[CardReport]):
list_display = ("card", "reason", "text", "anonymous_id", "user", "created_at")
Expand Down
19 changes: 13 additions & 6 deletions MPCAutofill/cardpicker/integrations/game/scryfall_bulk_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

* `cardpicker/printing_metadata_import.py` (its own `BulkDataEntry`),
* `cardpicker/integrations/game/mtg.py` (its own `BulkDataRow`/`BulkDataResponse`),
* `cardpicker/management/commands/import_external_ip_tags.py` (its own `_BulkDataEntry`).
* `cardpicker/management/commands/import_external_ip_tags.py` (its own `_BulkDataEntry`) -
RETIRED 2026-07-29 along with `PrintingTagVote`; it is named here because it is half the
reason this module exists, not because it still calls in. Two importers remain.

When Scryfall retired the old bulk format (blog "Two New Ways to Sync Scryfall Data",
2026-07-01; retirement 2026-07-20), exactly ONE of the three had been hardened for it - the
Expand All @@ -20,9 +22,8 @@
`GameIntegration`) that exists precisely to keep game-specific vendor knowledge out of
`cardpicker/`. Putting Scryfall's wire format at `cardpicker/` level would make the generic
layer own an MTG vendor's schema. The dependency direction is also already established and is
preserved here: `cardpicker.printing_metadata_import` and
`cardpicker.management.commands.import_external_ip_tags` ALREADY import from
`cardpicker.integrations.game.mtg` (both pull `Scryfall` for its headers), i.e. cardpicker ->
preserved here: `cardpicker.printing_metadata_import` ALREADY imports from
`cardpicker.integrations.game.mtg` (pulling `Scryfall` for its headers), i.e. cardpicker ->
integrations. Nothing in this module imports back out of the integrations package, so no game
integration is made to depend on a cardpicker-level module.

Expand Down Expand Up @@ -70,6 +71,12 @@
# each call site.
DEFAULT_CARDS = "default_cards"
ORACLE_CARDS = "oracle_cards"
# `ART_TAGS` has had NO consumer since `import_external_ip_tags` was retired on 2026-07-29 with
# `PrintingTagVote`. Kept, with its live-endpoint test, because the Scryfall Tagger art-tag feed
# is the named input of the unified-Scryfall-importer work item that inherits that capability
# (docs/features/printing-tags.md's retirement record) - a bare constant plus one test is a
# cheaper thing to carry than a re-derivation of which bulk entry type the feed lives under, and
# the test is what would tell us if the entry type disappeared upstream in the meantime.
ART_TAGS = "art_tags"

# gzip's zlib window-bits selector: 16 + MAX_WBITS means "expect a gzip (RFC 1952) wrapper",
Expand Down Expand Up @@ -240,8 +247,8 @@ def download_and_decompress(url: str, path: Path, timeout: int = 60) -> None:

ON-DISK FORMAT NOTE: we store the file DECOMPRESSED even though the remote is compressed.
Keeping it gzipped would save ~596MB of the persistent `scryfall_cache` volume but would
force every reader (`printing_metadata_import._parse_rows`, the back-face lookup,
`import_external_ip_tags`' illustration index) to re-inflate 620MB on every pass, and would
force every reader (`printing_metadata_import._parse_rows`, the back-face lookup) to
re-inflate 620MB on every pass, and would
invalidate the already-deployed on-disk cache and the `ensure_scryfall_cache_present` guard
that points at it. Disk is already provisioned for the uncompressed size; CPU on every read
is not worth trading for it.
Expand Down
Loading
Loading