eoio.serialisation.codecs module#

eoio.serialisation.codecs - codec registry for attribute (de)serialisation

A codec converts a single Python attribute value to something a serialised format (netCDF, Zarr) can store, and back again. Codecs are registered under a stable name; that name is what eoio.serialisation.attrs records in the eoio:attr_encoding marker so decoding is exact rather than guessed.

New types are supported by registering a codec, without modifying this module:

from eoio.serialisation import register_codec

class MyCodec:
    name = "my_type"

    def applies(self, value):
        return isinstance(value, MyType)

    def encode(self, value):
        return str(value)

    def decode(self, encoded):
        return MyType(encoded)

register_codec(MyCodec(), priority=45)

Codecs are consulted in ascending priority order and the first match wins, so priority resolves subclass ambiguity: bool is a subclass of int and datetime is a subclass of date, and in both cases the more specific codec must be offered first.

class eoio.serialisation.codecs.AttrCodec(*args, **kwargs)[source]#

Bases: Protocol

Protocol implemented by attribute codecs.

applies(value: Any) → bool[source]#

Report whether this codec handles value.

Parameters:

value – Candidate attribute value.

Returns:

True when this codec can encode the value.

decode(encoded: Any) → Any[source]#

Reverse encode().

Parameters:

encoded – Previously encoded value.

Returns:

The restored Python object.

encode(value: Any) → Any[source]#

Convert value to a serialisation-safe representation.

Parameters:

value – Attribute value to encode.

Returns:

A value acceptable as a netCDF/Zarr attribute.

name: str#

Stable identifier recorded in the encoding marker.

eoio.serialisation.codecs.CODEC_REGISTRY: Dict[str, AttrCodec] = {'affine': <eoio.serialisation.codecs._AffineCodec object>, 'bool': <eoio.serialisation.codecs._BoolCodec object>, 'bytes': <eoio.serialisation.codecs._BytesCodec object>, 'complex': <eoio.serialisation.codecs._ComplexCodec object>, 'crs_pyproj': <eoio.serialisation.codecs._PyprojCrsCodec object>, 'crs_rasterio': <eoio.serialisation.codecs._RasterioCrsCodec object>, 'date': <eoio.serialisation.codecs._DateCodec object>, 'datetime': <eoio.serialisation.codecs._DatetimeCodec object>, 'datetime64': <eoio.serialisation.codecs._NumpyDatetimeCodec object>, 'datetime_list': <eoio.serialisation.codecs._DatetimeListCodec object>, 'json': <eoio.serialisation.codecs._JsonCodec object>, 'list': <eoio.serialisation.codecs._ListCodec object>, 'ndarray': <eoio.serialisation.codecs._NdarrayCodec object>, 'none': <eoio.serialisation.codecs._NoneCodec object>, 'numpy_scalar': <eoio.serialisation.codecs._NumpyScalarCodec object>, 'path': <eoio.serialisation.codecs._PathCodec object>, 'set': <eoio.serialisation.codecs._SetCodec object>, 'str': <eoio.serialisation.codecs._StrCodec object>, 'time': <eoio.serialisation.codecs._TimeCodec object>, 'timedelta': <eoio.serialisation.codecs._TimedeltaCodec object>, 'timedelta64': <eoio.serialisation.codecs._NumpyTimedeltaCodec object>, 'tuple': <eoio.serialisation.codecs._TupleCodec object>, 'wkt': <eoio.serialisation.codecs._ShapelyCodec object>}#

Registered codecs, keyed by name. Ordering is maintained separately by priority.

eoio.serialisation.codecs.MARKER_ATTR = 'eoio:attr_encoding'#

Attribute name holding the per-scope JSON map of attribute name -> codec name.

eoio.serialisation.codecs.get_codec(name: str) → AttrCodec[source]#

Look up a codec by name.

Parameters:

name – Registered codec name.

Returns:

The codec.

Raises:

KeyError – If no codec is registered under that name.

eoio.serialisation.codecs.is_serialisable(value: Any) → bool[source]#

Report whether a value can be written as an attribute without any encoding.

Grounded in what xarray/netCDF4 actually accepts rather than what looks reasonable: bool and None are rejected outright by the netCDF4 backend, and a mixed-type list such as [1, "a"] is silently coerced to ['1', 'a'], so neither is treated as safe here.

Parameters:

value – Attribute value.

Returns:

True when the value can be stored as-is.

eoio.serialisation.codecs.list_codecs() → List[str][source]#

List registered codec names in consultation order.

Returns:

Codec names, lowest priority value first.

eoio.serialisation.codecs.register_codec(codec: AttrCodec, priority: int = 100, overwrite: bool = False) → AttrCodec[source]#

Register a codec under its own name.

Parameters:
  • codec – Codec instance implementing AttrCodec.

  • priority – Consultation order; lower values are offered the value first.

  • overwrite – Whether replacing an already-registered name is permitted.

Returns:

The registered codec, so it can be assigned in the same statement.

Raises:

KeyError – If the name is already registered and overwrite is False.

eoio.serialisation.codecs.select_codec(value: Any) → AttrCodec | None[source]#

Find the codec responsible for value.

Parameters:

value – Attribute value.

Returns:

The first matching codec in priority order, or None if the value needs no encoding or no codec handles it.

eoio.serialisation.codecs.unregister_codec(name: str) → AttrCodec[source]#

Remove a registered codec.

Parameters:

name – Registered codec name.

Returns:

The removed codec.

Raises:

KeyError – If no codec is registered under that name.