f40-toolkit
Shared configuration, logging, caching, and common utilities for 40F services.
f40-toolkit is a dependency-light Python package intended to provide a stable set of building blocks that multiple services can share without duplicating glue code.
It currently focuses on four areas:
- Config (
f40_toolkit.config) — local single-file and layered config loading, env overrides, canonical key aliases, and optional remote config overlays from HTTP or S3-compatible object storage. - Logging (
f40_toolkit.logging) — opinionated logging setup with console / rotating-file handlers and channel-based level overrides. - Cache (
f40_toolkit.cache) — backend-agnostic cache manager with memory, file, and optional Redis backends. - Common (
f40_toolkit.common) — shared utilities used across the modules above.
Requirements
- Python 3.12+
Installation
Core package, with minimal dependencies:
pip install f40-toolkit
Optional extras:
# Marker extra for cache (memory/file backends; no extra dependency)
pip install f40-toolkit[cache]
# Redis backend support for cache
pip install f40-toolkit[cache-redis]
# YAML support for config loading
pip install f40-toolkit[config]
# S3-compatible remote config support
pip install f40-toolkit[config-s3]
# YAML + S3-compatible remote config support
pip install f40-toolkit[config,config-s3]
# Convenience install for all optional runtime features
pip install f40-toolkit[all]
What is included
f40_toolkit.config
The configuration subsystem is designed to let services use a homogeneous API while staying flexible about where configuration comes from.
Highlights:
- single-file mode via
<PREFIX>CONFIG_PATH - layered mode via
<PREFIX>CONFIG_DIR,<PREFIX>PROJECT, and<PREFIX>ENV - deep env var overrides with
__ - canonical key aliases for migrations
- optional remote overlay support from:
- HTTP/HTTPS
- S3-compatible object storage (for example Scaleway object storage)
- optional mirrored remote layered loading
Typical usage:
from f40_toolkit.config import get_config
cfg = get_config()
include_system = cfg.get("ops.include_system_in_health", False)
f40_toolkit.logging
Logging is explicit and does not configure itself at import time.
Highlights:
- console + file logging configuration helpers
- channel-based level overrides
- session-aware loggers
- safe defaults for service startup
f40_toolkit.cache
The cache module provides a common cache API that can be backed by different storage implementations.
Highlights:
- memory backend
- file backend (single-host use; multi-process safe via a file lock, but not optimized for large or high-throughput caches — use the redis backend at scale)
- optional Redis backend
- cache key helpers
- simple observability / health-check support
get_or_set(...)convenience flow
f40_toolkit.common
Shared helpers used by the rest of the toolkit, including:
- env parsing
- deep merge / dict helpers
- config redaction for logging (
sanitize_configfor recursive redaction of arbitrary nested structures) - small filesystem / path helpers
Quickstart
Configuration
Minimal usage:
from f40_toolkit.config import configure_global_config, get_config
configure_global_config()
cfg = get_config()
port = cfg.get("server.port", 8080)
Using canonical keys during a migration:
from f40_toolkit.config import configure_global_config, get_config
CANONICAL_KEYS = {
"server.port": ["server.backend_port", "server_settings.port"],
}
configure_global_config(canonical_keys=CANONICAL_KEYS)
cfg = get_config()
port = cfg.get_canonical("server.port", default=8080)
Logging
from f40_toolkit.logging import configure_logging, get_logger
configure_logging()
log = get_logger("service.startup", channel="service")
log.info("Service booted")
Cache
from f40_toolkit.cache import create_cache_from_config, InvalidCacheValue
cfg = {
"env": "prod",
"service": {"name": "billing"},
"customer": "acme",
"cache": {
"backend": "memory", # "memory" | "file" | "redis"
"default_timeout": 300,
"serializer": "json",
},
}
cache = create_cache_from_config(cfg)
cache.set("example", {"ok": True}, timeout=60)
try:
value = cache.get("example")
except InvalidCacheValue:
value = None
print(value)
Memoization helper:
def expensive(a: int, b: int) -> int:
return a + b
value = cache.get_or_set(
key="sum:1:2",
func=expensive,
f_args=[1, 2],
timeout=120,
)
Configuration conventions
By default the config loader uses the F40_ env prefix.
Important env vars:
F40_CONFIG_PATH— enables single-file modeF40_CONFIG_EXTRA— optional extra files appended after local configF40_CONFIG_DIR— root directory for layered modeF40_PROJECT— project name for layered modeF40_ENV— environment / stage for layered mode
F40_CONFIG_EXTRA uses the platform path separator:
- Linux / macOS:
: - Windows:
;
Deep env var overrides use __ as a path separator:
export F40_DB__HOST="db.internal"
export F40_SERVER__PORT="8080"
export F40_FEATURES__0__NAME="beta"
Those can be read back with the same dotted path style:
cfg.get("features.0.name")
Remote config
Remote config is bootstrapped from local config and/or environment variables.
Supported remote providers:
https3
Supported remote modes:
overlaymirrored_layers
Example HTTP overlay bootstrap:
[remote_config]
enabled = true
provider = "http"
mode = "overlay"
url = "https://example.internal/config/my-service.toml"
Example S3-compatible overlay bootstrap:
[remote_config]
enabled = true
provider = "s3"
mode = "overlay"
bucket_name = "service-config"
object_path = "my-service/prod.toml"
endpoint_url = "https://s3.fr-par.scw.cloud"
region_name = "fr-par"
access_key_env = "SCW_ACCESS_KEY"
secret_key_env = "SCW_SECRET_KEY"
Effective precedence is:
- local main file or local layered files
- local extra files from
<PREFIX>CONFIG_EXTRA - remote overlay or remote mirrored layers
- env var overrides
Env vars always win.
Development
Editable install:
pip install -e .[dev]
Run checks:
pytest
ruff check .
mypy src
Local documentation
The repository includes Markdown docs under docs/.
They can be:
- read directly in the repository
- served locally with MkDocs
To run a local docs site:
pip install -e .[docs]
mkdocs serve
License
MIT. See LICENSE.
Release files for f40-toolkit 1.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| f40_toolkit-1.5.0.tar.gz | 67.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| f40_toolkit-1.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 133.9 kB
Release files / f40_toolkit-1.5.0.tar.gz
| Download URL | f40_toolkit-1.5.0.tar.gz |
|---|---|
| Size | 67.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
871f6e877450d30ae22f5a16e75899d96d42c72136cf4243204f9010ce8b4eed
|
|
BLAKE2b-256 checksum How to use checksums |
239dfe32bd7b03f1abff10b5f7475773379119e43fd9d38c22470da4655ccb4a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / f40_toolkit-1.5.0-py3-none-any.whl
| Download URL | f40_toolkit-1.5.0-py3-none-any.whl |
|---|---|
| Size | 66.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
464b88d804429760b643f89bf6943751188f7df5b8d07c87086e7c2c63b3d9ba
|
|
BLAKE2b-256 checksum How to use checksums |
39f54d1fa743fc568660f33f53baaba428b80d68be93957a50ae5875e994bf2b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|