Connectors¶
The unit of dataset integration: one connector class per dataset. A connector fetches raw data and
converts it into a TimeFDataset. It has no knowledge of the registry, the engine,
or any other connector, and the consumer SDK never runs it.
The contract, BaseConnector, lives in the timenet package (timenet.connectors). Concrete
connectors live in the timenet-connectors repo alongside their dataset card.
BaseConnector¶
from pathlib import Path
from timenet.connectors import BaseConnector
from timenet.dataset import TimeFDataset
class MyConnector(BaseConnector[MyRawRef]):
def download(self, cache_dir: Path) -> list[MyRawRef]: ...
def convert(self, raw_refs: list[MyRawRef]) -> TimeFDataset: ...
convert is the one abstract stage; download is concrete with a default return [], so a synthetic
connector implements convert alone. The engine drives download -> convert -> derive_schema -> store:
| Method | Nature | Contract |
|---|---|---|
download(cache_dir) |
I/O only, optional (default no-op) | Fetch/discover raw files, return lightweight references. Idempotent; no parsing. |
convert(raw_refs) |
CPU only, required | Parse references into a TimeFDataset. No network. |
metadata() and store() are concrete methods you inherit, not stages you implement:
metadata()reads and validates the dataset'sdataset.yamlcard from disk (DatasetMetadata.from_yaml), so it does file I/O; override it only to point at a different card.metadata().dataset_idmust match the id the connector is curated under.store()writes the dataset through aTimeFWriter, deriving the schema first if absent, and returns the committed version directory; most connectors never override it.
Connectors take no constructor arguments. Configuration comes from environment variables read in
__init__. TRaw is whatever reference type the connector defines (a path, a small dataclass, an S3
key). Generic via PEP 695: class MyConnector(BaseConnector[MyRawRef]).
Sharing data¶
To share time-series data across samples, attach the same TimeSeries instance (or two instances
with the same explicit time_series_id) to each sample. The writer dedupes by time_series_id, so the
bytes are stored once. The same applies to annotations, which the writer dedupes by id.
Discovery and layout¶
Connectors are found lazily by dataset id: there is no central registry to maintain. A concrete
connector lives in its own folder at datasets/<org>/<name>/ (lowercase Python package names): the
package's __init__.py exposes a module-level CONNECTOR and a dataset.yaml card sits beside it, so
timenet-curate build <org>/<name> imports just that package. Reusable bases live under bases/. Each
connector declares its own id in metadata(); ids are lowercase org/name.
Optional dependencies and credentials¶
A connector may need libraries or credentials its source requires. Declare heavy libraries as an
optional extra and import them lazily inside the connector so base users don't have to install them;
a missing library should raise a clear error. Credentials come from the environment. For the
HuggingFace Hub, a token is read from HF_TOKEN automatically (needed only for gated/private sources).
Downloaded source files cache under <TIMENET_CACHE> (see client config).
Example connectors¶
timenet/hello-worldis a synthetic, offline reference connector. It needs no network and produces a fully deterministic dataset, so it doubles as the round-trip fixture: two modalities over a shared data source, a series shared across samples, a windowed sample, a chunk-split-sized series, all three annotation shapes (one shared), and aClassificationTask -> QATaskchain plus aLabelingTask. Its dataset card,dataset.yaml, sits beside it indatasets/timenet/hello_world/.chengsenwang/tsqais a time-series QA dataset: each row's series becomes aTimeSeriesand its question/answer aQATask.
timenet-curate build chengsenwang/tsqa # live download from the Hub into the local registry
timenet-curate build chengsenwang/tsqa --keep-cache # keep the raw sources for a faster rebuild
A successful build removes the dataset's raw download cache (<TIMENET_CACHE>/<dataset_id>), since the
sources are only needed during conversion; pass --keep-cache to retain them.
Keeping download and convert apart is what makes a connector testable offline: convert takes raw
references and touches no network, so a test hands it a checked-in fixture and skips download
entirely. See packages/timenet-connectors/tests/fixtures/ and the _convert() helpers beside them.
Once built, load and inspect a dataset with the SDK. See examples/load_tsqa.py, which loads a dataset
and calls describe() to print its identity, counts, per-spec columns, and a sample preview.
See the API reference for timenet.connectors for the full symbol listing.