Skip to main content

Convert Python typing annotations, Pydantic v2 models, and dataclasses into a compact, human-readable schema

Project description

SimpleSpec

License Python 3.11+ PyPI version

Convert Python typing annotations, Pydantic v2 models, and dataclasses into a compact, human‑readable schema specification.

Features

  • 🔍 Clear, readable type strings - Modern Python syntax (e.g., list[T], dict[K, V], Union via |)
  • 📝 Preserve constraints and descriptions - Field descriptions and validation constraints
  • 🏗️ First-class Pydantic & dataclass support - Referenced types with proper handling
  • 🔄 Deterministic naming - Collision handling for types with same names
  • 🛡️ Depth control - Configurable limits for cyclic/recursive structures
  • Fast and lightweight - Minimal dependencies

Quick Start

Installation

# Using uv (recommended)
uv add simplespec

# Using pip
pip install simplespec

Basic Usage

from pydantic import BaseModel, Field
from simplespec import generate_simple_spec

class Address(BaseModel):
    street: str
    city: str

class User(BaseModel):
    name: str
    age: int = Field(ge=18, description="User's age in years")
    address: Address

spec = generate_simple_spec(User)
print(spec)

Output:

Referenced specs:
Address
    street: str
    city: str
Spec:
User
    name: str
    age: int, User's age in years [ge=18]
    address: Address

API Reference

generate_simple_spec

from simplespec import generate_simple_spec, DepthLimitExceededError, SimpleSpecError

spec = generate_simple_spec(root_type_obj, max_depth: int | None = None)

Parameters:

  • root_type_obj: Any supported type (Pydantic BaseModel class, dataclass type, or typing annotations like list[str], dict[str, int], Union, etc.)
  • max_depth: Optional recursion limit for referenced types (default: 4)

Returns:

  • Spec: A dataclass containing:
    • self: Ref — The root type definition
    • refs: list[Ref] — Referenced Pydantic models/dataclasses, sorted by depth then name

Raises:

  • DepthLimitExceededError — When walking exceeds max_depth
  • SimpleSpecError — For other analysis/build failures

Output Data Structures

@dataclass
class Prop:
    type: str
    description: str | None = None

@dataclass  
class Ref:
    type: str
    description: str | None = None
    properties: dict[str, Prop] = field(default_factory=dict)

@dataclass
class Spec:
    self: Ref
    refs: list[Ref] = field(default_factory=list)

Type Resolution Examples

SimpleSpec normalizes type names to modern Python syntax:

Input Type Output
dict[str, int] "dict[str, int]"
list[User | None] "list[User | None]"
Optional[str] "str | None"
Union[str, int, None] "int | str | None"
tuple[str, int] "tuple[str, int]"
set[int] "set[int]"
Literal['a', 'b'] "Literal['a', 'b']"

Advanced Examples

Recursive Types

class TreeNode(BaseModel):
    value: str
    children: list["TreeNode"] = []
    parent: Optional["TreeNode"] = None

TreeNode.model_rebuild()  # Required for forward references

spec = generate_simple_spec(TreeNode)
print(spec.self.properties["children"].type)  # "list[TreeNode]"

Dataclass Support

from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float = 0.0

class Shape(BaseModel):
    center: Point
    points: list[Point]

spec = generate_simple_spec(Shape)
# Point appears in spec.refs as a referenced type

Complex Constraints

class Product(BaseModel):
    name: str = Field(min_length=1, max_length=100, description="Product name")
    price: float = Field(gt=0, le=10000, description="Price in USD")
    quantity: int = Field(ge=0, multiple_of=1)

spec = generate_simple_spec(Product)
# Constraints appear as: "str, Product name [min_length=1] [max_length=100]"

Development

Setup

# Clone the repository
git clone https://github.com/denizkenan/simplespec.git
cd simplespec

# Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh

# Install dependencies
uv sync --all-extras

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

Running Tests

# Run all tests
uv run pytest

# Run with coverage
uv run pytest --cov=simplespec --cov-report=html

# Run specific test
uv run pytest tests/test_simplespec.py::test_simple_for_primitive_type -v

Code Quality

# Format code
uv run ruff format

# Lint code  
uv run ruff check

# Type check
uv run mypy simplespec

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass (uv run pytest)
  6. Run code quality checks (uv run ruff check && uv run mypy simplespec)
  7. Commit your changes (git commit -m 'Add amazing feature')
  8. Push to the branch (git push origin feature/amazing-feature)
  9. Open a Pull Request

Compatibility

  • Python: 3.11+
  • Pydantic: v2.0+
  • Dependencies: pydantic>=2.0.0, annotated-types>=0.6.0

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Acknowledgments

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

simplespec-0.1.1.tar.gz (78.1 kB view details)

Uploaded Source

Built Distribution

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

simplespec-0.1.1-py3-none-any.whl (19.8 kB view details)

Uploaded Python 3

File details

Details for the file simplespec-0.1.1.tar.gz.

File metadata

  • Download URL: simplespec-0.1.1.tar.gz
  • Upload date:
  • Size: 78.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.13

File hashes

Hashes for simplespec-0.1.1.tar.gz
Algorithm Hash digest
SHA256 748d21000743b6215e745bea8b2e6caf9e4b0138db3eb9c56fab448cfb944a86
MD5 13dae1dce8f4ec81282b4ae879b8e62f
BLAKE2b-256 e1fbfa313069e58160ecca134054fe7971bcfcef1aa13ae916f8d068d646412c

See more details on using hashes here.

File details

Details for the file simplespec-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: simplespec-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 19.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.13

File hashes

Hashes for simplespec-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c6545622a94c87f74f997fc4a9d1a4e7df7e6b57e27a65686bec4d251783a93c
MD5 0ef3efd06b6ec0316e5148ca84230c68
BLAKE2b-256 d6c990d3a5f09aa76a3b462e162ef1f93f18d737bbe641037f6e40ccaad88cfe

See more details on using hashes here.

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