Store
persista.store ¶
Contain stores.
persista.store.OnConflict
module-attribute
¶
OnConflict = Literal['raise', 'skip', 'overwrite', 'merge']
Strategy for handling keys that already exist in the store.
Used by :meth:BaseStore.set, :meth:BaseStore.set_many, and
:meth:BaseStore.set_batches to control what happens when a key being
written already has a value in the store.
Example
>>> from persista.store import InMemoryStore
>>> with InMemoryStore() as store:
... store.set("key", {"a": 1})
... store.set("key", {"b": 2}, on_conflict="merge")
... store.get("key")
...
{'a': 1, 'b': 2}
persista.store.BaseDuckDBStore ¶
Bases: ThreadedAsyncStoreMixin, BaseStore, MultilineDisplayMixin
Define a base class for DuckDB-backed key-value stores.
Subclasses only need to implement :meth:_select_columns,
:meth:_row_to_kv, :meth:_set_many, and :meth:filter, which
control how a value is laid out across the table's columns (see
:class:DuckDBStore for a single JSON column layout and
:class:~persista.store.duckdb_typed.TypedDuckDBStore for a typed
column layout with a JSON overflow column).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
database
|
Path | str
|
Path to the DuckDB file, or |
required |
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
persista.store.BaseDuckDBStore.get_columns_info ¶
get_columns_info() -> dict[str, str]
Return the column names and types of the store's table.
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
A mapping of column name to DuckDB type name. |
Example
>>> from persista.store import DuckDBStore
>>> with DuckDBStore(":memory:") as store:
... store.get_columns_info()
...
{'key': 'VARCHAR', 'value': 'JSON'}
persista.store.BaseDuckDBStore.show_columns_info ¶
show_columns_info() -> None
Print the store's table column names and types to stdout.
This is a convenience wrapper around :meth:get_columns_info
for interactive/debugging use. For programmatic access, use
:meth:get_columns_info instead.
persista.store.BaseFileStore ¶
Bases: ThreadedAsyncStoreMixin, BaseStore, MultilineDisplayMixin
Define a base class for file-based key-value stores.
Each value is persisted as its own file in a directory, using
:mod:iden.io to read and write files. Keys are mapped to
filenames with urllib.parse.quote, so keys containing
characters like / or .. cannot escape the store's
directory. There is no index of keys beyond the directory
listing itself, so :meth:keys, :meth:filter, and
:meth:iter_batches all work by scanning the directory.
Subclasses only need to set :attr:extension and implement
:meth:_save and :meth:_load, which control how a value is
serialized to and from a file (see :class:JsonFileStore for a
JSON encoding and :class:PickleFileStore for a pickle
encoding).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
The directory where value files are stored. Created automatically if it does not already exist. |
required |
**kwargs
|
Any
|
Additional keyword arguments to pass to the
underlying |
{}
|
persista.store.BaseLmdbStore ¶
Bases: ThreadedAsyncStoreMixin, BaseStore, MultilineDisplayMixin
Define a base class for LMDB-backed key-value stores.
LMDB is an embedded, memory-mapped key-value store backed by a
single-directory environment on disk, so unlike Redis this store
needs no separate server process and no explicit tracking of keys:
the environment's own B+tree already provides ordered iteration,
membership checks, and a cheap entry count. :meth:filter is
still implemented client-side by scanning every value in the
store, since LMDB has no query language for matching on the
content of a value.
Subclasses only need to implement :meth:_encode and
:meth:_decode, which control how a value is serialized to and
from what is stored in LMDB (see :class:LmdbStore for a JSON
encoding and :class:PickleLmdbStore for a pickle encoding).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
The directory where the LMDB environment is stored. Created automatically if it does not already exist. |
required |
map_size
|
int
|
The maximum size in bytes of the memory map, i.e.
the upper bound on the total size of the environment
(keys and values combined). Passed to |
_DEFAULT_MAP_SIZE
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
persista.store.BasePostgresStore ¶
Bases: BaseStore, MultilineDisplayMixin
Define a base class for Postgres-backed key-value stores.
Holds both a psycopg.Connection (opened eagerly in
__init__) and a psycopg.AsyncConnection (opened lazily,
on first async use, guarded by an asyncio.Lock). Unlike
:class:~persista.store.sqlite.BaseSQLiteStore (where
aiosqlite is a separate optional package layered on stdlib
sqlite3), psycopg bundles both psycopg.Connection and
psycopg.AsyncConnection in the same package, which is already
a hard requirement for the sync side -- so every async method here
always uses :class:psycopg.AsyncConnection directly, with no
asyncio.to_thread fallback.
A single table (named by the table argument, "store" by
default) backs every value; the primary key column is named by
:attr:_key_column. :meth:get, :meth:get_many, :meth:filter,
and :meth:iter_batches (and their async equivalents) all query
the full row and hand it to :meth:_row_to_value to turn it back
into a value dict, which is what lets subclasses differ in how a
value is laid out across columns (a single JSONB column vs. typed
columns plus a JSONB overflow column) without duplicating any of
the surrounding query logic. This mirrors
:class:~persista.store.sqlite.BaseSQLiteStore.
Subclasses only need to implement :meth:_create_table_sql,
:meth:_row_to_value, :meth:_build_filter_condition,
:meth:_set_many, and :meth:_aset_many (see :class:PostgresStore
for a JSONB-only layout and
:class:~persista.store.postgres.TypedPostgresStore for an
optionally typed one).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conninfo
|
str
|
The connection string/DSN passed to
|
required |
table
|
str
|
The name of the table backing this store. Must be a valid SQL identifier (letters, digits, underscores, not starting with a digit). |
'store'
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
persista.store.BaseRedisStore ¶
Bases: BaseStore, MultilineDisplayMixin
Define a base class for Redis-backed key-value stores.
A Redis set at __keys__ tracks the keys currently in the
store, which allows :meth:count, :meth:keys, and
:meth:contains_many to avoid scanning the whole keyspace.
Unlike the SQL-backed stores, Redis has no query language for
matching on the content of a value, so :meth:filter is
implemented client-side by scanning every value in the store.
Subclasses only need to implement :meth:_encode and
:meth:_decode, which control how a value is serialized to and
from what is stored in Redis (see :class:RedisStore for a JSON
encoding and :class:~persista.store.redis_pickle.PickleRedisStore
for a pickle encoding).
Every sync method runs through the eagerly-created redis.Redis
client; every async (a-prefixed) method runs through a
redis.asyncio.Redis client, created lazily on first use, since
redis-py bundles both under one package (unlike
SQLite/aiosqlite, no asyncio.to_thread fallback is needed
here).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The Redis connection URL passed to
|
'redis://localhost:6379/0'
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
persista.store.BaseSQLiteStore ¶
Bases: BaseStore, MultilineDisplayMixin
Define a base class for SQLite-backed key-value stores.
A single store table backs every value; the primary key
column is named by :attr:_key_column. :meth:get,
:meth:get_many, :meth:filter, and :meth:iter_batches all
query the full row and hand it to :meth:_row_to_value to turn
it back into a value dict, which is what lets subclasses differ
in how a value is laid out across columns (a single JSON column
vs. typed columns plus a JSON overflow column) without
duplicating any of the surrounding query logic.
Subclasses only need to implement :meth:_create_table_sql,
:meth:_row_to_value, :meth:_filter_expr, and
:meth:_set_many (see :class:SQLiteStore for a JSON-only
layout and :class:~persista.store.sqlite_typed.TypedSQLiteStore
for an optionally typed one).
The constructor mirrors :func:sqlite3.connect: the first
positional argument is the database argument accepted by
sqlite3.connect (a path, ":memory:", or a file: URI
when uri=True is passed), and any additional keyword
arguments are forwarded as-is. Use :meth:from_path for a more
convenient constructor that builds the appropriate URI for you,
including read-only access.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
database
|
Path | str
|
The |
required |
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
persista.store.BaseSQLiteStore.from_path
classmethod
¶
from_path(
path: Path | str,
*,
read_only: bool = False,
**kwargs: Any
) -> Self
Construct a store from a file path.
Builds the appropriate file: URI for sqlite3.connect,
including read-only access, so callers don't need to
construct SQLite URIs themselves.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path | str
|
Path to the SQLite file, or |
required |
read_only
|
bool
|
If |
False
|
**kwargs
|
Any
|
Additional keyword arguments to pass to the
constructor (and, from there, to |
{}
|
Returns:
| Type | Description |
|---|---|
Self
|
A new store connected to |
Example
>>> import tempfile
>>> from persista.store import SQLiteStore
>>> with tempfile.TemporaryDirectory() as tmpdir:
... with SQLiteStore.from_path(f"{tmpdir}/data.db") as store:
... store.set("1", {"title": "Intro to Python"})
... store.get("1")
...
{'title': 'Intro to Python'}
persista.store.BaseSQLiteStore.get_columns_info ¶
get_columns_info() -> dict[str, str]
Return the column names and types of the store's table.
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
A mapping of column name to SQLite declared type. |
Example
>>> from persista.store import SQLiteStore
>>> with SQLiteStore(":memory:") as store:
... store.get_columns_info()
...
{'key': 'TEXT', 'value': 'JSON'}
persista.store.BaseSQLiteStore.show_columns_info ¶
show_columns_info() -> None
Print the store's table column names and types to stdout.
This is a convenience wrapper around :meth:get_columns_info
for interactive/debugging use. For programmatic access, use
:meth:get_columns_info instead.
persista.store.BaseStore ¶
Bases: ABC
Abstract base class for key-value stores.
Defines the common interface that all key-value store
implementations must provide. Values are stored as dicts, which
allows :meth:filter to match on the content of a value.
Every operation that touches the underlying store has a sync
method (e.g. :meth:get) and an async twin prefixed with a
(e.g. :meth:aget), both callable on the same instance -- there
is no separate async class. Implementations back these with
whatever mix of blocking and native-async drivers suits the
backend (see subclasses for details); callers only need to pick
which method to call based on whether they're in sync or async
code.
To implement a custom store, subclass :class:BaseStore and
implement all abstract methods.
Implementations are expected to support use as a sync context
manager (with SomeStore(...) as store: ..., calling
:meth:open on entry and :meth:close on exit) and as an async
context manager (async with SomeStore(...) as store: ...,
calling :meth:aopen on entry and :meth:aclose on exit).
Constructing a store does not connect to the underlying backend:
implementations must defer that to :meth:open/:meth:aopen, so
every other method (including :meth:close) raises until the
store has been opened, either explicitly or via the context
manager.
Example
>>> from persista.store import InMemoryStore
>>> with InMemoryStore() as store: # calls open()/close() automatically
... store.set("user:1", {"name": "Ann"})
... store.get("user:1")
...
{'name': 'Ann'}
persista.store.BaseStore.closed
abstractmethod
property
¶
closed: bool
Indicate whether the store is closed.
Returns:
| Type | Description |
|---|---|
bool
|
|
bool
|
open and ready to use. |
persista.store.BaseStore.aclear
abstractmethod
async
¶
aclear() -> None
Async equivalent of :meth:clear.
persista.store.BaseStore.aclose
abstractmethod
async
¶
aclose() -> None
Async equivalent of :meth:close.
persista.store.BaseStore.acontains
abstractmethod
async
¶
acontains(key: str) -> bool
Async equivalent of :meth:contains.
persista.store.BaseStore.acontains_many
abstractmethod
async
¶
acontains_many(keys: list[str]) -> list[bool]
Async equivalent of :meth:contains_many.
persista.store.BaseStore.acount
abstractmethod
async
¶
acount() -> int
Async equivalent of :meth:count.
persista.store.BaseStore.adelete
abstractmethod
async
¶
adelete(key: str) -> None
Async equivalent of :meth:delete.
persista.store.BaseStore.adelete_many
abstractmethod
async
¶
adelete_many(keys: list[str]) -> None
Async equivalent of :meth:delete_many.
persista.store.BaseStore.afilter
abstractmethod
async
¶
afilter(**field_filters: Any) -> list[dict[str, Any]]
Async equivalent of :meth:filter.
persista.store.BaseStore.aget
abstractmethod
async
¶
aget(key: str) -> dict[str, Any] | None
Async equivalent of :meth:get.
persista.store.BaseStore.aget_many
abstractmethod
async
¶
aget_many(keys: list[str]) -> list[dict[str, Any] | None]
Async equivalent of :meth:get_many.
persista.store.BaseStore.aiter_batches
abstractmethod
¶
aiter_batches(
batch_size: int = 32,
) -> AsyncIterator[dict[str, dict[str, Any]]]
Async equivalent of :meth:iter_batches.
persista.store.BaseStore.akeys
abstractmethod
¶
akeys() -> AsyncIterator[str]
Async equivalent of :meth:keys.
persista.store.BaseStore.aopen
abstractmethod
async
¶
aopen() -> None
Async equivalent of :meth:open.
persista.store.BaseStore.aset
abstractmethod
async
¶
aset(
key: str,
value: dict[str, Any],
on_conflict: OnConflict = "overwrite",
) -> None
Async equivalent of :meth:set.
persista.store.BaseStore.aset_batches
async
¶
aset_batches(
items: Iterable[tuple[str, dict[str, Any]]],
batch_size: int = 32,
on_conflict: OnConflict = "overwrite",
) -> None
Async equivalent of :meth:set_batches.
persista.store.BaseStore.aset_many
abstractmethod
async
¶
aset_many(
items: Mapping[str, dict[str, Any]],
on_conflict: OnConflict = "overwrite",
) -> None
Async equivalent of :meth:set_many.
persista.store.BaseStore.avalues
async
¶
avalues(
batch_size: int = 32,
) -> AsyncIterator[dict[str, Any]]
Async equivalent of :meth:values.
persista.store.BaseStore.clear
abstractmethod
¶
clear() -> None
Remove every key-value pair from the store.
This is equivalent to resetting the store to empty, without closing it.
persista.store.BaseStore.close
abstractmethod
¶
close() -> None
Close the store and release any underlying resources (e.g. database connections, file handles).
Implementations should make repeated calls to close() safe
(i.e. idempotent), since :meth:__exit__ calls it
unconditionally and callers may also close a store manually
before using it as a context manager.
persista.store.BaseStore.contains
abstractmethod
¶
contains(key: str) -> bool
Check if the key exists in the store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
The key to check. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the key exists in the store, False otherwise. |
persista.store.BaseStore.contains_many
abstractmethod
¶
contains_many(keys: list[str]) -> list[bool]
Check which keys exist in the store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
keys
|
list[str]
|
The keys to check. |
required |
Returns:
| Type | Description |
|---|---|
list[bool]
|
A list of booleans, in the same order as |
list[bool]
|
each entry is |
list[bool]
|
the store and |
persista.store.BaseStore.count
abstractmethod
¶
count() -> int
Return the total number of key-value pairs in the store.
Returns:
| Type | Description |
|---|---|
int
|
The number of key-value pairs currently stored. |
persista.store.BaseStore.delete
abstractmethod
¶
delete(key: str) -> None
Delete a value by its key.
Keys that do not exist should be silently ignored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
The key of the value to delete. |
required |
persista.store.BaseStore.delete_many
abstractmethod
¶
delete_many(keys: list[str]) -> None
Delete multiple values by their keys.
Keys that do not exist should be silently ignored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
keys
|
list[str]
|
The keys of the values to delete. |
required |
persista.store.BaseStore.filter
abstractmethod
¶
filter(**field_filters: Any) -> list[dict[str, Any]]
Retrieve values whose content matches all provided field filters.
All filters should be combined with AND. Each keyword
argument matches the corresponding key in the stored value
exactly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**field_filters
|
Any
|
Key-value pairs where each key is a field name within a stored value and the value is the exact value to match. Calling with no arguments should return every value in the store. |
{}
|
Returns:
| Type | Description |
|---|---|
list[dict[str, Any]]
|
A list of matching values. |
persista.store.BaseStore.from_uri
abstractmethod
classmethod
¶
from_uri(uri: str, *, read_only: bool = False) -> Self
Reconstruct a store from a URI produced by :meth:to_uri.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
uri
|
str
|
A URI produced by :meth: |
required |
read_only
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
Self
|
A new store instance. |
persista.store.BaseStore.get
abstractmethod
¶
get(key: str) -> dict[str, Any] | None
Retrieve a single value by its key.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
The key to look up. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any] | None
|
The value associated with |
dict[str, Any] | None
|
key is not found. |
persista.store.BaseStore.get_many
abstractmethod
¶
get_many(keys: list[str]) -> list[dict[str, Any] | None]
Retrieve multiple values by their keys.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
keys
|
list[str]
|
The keys to look up. |
required |
Returns:
| Type | Description |
|---|---|
list[dict[str, Any] | None]
|
A list the same length as |
list[dict[str, Any] | None]
|
corresponding value for each key that exists, or |
list[dict[str, Any] | None]
|
|
persista.store.BaseStore.iter_batches
abstractmethod
¶
iter_batches(
batch_size: int = 32,
) -> Iterator[dict[str, dict[str, Any]]]
Yield key-value pairs in batches, avoiding loading the whole store into memory at once.
This is the scalable equivalent of :meth:values: instead of
materializing every value as a single mapping, it streams
them from the underlying store in chunks of batch_size.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch_size
|
int
|
The maximum number of pairs to yield per batch. Must be a positive integer. |
32
|
Yields:
| Type | Description |
|---|---|
dict[str, dict[str, Any]]
|
Dicts mapping key to value, each with at most |
dict[str, dict[str, Any]]
|
|
dict[str, dict[str, Any]]
|
meth: |
dict[str, dict[str, Any]]
|
|
persista.store.BaseStore.keys
abstractmethod
¶
keys() -> Iterator[str]
Iterate over all keys in the store.
Yields:
| Type | Description |
|---|---|
str
|
Every key currently in the store. |
persista.store.BaseStore.open
abstractmethod
¶
open() -> None
Connect to the underlying backend and prepare the store for use (e.g. open a database connection, create a directory).
The constructor must not do this itself: implementations
connect lazily, only once open() (or :meth:__enter__) is
called. Implementations should make repeated calls to
open() safe (i.e. idempotent), since a store may be
reopened after :meth:close.
persista.store.BaseStore.set
abstractmethod
¶
set(
key: str,
value: dict[str, Any],
on_conflict: OnConflict = "overwrite",
) -> None
Add a single key-value pair to the store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
The key to set. |
required |
value
|
dict[str, Any]
|
The value to associate with |
required |
on_conflict
|
OnConflict
|
The strategy to use if
|
'overwrite'
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
persista.store.BaseStore.set_batches ¶
set_batches(
items: Iterable[tuple[str, dict[str, Any]]],
batch_size: int = 32,
on_conflict: OnConflict = "overwrite",
) -> None
Add key-value pairs from an iterable, writing them to the store in mini-batches.
This is the streaming equivalent of :meth:set_many: instead
of requiring every key-value pair to be materialized into a
single mapping upfront, it consumes items lazily and
writes at most batch_size pairs at a time. This keeps
memory usage bounded when items comes from a generator
over a large or unbounded source.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
items
|
Iterable[tuple[str, dict[str, Any]]]
|
An iterable of |
required |
batch_size
|
int
|
The maximum number of pairs to write to the
store per underlying :meth: |
32
|
on_conflict
|
OnConflict
|
The strategy to use for keys that already
exist in the store. See :meth: |
'overwrite'
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
persista.store.BaseStore.set_many
abstractmethod
¶
set_many(
items: Mapping[str, dict[str, Any]],
on_conflict: OnConflict = "overwrite",
) -> None
Add multiple key-value pairs to the store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
items
|
Mapping[str, dict[str, Any]]
|
The values to add, keyed by their unique key. |
required |
on_conflict
|
OnConflict
|
The strategy to use for keys in |
'overwrite'
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
persista.store.BaseStore.to_uri
abstractmethod
¶
to_uri() -> str
Return a URI that identifies where this store's data lives.
Returns:
| Type | Description |
|---|---|
str
|
A URI. For a store backed by a file/database, passing |
str
|
this URI to :meth: |
str
|
data. For a process-local store, the URI carries no |
str
|
reconnection information and :meth: |
str
|
fresh, empty store. |
persista.store.BaseStore.values ¶
values(batch_size: int = 32) -> Iterator[dict[str, Any]]
Iterate over all values without loading them all into memory at once.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch_size
|
int
|
The batch size used internally when pulling values from the underlying store. Does not affect the granularity of what is yielded -- values are always yielded one at a time. |
32
|
Yields:
| Type | Description |
|---|---|
dict[str, Any]
|
One value at a time, in the same order as |
dict[str, Any]
|
meth: |
persista.store.DuckDBStore ¶
Bases: BaseDuckDBStore
A DuckDB-backed key-value store.
Persists values to a DuckDB database and supports adding, retrieving, filtering, and deleting key-value pairs. Each value is stored as a JSON column, which provides flexibility for arbitrary value fields without requiring a fixed schema.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
database
|
Path | str
|
Path to the DuckDB file, or |
':memory:'
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store import DuckDBStore
>>> with DuckDBStore(":memory:") as store:
... store.set_many(
... {
... "1": {
... "title": "Intro to Python",
... "author": "Alice",
... "category": "Programming",
... },
... "2": {
... "title": "Advanced Python",
... "author": "Alice",
... "category": "Programming",
... },
... "3": {"title": "History of Rome", "author": "Bob", "category": "History"},
... }
... )
... len(store.filter(author="Alice"))
... len(store.filter(author="Alice", category="Programming"))
... len(store.filter(category="History"))
...
2
2
1
persista.store.InMemoryStore ¶
Bases: ThreadedAsyncStoreMixin, BaseStore, InlineDisplayMixin
A :class:~persista.store.BaseStore implementation backed
by a plain dict.
Values are held entirely in process memory -- nothing is
persisted to disk. This is primarily useful for testing,
small-scale exploration, or pipelines that don't need durability.
Async methods (aget, aset, ...) are provided by
:class:~persista.store._threaded.ThreadedAsyncStoreMixin, which
runs each sync call in a worker thread.
Values are deep-copied on both write and read so that mutating a
value returned by this store (or a value passed into :meth:set
/ :meth:set_many) never affects the store's internal state.
This trades some performance for isolation; for very large values
or hot loops, consider a store that doesn't copy on every access.
Example
>>> from persista.store import InMemoryStore
>>> with InMemoryStore() as store:
... store.set("1", {"text": "hello"})
... store.count()
... store.get("1")
...
1
{'text': 'hello'}
persista.store.JsonFileStore ¶
Bases: BaseFileStore
A file-based key-value store that serializes each value to its own JSON file.
Values are stored in human-readable form and can be read by any
JSON-compatible tool, but only JSON-compatible value fields (str,
int, float, bool, None, list, dict) are supported; use
:class:PickleFileStore if you need to persist arbitrary Python
objects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
The directory where value files are stored. Created automatically if it does not already exist. |
required |
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> import tempfile
>>> from persista.store import JsonFileStore
>>> with tempfile.TemporaryDirectory() as tmpdir, JsonFileStore(tmpdir) as store:
... store.set_many(
... {
... "1": {
... "title": "Intro to Python",
... "author": "Alice",
... "category": "Programming",
... },
... "2": {
... "title": "Advanced Python",
... "author": "Alice",
... "category": "Programming",
... },
... "3": {"title": "History of Rome", "author": "Bob", "category": "History"},
... }
... )
... len(store.filter(author="Alice"))
...
2
persista.store.LmdbStore ¶
Bases: BaseLmdbStore
An LMDB-backed key-value store.
Persists values to an LMDB environment and supports adding,
retrieving, filtering, and deleting key-value pairs. Each value
is stored as a JSON-encoded string, which provides flexibility
for arbitrary value fields without requiring a fixed schema and
can be read back by any LMDB client regardless of language. This
means only JSON-compatible value fields (str, int, float, bool,
None, list, dict) are supported; use :class:PickleLmdbStore if
you need to persist arbitrary Python objects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
The directory where the LMDB environment is stored. Created automatically if it does not already exist. |
required |
map_size
|
int
|
The maximum size in bytes of the memory map, i.e.
the upper bound on the total size of the environment
(keys and values combined). Passed to |
_DEFAULT_MAP_SIZE
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> import tempfile
>>> from persista.store import LmdbStore
>>> with tempfile.TemporaryDirectory() as tmpdir, LmdbStore(tmpdir) as store:
... store.set_many(
... {
... "1": {
... "title": "Intro to Python",
... "author": "Alice",
... "category": "Programming",
... },
... "2": {
... "title": "Advanced Python",
... "author": "Alice",
... "category": "Programming",
... },
... "3": {"title": "History of Rome", "author": "Bob", "category": "History"},
... }
... )
... len(store.filter(author="Alice"))
...
2
persista.store.NullStore ¶
Bases: BaseStore, InlineDisplayMixin
A :class:~persista.store.BaseStore implementation that
forgets everything written to it.
Every :meth:set/:meth:aset/:meth:set_many/:meth:aset_many
call is silently discarded, so :meth:get/:meth:aget always
report a miss and the store always reports as empty. Because
nothing is ever stored, on_conflict="raise" can never
actually raise KeyError here, unlike other
:class:~persista.store.BaseStore implementations. This is
primarily useful for plugging into
:class:~persista.cache.cache.Cache to disable caching without
changing any calling code: every lookup misses, so
get_or_compute/memoize always recompute the value.
There is no I/O to offload here, so the async methods run inline rather than through a thread pool.
Example
>>> from persista.store import NullStore
>>> from persista.cache import Cache
>>> with Cache(store=NullStore()) as cache:
... cache.set("greeting", "hello")
... cache.get("greeting") is None
...
True
persista.store.PickleFileStore ¶
Bases: BaseFileStore
A file-based key-value store that serializes each value to its own pickle file.
Unlike :class:JsonFileStore, this store can persist arbitrary
Python objects within a value's fields (tuples, sets, custom
classes, etc.), not just JSON-compatible types. The tradeoff is
that value files are opaque binary blobs (not human-readable),
and, since :func:pickle.loads can execute arbitrary code, this
store must never be pointed at a directory that isn't fully
trusted.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
The directory where value files are stored. Created automatically if it does not already exist. |
required |
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> import tempfile
>>> from persista.store import PickleFileStore
>>> with tempfile.TemporaryDirectory() as tmpdir, PickleFileStore(tmpdir) as store:
... store.set("1", {"title": "Intro to Python", "tags": ("python", "intro")})
... store.get("1")
...
{'title': 'Intro to Python', 'tags': ('python', 'intro')}
persista.store.PickleLmdbStore ¶
Bases: BaseLmdbStore
An LMDB-backed key-value store that serializes values with
pickle instead of JSON.
Unlike :class:LmdbStore, this store can persist arbitrary
Python objects within a value's fields (tuples, sets, custom
classes, etc.), not just JSON-compatible types. The tradeoff is
that values are opaque binary blobs from outside Python (not
human-readable, not inspectable from non-Python LMDB clients),
and, since :func:pickle.loads can execute arbitrary code, this
store must never be pointed at an LMDB environment that isn't
fully trusted.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
The directory where the LMDB environment is stored. Created automatically if it does not already exist. |
required |
map_size
|
int
|
The maximum size in bytes of the memory map, i.e.
the upper bound on the total size of the environment
(keys and values combined). Passed to |
_DEFAULT_MAP_SIZE
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> import tempfile
>>> from persista.store import PickleLmdbStore
>>> with tempfile.TemporaryDirectory() as tmpdir, PickleLmdbStore(tmpdir) as store:
... store.set("1", {"title": "Intro to Python", "tags": ("python", "intro")})
... store.get("1")
...
{'title': 'Intro to Python', 'tags': ('python', 'intro')}
persista.store.PickleRedisStore ¶
Bases: BaseRedisStore
A Redis-backed key-value store that serializes values with
pickle instead of JSON.
Unlike :class:~persista.store.RedisStore, this store can persist
arbitrary Python objects within a value's fields (tuples, sets,
custom classes, etc.), not just JSON-compatible types. The
tradeoff is that values are opaque binary blobs from outside
Python (not human-readable, not inspectable from non-Python Redis
clients), and, since :func:pickle.loads can execute arbitrary
code, this store must never be pointed at a Redis instance that
isn't fully trusted.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The Redis connection URL passed to
|
'redis://localhost:6379/0'
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store import PickleRedisStore
>>> with PickleRedisStore("redis://localhost:6379/0") as store: # doctest: +SKIP
... store.set("1", {"title": "Intro to Python", "tags": {"python", "intro"}})
... store.get("1")
...
{'title': 'Intro to Python', 'tags': {'python', 'intro'}}
persista.store.PickleSQLiteStore ¶
Bases: BaseSQLiteStore
A SQLite-backed key-value store that serializes values with
pickle instead of JSON.
Unlike :class:SQLiteStore, this store can persist arbitrary
Python objects within a value's fields (tuples, sets, datetimes,
custom classes, etc.), not just JSON-compatible types. The
tradeoff is that values are opaque binary blobs: SQLite's
json1 functions can't see into them, so :meth:filter can't
push field comparisons down to SQL and instead falls back to
scanning and unpickling every row in Python. Since
:func:pickle.loads can execute arbitrary code, this store must
never be pointed at a database file that isn't fully trusted.
The constructor mirrors :func:sqlite3.connect directly. For the
common case of opening a file by path (optionally read-only), use
:meth:from_path instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
database
|
Path | str
|
The |
':memory:'
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store import PickleSQLiteStore
>>> with PickleSQLiteStore(":memory:") as store:
... store.set("1", {"title": "Intro to Python", "tags": ["python", "intro"]})
... store.get("1")
...
{'title': 'Intro to Python', 'tags': ['python', 'intro']}
persista.store.PostgresStore ¶
Bases: BasePostgresStore
A Postgres-backed key-value store.
Persists values to a Postgres database and supports adding, retrieving, filtering, and deleting key-value pairs. Each value is stored as a JSONB column, which provides flexibility for arbitrary value fields without requiring a fixed schema.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conninfo
|
str
|
The connection string/DSN passed to
|
required |
table
|
str
|
The name of the table backing this store. |
'store'
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store import PostgresStore
>>> with PostgresStore( # doctest: +SKIP
... "postgresql://user:pass@localhost/dbname"
... ) as store:
... store.set_many(
... {
... "1": {"title": "Intro to Python", "author": "Alice"},
... "2": {"title": "Advanced Python", "author": "Alice"},
... }
... )
... len(store.filter(author="Alice"))
...
2
persista.store.RedisStore ¶
Bases: BaseRedisStore
A Redis-backed key-value store.
Persists values to Redis and supports adding, retrieving,
filtering, and deleting key-value pairs. Each value is stored as
a JSON string, which provides flexibility for arbitrary value
fields without requiring a fixed schema, is human-readable
directly from Redis, and can be read by any Redis client
regardless of language. This means only JSON-compatible value
fields (str, int, float, bool, None, list, dict) are supported;
use :class:~persista.store.redis_pickle.PickleRedisStore if you
need to persist arbitrary Python objects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The Redis connection URL passed to
|
'redis://localhost:6379/0'
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store import RedisStore
>>> with RedisStore("redis://localhost:6379/0") as store: # doctest: +SKIP
... store.set_many(
... {
... "1": {
... "title": "Intro to Python",
... "author": "Alice",
... "category": "Programming",
... },
... "2": {
... "title": "Advanced Python",
... "author": "Alice",
... "category": "Programming",
... },
... "3": {"title": "History of Rome", "author": "Bob", "category": "History"},
... }
... )
... len(store.filter(author="Alice"))
...
2
persista.store.SQLiteStore ¶
Bases: BaseSQLiteStore
A SQLite-backed key-value store.
Persists values to a SQLite database and supports adding,
retrieving, filtering, and deleting key-value pairs. Each value
is stored as a JSON column (using SQLite's built-in json1
functions), which provides flexibility for arbitrary value
fields without requiring a fixed schema.
The constructor mirrors :func:sqlite3.connect directly. For the
common case of opening a file by path (optionally read-only), use
:meth:from_path instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
database
|
Path | str
|
The |
':memory:'
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store import SQLiteStore
>>> with SQLiteStore(":memory:") as store:
... store.set_many(
... {
... "1": {
... "title": "Intro to Python",
... "author": "Alice",
... "category": "Programming",
... },
... "2": {
... "title": "Advanced Python",
... "author": "Alice",
... "category": "Programming",
... },
... "3": {"title": "History of Rome", "author": "Bob", "category": "History"},
... }
... )
... len(store.filter(author="Alice"))
... len(store.filter(author="Alice", category="Programming"))
... len(store.filter(category="History"))
...
2
2
1
persista.store.TypedDuckDBStore ¶
Bases: BaseDuckDBStore
A DuckDB-backed key-value store with an optional typed value schema.
Persists values to a DuckDB database and supports adding,
retrieving, and filtering by value fields. An optional
value_schema maps known value field names to DuckDB types.
Known fields are stored as typed columns for fast, index-friendly
queries. Any value fields not in the schema are stored in an
extra JSON overflow column, so nothing is lost.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
database
|
Path | str
|
Path to the DuckDB file, or |
':memory:'
|
value_schema
|
dict[str, str] | None
|
Optional mapping of value field names to DuckDB
type strings (e.g. |
None
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store import TypedDuckDBStore
>>> schema = {"author": "VARCHAR", "year": "INTEGER", "category": "VARCHAR"}
>>> with TypedDuckDBStore(":memory:", value_schema=schema) as store:
... store.set_many(
... {
... "1": {
... "title": "Intro to Python",
... "author": "Alice",
... "category": "Programming",
... },
... "2": {
... "title": "Advanced Python",
... "author": "Alice",
... "category": "Programming",
... },
... "3": {"title": "History of Rome", "author": "Bob", "category": "History"},
... }
... )
... len(store.filter(author="Alice"))
... len(store.filter(author="Alice", category="Programming"))
... len(store.filter(category="History"))
...
2
2
1
Note
:meth:from_uri reconstructs the store with an empty
value_schema, so value fields that were stored in typed
columns won't appear in :meth:get/:meth:filter results
until the caller re-supplies the original value_schema to
a fresh construction; the data itself isn't lost in the
database, just not visible through the reconstructed store.
persista.store.TypedPostgresStore ¶
Bases: BasePostgresStore
A Postgres-backed key-value store with an optional typed value schema.
Persists values to a Postgres database and supports adding,
retrieving, and filtering by value fields. An optional
value_schema maps known value field names to Postgres types.
Known fields are stored as typed columns for fast, index-friendly
queries. Any value fields not in the schema are stored in an
extra JSONB overflow column, so nothing is lost. Mirrors
:class:~persista.store.sqlite.TypedSQLiteStore.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conninfo
|
str
|
The connection string/DSN passed to
|
required |
table
|
str
|
The name of the table backing this store. |
'store'
|
value_schema
|
dict[str, str] | None
|
Optional mapping of value field names to
Postgres type strings (e.g. |
None
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store import TypedPostgresStore
>>> schema = {"author": "TEXT", "year": "INTEGER"}
>>> with TypedPostgresStore( # doctest: +SKIP
... "postgresql://user:pass@localhost/dbname", value_schema=schema
... ) as store:
... store.set_many(
... {
... "1": {"title": "Intro to Python", "author": "Alice", "year": 2022},
... "2": {"title": "History of Rome", "author": "Bob", "year": 2021},
... }
... )
... len(store.filter(author="Alice"))
...
1
Note
:meth:from_uri reconstructs the store with an empty
value_schema and the default table name, so value
fields that were stored in typed columns won't appear in
:meth:get/:meth:filter results until the caller
re-supplies the original value_schema/table to a
fresh construction; the data itself isn't lost in the
database, just not visible through the reconstructed store.
persista.store.TypedSQLiteStore ¶
Bases: BaseSQLiteStore
A SQLite-backed key-value store with an optional typed value schema.
Persists values to a SQLite database and supports adding,
retrieving, and filtering by value fields. An optional
value_schema maps known value field names to SQLite types.
Known fields are stored as typed columns for fast, index-friendly
queries. Any value fields not in the schema are stored in an
extra JSON overflow column, so nothing is lost.
The constructor mirrors :func:sqlite3.connect directly (plus the
value_schema argument). For the common case of opening a file
by path (optionally read-only), use :meth:from_path instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
database
|
Path | str
|
The |
':memory:'
|
value_schema
|
dict[str, str] | None
|
Optional mapping of value field names to SQLite
type strings (e.g. |
None
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store import TypedSQLiteStore
>>> schema = {"author": "TEXT", "year": "INTEGER", "category": "TEXT"}
>>> with TypedSQLiteStore(":memory:", value_schema=schema) as store:
... store.set_many(
... {
... "1": {
... "title": "Intro to Python",
... "author": "Alice",
... "category": "Programming",
... },
... "2": {
... "title": "Advanced Python",
... "author": "Alice",
... "category": "Programming",
... },
... "3": {"title": "History of Rome", "author": "Bob", "category": "History"},
... }
... )
... len(store.filter(author="Alice"))
... len(store.filter(author="Alice", category="Programming"))
... len(store.filter(category="History"))
...
2
2
1
Note
:meth:from_uri reconstructs the store with an empty
value_schema, so value fields that were stored in typed
columns won't appear in :meth:get/:meth:filter results
until the caller re-supplies the original value_schema to
a fresh construction; the data itself isn't lost in the
database, just not visible through the reconstructed store.
persista.store.normalize_on_conflict ¶
normalize_on_conflict(on_conflict: str) -> OnConflict
Normalize and validate an on_conflict value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
on_conflict
|
str
|
The value to normalize. Matched case-insensitively, with leading/trailing whitespace stripped. |
required |
Returns:
| Type | Description |
|---|---|
OnConflict
|
The normalized value, one of :data: |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the normalized value is not one of
:data: |
Example
>>> from persista.store.validation import normalize_on_conflict
>>> normalize_on_conflict(" Overwrite ")
'overwrite'
persista.store.register_scheme ¶
register_scheme(
scheme: str, store_cls: type[BaseStore]
) -> None
Register a store class for a URI scheme used by
:func:store_from_uri.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scheme
|
str
|
The URI scheme to associate with |
required |
store_cls
|
type[BaseStore]
|
The |
required |
Example
>>> from persista.store import InMemoryStore
>>> from persista.store.registry import register_scheme
>>> register_scheme("memory", InMemoryStore)
persista.store.resolve_store ¶
Resolve a :class:~persista.store.BaseStore instance from an
existing object or a configuration dictionary.
If store is already a :class:~persista.store.BaseStore
instance it is returned as-is. If it is a :class:dict, it is
treated as an objectory factory configuration and instantiated
via :func:objectory.factory. See
:func:~coola.factory.resolve_object for details.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
store
|
BaseStore | dict[str, Any]
|
Either a fully configured
:class: |
required |
Returns:
| Type | Description |
|---|---|
BaseStore
|
A configured :class: |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the resolved object is not a
:class: |
Example
>>> from persista.store import InMemoryStore, resolve_store
>>> # From an existing instance:
>>> store = resolve_store(InMemoryStore())
>>> # From a configuration dictionary:
>>> store = resolve_store({"_target_": "persista.store.InMemoryStore"})
persista.store.split_present_missing ¶
split_present_missing(
keys: list[str], flags: list[bool]
) -> tuple[list[str], list[str]]
Split keys into present and missing lists based on flags.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
keys
|
list[str]
|
The keys to split. |
required |
flags
|
list[bool]
|
The presence flags for each key, in the same order as
|
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
A |
list[str]
|
same relative order as |
Example
>>> from persista.store.keys import split_present_missing
>>> split_present_missing(["a", "b", "c"], [True, False, True])
(['a', 'c'], ['b'])
persista.store.store_from_uri ¶
store_from_uri(
uri: str, *, read_only: bool = False
) -> BaseStore
Reconstruct a :class:~persista.store.BaseStore from a URI.
Dispatches on uri's scheme to the matching store class's
:meth:~persista.store.base.BaseStore.from_uri. The returned
store supports both sync and async access. Store classes whose
scheme is shared with another class (TypedPostgresStore reuses
PostgresStore's native postgresql:// scheme,
PickleRedisStore reuses RedisStore's native redis://
scheme) aren't reachable through this dispatcher -- call
TheClass.from_uri(uri) directly for those.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
uri
|
str
|
A URI produced by some |
required |
read_only
|
bool
|
Forwarded to the matched class's |
False
|
Returns:
| Type | Description |
|---|---|
BaseStore
|
A new, already-open store instance. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Example
>>> import tempfile
>>> from persista.store import JsonFileStore, store_from_uri
>>> with tempfile.TemporaryDirectory() as tmpdir:
... with JsonFileStore(tmpdir) as store:
... store.set("key", {"value": 1})
... uri = store.to_uri()
... with store_from_uri(uri) as restored:
... print(restored.get("key"))
...
{'value': 1}
persista.store.validate_batch_size ¶
validate_batch_size(batch_size: int) -> None
Validate that a value is a valid batch_size strategy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch_size
|
int
|
The value to validate. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Example
>>> from persista.store.validation import validate_batch_size
>>> validate_batch_size(32)
persista.store.validate_field_name ¶
validate_field_name(name: str) -> None
Validate that a value filter field name is safe to interpolate into a SQL fragment.
BaseStore.filter implementations build SQL by interpolating
the field name directly (only the filter value is passed as a
bound parameter), so an unrestricted field name is a SQL
injection vector. Restricting it to a simple identifier shape
closes that off.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The field name to validate. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Example
>>> from persista.store.validation import validate_field_name
>>> validate_field_name("user_id")
>>> validate_field_name("bad name")
Traceback (most recent call last):
...
ValueError: Invalid filter field name: 'bad name'. Field names must match '^[A-Za-z_][A-Za-z0-9_]*$'
persista.store.validate_on_conflict ¶
validate_on_conflict(on_conflict: str) -> None
Validate that a value is a valid on_conflict strategy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
on_conflict
|
str
|
The value to validate. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Example
>>> from persista.store.validation import validate_on_conflict
>>> validate_on_conflict("overwrite")
persista.store.factory ¶
Contain factories for stores.
persista.store.factory.BaseStoreFactory ¶
Bases: ABC
Abstract base class for :class:~persista.store.BaseStore
factories.
Subclasses implement :meth:make_store to instantiate
and return a configured
:class:~persista.store.BaseStore object.
This pattern decouples store creation from the rest of the
codebase, making it easy to swap stores (e.g. in-memory, SQLite,
DuckDB) without changing call sites.
Example
>>> from persista.store import InMemoryStore, BaseStore
>>> from persista.store.factory import BaseStoreFactory
>>> class MyStoreFactory(BaseStoreFactory):
... def make_store(self) -> BaseStore:
... return InMemoryStore()
...
>>> factory = MyStoreFactory()
>>> store = factory.make_store()
persista.store.factory.ConfigurableStoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A concrete BaseStore factory that accepts either a pre-built
:class:~persista.store.BaseStore instance or a configuration
dictionary.
When a dict is provided it is resolved at each
:meth:make_store call via
:func:~persista.store.resolve.resolve_store,
which uses objectory to instantiate the configured class.
When an instance is provided it is returned as-is.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
store
|
BaseStore | dict[str, Any]
|
A fully configured
:class: |
required |
Example
>>> from persista.store import InMemoryStore
>>> from persista.store.factory import ConfigurableStoreFactory
>>> factory = ConfigurableStoreFactory(InMemoryStore())
>>> store = factory.make_store()
persista.store.factory.DuckDBStoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A factory that creates a new :class:~persista.store.DuckDBStore
instance on each call to :meth:make_store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
database
|
Path | str
|
Path to the DuckDB file, or |
':memory:'
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store.factory import DuckDBStoreFactory
>>> factory = DuckDBStoreFactory(":memory:")
>>> store = factory.make_store()
persista.store.factory.InMemoryStoreFactory ¶
Bases: BaseStoreFactory, InlineDisplayMixin
A factory that creates a new
:class:~persista.store.InMemoryStore instance on each call to
:meth:make_store.
Example
>>> from persista.store.factory import InMemoryStoreFactory
>>> factory = InMemoryStoreFactory()
>>> store = factory.make_store()
persista.store.factory.JsonFileStoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A factory that creates a new
:class:~persista.store.JsonFileStore instance on each call to
:meth:make_store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
The directory where value files are stored. |
required |
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> import tempfile
>>> from persista.store.factory import JsonFileStoreFactory
>>> with tempfile.TemporaryDirectory() as tmpdir:
... factory = JsonFileStoreFactory(tmpdir)
... store = factory.make_store()
...
persista.store.factory.LmdbStoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A factory that creates a new :class:~persista.store.LmdbStore
instance on each call to :meth:make_store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
The directory where the LMDB environment is stored. |
required |
map_size
|
int
|
The maximum size in bytes of the memory map. Passed
to |
_DEFAULT_MAP_SIZE
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> import tempfile
>>> from persista.store.factory import LmdbStoreFactory
>>> with tempfile.TemporaryDirectory() as tmpdir:
... factory = LmdbStoreFactory(tmpdir)
... store = factory.make_store()
...
persista.store.factory.NullStoreFactory ¶
Bases: BaseStoreFactory, InlineDisplayMixin
A factory that creates a new :class:~persista.store.NullStore
instance on each call to :meth:make_store.
Example
>>> from persista.store.factory import NullStoreFactory
>>> factory = NullStoreFactory()
>>> store = factory.make_store()
persista.store.factory.PickleFileStoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A factory that creates a new
:class:~persista.store.PickleFileStore instance on each call to
:meth:make_store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
The directory where value files are stored. |
required |
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> import tempfile
>>> from persista.store.factory import PickleFileStoreFactory
>>> with tempfile.TemporaryDirectory() as tmpdir:
... factory = PickleFileStoreFactory(tmpdir)
... store = factory.make_store()
...
persista.store.factory.PickleLmdbStoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A factory that creates a new
:class:~persista.store.PickleLmdbStore instance on each call to
:meth:make_store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
The directory where the LMDB environment is stored. |
required |
map_size
|
int
|
The maximum size in bytes of the memory map. Passed
to |
_DEFAULT_MAP_SIZE
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> import tempfile
>>> from persista.store.factory import PickleLmdbStoreFactory
>>> with tempfile.TemporaryDirectory() as tmpdir:
... factory = PickleLmdbStoreFactory(tmpdir)
... store = factory.make_store()
...
persista.store.factory.PickleRedisStoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A factory that creates a new
:class:~persista.store.PickleRedisStore instance on each call to
:meth:make_store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The Redis connection URL passed to
|
'redis://localhost:6379/0'
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store.factory import PickleRedisStoreFactory
>>> factory = PickleRedisStoreFactory("redis://localhost:6379/0")
>>> store = factory.make_store() # doctest: +SKIP
persista.store.factory.PickleSQLiteStoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A factory that creates a new
:class:~persista.store.PickleSQLiteStore instance on each call to
:meth:make_store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
database
|
Path | str
|
The |
':memory:'
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store.factory import PickleSQLiteStoreFactory
>>> factory = PickleSQLiteStoreFactory(":memory:")
>>> store = factory.make_store()
persista.store.factory.PostgresStoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A factory that creates a new
:class:~persista.store.PostgresStore instance on each call to
:meth:make_store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conninfo
|
str
|
The connection string/DSN passed to
|
required |
table
|
str
|
The name of the table backing this store. |
'store'
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store.factory import PostgresStoreFactory
>>> factory = PostgresStoreFactory("postgresql://user:pass@localhost/dbname")
>>> store = factory.make_store() # doctest: +SKIP
persista.store.factory.RedisStoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A factory that creates a new :class:~persista.store.RedisStore
instance on each call to :meth:make_store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The Redis connection URL passed to
|
'redis://localhost:6379/0'
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store.factory import RedisStoreFactory
>>> factory = RedisStoreFactory("redis://localhost:6379/0")
>>> store = factory.make_store() # doctest: +SKIP
persista.store.factory.SQLiteStoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A factory that creates a new :class:~persista.store.SQLiteStore
instance on each call to :meth:make_store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
database
|
Path | str
|
The |
':memory:'
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store.factory import SQLiteStoreFactory
>>> factory = SQLiteStoreFactory(":memory:")
>>> store = factory.make_store()
persista.store.factory.StoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A concrete BaseStore factory that wraps a pre-built
:class:~persista.store.BaseStore instance.
Use this when the store is already instantiated and you simply
want to wrap it in the :class:~BaseStoreFactory interface —
for example, when injecting a fixed store into a component that
expects a factory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
store
|
BaseStore
|
A fully configured
:class: |
required |
Example
>>> from persista.store import InMemoryStore
>>> from persista.store.factory import StoreFactory
>>> factory = StoreFactory(InMemoryStore())
>>> store = factory.make_store()
persista.store.factory.TypedDuckDBStoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A factory that creates a new
:class:~persista.store.TypedDuckDBStore instance on each call to
:meth:make_store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
database
|
Path | str
|
Path to the DuckDB file, or |
':memory:'
|
value_schema
|
dict[str, str] | None
|
Optional mapping of value field names to DuckDB type strings. |
None
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store.factory import TypedDuckDBStoreFactory
>>> factory = TypedDuckDBStoreFactory(":memory:", value_schema={"author": "TEXT"})
>>> store = factory.make_store()
persista.store.factory.TypedPostgresStoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A factory that creates a new
:class:~persista.store.TypedPostgresStore instance on each call to
:meth:make_store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conninfo
|
str
|
The connection string/DSN passed to
|
required |
table
|
str
|
The name of the table backing this store. |
'store'
|
value_schema
|
dict[str, str] | None
|
Optional mapping of value field names to Postgres type strings. |
None
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store.factory import TypedPostgresStoreFactory
>>> factory = TypedPostgresStoreFactory(
... "postgresql://user:pass@localhost/dbname", value_schema={"author": "TEXT"}
... )
>>> store = factory.make_store() # doctest: +SKIP
persista.store.factory.TypedSQLiteStoreFactory ¶
Bases: BaseStoreFactory, MultilineDisplayMixin
A factory that creates a new
:class:~persista.store.TypedSQLiteStore instance on each call to
:meth:make_store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
database
|
Path | str
|
The |
':memory:'
|
value_schema
|
dict[str, str] | None
|
Optional mapping of value field names to SQLite type strings. |
None
|
**kwargs
|
Any
|
Additional keyword arguments to pass to
|
{}
|
Example
>>> from persista.store.factory import TypedSQLiteStoreFactory
>>> factory = TypedSQLiteStoreFactory(":memory:", value_schema={"author": "TEXT"})
>>> store = factory.make_store()