fleche.storage.sql

Attributes

logger

Base

SQLITE_FOREIGN_KEYS_ON

Classes

Sql

SQLAlchemy-backed CallStorage with JSON metadata and DB-backed expand().

Functions

_coerce_sqlite_url(→ str)

Normalise the user-facing url= argument.

_enable_sqlite_foreign_keys(→ None)

Module Contents

fleche.storage.sql.logger[source]
fleche.storage.sql.Base[source]
fleche.storage.sql._coerce_sqlite_url(path_or_url: str | None) str[source]

Normalise the user-facing url= argument.

Accepts a filesystem path (treated as sqlite), a sqlite: URL (passed through, parent dir auto-created), or any other SQLAlchemy URL such as postgresql:// / mysql+pymysql:// (passed through verbatim). Only sqlite paths get the parent-dir-create convenience. Leading ~ is expanded to the home directory in both bare paths and sqlite:/// URLs.

fleche.storage.sql.SQLITE_FOREIGN_KEYS_ON = 'PRAGMA foreign_keys=ON'[source]
fleche.storage.sql._enable_sqlite_foreign_keys(engine) None[source]
class fleche.storage.sql.Sql[source]

Bases: fleche.storage.thread_safe.PerKeyLockMixin, fleche.storage.base.CallStorage

SQLAlchemy-backed CallStorage with JSON metadata and DB-backed expand().

url: str | None = None[source]
echo: bool = False[source]
engine: Any[source]
session: Any[source]
_local: threading.local[source]
__post_init__() None[source]
__reduce__()[source]
_session_context()[source]
_operation_context(key)[source]

Context manager entered around every operation on key.

The base implementation is a no-op. Override in a mixin to inject any resource scoped to the operation — a threading lock, a SQLAlchemy session, an open file handle, a decompression stream, etc.

Receiving key lets implementations choose between a single global resource (ignore the key) or per-key resources (e.g. a striped lock table or a key-specific file handle).

Composing multiple mixins: use super() to chain so that every mixin in the MRO gets to wrap the operation:

@contextlib.contextmanager
def _operation_context(self, key):
    with self._lock:                   # this mixin's resource
        with super()._operation_context(key):
            yield
put(call: fleche.call.DigestedCall, key: fleche.digest.Digest) fleche.digest.Digest[source]
get(key: fleche.digest.Digest) fleche.call.DigestedCall[source]
_contains(key: fleche.digest.Digest) bool[source]
list() Iterable[fleche.digest.Digest][source]
expand(key: fleche.digest.Digest | str) fleche.digest.Digest[source]

Expands a short-hand digest to the full length one.

_evict(key: fleche.digest.Digest) None[source]
save(call: fleche.call.DigestedCall) fleche.digest.Digest[source]
load(key: fleche.digest.Digest | str) fleche.call.DigestedCall[source]
_normalize_value(v: Any) str[source]

Return the stored form used in SQL for argument/result matching.

We must match the generic CallStorage.query semantics which compare digest(template_value) == digest(stored_call_value). In this backend, stored argument/result values are hex-digest strings, and digest(Digest(x)) == x. Therefore we should always compare Arg.value/CallModel.result to str(digest(template_value)).

_build_call_conditions(template: fleche.call.QueryCall) List[Any][source]
_apply_argument_filters(stmt: Any, arguments: dict[str, Any] | None) Any[source]
_apply_metadata_filters(stmt: Any, meta_specs: dict[str, dict[str, Any]] | None) Any[source]
query(template: fleche.call.QueryCall) Iterable[fleche.call.DigestedCall][source]

Find cached calls matching a template using SQL-side filtering.

Semantics match CallStorage.query: - Fields set to None are wildcards. - Arguments and result are compared by digest(template_value) == digest(stored_value). - Metadata can be filtered by providing template.metadata as a mapping of

metadata name -> dict of key/value filters. An empty dict for a given name means “presence of that metadata name”. Filters with simple types (str, bool, int, float) are pushed down to SQL via JSON-extract expressions; other types (e.g., lists) or None values fall back to client-side checks after loading.

This method builds a SELECT over calls, joining the arguments table and metadata table as needed to reduce candidate rows, then loads the resulting calls and performs any remaining client-side validation.

Parameters:

template – A Call used as a template. None-valued fields are wildcards.

Yields:

Call – Matching calls including their decoded metadata.