"""muse.core.record_helpers — typed accessor helpers for deserialized storage dicts. Used by CommitRecord, SnapshotRecord, TagRecord, and ReleaseRecord to safely extract typed values from raw JSON/msgpack mappings without raising on missing or wrong-typed fields. """ from __future__ import annotations from muse.core.types import MsgpackDict, Manifest def _str_val( d: MsgpackDict, key: str, default: str = "" ) -> str: """Return ``d[key]`` as ``str``, or *default* if absent or wrong type.""" val = d.get(key, default) return val if isinstance(val, str) else default def _int_val( d: MsgpackDict, key: str, default: int = 0 ) -> int: """Return ``d[key]`` as ``int``, or *default* if absent or wrong type. Excludes ``bool`` (which is a subclass of ``int`` in Python) to prevent accidental coercion. """ val = d.get(key, default) return val if isinstance(val, int) and not isinstance(val, bool) else default def _str_or_none( d: MsgpackDict, key: str ) -> str | None: """Return ``d[key]`` as ``str | None``.""" val = d.get(key) return val if isinstance(val, str) else None def _str_list( d: MsgpackDict, key: str ) -> list[str]: """Return ``d[key]`` as ``list[str]``, filtering non-string elements.""" val = d.get(key) if not isinstance(val, list): return [] return [x for x in val if isinstance(x, str)] def _str_dict( d: MsgpackDict, key: str ) -> Manifest: """Return ``d[key]`` as ``dict[str, str]``, filtering non-string values.""" val = d.get(key) if not isinstance(val, dict): return {} return {k: v for k, v in val.items() if isinstance(v, str)} def _float_val( d: MsgpackDict, key: str, default: float | None = None ) -> float | None: """Return ``d[key]`` as ``float | None``, or *default* if absent or wrong type. Accepts ``int`` values (coerced to float) since stored JSON may encode a round float like ``1.0`` as an integer. Excludes ``bool`` to prevent accidental coercion from boolean-typed fields. """ val = d.get(key, default) if val is None: return None if isinstance(val, bool): return default if isinstance(val, (int, float)): return float(val) return default