stores¶
CompositeStore ¶
Bases: StoreBase
Routes each kind to a backend by record name, falling back to a default store.
This is what composition buys over subclassing: a deployment keeping rigs and tasks on a network share but trainer state in Dataverse is a routing table, not a class.
Example
from clabe.stores.dataverse import DataverseStore
store = CompositeStore(
default=LocalFileStore(root=VR_LIB),
routes={"trainer_state": DataverseStore()},
)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
default
|
Store | None
|
Serves any kind not named in |
None
|
routes
|
Mapping[str, Store] | None
|
Maps a :attr: |
None
|
Source code in src/clabe/stores/_base.py
318 319 320 321 322 323 324 325 326 327 | |
resolve ¶
resolve(
kind: KindLike[T],
*,
scope: Scope | None = None,
pick_kwargs: PickRequestKwargs | None = None,
) -> T
Delegates to the routed backend, so its own presentation is used.
Source code in src/clabe/stores/_base.py
345 346 347 348 349 350 351 352 353 354 | |
list ¶
list(
kind: KindLike[T], *, scope: Scope | None = None
) -> Sequence[T]
Delegates to the routed backend.
Source code in src/clabe/stores/_base.py
356 357 358 359 | |
write ¶
write(
kind: KindLike[T],
value: T,
*,
scope: Scope | None = None,
) -> None
Delegates to the routed backend.
Source code in src/clabe/stores/_base.py
361 362 363 364 | |
scoped ¶
scoped(**scope: str) -> CompositeStore
Returns a composite whose every backend is narrowed by the given scope.
Source code in src/clabe/stores/_base.py
366 367 368 369 370 371 | |
Kind ¶
Kind(
model: type[T],
name: str | None = None,
*,
validators: Callable[[T], T]
| Iterable[Callable[[T], T]]
| None = None,
)
Bases: Generic[T]
A record name bound to the pydantic model that parses it.
The name routes the record to a backend and determines its storage layout; the model types the return value of every store call made with this kind.
Canonical kinds should be built through :meth:from_rig, :meth:from_task,
:meth:from_session or :meth:from_trainer_state, which fix the framework
name. The bare constructor derives the name from the model class instead,
so Kind(AindVrForagingRig) is named "aind_vr_foraging_rig", not
"rig" -- it is for custom records only.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
type[T]
|
The pydantic model records of this kind deserialize to. |
required |
name
|
str | None
|
The record name. Defaults to the snake-cased model class name. |
None
|
validators
|
Callable[[T], T] | Iterable[Callable[[T], T]] | None
|
One callable, an iterable of callables, or |
None
|
Source code in src/clabe/stores/_base.py
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | |
adapter
cached
property
¶
adapter: TypeAdapter[T]
Serializes and parses records of this kind. Also covers models that are not BaseModel.
from_rig
staticmethod
¶
from_rig(
model: type[TRig],
*,
validators: Callable[[TRig], TRig]
| Iterable[Callable[[TRig], TRig]]
| None = validators,
) -> Kind[TRig]
Builds the canonical "rig" kind for a rig model.
Source code in src/clabe/stores/_base.py
118 119 120 121 122 123 124 125 | |
from_task
staticmethod
¶
Builds the canonical "task" kind for a task model.
Source code in src/clabe/stores/_base.py
127 128 129 130 | |
from_session
staticmethod
¶
from_session() -> Kind[Session]
Builds the canonical "session" kind for a session model.
Source code in src/clabe/stores/_base.py
132 133 134 135 | |
from_trainer_state
staticmethod
¶
from_trainer_state() -> Kind[TrainerState]
Builds the canonical "trainer_state" kind.
Source code in src/clabe/stores/_base.py
137 138 139 140 141 | |
Store ¶
Bases: Protocol
Reads, resolves and writes records of a given :class:Kind.
Which kinds a store actually serves is a deployment fact, not a type-level one: an unsupported kind raises when the call is made.
resolve ¶
resolve(
kind: KindLike[T],
*,
scope: Scope | None = None,
pick_kwargs: PickRequestKwargs | None = None,
) -> T
Selects a single record, prompting the user when the choice is ambiguous.
Source code in src/clabe/stores/_base.py
170 171 172 173 174 175 176 177 178 | |
list ¶
list(
kind: KindLike[T], *, scope: Scope | None = None
) -> Sequence[T]
Returns every record of this kind in scope, without prompting.
Source code in src/clabe/stores/_base.py
180 181 182 | |
write ¶
write(
kind: KindLike[T],
value: T,
*,
scope: Scope | None = None,
) -> None
Persists a record. Whether that overwrites, versions or appends is the store's contract.
Source code in src/clabe/stores/_base.py
184 185 186 | |
StoreBase ¶
StoreBase(*, scope: Scope | None = None)
Bases: ABC
Base for stores, supplying scope narrowing and the default resolution policy.
Subclasses implement :meth:_candidates and :meth:write, and may override
:meth:resolve when their backend affords a better presentation than a flat
pick list.
Source code in src/clabe/stores/_base.py
210 211 | |
scoped ¶
Returns a view sharing this store's data, narrowed by the given scope.
The view is the same concrete store type, so narrowing never loses backend-specific typing.
Source code in src/clabe/stores/_base.py
218 219 220 221 222 223 224 225 226 | |
write
abstractmethod
¶
write(
kind: KindLike[T],
value: T,
*,
scope: Scope | None = None,
) -> None
Persists a record. See :meth:Store.write.
Source code in src/clabe/stores/_base.py
236 237 238 | |
list ¶
list(
kind: KindLike[T], *, scope: Scope | None = None
) -> Sequence[T]
Returns every record of this kind in scope, validated but unprompted.
Source code in src/clabe/stores/_base.py
240 241 242 243 | |
resolve ¶
resolve(
kind: KindLike[T],
*,
scope: Scope | None = None,
pick_kwargs: PickRequestKwargs | None = None,
) -> T
Selects a single record: raises on none, auto-selects a lone candidate, prompts otherwise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
KindLike[T]
|
The kind of record to resolve. |
required |
scope
|
Scope | None
|
Narrows which records are considered. Layered over the store's own scope. |
None
|
pick_kwargs
|
PickRequestKwargs | None
|
Optional overrides for the :class: |
None
|
Raises:
| Type | Description |
|---|---|
LookupError
|
If no record of this kind exists in scope, or the user declined to pick one. |
NoFrontendError
|
If a choice must be made and no frontend is registered. |
Source code in src/clabe/stores/_base.py
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | |
DefaultLayout ¶
The config library tree as it exists on the shared drive today.
Rig/<computer_name>/*.json, Task/*.json and
Subjects/<subject>/<kind>.json. Tasks read from the subject folder first
and fall back to the shared library, which is the ordered scope chain that
replaces the nested lookup the picker used to do inline.
Kinds other than rig and task are per-subject state, living beside
the subject's task; with no subject in scope they sit at the library root,
which is what makes a one-off store pointed at a session directory work.
read ¶
Returns the glob patterns for this kind, subject folder before shared library.
Source code in src/clabe/stores/_local.py
48 49 50 51 52 53 54 55 56 | |
write ¶
Returns the single path this kind is written to.
Source code in src/clabe/stores/_local.py
58 59 60 61 62 | |
Layout ¶
Bases: Protocol
Maps a record kind and scope onto paths within a config library.
read ¶
Returns library-relative glob patterns to read from, highest priority first.
Source code in src/clabe/stores/_local.py
25 26 27 | |
LocalFileStore ¶
LocalFileStore(
root: PathLike | str,
*,
layout: Layout | None = None,
scope: Scope | None = None,
)
Bases: StoreBase
A store over a directory of JSON files, i.e. the config library.
Writes overwrite, and create the directories they need. Files that fail to parse are skipped with a warning rather than failing the whole listing.
Example
store = LocalFileStore(root=r"\\allen\aind\scratch\AindBehavior.db\AindVrForaging")
rig = store.resolve(Kind.from_rig(AindVrForagingRig))
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
PathLike | str
|
The config library directory. |
required |
layout
|
Layout | None
|
Maps kinds onto paths within |
None
|
scope
|
Scope | None
|
Initial scope. |
None
|
Source code in src/clabe/stores/_local.py
84 85 86 87 88 89 90 91 92 93 | |
scoped ¶
Returns a view sharing this store's data, narrowed by the given scope.
The view is the same concrete store type, so narrowing never loses backend-specific typing.
Source code in src/clabe/stores/_base.py
218 219 220 221 222 223 224 225 226 | |
list ¶
list(
kind: KindLike[T], *, scope: Scope | None = None
) -> Sequence[T]
Returns every record of this kind in scope, validated but unprompted.
Source code in src/clabe/stores/_base.py
240 241 242 243 | |
resolve ¶
resolve(
kind: KindLike[T],
*,
scope: Scope | None = None,
pick_kwargs: PickRequestKwargs | None = None,
) -> T
Selects a single record: raises on none, auto-selects a lone candidate, prompts otherwise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
KindLike[T]
|
The kind of record to resolve. |
required |
scope
|
Scope | None
|
Narrows which records are considered. Layered over the store's own scope. |
None
|
pick_kwargs
|
PickRequestKwargs | None
|
Optional overrides for the :class: |
None
|
Raises:
| Type | Description |
|---|---|
LookupError
|
If no record of this kind exists in scope, or the user declined to pick one. |
NoFrontendError
|
If a choice must be made and no frontend is registered. |
Source code in src/clabe/stores/_base.py
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | |
write ¶
write(
kind: KindLike[T],
value: T,
*,
scope: Scope | None = None,
) -> None
Overwrites the file this kind maps to, creating parent directories.
Source code in src/clabe/stores/_local.py
117 118 119 120 121 122 123 | |
MemoryStore ¶
MemoryStore(*, scope: Scope | None = None)
Bases: StoreBase
A store holding records in memory, for tests and for assembling records in-process.
Writes append, as Dataverse does, so several records of one kind can be offered as candidates. A record is visible to a read whose scope agrees with every narrowing the record was written under, so a record written unscoped is library-wide.
Source code in src/clabe/stores/_memory.py
19 20 21 | |
scoped ¶
Returns a view sharing this store's data, narrowed by the given scope.
The view is the same concrete store type, so narrowing never loses backend-specific typing.
Source code in src/clabe/stores/_base.py
218 219 220 221 222 223 224 225 226 | |
list ¶
list(
kind: KindLike[T], *, scope: Scope | None = None
) -> Sequence[T]
Returns every record of this kind in scope, validated but unprompted.
Source code in src/clabe/stores/_base.py
240 241 242 243 | |
resolve ¶
resolve(
kind: KindLike[T],
*,
scope: Scope | None = None,
pick_kwargs: PickRequestKwargs | None = None,
) -> T
Selects a single record: raises on none, auto-selects a lone candidate, prompts otherwise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
KindLike[T]
|
The kind of record to resolve. |
required |
scope
|
Scope | None
|
Narrows which records are considered. Layered over the store's own scope. |
None
|
pick_kwargs
|
PickRequestKwargs | None
|
Optional overrides for the :class: |
None
|
Raises:
| Type | Description |
|---|---|
LookupError
|
If no record of this kind exists in scope, or the user declined to pick one. |
NoFrontendError
|
If a choice must be made and no frontend is registered. |
Source code in src/clabe/stores/_base.py
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | |
write ¶
write(
kind: KindLike[T],
value: T,
*,
scope: Scope | None = None,
) -> None
Appends a record, so repeated writes accumulate as candidates.
Source code in src/clabe/stores/_memory.py
34 35 36 | |
as_kind ¶
as_kind(kind: KindLike[T]) -> Kind[T]
Normalizes a kind-or-model argument into a :class:Kind.
Source code in src/clabe/stores/_base.py
156 157 158 | |