Skip to content

Source registry

Every data source — file or live — registers here under a name, the one registry shared by both. Built-in sources self-register on import; third-party sources load through the ob_analytics.sources entry-point group (see Extending). A registered value is a Source class; construct it and use the capability you need — OfflineSource for file replay (Pipeline(source=...)), LiveSource for live capture.

Per-source configuration is a typed SourceSettings (a frozen pydantic model), not an untyped dict — subclass it per source, e.g. CcxtSettings. A source that needs an API key marks the field with Credential (see Use an API key).

register_source

register_source(
    name: str, source_cls: type[Source]
) -> None

Register a :class:~ob_analytics.protocols.Source class under name.

Case-insensitive; overwriting an existing registration is allowed (handy for tests and for a plug-in that intentionally shadows a built-in).

list_sources

list_sources() -> list[str]

Return a sorted list of registered source names.

get_source

get_source(name: str) -> type[Source]

Return the source class registered under name (case-insensitive).

Raises:

Type Description
KeyError

If no source is registered under name; the message lists the registered names.

load_source_plugins

load_source_plugins(*, force: bool = False) -> list[str]

Discover and register sources advertised via entry points.

Scans the :data:ENTRY_POINT_GROUP entry-point group; each entry's value is loaded to a :class:~ob_analytics.protocols.Source class and registered under the entry-point name. This is what lets a source live in a separate installable package without editing ob-analytics.

Idempotent: the scan runs once per process unless force is set (the test suite forces a re-scan after monkeypatching the entry points). A plug-in that fails to import is logged and skipped, so one broken package cannot stop the rest from loading.

Returns:

Type Description
list of str

The names newly registered by this call.

SourceSettings

Bases: BaseModel

Base class for a data source's typed, immutable settings.

The typed replacement for the untyped per-source settings dict that live capturers used to carry (CaptureConfig.extras). Every :class:~ob_analytics.protocols.Source declares a settings value of this type; a source that needs no configuration uses the empty base, and a source with venue knobs subclasses it with typed, validated fields — e.g. :class:~ob_analytics.live.ccxt_source.CcxtSettings (exchange / depth_limit / poll_interval).

Frozen so a source's settings are fixed for the run, matching :class:PipelineConfig.

A source that needs an API key declares it as a field marked with :class:Credential. The settings read an unset credential from its environment variable, and every credential's value is removed from the files a capture writes.

credentials classmethod

credentials() -> dict[str, Credential]

The fields marked with :class:Credential, by field name.

remember_secrets

remember_secrets() -> None

Register every SecretStr value held here for redaction.

Validation does this already. A capture does it again as it starts, for settings built without validation (model_copy(update=...)).

check_credentials

check_credentials(source: str) -> None

Raise :class:~ob_analytics.exceptions.ConfigError if a credential is unset.

The message names each missing key's environment variable and where the venue issues keys. source is the source's name, for the message. The keys that are set are registered for redaction.

Credential dataclass

Credential(
    env: str, issued_at: str, from_file: bool = False
)

Marks a :class:SourceSettings field as a key the user supplies.

Put it on a SecretStr | None field with typing.Annotated. When the field is not given, the settings read it from the environment variable env. A key is never a command-line option, because a command line stays in the shell history::

class VenueSettings(SourceSettings):
    api_key: Annotated[
        SecretStr | None,
        Credential(env="VENUE_API_KEY", issued_at="https://venue.example/keys"),
    ] = None

An empty value counts as unset. A value shorter than eight characters is refused, since no venue issues a key that short. A capture checks that every credential is set before it writes anything (:meth:SourceSettings.check_credentials).

Attributes:

Name Type Description
env str

The environment variable the key is read from.

issued_at str

Where the venue issues keys, usually a URL. The error for a missing key names it.

from_file bool

The variable holds the path of a file, and the field holds the file's contents. For a private key, which lives in a file. From Python, pass a :class:~pathlib.Path to read a file, or a str that is the key itself.