Convert Python typing annotations, Pydantic v2 models, and dataclasses into a compact, human-readable schema
Project description
SimpleSpec
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],Unionvia|) - 📝 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 likelist[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 definitionrefs:list[Ref]— Referenced Pydantic models/dataclasses, sorted by depth then name
Raises:
DepthLimitExceededError— When walking exceeds max_depthSimpleSpecError— 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
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests for new functionality
- Ensure all tests pass (
uv run pytest) - Run code quality checks (
uv run ruff check && uv run mypy simplespec) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - 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
- Built with Pydantic for model handling
- Uses annotated-types for constraint extraction
- Development tooling by uv and Ruff
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
748d21000743b6215e745bea8b2e6caf9e4b0138db3eb9c56fab448cfb944a86
|
|
| MD5 |
13dae1dce8f4ec81282b4ae879b8e62f
|
|
| BLAKE2b-256 |
e1fbfa313069e58160ecca134054fe7971bcfcef1aa13ae916f8d068d646412c
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c6545622a94c87f74f997fc4a9d1a4e7df7e6b57e27a65686bec4d251783a93c
|
|
| MD5 |
0ef3efd06b6ec0316e5148ca84230c68
|
|
| BLAKE2b-256 |
d6c990d3a5f09aa76a3b462e162ef1f93f18d737bbe641037f6e40ccaad88cfe
|