55 lines
1.7 KiB
Python
55 lines
1.7 KiB
Python
|
|
"""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"]))
|