Utilities¶
from sqlspec.utils import (
correlation,
deprecation,
env,
fixtures,
module_loader,
schema,
serializers,
sync_tools,
text,
type_guards,
uuids,
)
Reusable helpers for runtime type narrowing, JSON serialization, schema model conversion, UUID/NanoID generation, table fixture loading/exporting, correlation tracking, and sync/async bridging.
Schema, Serialization & Identifiers¶
to_schema
¶
Convert data to a specified schema type.
Supports transformation to various schema types including
- TypedDict
- dataclasses
- msgspec Structs
- Pydantic models
- attrs classes
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Any
|
Input data to convert (dict, list of dicts, or other) |
required |
schema_type
|
Any
|
Target schema type for conversion. If None, returns data unchanged. |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
Converted data in the specified schema type, or original data if schema_type is None |
Raises:
| Type | Description |
|---|---|
SQLSpecError
|
If schema_type is not a supported type |
uuid4
¶
Generate a random UUID (version 4).
Uses uuid-utils for performance when available, falls back to standard library uuid.uuid4() silently (equivalent output).
Returns:
| Type | Description |
|---|---|
UUID
|
A randomly generated UUID. |
uuid7
¶
Generate a time-ordered UUID (version 7).
Uses uuid-utils when available, falls back to Python 3.14+ native uuid.uuid7() or uuid4() with a warning.
UUIDv7 is the recommended time-ordered UUID format per RFC 9562, providing millisecond precision timestamps. It is designed for modern distributed systems and database primary keys.
Returns:
| Type | Description |
|---|---|
UUID
|
A time-ordered UUID, or a random UUID if time-ordered generation unavailable. |
nanoid
¶
Generate a Nano ID.
Uses fastnanoid for performance when available. When fastnanoid is not installed, falls back to uuid4().hex with a warning.
Nano IDs are URL-safe, compact 21-character identifiers suitable
for use as primary keys or short identifiers. The default alphabet
uses A-Za-z0-9_- characters.
Returns:
| Type | Description |
|---|---|
str
|
A 21-character Nano ID string, or 32-character UUID hex if |
str
|
fastnanoid unavailable. |
camelize
¶
snake_case
¶
Table Fixtures & Environment Helpers¶
load_table_fixtures_async
¶
load_table_fixtures_async(
driver,
fixtures_path,
*,
tables=None,
table_order=None,
conflict_keys=None,
batch_size=500,
resync_sequences=False,
ignore_unknown_columns=False,
exclude_update_columns=None,
)
Load per-table fixture files into database tables asynchronously.
Each table reads from one file named after it: <table>.json holding a JSON
array of row objects, or <table>.jsonl holding one row object per line, either
optionally gzipped (.gz). Sparse row objects are normalized across the ordered
union of column keys in the file, defaulting omitted keys to None. Table and
column names are quoted, so they must match the database spelling exactly. Rows
are inserted in batches with execute_many; each file is read into memory in a
worker thread. Transaction control stays with the caller.
On PostgreSQL-family, MySQL, DuckDB, and SQLite drivers the target table's columns
are read from the driver's data dictionary first, and JSON values of these column
types are converted: ISO 8601 strings in timestamp, datetime, date, and (except on
MySQL) time columns to datetimes, dates, and times; ISO 8601 durations without year
or month parts and numbers of seconds in interval columns to timedelta, and
DuckDB [months, days, nanoseconds] interval lists to interval text; strings and
numbers in numeric and decimal columns to Decimal; strings in uuid columns to
UUID; base64 strings in bytea, blob, binary, and varbinary columns to bytes; and
PostgreSQL, MySQL, DuckDB, and SQLite json and jsonb values to JSON text. SQLite
only converts binary and JSON columns. All other values, including array elements
and durations with year or month parts such as P1M, are passed to the driver as decoded from JSON. Values
of generated columns are ignored. On PostgreSQL, GENERATED ALWAYS identity
columns receive the loaded values through OVERRIDING SYSTEM VALUE and are never
updated by upserts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
driver
|
AsyncDriverAdapterBase
|
Async driver that runs the inserts. |
required |
fixtures_path
|
str | Path
|
Directory containing the table fixture files. |
required |
tables
|
Sequence[str] | None
|
Tables to load. Defaults to every table fixture file in the directory; files whose names are not table identifiers are skipped with a debug log, and a dot in a file name marks a schema-qualified table. |
None
|
table_order
|
Sequence[str] | None
|
Tables to load first, in this order. Remaining tables load afterwards in alphabetical order; names not being loaded are ignored. |
None
|
conflict_keys
|
Mapping[str, Sequence[str] | str] | None
|
Mapping of table name to a column name or sequence of key column
names of a unique constraint; tables not being loaded are ignored. Rows for
matched tables are upserted, updating every non-key, non-excluded column
when a row with the same key already exists. Supported on PostgreSQL-family,
SQLite, and DuckDB drivers ( |
None
|
batch_size
|
int
|
Maximum number of rows per |
500
|
resync_sequences
|
bool
|
On PostgreSQL-family drivers, set the sequence behind each serial or identity column of a loaded table to the column's maximum value, or back to the sequence's minimum value for an empty table, so the next generated value follows the loaded rows. On other dialects the option is skipped with a debug log. |
False
|
ignore_unknown_columns
|
bool
|
When |
False
|
exclude_update_columns
|
Sequence[str] | Mapping[str, Sequence[str] | str] | None
|
Column names (or per-table mapping of column names) to
omit from the |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, int]
|
Mapping of table name to the number of rows loaded, in load order. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
TypeError
|
If a fixture file does not hold a list of row objects, or
|
FileNotFoundError
|
If a requested table has no fixture file. |
export_table_fixtures_async
¶
Export database tables to per-table fixture files asynchronously.
Writes every row of each table to <table>.json (a JSON array) or, with
jsonl, <table>.jsonl (one JSON object per line), gzipped with a .gz
suffix when compress is set. Generated columns are left out. Rows are ordered by
the primary key, or by every orderable column when the table has none, and each
table is read into memory. Dates,
times, and datetimes are written as ISO 8601 strings, Decimal and UUID
values as strings, and bytes as base64 strings, which
:func:load_table_fixtures_async converts back for typed columns.
Each file is written to a temporary file in the directory, created with the process umask, and then moved into place; after that, other table fixture files for the same table in the directory are removed, so the next load reads the exported file. The directory is created when missing, and file writes run in a worker thread. Table names are quoted and must match the database spelling exactly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
driver
|
AsyncDriverAdapterBase
|
Async driver that reads the tables. |
required |
fixtures_path
|
str | Path
|
Directory to write the fixture files to. |
required |
tables
|
Sequence[str]
|
Tables to export. |
required |
compress
|
bool
|
Whether to gzip the written files. |
True
|
jsonl
|
bool
|
Whether to write one JSON object per line instead of a JSON array. |
False
|
Returns:
| Type | Description |
|---|---|
dict[str, int]
|
Mapping of table name to the number of rows written. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a table name is not a plain SQL identifier. |
get_env
¶
Return a callable that parses an environment variable on demand.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Environment variable name. |
required |
default
|
ParseType
|
Value returned when the variable is unset. |
required |
type_hint
|
object
|
Optional parse target, including generic aliases such as |
_UNSET
|
Returns:
| Type | Description |
|---|---|
Callable[[], Any]
|
Callable that returns the parsed value. |
Type Guards & Module Loading¶
is_msgspec_struct
¶
Check if a value is a msgspec struct class or instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
Any
|
Value to check. |
required |
Returns:
| Type | Description |
|---|---|
TypeGuard[StructStub]
|
bool |
is_pydantic_model
¶
Check if a value is a pydantic model class or instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
Any
|
Value to check. |
required |
Returns:
| Type | Description |
|---|---|
TypeGuard[BaseModelStub]
|
bool |
is_schema
¶
Check if a value is a msgspec Struct, Pydantic model, attrs instance, or schema class.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
Any
|
Value to check. |
required |
Returns:
| Type | Description |
|---|---|
TypeGuard[SupportedSchemaModel]
|
bool |
import_string
¶
Import a module or attribute from a dotted path string.
Failures are reported as ImportError, except for SQLSpec errors raised by
the imported module itself, which propagate unchanged so their own message
survives. MissingDependencyError is reported as ImportError because it
describes an import failure.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dotted_path
|
str
|
The path of the module to import. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
The imported object. |
import_optional
¶
Return the imported module if available, otherwise None.
Silent-fallback twin of the :func:ensure_pyarrow-style helpers: use it
when the caller has a working fallback (e.g. stdlib uuid) and must not
raise on a missing optional dependency. The resolved module (or None)
is cached per interpreter session; call :func:reset_dependency_cache to
invalidate it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module_name
|
str
|
Dotted module path to import. |
required |
Returns:
| Type | Description |
|---|---|
ModuleType | None
|
The imported module, or |
Sync/Async Bridging, Correlation & Deprecation¶
run_
¶
Convert an async function to a blocking function using asyncio.run().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
async_function
|
Callable[ParamSpecT, Coroutine[Any, Any, ReturnT]]
|
The async function to convert. |
required |
Returns:
| Type | Description |
|---|---|
Callable[ParamSpecT, ReturnT]
|
A blocking function that runs the async function. |
async_
¶
Convert a blocking function to an async one using a thread executor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
function
|
Callable[ParamSpecT, ReturnT]
|
The blocking function to convert. |
required |
limiter
|
CapacityLimiter | None
|
Limit the total number of threads. |
None
|
executor
|
ThreadPoolExecutor | None
|
Optional thread executor to use instead of SQLSpec's managed default thread executor. |
None
|
Returns:
| Type | Description |
|---|---|
Callable[ParamSpecT, Awaitable[ReturnT]]
|
An async function that runs the original function in a thread. |
CorrelationContext
¶
Context manager for correlation ID tracking.
This class provides a context-aware way to track correlation IDs across async and sync operations.
deprecated
¶
Create a decorator wrapping a function, method or property with a deprecation warning.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
version
|
str
|
SQLSpec version where the deprecation will occur |
required |
removal_in
|
str | None
|
SQLSpec version where the deprecated function will be removed |
None
|
alternative
|
str | None
|
Name of a function that should be used instead |
None
|
info
|
str | None
|
Additional information |
None
|
pending
|
bool
|
Use :class: |
False
|
kind
|
Literal['function', 'method', 'classmethod', 'property'] | None
|
Type of the deprecated callable. If |
None
|
Returns:
| Type | Description |
|---|---|
Callable[[Callable[P, T]], Callable[P, T]]
|
A decorator wrapping the function call with a warning |