Add retry logic with exponential backoff for 429 rate limits
This commit is contained in:
@@ -352,12 +352,12 @@ for name, count in sorted(cards.items()):
|
||||
|
||||
## Collection Stats
|
||||
|
||||
- **Total cards:** 0
|
||||
- **Unique cards:** 0
|
||||
- **Total cards:** 1356
|
||||
- **Unique cards:** 916
|
||||
- **By type:**
|
||||
- Artifacts: 77
|
||||
- Creatures: 390
|
||||
- Enchantments: 63
|
||||
- Creatures: 392
|
||||
- Enchantments: 64
|
||||
- Instants: 109
|
||||
- Lands: 72
|
||||
- Planeswalkers: 2
|
||||
|
||||
50
hydrate.py
50
hydrate.py
@@ -40,27 +40,43 @@ def parse_decklist(filepath: str) -> list[dict]:
|
||||
return cards
|
||||
|
||||
|
||||
def fetch_card(name: str) -> Optional[dict]:
|
||||
def fetch_card(name: str, retry_count: int = 3) -> Optional[dict]:
|
||||
"""Fetch card data from Scryfall API using fuzzy search."""
|
||||
encoded = urllib.parse.quote(name)
|
||||
url = f"{SCRYFALL_API}/cards/named?fuzzy={encoded}"
|
||||
|
||||
try:
|
||||
req = urllib.request.Request(url, headers={
|
||||
"User-Agent": "EDHDeckBuilder/1.0",
|
||||
"Accept": "*/*"
|
||||
})
|
||||
with urllib.request.urlopen(req, timeout=30) as response:
|
||||
return json.loads(response.read().decode("utf-8"))
|
||||
except urllib.error.HTTPError as e:
|
||||
print(f" Error fetching '{name}': HTTP {e.code}", file=sys.stderr)
|
||||
return None
|
||||
except urllib.error.URLError as e:
|
||||
print(f" Error fetching '{name}': {e.reason}", file=sys.stderr)
|
||||
return None
|
||||
except json.JSONDecodeError:
|
||||
print(f" Error parsing response for '{name}'", file=sys.stderr)
|
||||
return None
|
||||
for attempt in range(retry_count):
|
||||
try:
|
||||
req = urllib.request.Request(url, headers={
|
||||
"User-Agent": "EDHDeckBuilder/1.0",
|
||||
"Accept": "*/*"
|
||||
})
|
||||
with urllib.request.urlopen(req, timeout=30) as response:
|
||||
return json.loads(response.read().decode("utf-8"))
|
||||
except urllib.error.HTTPError as e:
|
||||
if e.code == 429:
|
||||
retry_after = int(e.headers.get("Retry-After", 60))
|
||||
print(f" Rate limited. Waiting {retry_after}s...", file=sys.stderr)
|
||||
time.sleep(retry_after)
|
||||
elif e.code == 404:
|
||||
print(f" Error fetching '{name}': Not found", file=sys.stderr)
|
||||
return None
|
||||
else:
|
||||
if attempt < retry_count - 1:
|
||||
wait_time = 2 ** attempt
|
||||
print(f" HTTP {e.code}, retrying in {wait_time}s...", file=sys.stderr)
|
||||
time.sleep(wait_time)
|
||||
else:
|
||||
print(f" Error fetching '{name}': HTTP {e.code}", file=sys.stderr)
|
||||
return None
|
||||
except urllib.error.URLError as e:
|
||||
print(f" Error fetching '{name}': {e.reason}", file=sys.stderr)
|
||||
return None
|
||||
except json.JSONDecodeError:
|
||||
print(f" Error parsing response for '{name}'", file=sys.stderr)
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def extract_card_info(card_data: dict) -> dict:
|
||||
|
||||
Reference in New Issue
Block a user