Skip to main content

SQL Server stored procedure introspection and Pydantic model generator

Project description

Singularity

SQL Server → Pydantic v2. Automatically.

CI Python Ruff

Singularity bridges the gap between SQL Server and Python. Connect to your database, point at a stored procedure, and get a Pydantic v2 model — as a runtime class or a .py file you can commit.

singularity --config config.toml
from singularity import SQLServerIntrospector, generate_model

introspector = SQLServerIntrospector("DRIVER={ODBC Driver 17};SERVER=...;DATABASE=...")
meta = introspector.introspect("usp_GetOrders")
model = generate_model(meta, mode="dynamic")
# <class 'pydantic.main.UspGetOrders'>

Why Singularity?

The problem: You have dozens of complex stored procedures in SQL Server. Calling them from Python means manually writing Pydantic models for every parameter and result set. One typo, and you get a runtime error.

The solution: Singularity reads SQL Server's system catalog (sys.parameters, sp_describe_first_result_set) and generates the models for you. Zero manual mapping.

Approach Lines of code Maintainable Type-safe
Manual Pydantic models 100s–1000s ⚠️ (manual)
Raw dicts / tuples Fewer
Singularity Zero

Features

  • 🔌 Auto-connect — pyodbc connection with @@VERSION detection
  • 🧠 Version-aware — Modern (2016+), Legacy (2008–2014), and Azure SQL strategies
  • 📦 Two output modes:
    • "dynamic"create_model() at runtime, usable immediately
    • "source".py files you can commit and review
  • 🏷️ Full type mappingINTint, VARCHARstr, DATETIMEdatetime, BITbool, etc.
  • 🎨 Configurable naming — snake_case, camelCase, PascalCase for field names
  • 🗂️ File naming templates{schema}_{sp_name}.py, {database}_{sp_name}.py, etc.
  • 🛡️ Nullable awarenessOptional[T] for nullable columns
  • UV-first — fast dependency management

Installation

uv add singularity
# or
pip install singularity

Prerequisite: ODBC Driver for SQL Server (17 or 18).

Quick Start

1. Create a config file

# config.toml
[connection]
server = "localhost"
database = "AdventureWorks"
driver = "ODBC Driver 18 for SQL Server"
trusted_connection = true

[sp_selection]
pattern = "usp_%"

[output]
directory = "generated_models"
mode = "source"
file_naming = "{schema}_{sp_name}.py"
naming_convention = "snake_case"

2. Generate models

singularity --config config.toml
Connected. Detected version: modern
  Introspecting usp_GetOrders... → generated_models/dbo_usp_GetOrders.py
  Introspecting usp_GetCustomers... → generated_models/dbo_usp_GetCustomers.py

Done. 2 succeeded, 0 failed.

3. Use the generated models

from generated_models.dbo_usp_GetOrders import UspGetOrders

order = UspGetOrders(id=1, customer_name="Acme Corp", total=99.99)

Library Usage

from singularity import SQLServerIntrospector, generate_model

# Connect and introspect
introspector = SQLServerIntrospector(conn_str)
introspector.connect()
version = introspector.detect_version()  # ServerVersion.MODERN
metadata = introspector.introspect("usp_GetOrders")

# Runtime model
DynamicModel = generate_model(metadata, mode="dynamic")
instance = DynamicModel(id=1, customer_name="Acme")

# Source code string
source_code = generate_model(metadata, mode="source")
with open("models/usp_GetOrders.py", "w") as f:
    f.write(source_code)

Configuration Reference

[connection]

Field Required Default Description
server Server hostname or IP
database Database name
driver ODBC Driver 18 for SQL Server ODBC driver name
trusted_connection true Use Windows auth
username SQL auth username
password SQL auth password

[sp_selection]

Field Required Description
procedures Explicit list of SP names
pattern Wildcard pattern (e.g. usp_%)

At least one of procedures or pattern must be specified.

[output]

Field Required Default Description
directory . Output directory
mode source source or dynamic
file_naming {sp_name}.py Template with {schema}, {database}, {sp_name}
naming_convention snake_case snake_case, camelCase, or PascalCase

Supported SQL Server Versions

Version Strategy Parameter introspection Result set metadata
2016+ Modern sys.parameters sp_describe_first_result_set
2008–2014 Legacy sys.parameters sp_describe_first_result_set + sys.columns fallback
Azure SQL Azure sys.parameters sys.dm_exec_describe_first_result_set

Type Mapping

SQL Server Python Pydantic
INT, BIGINT, SMALLINT, TINYINT int int
VARCHAR, NVARCHAR, CHAR, NCHAR, TEXT str str
DATETIME, DATETIME2, DATE, SMALLDATETIME datetime datetime
BIT bool bool
DECIMAL, NUMERIC, FLOAT, REAL, MONEY float float
UNIQUEIDENTIFIER str str
Unknown types str + warning str

Development

# Clone and install
git clone https://github.com/Samuel-Urrego/Singularity
cd singularity
uv sync

# Run tests
uv run pytest

# Lint and type-check
uv run ruff check .
uv run mypy singularity/

# Install pre-commit hooks
uv run pre-commit install

License

MIT — see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

singularitysql-0.1.0.tar.gz (31.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

singularitysql-0.1.0-py3-none-any.whl (28.9 kB view details)

Uploaded Python 3

File details

Details for the file singularitysql-0.1.0.tar.gz.

File metadata

  • Download URL: singularitysql-0.1.0.tar.gz
  • Upload date:
  • Size: 31.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for singularitysql-0.1.0.tar.gz
Algorithm Hash digest
SHA256 fd39ca3d451834383dd0ab830e9dc70b126d80bcdaf4bb2f522da3f825307717
MD5 b33af32114bfacf052381c7945498529
BLAKE2b-256 0d67084d4fe0c6ae397e494e4882ad0652c652414fe5f95d9d9f1c6ab5f25952

See more details on using hashes here.

Provenance

The following attestation bundles were made for singularitysql-0.1.0.tar.gz:

Publisher: publish.yml on Samuel-Urrego/Singularity

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file singularitysql-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: singularitysql-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 28.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for singularitysql-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f73b083ed82ca4fc5399434a4e4adc57ca5726cee4ba0b4623b5dce5faaf4c38
MD5 15ea0a9be43cdab90a96489693638fa5
BLAKE2b-256 c72828d4bec1c65ce8748044012cff8c27ef379e4b3e2ba6e366799ccc219595

See more details on using hashes here.

Provenance

The following attestation bundles were made for singularitysql-0.1.0-py3-none-any.whl:

Publisher: publish.yml on Samuel-Urrego/Singularity

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page