Add Python tool scaffold for PokeDB data import
Set up tools/import-pokedb/ with CLI, JSON loader, and output models. Replaces the Go/PokeAPI approach with local PokeDB.org JSON processing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
150
tools/import-pokedb/import_pokedb/loader.py
Normal file
150
tools/import-pokedb/import_pokedb/loader.py
Normal file
@@ -0,0 +1,150 @@
|
||||
"""Load and validate PokeDB JSON export files."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
REQUIRED_FILES = [
|
||||
"encounters.json",
|
||||
"locations.json",
|
||||
"location_areas.json",
|
||||
"encounter_methods.json",
|
||||
"versions.json",
|
||||
"pokemon_forms.json",
|
||||
]
|
||||
|
||||
|
||||
class PokeDBData:
|
||||
"""Container for all loaded PokeDB export data."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
encounters: list[dict[str, Any]],
|
||||
locations: list[dict[str, Any]],
|
||||
location_areas: list[dict[str, Any]],
|
||||
encounter_methods: list[dict[str, Any]],
|
||||
versions: list[dict[str, Any]],
|
||||
pokemon_forms: list[dict[str, Any]],
|
||||
) -> None:
|
||||
self.encounters = encounters
|
||||
self.locations = locations
|
||||
self.location_areas = location_areas
|
||||
self.encounter_methods = encounter_methods
|
||||
self.versions = versions
|
||||
self.pokemon_forms = pokemon_forms
|
||||
|
||||
def summary(self) -> str:
|
||||
return (
|
||||
f"PokeDB data loaded:\n"
|
||||
f" encounters: {len(self.encounters):,}\n"
|
||||
f" locations: {len(self.locations):,}\n"
|
||||
f" location_areas: {len(self.location_areas):,}\n"
|
||||
f" encounter_methods: {len(self.encounter_methods):,}\n"
|
||||
f" versions: {len(self.versions):,}\n"
|
||||
f" pokemon_forms: {len(self.pokemon_forms):,}"
|
||||
)
|
||||
|
||||
|
||||
def load_pokedb_data(data_dir: Path) -> PokeDBData:
|
||||
"""Load all PokeDB JSON export files from a directory.
|
||||
|
||||
Exits with an error message if any required files are missing or unparseable.
|
||||
"""
|
||||
missing = [f for f in REQUIRED_FILES if not (data_dir / f).exists()]
|
||||
if missing:
|
||||
print(
|
||||
f"Error: Missing required PokeDB files in {data_dir}:",
|
||||
file=sys.stderr,
|
||||
)
|
||||
for f in missing:
|
||||
print(f" - {f}", file=sys.stderr)
|
||||
print(
|
||||
"\nDownload the JSON export from https://pokedb.org/data-export",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
def _load(filename: str) -> list[dict[str, Any]]:
|
||||
path = data_dir / filename
|
||||
try:
|
||||
with open(path) as f:
|
||||
data = json.load(f)
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error: Failed to parse {path}: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if not isinstance(data, list):
|
||||
print(
|
||||
f"Error: Expected a JSON array in {path}, got {type(data).__name__}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
return data
|
||||
|
||||
return PokeDBData(
|
||||
encounters=_load("encounters.json"),
|
||||
locations=_load("locations.json"),
|
||||
location_areas=_load("location_areas.json"),
|
||||
encounter_methods=_load("encounter_methods.json"),
|
||||
versions=_load("versions.json"),
|
||||
pokemon_forms=_load("pokemon_forms.json"),
|
||||
)
|
||||
|
||||
|
||||
class SeedConfig:
|
||||
"""Container for existing seed configuration files."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
version_groups: dict[str, Any],
|
||||
route_order: dict[str, list[str]],
|
||||
special_encounters: dict[str, Any] | None,
|
||||
) -> None:
|
||||
self.version_groups = version_groups
|
||||
self.route_order = route_order
|
||||
self.special_encounters = special_encounters
|
||||
|
||||
|
||||
def load_seed_config(seeds_dir: Path) -> SeedConfig:
|
||||
"""Load existing seed configuration files (version_groups, route_order, etc.).
|
||||
|
||||
Exits with an error message if required config files are missing.
|
||||
"""
|
||||
vg_path = seeds_dir / "version_groups.json"
|
||||
if not vg_path.exists():
|
||||
print(f"Error: version_groups.json not found at {vg_path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
with open(vg_path) as f:
|
||||
version_groups = json.load(f)
|
||||
|
||||
# Load route_order.json and resolve aliases
|
||||
ro_path = seeds_dir / "route_order.json"
|
||||
if not ro_path.exists():
|
||||
print(f"Error: route_order.json not found at {ro_path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
with open(ro_path) as f:
|
||||
ro_raw = json.load(f)
|
||||
|
||||
route_order: dict[str, list[str]] = dict(ro_raw.get("routes", {}))
|
||||
for alias, target in ro_raw.get("aliases", {}).items():
|
||||
if target in route_order:
|
||||
route_order[alias] = route_order[target]
|
||||
|
||||
# Load special_encounters.json (optional)
|
||||
se_path = seeds_dir / "special_encounters.json"
|
||||
special_encounters = None
|
||||
if se_path.exists():
|
||||
with open(se_path) as f:
|
||||
special_encounters = json.load(f)
|
||||
|
||||
return SeedConfig(
|
||||
version_groups=version_groups,
|
||||
route_order=route_order,
|
||||
special_encounters=special_encounters,
|
||||
)
|
||||
Reference in New Issue
Block a user