API reference
Public modules
| Module or command | Availability | Purpose |
|---|---|---|
std.__version__ |
Core | Installed distribution version string |
std.config |
Core | YAML/TOML loading, Pydantic Settings sources, and immutable snapshots |
std.collections |
Core | Nested mapping merge and path helpers |
std.files |
Core | Atomic text-file replacement |
std.logging |
Core | Environment-aware standard logging presets and structured JSON output |
std.service |
Core | Async service lifecycle and managed background tasks |
std command |
Core | Agent guidance and the packaged Python skill |
std.fastapi |
standard-fastapi or standard[fastapi] |
App setup, lifecycle, token auth, health checks, request logging, and Pydantic Settings dependencies |
std.aws |
standard-aws or standard[aws] |
AWS Secrets Manager loader and Pydantic source |
std.http |
standard-http or standard[http] |
Async HTTPX client, retries, response models, and authentication |
std.cache |
standard-cache or standard[cache] |
Redis client, sync/async cache decorators, and distributed locks |
std.rdbms |
standard-rdbms or standard[rdbms] |
Async SQLAlchemy database managers for SQLite, PostgreSQL, and MySQL |
The current coordinated release is 0.2.4; each integration has its own
distribution and matching convenience extra. Install standard for core APIs,
then select only the provider packages your application uses. From a checkout,
install core plus the relevant packages/standard-* project in editable mode.
See current release status and
publishing for distribution links and release details. The focused guides cover
HTTP, Redis cache, and
relational databases.
Configuration
from std.config import ConfigManager
manager = ConfigManager.from_files("config/base.yaml", "config/local.toml")
snapshot = manager.snapshot
host = snapshot.get_path("database.host", "localhost")
updated = manager.reload()
ConfigManager.from_file(path, *, optional=False, environ=None)loads one YAML/TOML file or recursively reads a directory of supported files.ConfigManager.from_files(*paths, optional=False, environ=None)composes files and directories in argument order. Files discovered inside each directory are sorted by normalized relative POSIX path.ConfigManager.snapshotreturns the current immutableConfigSnapshot.ConfigManager.reload(*, environ=None)parses a complete candidate and publishes it atomically. It returns the new snapshot; if parsing fails, the previous snapshot remains current. An explicitenvironmapping applies to that reload only.ConfigSnapshot.revisionstarts at1and increments after each successful reload.ConfigSnapshot.sourcesis a tuple of the source file paths used to build that snapshot. Directory inputs expand to their matched YAML/TOML files in merge order.ConfigSnapshot.get_path(path, default=None)reads a dotted string or a sequence of string path segments. A missing segment returnsdefault.ConfigSnapshot.to_dict()returns an independent mutable copy. Nested mappings become dictionaries, sequences become lists, and frozen sets become sets.
Paths accept strings or os.PathLike values. A missing source raises MissingConfigSourceError unless optional=True; optional mode skips missing paths. An existing directory with no YAML/TOML files is empty. from_files() without paths raises ValueError.
The merge rules are: recursively merge mappings, append lists, and replace other conflicts with the later value. YAML and TOML string values support ${NAME}, ${NAME:-default}, and $$ interpolation. An unset required variable or invalid placeholder raises ConfigInterpolationError.
Errors
ConfigError is the public base class and exposes optional source and location attributes. Its subclasses identify the failure:
MissingConfigSourceError: a required file or directory is missing.ConfigFormatError: a file cannot be read or parsed, its root is not a mapping, or its format is unsupported.ConfigInterpolationError: a placeholder is malformed, unset, or cyclic.
Errors include the source path and location when available. Interpolation and parser errors do not include configuration or environment values.
Pydantic Settings
Define the application's settings aggregate in core/settings.py:
from std.config import YamlSettings
class Settings(YamlSettings):
std_config_file = "settings.yaml"
service_name: str
port: int = 8080
YamlSettings reads settings.yaml by default; TomlSettings reads settings.toml. Set std_config_file to choose another file or directory, and set std_config_optional = True only when it is valid for the source to be missing. Both bases order Pydantic sources as init kwargs, config files, process environment, dotenv, and file secrets. The first source has the highest priority.
The source classes are also public:
ConfigSettingsSource(settings_cls, *paths, optional=False, allowed_extensions=None)accepts YAML and TOML by default.YamlSettingsSource(settings_cls, *paths, optional=False)accepts.yamland.ymlfiles.TomlSettingsSource(settings_cls, *paths, optional=False)accepts.tomlfiles.
Each source returns the loaded mapping to Pydantic Settings. Use one in settings_customise_sources when a Settings class needs its own file path or source priority.
Collections and files
std.collections.deep_merge(*mappings)recursively merges mappings, appends lists, replaces other conflicts with later values, and does not mutate the inputs. Values in the result are independent copies. With no inputs, it returns{}.std.collections.get_path(mapping, path, default=None)reads nested mappings. For a dotted string, empty path segments are ignored; a missing segment returnsdefault.std.collections.set_path(mapping, path, value)mutates the supplied dictionary, creating intermediate dictionaries. The path must contain at least one non-empty string segment. It raisesValueErrorfor an empty/invalid path andTypeErrorif it must descend through a non-dictionary value.std.files.atomic_write_text(path, text, *, encoding="utf-8", mode=0o600, create_parents=False)returns the targetPathafter writing a temporary sibling, flushing it, and atomically replacing the destination. Parent directories must already exist unlesscreate_parents=True. The default mode is owner-only; setmodeto choose another permission mode.
Logging
std.logging.LoggingEnvironment, LoggingLevel, and LoggingFormat describe
the supported values. LoggingConfig validates environment-independent
formatter, stream, color, source, and named-logger options. Its format field
accepts auto, console, json, or custom; custom formatting requires a
formatter string and supports the standard %, {, and $ styles.
configure_logging(config=None, *, environment="development", service_name=None)
configures the process root logger. Environment defaults are DEBUG plus
console in development, WARNING plus console for tests, and INFO plus JSON
for staging and production. Explicit level and format settings override
those defaults independently. Logs go to stdout by default; the config can
select stderr. Existing loggers stay enabled. See the logging guide
for YAML, JSON fields, overrides, and security considerations.
Services
std.service.Service provides serialized asynchronous start() and stop()
transitions, a ServiceState, health checks, and async context-manager support.
Implement _start() and _stop() to acquire and release resources. Repeated
starts while running and stops while idle or stopped are safe. If startup
fails, the service enters failed; call stop() to release partially acquired
resources before retrying.
BackgroundService extends Service and runs its run() coroutine in a
managed task. The coroutine can wait on stop_event to exit gracefully.
Shutdown waits for shutdown_timeout, cancels a worker that does not exit,
then waits once more for cancellation cleanup. Unexpected exit sets
state == ServiceState.FAILED; failure exposes its cause and wait() raises
BackgroundServiceError chained from that cause. A failed service can still be
stopped to release its resources.
import asyncio
from std.service import BackgroundService
class QueueWorker(BackgroundService):
async def run(self) -> None:
while not self.stop_event.is_set():
await asyncio.sleep(0.1) # Replace with a queue receive operation.
async def main() -> None:
worker = QueueWorker("queue-worker")
await worker.start()
await worker.stop()
asyncio.run(main())
Optional integrations
FastAPI
Install standard-fastapi directly or with the standard[fastapi] extra. From a source checkout, install packages/standard-fastapi in editable mode.
In main.py, construct that settings model once and inject it into the FastAPI application:
from typing import Annotated
from fastapi import FastAPI
from app.core.settings import Settings
from std.fastapi import settings_dependency
def create_app() -> FastAPI:
# main.py is the composition root; construct and validate settings once.
settings = Settings()
app = FastAPI()
app.state.settings = settings
settings_dep = settings_dependency(Settings)
@app.get("/health")
async def health(settings: Annotated[Settings, settings_dep]) -> dict[str, str]:
return {"service": settings.service_name}
return app
Call create_app() once when loading the application. Keep all Settings()
construction in main.py; route modules and dependencies receive the
validated instance rather than constructing another one. The
sample consumer
exercises this startup flow end to end.
settings_dependency(settings_type) requires a BaseSettings subclass and
returns a FastAPI Depends object that retrieves the matching instance from
request.app.state.settings. Add that object directly as Annotated metadata;
do not wrap it in another Depends(...). Construct settings and the dependency
in main.py, store the settings instance before serving requests, and pass the
dependency into feature routers as needed. The helper never constructs or
reloads settings. An absent or wrong-typed value returns HTTP 500 with a
configuration message. Use app.dependency_overrides when tests need a
replacement.
APIConfig validates app metadata, deployment environment, server options, and
CORS policy. FastAPISetup(api_config, log_config=None, setup_handler=None,
*, services=()) creates the app, configures logging when requested, installs
CORS, and wires a LifecycleManager into the ASGI lifespan. The host,
port, workers, reload, and enabled fields are available to the server
entry point; the setup helper does not launch Uvicorn.
APIConfig.env accepts dev, stage, or prod. std.logging also has a
test profile. In tests, pass LoggingEnvironment.TEST to
configure_logging() to keep warning-level console output, and map test to
Environment.DEV when building APIConfig; the FastAPI environment enum does
not accept test.
LifecycleManager starts injected services in order and stops them in reverse
order. It calls cleanup for the service whose startup failed, continues
cleaning earlier services, and preserves the startup exception. Shutdown
attempts every cleanup hook and raises an ExceptionGroup if multiple hooks
fail. The ASGI server owns process signal handling.
AppTokenConfig stores a configurable header, unique application tokens, an
enabled flag, and exact or wildcard excluded paths. Token values are omitted
from the model representation. AppTokenAuth can be used as a FastAPI
dependency and returns the matching application name; missing or invalid
tokens raise HTTP 401. apply_token_auth_middleware protects requests before
route dispatch and puts the authenticated name in request.state.app_name.
Both auth helpers skip excluded paths. setup_token_auth returns the
dependency; setup_app_token_auth is its alias. add_api_key_security_scheme
adds the configured header to generated OpenAPI.
HealthCheck accepts sync or async functions. Synchronous checks run through
the event loop's executor, check failures produce sanitized details containing
the exception type, and any error, unhealthy, or down result makes the
aggregate response unhealthy. create_health_endpoint is the app-registration
factory. The endpoint retains HTTP 200 and reports state in its response body.
LoggingMiddleware logs method, path, response status, and elapsed time, adds
an X-Process-Time response header, and can omit the client address with
include_client=False. It never reads request or response bodies. APIService
is a small base for registering one route group on an injected FastAPI app.
AWS Secrets Manager
Install standard-aws directly or with the standard[aws] convenience extra:
from std.aws import load_secret
settings_values = load_secret("my-service/settings", region_name="eu-west-1")
load_secret(secret_id, *, region_name=None, client=None) accepts a non-empty secret ID and returns a dictionary parsed from a JSON object in SecretString or UTF-8 SecretBinary. It rejects duplicate object keys, non-standard NaN/Infinity values, and non-object payloads. ValueError indicates an empty ID; AwsSecretError indicates a retrieval or payload failure. Failure messages do not expose the secret ID or response details. Pass client to use an existing or test client; otherwise the integration creates a boto3 Secrets Manager client with the optional region.
AwsSecretsManagerSettingsSource(settings_cls, secret_id, *, region_name=None, client=None) loads the secret as a Pydantic Settings source when Pydantic reads it. AWS credentials, region policy, and refresh lifecycle remain with the application.
Agent CLI
std --version
std guide [--format text|json]
std skill show
std skill path
std skill install [destination] [--force]
std guide prints concise usage instructions. std guide --format json emits a JSON object with schema_version: 1, distribution/import/command names, version and Python requirement, shell-ready install commands, module availability, commands, skill location, documentation URLs, and the text guide. Consumers should check schema_version and ignore unrecognized fields.
std skill show prints the packaged idiomatic-Python skill. std skill path prints its filesystem path when the package was installed on the filesystem; for a non-filesystem package resource, it returns status 1 and directs the caller to show or install. std skill install copies it into the current repository at .agents/skills/standard-idiomatic-python/SKILL.md by default. That directory name matches the skill's name metadata as required by the Agent Skills specification. It returns status 2 and refuses to overwrite an existing path unless --force is supplied; filesystem failures return status 1.
The supported command-line interface is the installed std executable. std.cli.main is its implementation entry point, not a separate library API. The root std package exposes __version__; import public utilities from the documented modules above.