"""Access to the curated city set (backend/cities.json) that gets crawlable climate pages. Loaded once, lazily; regenerate the JSON with gen_cities.py.""" import json import os _PATH = os.path.join(os.path.dirname(__file__), "cities.json") _CITIES: list[dict] | None = None _BY_SLUG: dict[str, dict] | None = None def _load() -> list[dict]: global _CITIES, _BY_SLUG if _CITIES is None: with open(_PATH, encoding="utf-8") as f: _CITIES = json.load(f) _BY_SLUG = {c["slug"]: c for c in _CITIES} return _CITIES def all_cities() -> list[dict]: return _load() def all_slugs() -> list[str]: return [c["slug"] for c in _load()] def get(slug: str) -> dict | None: """The city for a slug, or None (→ 404).""" _load() return _BY_SLUG.get(slug) def display_name(city: dict) -> str: """Human label: 'Seattle, Washington, United States' (drops repeated admin1).""" parts = [city["name"]] if city.get("admin1") and city["admin1"] != city["name"]: parts.append(city["admin1"]) if city.get("country"): parts.append(city["country"]) return ", ".join(parts) def by_country() -> dict[str, list[dict]]: """Cities grouped by country (population-descending within each), country keys ordered by their largest city — for the /climate hub's crawlable link graph.""" groups: dict[str, list[dict]] = {} for c in _load(): key = c.get("country") or c.get("country_code") or "Other" groups.setdefault(key, []).append(c) for v in groups.values(): v.sort(key=lambda x: -x["population"]) # order countries by their biggest city's population (most prominent first) return dict(sorted(groups.items(), key=lambda kv: -kv[1][0]["population"]))