mtg-ssm 2.8.3.dev2__tar.gz → 2.8.3.dev5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/PKG-INFO +3 -2
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/README.rst +2 -1
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/_version.py +3 -3
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/scryfall/fetcher.py +26 -2
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/scryfall/models.py +7 -4
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm.egg-info/PKG-INFO +3 -2
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm.egg-info/SOURCES.txt +1 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm.egg-info/scm_file_list.json +1 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm.egg-info/scm_version.json +2 -2
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/containers/test_bundles.py +9 -2
- mtg_ssm-2.8.3.dev5/tests/data/.gitattributes +1 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/data/bulk_data.json +3 -4
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/data/cards.json +4684 -2824
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/data/migrations.json +10 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/data/sets.json +56 -54
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/data/sets1.json +27 -27
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/data/sets2.json +29 -27
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/gen_testdata.py +2 -2
- mtg_ssm-2.8.3.dev5/tests/scryfall/test_fetcher.py +136 -0
- mtg_ssm-2.8.3.dev5/tests/scryfall/test_models.py +58 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/serialization/__snapshots__/test_xlsx_serializer.ambr +42 -42
- mtg_ssm-2.8.3.dev2/tests/scryfall/test_fetcher.py +0 -66
- mtg_ssm-2.8.3.dev2/tests/scryfall/test_models.py +0 -26
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/.editorconfig +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/.github/dependabot.yml +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/.github/workflows/integration.yml +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/.github/workflows/pre-commit.yml +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/.github/workflows/publish.yml +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/.github/workflows/run-tests.yml +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/.gitignore +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/.pre-commit-config.yaml +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/LICENSE.txt +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/TODO.md +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/__init__.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/containers/__init__.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/containers/bundles.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/containers/collection.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/containers/counts.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/containers/indexes.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/containers/legacy.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/mtg/__init__.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/mtg/util.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/py.typed +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/scryfall/__init__.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/serialization/__init__.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/serialization/csv_serializer.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/serialization/interface.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/serialization/xlsx_serializer.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm/ssm.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm.egg-info/dependency_links.txt +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm.egg-info/entry_points.txt +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm.egg-info/requires.txt +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/mtg_ssm.egg-info/top_level.txt +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/pyproject.toml +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/setup.cfg +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/__init__.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/conftest.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/containers/__init__.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/containers/test_counts.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/containers/test_indexes.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/containers/test_legacy.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/data/LICENSE.txt +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/mtg/__init__.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/mtg/test_util.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/scryfall/__init__.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/serialization/__init__.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/serialization/__snapshots__/test_csv_serializer.ambr +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/serialization/test_csv_serializer.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/serialization/test_interface.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/serialization/test_xlsx_serializer.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/tests/test_ssm.py +0 -0
- {mtg_ssm-2.8.3.dev2 → mtg_ssm-2.8.3.dev5}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mtg_ssm
|
|
3
|
-
Version: 2.8.3.
|
|
3
|
+
Version: 2.8.3.dev5
|
|
4
4
|
Summary: A tool to manage Magic: the Gathering collection spreadsheets
|
|
5
5
|
Author-email: George Leslie-Waksman <waksman@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -243,7 +243,8 @@ Changelog
|
|
|
243
243
|
Development
|
|
244
244
|
-----------
|
|
245
245
|
|
|
246
|
-
-
|
|
246
|
+
- Fix Scryfall fetching with application request headers, JSON Lines bulk
|
|
247
|
+
downloads, and updated card layout and format values.
|
|
247
248
|
|
|
248
249
|
2.8.1
|
|
249
250
|
-----
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '2.8.3.
|
|
22
|
-
__version_tuple__ = version_tuple = (2, 8, 3, '
|
|
21
|
+
__version__ = version = '2.8.3.dev5'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 8, 3, 'dev5')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gbe794fd02'
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"""Scryfall data fetcher."""
|
|
2
2
|
|
|
3
3
|
import gzip
|
|
4
|
+
import io
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
|
|
6
7
|
import msgspec
|
|
7
8
|
from platformdirs import user_cache_dir
|
|
8
9
|
from requests_cache import CachedSession, SerializerPipeline, Stage, pickle_serializer
|
|
9
10
|
|
|
11
|
+
from mtg_ssm import __version__
|
|
10
12
|
from mtg_ssm.containers.bundles import ScryfallDataSet
|
|
11
13
|
from mtg_ssm.scryfall.models import ScryBulkData, ScryCard, ScryList, ScryMigration, ScrySet
|
|
12
14
|
|
|
@@ -27,6 +29,12 @@ SESSION = CachedSession(
|
|
|
27
29
|
cache_control=True,
|
|
28
30
|
expire_after=86400,
|
|
29
31
|
)
|
|
32
|
+
SESSION.headers.update(
|
|
33
|
+
{
|
|
34
|
+
"User-Agent": f"mtg-ssm/{__version__} (https://github.com/gwax/mtg_ssm)",
|
|
35
|
+
"Accept": "application/json;q=0.9,*/*;q=0.8",
|
|
36
|
+
}
|
|
37
|
+
)
|
|
30
38
|
|
|
31
39
|
BULK_DATA_ENDPOINT = "https://api.scryfall.com/bulk-data"
|
|
32
40
|
SETS_ENDPOINT = "https://api.scryfall.com/sets"
|
|
@@ -44,6 +52,22 @@ def _fetch_endpoint(endpoint: str) -> bytes:
|
|
|
44
52
|
return response.content
|
|
45
53
|
|
|
46
54
|
|
|
55
|
+
def _fetch_cards(bulk: ScryBulkData) -> list[ScryCard]:
|
|
56
|
+
if bulk.jsonl_download_uri is not None:
|
|
57
|
+
content = _fetch_endpoint(bulk.jsonl_download_uri)
|
|
58
|
+
decoder = msgspec.json.Decoder(ScryCard)
|
|
59
|
+
# Requests may already have decoded gzip supplied as an HTTP encoding.
|
|
60
|
+
with (
|
|
61
|
+
io.BytesIO(content) as stream,
|
|
62
|
+
gzip.GzipFile(fileobj=stream) if content.startswith(b"\x1f\x8b") else stream as lines,
|
|
63
|
+
):
|
|
64
|
+
return [decoder.decode(line) for line in lines if line.strip()]
|
|
65
|
+
if bulk.download_uri is not None:
|
|
66
|
+
return msgspec.json.decode(_fetch_endpoint(bulk.download_uri), type=list[ScryCard])
|
|
67
|
+
msg = f"No download URI for Scryfall bulk data: {bulk.type}"
|
|
68
|
+
raise ValueError(msg)
|
|
69
|
+
|
|
70
|
+
|
|
47
71
|
def scryfetch() -> ScryfallDataSet:
|
|
48
72
|
"""Retrieve and deserialize Scryfall object data."""
|
|
49
73
|
print("Reading data from scryfall")
|
|
@@ -67,7 +91,7 @@ def scryfetch() -> ScryfallDataSet:
|
|
|
67
91
|
)
|
|
68
92
|
migrations_data += migrations_list.data
|
|
69
93
|
|
|
70
|
-
[
|
|
71
|
-
cards_data =
|
|
94
|
+
[cards_bulk] = [bd for bd in bulk_data if bd.type == BULK_TYPE]
|
|
95
|
+
cards_data = _fetch_cards(cards_bulk)
|
|
72
96
|
|
|
73
97
|
return ScryfallDataSet(sets=sets_data, cards=cards_data, migrations=migrations_data)
|
|
@@ -62,6 +62,7 @@ class ScryCardLayout(str, Enum):
|
|
|
62
62
|
DOUBLE_SIDED = "double_sided"
|
|
63
63
|
EMBLEM = "emblem"
|
|
64
64
|
FLIP = "flip"
|
|
65
|
+
FRONT_CARD = "front_card"
|
|
65
66
|
HOST = "host"
|
|
66
67
|
LEVELER = "leveler"
|
|
67
68
|
MELD = "meld"
|
|
@@ -202,6 +203,7 @@ class ScryFormat(str, Enum):
|
|
|
202
203
|
ALCHEMY = "alchemy"
|
|
203
204
|
BRAWL = "brawl"
|
|
204
205
|
COMMANDER = "commander"
|
|
206
|
+
COMPETITIVEBRAWL = "competitivebrawl"
|
|
205
207
|
DUEL = "duel"
|
|
206
208
|
EXPLORER = "explorer"
|
|
207
209
|
FRONTIER = "frontier"
|
|
@@ -326,7 +328,7 @@ class CardPreviewBlock(Struct):
|
|
|
326
328
|
"""Model for card preview block."""
|
|
327
329
|
|
|
328
330
|
source: str
|
|
329
|
-
source_uri: str
|
|
331
|
+
source_uri: str | None
|
|
330
332
|
previewed_at: dt.date
|
|
331
333
|
|
|
332
334
|
|
|
@@ -442,11 +444,12 @@ class ScryBulkData(
|
|
|
442
444
|
type: str
|
|
443
445
|
name: str
|
|
444
446
|
description: str
|
|
445
|
-
download_uri: str
|
|
447
|
+
download_uri: str | None = None
|
|
448
|
+
jsonl_download_uri: str | None = None
|
|
446
449
|
updated_at: dt.datetime
|
|
447
450
|
compressed_size: int | None = None
|
|
448
|
-
content_type: str
|
|
449
|
-
content_encoding: str
|
|
451
|
+
content_type: str | None = None
|
|
452
|
+
content_encoding: str | None = None
|
|
450
453
|
|
|
451
454
|
|
|
452
455
|
class ScryMigration(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mtg_ssm
|
|
3
|
-
Version: 2.8.3.
|
|
3
|
+
Version: 2.8.3.dev5
|
|
4
4
|
Summary: A tool to manage Magic: the Gathering collection spreadsheets
|
|
5
5
|
Author-email: George Leslie-Waksman <waksman@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -243,7 +243,8 @@ Changelog
|
|
|
243
243
|
Development
|
|
244
244
|
-----------
|
|
245
245
|
|
|
246
|
-
-
|
|
246
|
+
- Fix Scryfall fetching with application request headers, JSON Lines bulk
|
|
247
|
+
downloads, and updated card layout and format values.
|
|
247
248
|
|
|
248
249
|
2.8.1
|
|
249
250
|
-----
|
|
@@ -8,6 +8,7 @@ from mtg_ssm.scryfall.models import ScryCardLayout, ScrySetType
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def test_remove_digital(scryfall_data: bundles.ScryfallDataSet) -> None:
|
|
11
|
+
digital_pathway_id = UUID("edc71870-656c-40f9-b2b0-f69a46bf8c51")
|
|
11
12
|
set_codes = {s.code for s in scryfall_data.sets}
|
|
12
13
|
card_ids = {c.id for c in scryfall_data.cards}
|
|
13
14
|
card_names = {c.name for c in scryfall_data.cards}
|
|
@@ -17,7 +18,10 @@ def test_remove_digital(scryfall_data: bundles.ScryfallDataSet) -> None:
|
|
|
17
18
|
|
|
18
19
|
assert "khm" in set_codes
|
|
19
20
|
assert "Cosmos Elixir" in card_names
|
|
20
|
-
|
|
21
|
+
|
|
22
|
+
assert "znr" in set_codes
|
|
23
|
+
assert "Needleverge Pathway // Pillarverge Pathway" in card_names
|
|
24
|
+
assert digital_pathway_id in card_ids
|
|
21
25
|
|
|
22
26
|
assert "yecl" in set_codes
|
|
23
27
|
assert "Thoughtsteal Sprites" in card_names
|
|
@@ -32,7 +36,10 @@ def test_remove_digital(scryfall_data: bundles.ScryfallDataSet) -> None:
|
|
|
32
36
|
|
|
33
37
|
assert "khm" in set_codes2
|
|
34
38
|
assert "Cosmos Elixir" in card_names2
|
|
35
|
-
|
|
39
|
+
|
|
40
|
+
assert "znr" in set_codes2
|
|
41
|
+
assert "Needleverge Pathway // Pillarverge Pathway" in card_names2
|
|
42
|
+
assert digital_pathway_id not in card_ids2
|
|
36
43
|
|
|
37
44
|
assert "yecl" not in set_codes2
|
|
38
45
|
assert "Thoughtsteal Sprites" not in card_names2
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*.json linguist-generated=true
|
|
@@ -8,10 +8,9 @@
|
|
|
8
8
|
"type": "default_cards",
|
|
9
9
|
"name": "Default Cards",
|
|
10
10
|
"description": "A JSON file containing every card object on Scryfall in English or the printed language if the card is only available in one language.",
|
|
11
|
-
"
|
|
12
|
-
"updated_at": "2026-
|
|
13
|
-
"
|
|
14
|
-
"content_encoding": "gzip"
|
|
11
|
+
"jsonl_download_uri": "https://data.scryfall.io/default-cards/default-cards-20261016090544.jsonl.gz",
|
|
12
|
+
"updated_at": "2026-10-16T09:05:44.990000Z",
|
|
13
|
+
"compressed_size": 79720941
|
|
15
14
|
}
|
|
16
15
|
],
|
|
17
16
|
"has_more": false
|