Spec Adapters¶
Adapters convert various input specifications into a normalized format for parsing.
Learn how to create custom adapters in the Advanced Usage guide.
The following built-in adapters are not meant to be used directly. They serve more as an example than anything else.
anyschema.adapters
¶
attrs_adapter(spec: AttrsClassType) -> FieldSpecIterable
¶
Adapter for attrs classes.
Extracts field information from an attrs class and converts it into an iterator
yielding field information as (field_name, field_type, constraints, metadata) tuples.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
AttrsClassType
|
An attrs class (not an instance). |
required |
Yields:
| Type | Description |
|---|---|
FieldSpecIterable
|
A tuple of |
Examples:
>>> from attrs import define, field
>>>
>>> @define
... class Student:
... name: str
... age: int = field(metadata={"description": "Student age"})
>>>
>>> list(attrs_adapter(Student))
[('name', <class 'str'>, (), {}), ('age', <class 'int'>, (), {'description': 'Student age'})]
Source code in anyschema/adapters.py
dataclass_adapter(spec: DataclassType) -> FieldSpecIterable
¶
Adapter for dataclasses.
Converts a dataclass into an iterator yielding field information as
(field_name, field_type, constraints, metadata) tuples.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
DataclassType
|
A dataclass with annotated fields. |
required |
Yields:
| Type | Description |
|---|---|
FieldSpecIterable
|
A tuple of |
FieldSpecIterable
|
Constraints are always empty, and metadata is extracted from dataclass field.metadata. |
Examples:
>>> from dataclasses import dataclass, field
>>>
>>> @dataclass
... class Student:
... name: str
... age: int = field(metadata={"description": "Student age"})
>>>
>>> list(dataclass_adapter(Student))
[('name', <class 'str'>, (), {}), ('age', <class 'int'>, (), {'description': 'Student age'})]
Source code in anyschema/adapters.py
into_ordered_dict_adapter(spec: IntoOrderedDict) -> FieldSpecIterable
¶
Adapter for Python mappings and sequences of field definitions.
Converts a mapping (e.g., dict) or sequence of 2-tuples into an iterator yielding field information as
(field_name, field_type, constraints, metadata) tuples.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
IntoOrderedDict
|
A mapping from field names to types, or a sequence of |
required |
Yields:
| Type | Description |
|---|---|
FieldSpecIterable
|
A tuple of |
FieldSpecIterable
|
Both constraints and metadata are always empty for this adapter. |
Examples:
>>> list(into_ordered_dict_adapter({"name": str, "age": int}))
[('name', <class 'str'>, (), {}), ('age', <class 'int'>, (), {})]
>>> list(into_ordered_dict_adapter([("age", int), ("name", str)]))
[('age', <class 'int'>, (), {}), ('name', <class 'str'>, (), {})]
Source code in anyschema/adapters.py
pydantic_adapter(spec: type[BaseModel]) -> FieldSpecIterable
¶
Adapter for Pydantic BaseModel classes.
Extracts field information from a Pydantic model class and converts it into an iterator
yielding field information as (field_name, field_type, constraints, metadata) tuples.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
type[BaseModel]
|
A Pydantic |
required |
Yields:
| Type | Description |
|---|---|
FieldSpecIterable
|
A tuple of |
Examples:
>>> from pydantic import BaseModel, Field
>>> from typing import Annotated
>>>
>>> class Student(BaseModel):
... name: str = Field(description="Student name")
... age: Annotated[int, Field(ge=0)]
>>>
>>> spec_fields = list(pydantic_adapter(Student))
>>> spec_fields[0]
('name', <class 'str'>, (), {'anyschema': {'description': 'Student name'}})
>>> spec_fields[1]
('age', ForwardRef('Annotated[int, Field(ge=0)]', is_class=True), (), {})
Source code in anyschema/adapters.py
sqlalchemy_adapter(spec: SQLAlchemyTableType) -> FieldSpecIterable
¶
Adapter for SQLAlchemy tables.
Extracts field information from a SQLAlchemy Table (Core) or DeclarativeBase class (ORM)
and converts it into an iterator yielding field information as (field_name, field_type, metadata) tuples.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
SQLAlchemyTableType
|
A SQLAlchemy Table instance or DeclarativeBase subclass. |
required |
Yields:
| Type | Description |
|---|---|
FieldSpecIterable
|
A tuple of |
Examples:
>>> from sqlalchemy import Table, Column, Integer, String, MetaData
>>>
>>> metadata = MetaData()
>>> user_table = Table(
... "user",
... metadata,
... Column("id", Integer, primary_key=True),
... Column("name", String(50)),
... )
>>>
>>> spec_fields = list(sqlalchemy_adapter(user_table))
>>> spec_fields[0]
('id', Integer(), (), {'anyschema': {'nullable': False}})
>>> spec_fields[1]
('name', String(length=50), (), {'anyschema': {'nullable': True}})
>>> from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
>>>
>>> class Base(DeclarativeBase):
... pass
>>>
>>> class User(Base):
... __tablename__ = "user"
... id: Mapped[int] = mapped_column(primary_key=True)
... name: Mapped[str]
>>>
>>> spec_fields = list(sqlalchemy_adapter(User))
>>> spec_fields[0]
('id', Integer(), (), {'anyschema': {'nullable': False}})
>>> spec_fields[1]
('name', String(length=50), (), {'anyschema': {'nullable': True}})
Source code in anyschema/adapters.py
typed_dict_adapter(spec: TypedDictType) -> FieldSpecIterable
¶
Adapter for TypedDict classes.
Converts a TypedDict into an iterator yielding field information as
(field_name, field_type, constraints, metadata) tuples.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
TypedDictType
|
A TypedDict class (not an instance). |
required |
Yields:
| Type | Description |
|---|---|
FieldSpecIterable
|
A tuple of |
FieldSpecIterable
|
Both constraints and metadata are always empty for this adapter. |
Examples:
>>> from typing_extensions import TypedDict
>>>
>>> class Student(TypedDict):
... name: str
... age: int
>>>
>>> list(typed_dict_adapter(Student))
[('name', <class 'str'>, (), {}), ('age', <class 'int'>, (), {})]
Source code in anyschema/adapters.py
Adapters specification¶
Adapters must follow this signature:
from typing import Iterator, TypeAlias, Callable, Any, Generator
from anyschema.typing import FieldConstraints, FieldMetadata, FieldName, FieldType
FieldSpec: TypeAlias = tuple[FieldName, FieldType, FieldConstraints, FieldMetadata]
def my_custom_adapter(spec: Any) -> Iterator[FieldSpec]:
"""
Yields tuples of (field_name, field_type, constraints, metadata).
- name (str): The name of the field
- type (type): The type annotation of the field
- constraints (tuple): Type constraints (e.g., Gt(0), Le(100) from annotated-types)
- metadata (dict): Custom metadata dictionary for additional information
"""
...
They don't need to be functions; any callable is acceptable.