Skip to content

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

to_schema(data, *, schema_type=None)

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

to_json

to_json(data, *, as_bytes=False)

Encode Python data into JSON.

from_json

from_json(data, *, decode_bytes=True)

Decode JSON input into Python data.

uuid4

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

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

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

camelize(string)

Convert a string to camel case.

Parameters:

Name Type Description Default
string str

The string to convert.

required

Returns:

Type Description
str

The converted string.

snake_case

snake_case(string)

Convert a string to snake_case.

Parameters:

Name Type Description Default
string str

The string to convert.

required

Returns:

Type Description
str

The snake_case version of the string.

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 (ON CONFLICT) and MySQL (ON DUPLICATE KEY UPDATE, which matches any unique key of the table).

None
batch_size int

Maximum number of rows per execute_many call.

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 True and table column metadata is available, strip fixture columns not present in the target table before inserting.

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 SET clause of upserts so existing values are preserved on conflict.

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 batch_size is below 1, conflict_keys is given for an unsupported dialect, a table or column name is not a plain SQL identifier, a table has more than one fixture file, a row in a fixture file is empty, or a fixture file only holds generated columns.

TypeError

If a fixture file does not hold a list of row objects, or conflict_keys / exclude_update_columns has an invalid type.

FileNotFoundError

If a requested table has no fixture file.

export_table_fixtures_async

export_table_fixtures_async(
    driver, fixtures_path, tables, *, compress=True, jsonl=False
)

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

get_env(key, default, type_hint=_UNSET)

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 list[int].

_UNSET

Returns:

Type Description
Callable[[], Any]

Callable that returns the parsed value.

Type Guards & Module Loading

is_msgspec_struct

is_msgspec_struct(obj)

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

is_pydantic_model(obj)

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

is_schema(obj)

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_string(dotted_path)

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

import_optional(module_name)

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 None when it is not installed.

Sync/Async Bridging, Correlation & Deprecation

run_

run_(async_function)

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_

async_(function, *, limiter=None, executor=None)

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

deprecated(
    version,
    *,
    removal_in=None,
    alternative=None,
    info=None,
    pending=False,
    kind=None,
)

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:warnings.PendingDeprecationWarning instead of :class:warnings.DeprecationWarning

False
kind Literal['function', 'method', 'classmethod', 'property'] | None

Type of the deprecated callable. If None, will use inspect to figure out if it's a function or method

None

Returns:

Type Description
Callable[[Callable[P, T]], Callable[P, T]]

A decorator wrapping the function call with a warning