Skip to content

Commit ff0b8cb

Browse files
authored
perf: defer optional typing imports (#634)
## Summary - resolve heavy optional typing exports lazily on first access - preserve precise analyzer-visible vendor types when their extras are installed - preserve stable runtime shims and Protocol fallbacks when optional dependencies are absent - defer optional imports in serializers, storage, schema, and type-guard consumers - keep `DEFAULT_TYPE_ENCODERS` fully dict-compatible with thread-safe, failure-retryable lazy registration ## Compatibility Users do not need optional libraries installed for SQLSpec imports or runtime annotations to work. Missing dependencies resolve to stable cached shims; installed dependencies retain their precise static vendor types. In a no-extras consumer type-checking environment, optional vendor aliases resolve as `Any` because the vendor type definitions are unavailable; the explicit SQLSpec Stub and Protocol types remain available where callers need a dependency-independent contract. Public exports, `dir()`, identity, pickle/repr behavior, cattrs fallback names, dict mutation/union behavior, and runtime type-adapter behavior are covered. ## Performance Bare `import sqlspec` median time decreased from 681 ms to 202.467 ms (70.27%). The import regression guard confirms pandas, polars, PyArrow, Litestar, Pydantic, OpenTelemetry, and Prometheus are not imported eagerly. ## Validation - lazy-export, fallback-shim, optional-boundary, serializer, storage, concurrency, retry, and dict-contract tests - Ruff, mypy, pyright, docs, compiled acceptance tests, and MyPyC wheel build - full GitHub unit/integration matrix on Python 3.10-3.14 All required GitHub checks pass on the final commit.
1 parent 7855fd0 commit ff0b8cb

18 files changed

Lines changed: 1091 additions & 284 deletions

docs/reference/typing.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,29 @@ SQLSpec.
77

88
.. currentmodule:: sqlspec.typing
99

10+
Optional dependency exports
11+
===========================
12+
13+
The :mod:`sqlspec.typing` and :mod:`sqlspec._typing` modules resolve heavy
14+
optional-dependency symbols lazily. Importing :mod:`sqlspec` does not import
15+
Pydantic, Litestar, PyArrow, pandas, Polars, OpenTelemetry, or Prometheus.
16+
Accessing one of their exported symbols imports its dependency on first use and
17+
caches the resolved object::
18+
19+
import sqlspec.typing as sqlspec_typing
20+
21+
arrow_table_type = sqlspec_typing.ArrowTable # Imports PyArrow here.
22+
23+
When an optional dependency is not installed, the same access returns a stable
24+
typed shim. Repeated access returns the identical real object or shim, preserving
25+
annotation and runtime identity behavior. Features that require the dependency
26+
still raise the normal missing-dependency error when enabled.
27+
28+
``msgspec`` remains eager because its core types and conversion functions are
29+
used throughout result mapping and serialization. ``orjson`` also remains on
30+
the existing eager path; both have a small measured import cost compared with
31+
the deferred integrations.
32+
1033
Metadata Types
1134
==============
1235

0 commit comments

Comments
 (0)