Configuration
fleche discovers configuration by walking the filesystem from the
current working directory upward, collecting every fleche.toml it
encounters. The walk stops at $HOME (inclusive) or at the filesystem
root, whichever comes first. $XDG_CONFIG_HOME/fleche/cache.toml is
then appended as a final lowest-priority layer, defaulting to
~/.config/fleche/cache.toml when $XDG_CONFIG_HOME is unset or
empty (per the XDG base directory spec).
All discovered files are shallow-merged at the top level: files closer
to the current directory win, and a closer file’s top-level table fully
replaces the same key in a farther file (tables are not recursively
merged). This makes it easy to keep a base config at ~/fleche.toml
(or in XDG) and override individual cache definitions in project
subdirectories.
If no configuration file is discovered, fleche falls back to a default
in-memory cache.
Reserved Cache Names
memory
The name memory is a reserved cache name. When requested, fleche will provide a transient in-memory cache. This cache is persistent for the duration of the process, but is not shared with other processes and is lost when the current process exits.
Example:
from fleche import cache
with cache("memory"):
# Results will be cached in memory. The cache persists for the lifetime of the process.
...
void
The name void is a reserved cache name. When requested, fleche will provide a no-op cache that discards all stored values. This is useful for disabling caching entirely without changing your code.
Example:
from fleche import cache
with cache("void"):
# Results will not be cached at all. Every call executes the function.
...
The [default] section
The [default] section is used to configure the default behavior of fleche.
cache
The cache key specifies the name of the default cache to use.
Example:
[default]
cache = "mycache"
metadata
The metadata key specifies the default metadata chain to use. This is a list of strings, where each string is the name of a metadata class from the fleche.metadata module.
Example:
[default]
metadata = ["Runtime"]
Note: The Tags metadata cannot be configured from the config file, as it requires arguments.
Cache sections
You can define multiple cache configurations in the same file, each in its own section.
Each cache section must define two storage backends: values and calls. values is used to store the results of function calls, and calls is used to store the function call details.
Storage backends
Each storage backend is configured using a type key, see the table below. Other keys in the same dict are
passed as keyword arguments to the storage constructor.
Example:
[mycache]
values.type = "memory"
calls.type = "memory"
Available storage types
Type |
Description |
Required |
Optional |
|---|---|---|---|
|
In-memory dictionary
( |
— |
|
|
— |
— |
|
|
Filesystem backend, standard |
|
|
|
Filesystem backend, |
|
same as |
|
Filesystem backend, |
|
same as |
|
HDF5 files via |
|
|
|
SQL via SQLAlchemy ( |
|
|
Key descriptions
rootPath to the storage directory (string;
~is expanded).compress(bool, default
false) — gzip-compress each stored file.lock_timeout(float, default
1.0) — maximum seconds to wait for a concurrent write lock before attempting a read anyway.secret_key(list of hex strings) — HMAC-SHA256 signing keys for tamper detection; see Security for details. If omitted, falls back to the
FLECHE_SECRET_KEYenvironment variable.urlSQLAlchemy connection URL, e.g.
"sqlite:///~/.cache/fleche/calls.db". Leading~is expanded to the home directory insqlite:///URLs.echo(bool, default
false) — log all SQL statements to stderr (useful for debugging).version_validator(str, default omitted) — version validation strategy passed to
bagofholding’sH5Bag.load. One of"exact","semantic-minor","semantic-major", or"none". When omitted,bagofholding’s own default applies.remaining_depth(int, default
0) — destructuring depth; see Destructuring below.
Destructuring
Most value backends ("memory", "pickle", "cloudpickle",
"dill", "bagofholding_hdf") store collections (list,
tuple, dict) by destructuring them: each element is stored
independently under its own cache key, and on load the original structure is
reassembled. This avoids redundant storage of shared sub-structures across
different cached calls.
The optional remaining_depth key (integer, default 0) controls the granularity:
remaining_depth = 0— maximum splitting: every element at every nesting level is stored as a separate entry.remaining_depth = N(positive) — elements whose structural depth is less than N are stored inline within their parent entry rather than as separate entries. Depth is measured from the deepest scalar leaf: scalars (int,str, etc.) have depth 0; a container has depth1 + max(children depths). Withremaining_depth = 1, scalars (depth 0) are inlined into their parent container, so a flat list or dict of only scalars becomes a single cache entry. Nested sub-collections (depth ≥ 1) are still stored as separate entries.
Higher values mean fewer, larger storage entries and less structural sharing between calls.
Example:
[mycache]
values.type = "cloudpickle"
values.root = "~/.cache/fleche/values"
values.remaining_depth = 1 # inline scalars into their parent container
calls.type = "cloudpickle"
calls.root = "~/.cache/fleche/calls"
Cache type
The cache type is selected implicitly from the shape of the section.
The default is a plain Cache; additional top-level
keys turn the section into a wrapper or specialised variant.
read_only
(bool, default false) — wrap the section in a
ReadOnlyCache. Loads continue to work, but saving
or evicting raises Rejected. Useful for pinning a
shared, immutable cache that should never be modified from the local
process.
[readonly]
values.type = "cloudpickle"
values.root = "~/.cache/fleche/values"
calls.type = "cloudpickle"
calls.root = "~/.cache/fleche/calls"
read_only = true
max_size
(int, optional) — turn the section into a
SizeLimitedCache that keeps at most max_size
call records. When the limit is exceeded a record is randomly selected for
eviction. Value storage is not pruned.
[limited]
values.type = "memory"
calls.type = "memory"
max_size = 100
read_only and max_size can be combined; the resulting cache is a
ReadOnlyCache wrapping a SizeLimitedCache.
CacheStack via array-of-tables
A TOML array of tables ([[name]]) defines a
CacheStack. Each element is configured exactly
like a normal cache section (including read_only / max_size).
The first element is the base cache (saves go here; fallback hits are
back-filled into it); subsequent elements are the fallback layers,
checked in order. See CacheStack for the runtime behaviour.
# Saves go to the first layer; loads fall through to the second,
# and hits there are copied back into the first.
[[mystack]]
values.type = "memory"
calls.type = "memory"
[[mystack]]
values.type = "cloudpickle"
values.root = "~/.cache/fleche/values"
calls.type = "cloudpickle"
calls.root = "~/.cache/fleche/calls"
Full Configuration Example
Below is an example of a complete configuration file demonstrating several features:
[default]
cache = "persistent"
metadata = ["Runtime"]
[persistent]
# Store values as cloudpickle files
values.type = "cloudpickle"
values.root = "~/.cache/fleche/values"
# Store call details as cloudpickle files
calls.type = "cloudpickle"
calls.root = "~/.cache/fleche/calls"
[fast]
# Simple in-memory cache
values.type = "memory"
calls.type = "memory"
[hdf5_values]
# HDF5 values backend with SQL call index
values.type = "bagofholding_hdf"
values.root = "~/.cache/fleche/hdf5_values"
calls.type = "sql"
calls.url = "sqlite:///~/.cache/fleche/calls.db"
# Size-limited in-memory cache (evicts random call records past 100)
[limited]
values.type = "memory"
calls.type = "memory"
max_size = 100
# Read-only view of a shared on-disk cache
[readonly]
values.type = "cloudpickle"
values.root = "~/.cache/fleche/values"
calls.type = "cloudpickle"
calls.root = "~/.cache/fleche/calls"
read_only = true
# CacheStack: fast in-memory layer in front of a persistent layer
[[layered]]
values.type = "memory"
calls.type = "memory"
[[layered]]
values.type = "cloudpickle"
values.root = "~/.cache/fleche/values"
calls.type = "cloudpickle"
calls.root = "~/.cache/fleche/calls"