Files
planet/backend/app/core/collected_data_fields.py
linkong e1984c7a35 release: bump version to 0.49.0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 17:42:27 +08:00

110 lines
3.2 KiB
Python

from typing import Any, Dict, Optional
FIELD_ALIASES = {
"country": ("country",),
"city": ("city",),
"latitude": ("latitude", "lat"),
"longitude": ("longitude", "lon", "lng"),
"value": ("value",),
"unit": ("unit",),
"cores": ("cores",),
"rmax": ("rmax", "r_max"),
"rpeak": ("rpeak", "r_peak"),
"power": ("power",),
}
NESTED_FIELD_ALIASES = {
"latitude": (
("location", "latitude"),
("location", "lat"),
("geo", "latitude"),
("geo", "lat"),
("coordinates", "latitude"),
("coordinates", "lat"),
),
"longitude": (
("location", "longitude"),
("location", "lon"),
("location", "lng"),
("geo", "longitude"),
("geo", "lon"),
("geo", "lng"),
("coordinates", "longitude"),
("coordinates", "lon"),
("coordinates", "lng"),
),
}
def get_metadata_field(metadata: Optional[Dict[str, Any]], field: str, fallback: Any = None) -> Any:
if isinstance(metadata, dict):
for key in FIELD_ALIASES.get(field, (field,)):
value = metadata.get(key)
if value not in (None, ""):
return value
for path in NESTED_FIELD_ALIASES.get(field, ()):
current: Any = metadata
for key in path:
if not isinstance(current, dict):
current = None
break
current = current.get(key)
if current not in (None, ""):
return current
if field in {"latitude", "longitude"}:
value = _get_coordinate_sequence_value(metadata, field)
if value not in (None, ""):
return value
return fallback
def _get_coordinate_sequence_value(metadata: Dict[str, Any], field: str) -> Any:
for key in ("coordinates", "coord", "coords"):
value = metadata.get(key)
if not isinstance(value, (list, tuple)) or len(value) < 2:
continue
# GeoJSON uses [longitude, latitude]. Most raw collector tuples in this
# codebase use explicit field names, so only sequence aliases are treated
# as GeoJSON-shaped to avoid guessing.
return value[1] if field == "latitude" else value[0]
return None
def build_dynamic_metadata(
metadata: Optional[Dict[str, Any]],
*,
country: Any = None,
city: Any = None,
latitude: Any = None,
longitude: Any = None,
value: Any = None,
unit: Any = None,
) -> Dict[str, Any]:
merged = dict(metadata) if isinstance(metadata, dict) else {}
fallbacks = {
"country": country,
"city": city,
"latitude": latitude,
"longitude": longitude,
"value": value,
"unit": unit,
}
for field, fallback in fallbacks.items():
if fallback not in (None, "") and get_metadata_field(merged, field) in (None, ""):
merged[field] = fallback
return merged
def get_record_field(record: Any, field: str) -> Any:
metadata = getattr(record, "extra_data", None) or {}
fallback_attr = field
if field in {"cores", "rmax", "rpeak", "power"}:
fallback = None
else:
fallback = getattr(record, fallback_attr, None)
return get_metadata_field(metadata, field, fallback=fallback)