mtg-ssm 2.6.9.dev2__tar.gz → 2.6.10__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.
Files changed (66) hide show
  1. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/PKG-INFO +21 -6
  2. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/README.rst +20 -5
  3. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/_version.py +2 -2
  4. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/containers/indexes.py +4 -6
  5. mtg_ssm-2.6.10/mtg_ssm/mtg/util.py +26 -0
  6. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/serialization/xlsx.py +18 -9
  7. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm.egg-info/PKG-INFO +21 -6
  8. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/containers/test_indexes.py +9 -0
  9. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/data/bulk_data.json +2 -2
  10. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/data/cards.json +1179 -563
  11. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/data/sets.json +59 -42
  12. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/data/sets1.json +21 -21
  13. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/data/sets2.json +38 -21
  14. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/gen_testdata.py +5 -4
  15. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/mtg/test_util.py +15 -21
  16. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/scryfall/test_fetcher.py +1 -1
  17. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/serialization/__snapshots__/test_xlsx.ambr +154 -70
  18. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/serialization/test_csv.py +2 -2
  19. mtg_ssm-2.6.9.dev2/mtg_ssm/mtg/util.py +0 -34
  20. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/.editorconfig +0 -0
  21. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/.github/dependabot.yml +0 -0
  22. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/.github/workflows/integration.yml +0 -0
  23. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/.github/workflows/pre-commit.yml +0 -0
  24. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/.github/workflows/publish.yml +0 -0
  25. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/.github/workflows/run-tests.yml +0 -0
  26. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/.gitignore +0 -0
  27. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/.pre-commit-config.yaml +0 -0
  28. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/LICENSE.txt +0 -0
  29. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/TODO.md +0 -0
  30. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/__init__.py +0 -0
  31. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/containers/__init__.py +0 -0
  32. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/containers/bundles.py +0 -0
  33. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/containers/collection.py +0 -0
  34. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/containers/counts.py +0 -0
  35. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/containers/legacy.py +0 -0
  36. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/mtg/__init__.py +0 -0
  37. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/py.typed +0 -0
  38. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/scryfall/__init__.py +0 -0
  39. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/scryfall/fetcher.py +0 -0
  40. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/scryfall/models.py +0 -0
  41. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/serialization/__init__.py +0 -0
  42. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/serialization/csv.py +0 -0
  43. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/serialization/interface.py +0 -0
  44. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm/ssm.py +0 -0
  45. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm.egg-info/SOURCES.txt +0 -0
  46. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm.egg-info/dependency_links.txt +0 -0
  47. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm.egg-info/entry_points.txt +0 -0
  48. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm.egg-info/requires.txt +0 -0
  49. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/mtg_ssm.egg-info/top_level.txt +0 -0
  50. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/pyproject.toml +0 -0
  51. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/setup.cfg +0 -0
  52. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/__init__.py +0 -0
  53. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/conftest.py +0 -0
  54. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/containers/__init__.py +0 -0
  55. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/containers/test_bundles.py +0 -0
  56. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/containers/test_counts.py +0 -0
  57. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/containers/test_legacy.py +0 -0
  58. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/data/LICENSE.txt +0 -0
  59. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/data/migrations.json +0 -0
  60. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/mtg/__init__.py +0 -0
  61. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/scryfall/__init__.py +0 -0
  62. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/serialization/__init__.py +0 -0
  63. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/serialization/__snapshots__/test_csv.ambr +0 -0
  64. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/serialization/test_interface.py +0 -0
  65. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/serialization/test_xlsx.py +0 -0
  66. {mtg_ssm-2.6.9.dev2 → mtg_ssm-2.6.10}/tests/test_ssm.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mtg_ssm
3
- Version: 2.6.9.dev2
3
+ Version: 2.6.10
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: MIT
@@ -223,13 +223,13 @@ Acknowledgments
223
223
  early '90s.
224
224
  - `Scryfall`_: Scryfall is a fantastic resource for anyone trying to lookup
225
225
  cards or build software on top of up to date Magic card information.
226
- - `MTG JSON`_: MTG JSON is an amazing resource for anyone looking to build
227
- tools around magic card data. Before Scryfall, MTG JSON was my primary
228
- source for card data and, without it, mtg-ssm would not exist.
226
+ - `MTGJSON`_: MTGJSON is an amazing resource for anyone looking to build
227
+ tools around magic card data. Before Scryfall, MTGJSON was my primary
228
+ source for card data and, without it, mtg-ssm would have died long ago.
229
229
 
230
230
  .. _Wizards of the Coast: http://magic.wizards.com
231
231
  .. _Scryfall: https://scryfall.com
232
- .. _MTG JSON: http://mtgjson.com
232
+ .. _MTGJSON: http://mtgjson.com
233
233
 
234
234
 
235
235
  Changelog
@@ -240,6 +240,11 @@ Development
240
240
 
241
241
  - ...
242
242
 
243
+ 2.6.9
244
+ -----
245
+
246
+ - Fix sorting of cards with collector number prefixes (primarily PLST).
247
+
243
248
  2.6.1
244
249
  -----
245
250
 
@@ -454,7 +459,7 @@ Development
454
459
  1.2.3
455
460
  -----
456
461
 
457
- - Hack to work around missing "releaseDate" and "type" in MTG JSON 3.3.14
462
+ - Hack to work around missing "releaseDate" and "type" in MTGJSON 3.3.14
458
463
 
459
464
  1.2.2
460
465
  -----
@@ -496,3 +501,13 @@ Development
496
501
  -----
497
502
 
498
503
  - Initial stable release.
504
+
505
+ GsMtgJson
506
+ ---------
507
+
508
+ Before mtg-ssm, this tool lived as a Google Apps Script project called
509
+ `GsMtgJson`_. As Magic added more cards, eventually the script became
510
+ too slow to function inside the constraints of Google Apps Script and
511
+ Google Sheets.
512
+
513
+ .. _GsMtgJson: https://github.com/gwax/GsMtgJson
@@ -162,13 +162,13 @@ Acknowledgments
162
162
  early '90s.
163
163
  - `Scryfall`_: Scryfall is a fantastic resource for anyone trying to lookup
164
164
  cards or build software on top of up to date Magic card information.
165
- - `MTG JSON`_: MTG JSON is an amazing resource for anyone looking to build
166
- tools around magic card data. Before Scryfall, MTG JSON was my primary
167
- source for card data and, without it, mtg-ssm would not exist.
165
+ - `MTGJSON`_: MTGJSON is an amazing resource for anyone looking to build
166
+ tools around magic card data. Before Scryfall, MTGJSON was my primary
167
+ source for card data and, without it, mtg-ssm would have died long ago.
168
168
 
169
169
  .. _Wizards of the Coast: http://magic.wizards.com
170
170
  .. _Scryfall: https://scryfall.com
171
- .. _MTG JSON: http://mtgjson.com
171
+ .. _MTGJSON: http://mtgjson.com
172
172
 
173
173
 
174
174
  Changelog
@@ -179,6 +179,11 @@ Development
179
179
 
180
180
  - ...
181
181
 
182
+ 2.6.9
183
+ -----
184
+
185
+ - Fix sorting of cards with collector number prefixes (primarily PLST).
186
+
182
187
  2.6.1
183
188
  -----
184
189
 
@@ -393,7 +398,7 @@ Development
393
398
  1.2.3
394
399
  -----
395
400
 
396
- - Hack to work around missing "releaseDate" and "type" in MTG JSON 3.3.14
401
+ - Hack to work around missing "releaseDate" and "type" in MTGJSON 3.3.14
397
402
 
398
403
  1.2.2
399
404
  -----
@@ -435,3 +440,13 @@ Development
435
440
  -----
436
441
 
437
442
  - Initial stable release.
443
+
444
+ GsMtgJson
445
+ ---------
446
+
447
+ Before mtg-ssm, this tool lived as a Google Apps Script project called
448
+ `GsMtgJson`_. As Magic added more cards, eventually the script became
449
+ too slow to function inside the constraints of Google Apps Script and
450
+ Google Sheets.
451
+
452
+ .. _GsMtgJson: https://github.com/gwax/GsMtgJson
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '2.6.9.dev2'
16
- __version_tuple__ = version_tuple = (2, 6, 9, 'dev2')
15
+ __version__ = version = '2.6.10'
16
+ __version_tuple__ = version_tuple = (2, 6, 10)
@@ -10,16 +10,14 @@ from mtg_ssm.mtg import util
10
10
  from mtg_ssm.scryfall.models import ScryCard, ScryMigrationStrategy, ScrySet
11
11
 
12
12
 
13
- def name_card_sort_key(card: ScryCard) -> Tuple[str, int, str]:
13
+ def name_card_sort_key(card: ScryCard) -> Tuple[str, str, int, str]:
14
14
  """Key function for sorting cards in a by-name list."""
15
- card_num, card_var = util.collector_int_var(card)
16
- return (card.set, card_num or 0, card_var or "") # TODO: sort by set release date
15
+ return (card.set, *util.collector_number_parts(card.collector_number))
17
16
 
18
17
 
19
- def set_card_sort_key(card: ScryCard) -> Tuple[int, str]:
18
+ def set_card_sort_key(card: ScryCard) -> Tuple[str, int, str]:
20
19
  """Key function for sorting cards in a by-set list."""
21
- card_num, card_var = util.collector_int_var(card)
22
- return (card_num or 0, card_var or "")
20
+ return util.collector_number_parts(card.collector_number)
23
21
 
24
22
 
25
23
  def build_snnmas(
@@ -0,0 +1,26 @@
1
+ """Utility functions for working with card data."""
2
+
3
+ import functools
4
+ import re
5
+ from typing import Tuple
6
+
7
+ STRICT_BASICS = frozenset({"Plains", "Island", "Swamp", "Mountain", "Forest"})
8
+
9
+ COLLECTOR_NUMBER_RE = re.compile(r"(?P<prefix>.*-|\D+)?(?P<number>\d+)?(?P<suffix>\D.*)?")
10
+
11
+
12
+ @functools.lru_cache(maxsize=None)
13
+ def collector_number_parts(collector_number: str) -> Tuple[str, int, str]:
14
+ """Split a collector number into its parts."""
15
+ match = COLLECTOR_NUMBER_RE.match(collector_number)
16
+ if not match:
17
+ return ("", 0, "")
18
+ prefix: str = match.group("prefix") or ""
19
+ number: int = int(match.group("number")) if match.group("number") else 0
20
+ suffix: str = match.group("suffix") or ""
21
+ return (prefix, number, suffix)
22
+
23
+
24
+ def is_strict_basic(card_name: str) -> bool:
25
+ """Is the card on of the five basic lands (not Snow or Wastes)."""
26
+ return card_name in STRICT_BASICS
@@ -28,15 +28,18 @@ ALL_SETS_SHEET_HEADER: Sequence[str] = [
28
28
  "release",
29
29
  "block",
30
30
  "type",
31
- "cards",
31
+ "printed",
32
+ "have",
32
33
  "unique",
33
34
  "playsets",
34
- "count",
35
+ "extras",
36
+ "nonfoil",
37
+ "foil",
35
38
  "value",
36
39
  ]
37
40
 
38
41
  ALL_SETS_SHEET_TOTALS: Sequence[Optional[str]] = ["Total", None, None, None, None] + [
39
- f"=SUM({c}3:{c}65535)" for c in "FGHIJ"
42
+ f"=SUM({c}3:{c}65535)" for c in "FGHIJKLM"
40
43
  ]
41
44
 
42
45
 
@@ -64,9 +67,12 @@ def create_all_sets(sheet: Worksheet, index: ScryfallDataIndex) -> None:
64
67
  card_set.block,
65
68
  card_set.set_type.value,
66
69
  len(index.setcode_to_cards[card_set.code]),
70
+ f"=SUM('{setcode}'!{_setsheet_col('have')}:{_setsheet_col('have')})",
67
71
  f"=COUNTIF('{setcode}'!{_setsheet_col('have')}:{_setsheet_col('have')},\">0\")",
68
72
  f"=COUNTIF('{setcode}'!{_setsheet_col('have')}:{_setsheet_col('have')},\">=4\")",
69
- f"=SUM('{setcode}'!{_setsheet_col('have')}:{_setsheet_col('have')})",
73
+ f"=SUMIF('{setcode}'!{_setsheet_col('have')}:{_setsheet_col('have')},\">4\")-4*COUNTIF('{setcode}'!{_setsheet_col('have')}:{_setsheet_col('have')},\">4\")",
74
+ f"=SUM('{setcode}'!{_setsheet_col('nonfoil')}:{_setsheet_col('nonfoil')})",
75
+ f"=SUM('{setcode}'!{_setsheet_col('foil')}:{_setsheet_col('foil')})",
70
76
  f"=SUM('{setcode}'!{_setsheet_col('value')}:{_setsheet_col('value')})",
71
77
  ]
72
78
  sheet.append(row)
@@ -81,11 +87,14 @@ def style_all_sets(sheet: Worksheet) -> None:
81
87
  ("C", 12, True, None),
82
88
  ("D", 22, True, None),
83
89
  ("E", 15, True, None),
84
- ("F", 6, False, None),
85
- ("G", 7, False, None),
86
- ("H", 8, False, None),
87
- ("I", 7, False, None),
88
- ("J", 10, False, FORMAT_CURRENCY_USD_SIMPLE),
90
+ ("F", 7, False, None),
91
+ ("G", 6, False, None),
92
+ ("H", 7, False, None),
93
+ ("I", 8, False, None),
94
+ ("J", 6, False, None),
95
+ ("K", 7, False, None),
96
+ ("L", 5, False, None),
97
+ ("M", 10, False, FORMAT_CURRENCY_USD_SIMPLE),
89
98
  ]
90
99
  for col, width, hidden, number_format in col_width_hidden_format:
91
100
  cdim = sheet.column_dimensions[col]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mtg_ssm
3
- Version: 2.6.9.dev2
3
+ Version: 2.6.10
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: MIT
@@ -223,13 +223,13 @@ Acknowledgments
223
223
  early '90s.
224
224
  - `Scryfall`_: Scryfall is a fantastic resource for anyone trying to lookup
225
225
  cards or build software on top of up to date Magic card information.
226
- - `MTG JSON`_: MTG JSON is an amazing resource for anyone looking to build
227
- tools around magic card data. Before Scryfall, MTG JSON was my primary
228
- source for card data and, without it, mtg-ssm would not exist.
226
+ - `MTGJSON`_: MTGJSON is an amazing resource for anyone looking to build
227
+ tools around magic card data. Before Scryfall, MTGJSON was my primary
228
+ source for card data and, without it, mtg-ssm would have died long ago.
229
229
 
230
230
  .. _Wizards of the Coast: http://magic.wizards.com
231
231
  .. _Scryfall: https://scryfall.com
232
- .. _MTG JSON: http://mtgjson.com
232
+ .. _MTGJSON: http://mtgjson.com
233
233
 
234
234
 
235
235
  Changelog
@@ -240,6 +240,11 @@ Development
240
240
 
241
241
  - ...
242
242
 
243
+ 2.6.9
244
+ -----
245
+
246
+ - Fix sorting of cards with collector number prefixes (primarily PLST).
247
+
243
248
  2.6.1
244
249
  -----
245
250
 
@@ -454,7 +459,7 @@ Development
454
459
  1.2.3
455
460
  -----
456
461
 
457
- - Hack to work around missing "releaseDate" and "type" in MTG JSON 3.3.14
462
+ - Hack to work around missing "releaseDate" and "type" in MTGJSON 3.3.14
458
463
 
459
464
  1.2.2
460
465
  -----
@@ -496,3 +501,13 @@ Development
496
501
  -----
497
502
 
498
503
  - Initial stable release.
504
+
505
+ GsMtgJson
506
+ ---------
507
+
508
+ Before mtg-ssm, this tool lived as a Google Apps Script project called
509
+ `GsMtgJson`_. As Magic added more cards, eventually the script became
510
+ too slow to function inside the constraints of Google Apps Script and
511
+ Google Sheets.
512
+
513
+ .. _GsMtgJson: https://github.com/gwax/GsMtgJson
@@ -67,6 +67,15 @@ def test_setcode_to_cards(scryfall_data: ScryfallDataSet) -> None:
67
67
  "74d",
68
68
  ]
69
69
 
70
+ # The List Sorting
71
+ assert [(c.collector_number, c.name) for c in index.setcode_to_cards["plst"]] == [
72
+ ("10E-20", "High Ground"),
73
+ ("10E-182", "Terror"),
74
+ ("AKH-2", "Anointed Procession"),
75
+ ("AKH-3", "Anointer Priest"),
76
+ ("ARB-1", "Ardent Plea"),
77
+ ]
78
+
70
79
 
71
80
  def test_id_to_setindex(scryfall_data: ScryfallDataSet) -> None:
72
81
  index = ScryfallDataIndex()
@@ -8,8 +8,8 @@
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
- "download_uri": "https://data.scryfall.io/default-cards/default-cards-20240510210636.json",
12
- "updated_at": "2024-05-10T21:06:36.150000Z",
11
+ "download_uri": "https://data.scryfall.io/default-cards/default-cards-20240826212052.json",
12
+ "updated_at": "2024-08-26T21:20:52.469000Z",
13
13
  "content_type": "application/json",
14
14
  "content_encoding": "gzip"
15
15
  }