Update update_currencies.py

Retries + logging: Set timestamped errors on 5xx/429 or JSON failures.

Empty-array guard: script exits non-zero if the API returns [], so won’t commit an empty file.

Exit codes: any API or I/O error yields sys.exit(1), triggering “no commit on failure” logic.
This commit is contained in:
Katos
2025-04-27 15:21:57 +01:00
committed by GitHub
parent 6a5d8d2ed7
commit 060062b484

View File

@@ -1,64 +1,99 @@
import requests #!/usr/bin/env python3
import json import json
import os import logging
import sys
from pathlib import Path
import requests
from requests.adapters import HTTPAdapter, Retry
API_URL = 'https://restcountries.com/v3.1/all?fields=name,common,currencies'
SAVE_PATH = Path('backend/internal/core/currencies/currencies.json')
TIMEOUT = 10 # seconds
def setup_logging():
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s %(levelname)s: %(message)s'
)
def fetch_currencies(): def fetch_currencies():
session = requests.Session()
retries = Retry(
total=3,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=frozenset(['GET'])
)
session.mount('https://', HTTPAdapter(max_retries=retries))
try: try:
response = requests.get('https://restcountries.com/v3.1/all?fields=name,common,currencies') resp = session.get(API_URL, timeout=TIMEOUT)
response.raise_for_status() resp.raise_for_status()
except requests.exceptions.RequestException as e: except requests.exceptions.RequestException as e:
print(f"An error occurred while making the request: {e}") logging.error("API request failed: %s", e)
return [] return None
try: try:
countries = response.json() countries = resp.json()
except json.JSONDecodeError: except ValueError as e:
print("Failed to decode JSON from the response.") logging.error("Failed to parse JSON response: %s", e)
return [] return None
currencies_list = [] result = []
for country in countries: for country in countries:
country_name = country.get('name', {}).get('common') country_name = country.get('name', {}).get('common') or "Unknown"
country_currencies = country.get('currencies', {}) for code, info in country.get('currencies', {}).items():
for currency_code, currency_info in country_currencies.items(): result.append({
symbol = currency_info.get('symbol', '') 'code': code,
currencies_list.append({ 'local': country_name,
'code': currency_code, 'symbol': info.get('symbol', ''),
'local': country_name, 'name': info.get('name', '')
'symbol': symbol,
'name': currency_info.get('name')
}) })
return currencies_list # sort by country name for consistency
return sorted(result, key=lambda x: x['local'].lower())
def save_currencies(currencies, file_path): def load_existing(path: Path):
# Sort the list by the "local" field if not path.exists():
sorted_currencies = sorted(currencies, key=lambda x: x['local'].lower() if x['local'] else "") return []
try: try:
os.makedirs(os.path.dirname(file_path), exist_ok=True) with path.open('r', encoding='utf-8') as f:
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(sorted_currencies, f, ensure_ascii=False, indent=4)
except IOError as e:
print(f"An error occurred while writing to the file: {e}")
def load_existing_currencies(file_path):
try:
with open(file_path, 'r', encoding='utf-8') as f:
return json.load(f) return json.load(f)
except (IOError, json.JSONDecodeError): except (IOError, ValueError) as e:
return [] # Return an empty list if file doesn't exist or is invalid logging.warning("Could not load existing file (%s): %s", path, e)
return []
def save_currencies(data, path: Path):
path.parent.mkdir(parents=True, exist_ok=True)
try:
with path.open('w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
logging.info("Wrote %d entries to %s", len(data), path)
except IOError as e:
logging.error("Failed to write file: %s", e)
sys.exit(1)
def main(): def main():
save_path = 'backend/internal/core/currencies/currencies.json' setup_logging()
logging.info("Starting currency update")
existing_currencies = load_existing_currencies(save_path) existing = load_existing(SAVE_PATH)
new_currencies = fetch_currencies() new = fetch_currencies()
if new_currencies == existing_currencies: if new is None:
print("Currencies up-to-date with API, skipping commit.") logging.error("Aborting: failed to fetch or parse API data.")
else: sys.exit(1)
save_currencies(new_currencies, save_path)
print("Currencies updated and saved.") if not new:
logging.error("Aborting: API returned an empty list.")
sys.exit(1)
if new == existing:
logging.info("No changes detected; skipping write.")
return
save_currencies(new, SAVE_PATH)
if __name__ == "__main__": if __name__ == "__main__":
main() main()