eoio.writers.base module#
eoio.writers.base - base classes for eoio dataset writers
Design goals#
Mirror
eoio.readers.baseso both halves of the library read the same way.Keep the base small: it owns configuration and orchestration, concrete writers own the format.
Keep import-time dependencies light (format backends are imported lazily).
Writer contract#
Concrete writers must implement:
- write_dataset(obj, path) -> None
- get_extension() -> str
and should set:
- name - the identifier the writer is registered under
Optionally override:
- can_write(obj) -> WriteCapability - to refuse objects the format cannot express
- default_write_params / all_write_params - to declare format-specific options
Typical usage#
writer = SomeWriter(write_params={…}) writer.write(ds, “output.nc”)
write() is the public entrypoint. Unlike a reader, which is constructed around a
single product path, a writer instance holds only configuration and can be reused
across many outputs - which is what write_multi relies on.
Note on history#
This is not a revival of the writer package deleted in 8d1a300. That one patched
existing products in place (copy a .SAFE tree, apply per-band corrections); this one
serialises datasets. The contracts have nothing in common.
- class eoio.writers.base.BaseWriter(write_params: Dict[str, Any] | None = None)[source]#
Bases:
ABCBase class for eoio writers.
This class is intentionally small. It owns: - config merge/validation - a single public entrypoint:
write()- the orchestration common to every format: capability check, conformance check,provenance, attribute encoding
Concrete writers implement
write_dataset()andget_extension().- property all_options: Dict[str, Any]#
Return the available options for this writer.
- Returns:
Dictionary of available write parameters.
- all_write_params: Dict[str, str] = {'create_parents': 'True/False', 'encode_attrs': 'True/False', 'on_nonconformance': 'warn/error/ignore', 'update_history': 'True/False'}#
- can_write(obj: Any) WriteCapability[source]#
Report whether this writer can express
obj.The default accepts any
DatasetorDataTree, which is correct for general-purpose formats: anything expressible in xarray is expressible in netCDF or Zarr. Format-specific writers should override this and explain what is missing - a Sentinel-2 SAFE writer needs an S2-shaped dataset, and saying so is more useful than emitting a broken product.- Parameters:
obj – Candidate object.
- Returns:
Capability, with a reason when the answer is no.
- check_conformance(obj: Dataset | DataTree) List[str][source]#
Check the object against CF-1.8 / ACDD / the controlled vocabulary.
Placeholder until the conformance checks land (see #205); returning no issues keeps the orchestration honest in the meantime rather than pretending to check.
- Parameters:
obj – Object about to be written.
- Returns:
Human-readable descriptions of non-conformances; empty when it conforms.
- default_write_params: Dict[str, Any] = {'create_parents': True, 'encode_attrs': True, 'on_nonconformance': 'warn', 'update_history': True}#
- abstractmethod static get_extension() str[source]#
Return the filename extension this writer produces, including the dot.
Used to name outputs when the caller gives a directory rather than a full path (see
write_multi).
- name: str = ''#
Name this writer is registered under. Concrete writers must set this.
- write(obj: Dataset | DataTree, path: Path | str) str[source]#
Public entrypoint: write an object to
path.Orchestration is the same for every format:
can_write()- refuse early, with a reason the user can act oncheck_conformance()- CF-1.8 / ACDD / controlled vocabularyprovenance - append to
historyandeoio:processing_stepsencode_attrs()- make attributes serialisablewrite_dataset()- the format-specific part
Provenance is added before encoding and writing, so that it ends up in the written file rather than only on a discarded in-memory copy.
The input object is never modified.
- Parameters:
obj – Dataset or DataTree to write.
path – Destination path.
- Returns:
The path written, as a string.
- Raises:
TypeError – If this writer cannot express
obj.
- abstractmethod write_dataset(obj: Dataset | DataTree, path: Path) None[source]#
Write the object in this writer’s format.
Called with attributes already encoded and provenance already applied, so implementations only have to deal with the format itself.
- Parameters:
obj – Dataset or DataTree to write.
path – Destination path, already resolved.
- eoio.writers.base.WritableObject#
Objects a writer accepts.
alias of
Dataset|DataTree
- class eoio.writers.base.WriteCapability(ok: bool, reason: str = '')[source]#
Bases:
objectWhether a writer can express a given object in its format.
- Parameters:
ok – Whether the object can be written.
reason – Why not, when
okis False. Should say what is missing, so the user can act on it.
- ok: bool#
- reason: str = ''#
- class eoio.writers.base.WriterConfig(write_params: Dict[str, Any], provided_write_params: FrozenSet[str] = frozenset({}))[source]#
Bases:
objectNormalised, validated configuration for a writer instance.
- provided_write_params: FrozenSet[str] = frozenset({})#
Names the caller actually supplied. Needed wherever a default and an explicitly requested value of the same parameter must behave differently: the Zarr writer refuses
modealongsideappend_dim, which it can only do without also refusing its own default.
- write_params: Dict[str, Any]#