ssb_timeseries.io.protocols

Defines the structural contracts for I/O handlers using typing.Protocol.

This module specifies the formal API that a custom I/O plugin must adhere to. By using Protocols (structural typing), external users can create handler classes that are compatible with ssb-timeseries without needing to inherit from any of its base classes. This provides maximum flexibility and decoupling for plugin authors.

class ArchiveWrite(repository, **options)

Bases: Protocol

Defines the contract for an archive handler.

An archive is a destination, not a source. It takes the dataset’s data as a frame and writes it in whatever layout the archive itself defines, which is why it is not a DataReadWrite.

Notably it does not ask the source handler for a file path. A data repository need not be a filesystem at all, so archiving a dataset held in a database or behind an HTTP API has to work the same way.

Parameters:
  • repository (str | dict)

  • options (Any)

__init__(repository, **options)

Initialize the archive handler with configuration for its destination.

Which dataset an operation concerns is passed to that operation as a DatasetRef, so one handler instance can serve any number of datasets.

Parameters:
  • repository (str | dict) – The archive repository name or configuration.

  • **options (typing.Any) – Any parameters defined for the handler in the configuration.

Return type:

None

write(ref, data, **kwargs)

Archive one version of a dataset’s data.

Parameters:
  • ref (DatasetRef) – The dataset being archived, which names the destination layout.

  • data (typing.Any) – The dataset’s data, as read from the data repository.

  • **kwargs (typing.Any) – Handler specific options, such as the data’s period.

Return type:

None

class DataReadWrite(repository, **options)

Bases: Protocol

Defines the contract (protocol) for data IO handlers.

Parameters:
  • repository (str | dict)

  • options (Any)

__init__(repository, **options)

Initialize the IO handler with configuration for a specific data storage.

This constructor is called by the IO dispatcher. It configures the handler from the repository and its options only. Which dataset an operation concerns is passed to that operation as a DatasetRef, so one handler instance can serve any number of datasets.

Parameters:
  • repository (str | dict) – The data repository name or configuration.

  • **options (typing.Any) – Any parameters defined for the handler in the configuration.

Return type:

None

exists(dataset)

Check if a dataset exists in the configured storage.

Parameters:

dataset (DatasetRef) – The dataset to check for.

Return type:

bool

read(dataset, *args, **kwargs)

Read a dataset’s data from the configured storage.

Parameters:
  • dataset (DatasetRef) – The dataset to read.

  • *args (typing.Any) – Accepted and ignored, for call compatibility.

  • **kwargs (typing.Any) – Handler specific read options, such as an interval.

Return type:

typing.Any

Returns:

The dataset’s data in a dataframe-like format (e.g., PyArrow Table). If the data does not exist, an empty dataframe should be returned.

versions(dataset)

Retrieve a list of available versions for a dataset.

A handler takes only the dataset ref, because the ref carries the versioning, and the handler’s configured options carry everything else about its own storage. Storage specific concerns such as a file name pattern are deliberately absent, so that a handler backed by a database or an HTTP API is not asked to interpret them.

Parameters:

dataset (DatasetRef) – The dataset to list versions for.

Return type:

list[datetime | str]

Returns:

A sorted list of version identifiers (datetimes or strings).

write(dataset, data, tags=None)

Write a dataset’s data to the configured storage.

This method should handle both the creation of new data files and the updating/merging of data into existing files, depending on the versioning strategy of the dataset.

Parameters:
  • dataset (DatasetRef) – The dataset to write.

  • data (typing.Any) – The data to be written (e.g., a pandas DataFrame or PyArrow Table).

  • tags (dict | None) – A dictionary of metadata tags to be stored with the data, often in the file’s schema.

Return type:

None

class MetadataReadWrite(repository, **options)

Bases: Protocol

Defines the contract (protocol) for metadata IO handlers.

Parameters:
  • repository (str | dict)

  • options (Any)

__init__(repository, **options)

Initialize the IO handler for a specific metadata storage.

This constructor is called by the IO dispatcher. The handler is configured from the repository and its options only. Which dataset an operation concerns is named in that operation.

Parameters:
  • repository (str | dict) – The metadata repository name or configuration.

  • **options (typing.Any) – Any parameters defined for the handler in the configuration.

Return type:

None

exists(name)

Check if metadata for a given dataset name exists.

Return type:

bool

Parameters:

name (str)

read(name)

Read the metadata of one dataset from the configured storage.

Return type:

dict[str, typing.Any]

Returns:

A dictionary containing the metadata tags for the dataset.

Parameters:

name (str)

search(**kwargs)

Search and retrieve metadata from the configured storage.

This method should allow searching for datasets based on various metadata criteria.

Return type:

list[dict[str, typing.Any]]

Returns:

A list of catalog items matching the criteria.

write(name, tags)

Write metadata for one dataset to the configured storage.

Parameters:
  • name (str) – The name of the dataset the tags belong to.

  • tags (dict[str, typing.Any]) – The metadata tags to write.

Return type:

None