Convert Python typing annotations, Pydantic v2 models, and dataclasses into a compact, humanβreadable schema specification.
- π 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
# Using uv (recommended)
uv add simplespec
# Using pip
pip install simplespecfrom 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
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
@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)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']" |
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]"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 typeclass 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]"# 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# 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# Format code
uv run ruff format
# Lint code
uv run ruff check
# Type check
uv run mypy simplespec- 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
See RELEASE.md for detailed release procedures. Quick summary:
# Update version in simplespec/__init__.py and pyproject.toml
# Update CHANGELOG.md
# Build and publish
./publish.sh# Update version and changelog, commit changes
git add -A && git commit -m "Bump version to x.y.z"
git push origin main
# Create and push tag to trigger GitHub Actions
git tag vx.y.z
git push origin vx.y.z- Python: 3.11+
- Pydantic: v2.0+
- Dependencies:
pydantic>=2.0.0,annotated-types>=0.6.0
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
- Built with Pydantic for model handling
- Uses annotated-types for constraint extraction
- Development tooling by uv and Ruff