eoio.writers package#
eoio.writers - dataset writers
Writers serialise an xarray Dataset or DataTree to a file format. They are
selected explicitly by name rather than inferred from the output path:
from eoio.writers import WriterFactory
writer_cls = WriterFactory.get_writer("netcdf")
writer_cls().write(ds, "output.nc")
See docs/content/developer_guide/writers/writers.rst for how to add one.
- class eoio.writers.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.
- class eoio.writers.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.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]#
- class eoio.writers.WriterFactory[source]#
Bases:
objectWriter Factory class
- static get_writer(name: str) Type[BaseWriter][source]#
Return the writer registered under
name.- Parameters:
name – Writer name, e.g.
"netcdf".- Returns:
Writer class.
- Raises:
ValueError – If no writer is registered under that name.
- eoio.writers.register_writer(name: str, writer_cls: Type[BaseWriter], overwrite: bool = False) Type[BaseWriter][source]#
- eoio.writers.register_writer(name: str, writer_cls: None = None, overwrite: bool = False) Callable[[Type[BaseWriter]], Type[BaseWriter]]
Register a writer class under a name.
Used as a decorator, matching
eoio.processors.registry.register_processor():@register_writer("netcdf") class NetCDFWriter(BaseWriter): ...
Or called directly, which is what you want for a class you do not own:
register_writer("geotiff", SomeThirdPartyWriter)
Either way the class gets its
nameset, so a registered writer always knows what it is called - which is what ends up in the provenance a write records.- Parameters:
name – Name used to select the writer, e.g.
"netcdf".writer_cls – Writer class. Omit it to use this as a decorator.
overwrite – Whether replacing an already-registered name is permitted.
- Returns:
The registered class, or the decorator that will register it.
- Raises:
KeyError – If the name is taken and
overwriteis False.
- eoio.writers.unregister_writer(name: str) Type[BaseWriter][source]#
Remove a writer registered with
register_writer().- Parameters:
name – Registered writer name.
- Returns:
The removed class.
- Raises:
KeyError – If no writer was registered at runtime under that name.