Drop the open-by-default on the first three countries (every <details> starts collapsed) and order the country sections alphabetically instead of by largest city's population.
68 lines
2.2 KiB
Python
68 lines
2.2 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")
|
|
_FLAVOR_PATH = os.path.join(os.path.dirname(__file__), "cities_flavor.json")
|
|
_CITIES: list[dict] | None = None
|
|
_BY_SLUG: dict[str, dict] | None = None
|
|
_FLAVOR: 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 flavor(slug: str) -> dict | None:
|
|
"""A city's descriptive blurb {extract, url, title} from cities_flavor.json, or
|
|
None when we have no confident match (the page renders fine without it)."""
|
|
global _FLAVOR
|
|
if _FLAVOR is None:
|
|
try:
|
|
with open(_FLAVOR_PATH, encoding="utf-8") as f:
|
|
_FLAVOR = json.load(f)
|
|
except (OSError, ValueError):
|
|
_FLAVOR = {}
|
|
return _FLAVOR.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 alphabetically — 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"])
|
|
return dict(sorted(groups.items(), key=lambda kv: kv[0].lower()))
|