MCPcopy Create free account
hub / github.com/Card-Forge/forge / fetch

Function fetch

forge-gui/tools/edhrec_to_forge.py:103–141  ·  view source on GitHub ↗
(url: str, cache_path: Path, refresh: bool, timeout: int, min_interval: float, jitter: float, retries: int)

Source from the content-addressed store, hash-verified

101
102
103def fetch(url: str, cache_path: Path, refresh: bool, timeout: int, min_interval: float, jitter: float, retries: int) -> str:
104 global LAST_REQUEST_AT
105 if cache_path.exists() and not refresh:
106 return cache_path.read_text(encoding="utf-8")
107
108 cache_path.parent.mkdir(parents=True, exist_ok=True)
109 request = Request(
110 url,
111 headers={
112 "User-Agent": "CommanderData/0.1 (+local Forge deckgen data build)",
113 "Accept": "text/html,application/xhtml+xml,application/json;q=0.9,*/*;q=0.8",
114 },
115 )
116 for attempt in range(retries + 1):
117 wait_for_rate_limit(min_interval, jitter)
118 try:
119 with urlopen(request, timeout=timeout) as response:
120 LAST_REQUEST_AT = time.monotonic()
121 body = response.read().decode(response.headers.get_content_charset() or "utf-8", errors="replace")
122 cache_path.write_text(body, encoding="utf-8")
123 return body
124 except HTTPError as exc:
125 LAST_REQUEST_AT = time.monotonic()
126 retry_after = exc.headers.get("Retry-After")
127 if exc.code in RETRY_STATUS_CODES and attempt < retries:
128 sleep_for = parse_retry_after(retry_after) or min(120.0, min_interval * (2 ** (attempt + 1)))
129 print(f"warning: {exc.code} for {url}; sleeping {sleep_for:.1f}s before retry", file=sys.stderr)
130 time.sleep(sleep_for)
131 continue
132 raise
133 except (URLError, TimeoutError):
134 LAST_REQUEST_AT = time.monotonic()
135 if attempt < retries:
136 sleep_for = min(120.0, min_interval * (2 ** (attempt + 1)))
137 print(f"warning: network error for {url}; sleeping {sleep_for:.1f}s before retry", file=sys.stderr)
138 time.sleep(sleep_for)
139 continue
140 raise
141 raise RuntimeError(f"unreachable fetch retry state for {url}")
142
143
144def parse_retry_after(value: str | None) -> float | None:

Callers 2

scrape_commandersFunction · 0.85
scrape_card_dataFunction · 0.85

Calls 5

wait_for_rate_limitFunction · 0.85
parse_retry_afterFunction · 0.85
getMethod · 0.65
decodeMethod · 0.45
readMethod · 0.45

Tested by

no test coverage detected