2A module that implements the Schema interface using pydantic. 
    9from pydantic 
import BaseModel, validate_call, ConfigDict, Field
 
   11import formatron.schemas.schema 
as schema
 
   12from formatron.schemas.schema 
import Schema, TypeWithMetadata
 
   17    A wrapper for pydantic FieldInfo. 
   19    __slots__ = (
"_field",)
 
   21    def __init__(self, field: pydantic.fields.FieldInfo):
 
   23        Initialize the field information. 
   29            for constraint 
in [
"min_length", 
"max_length", 
"pattern", 
"gt", 
"ge", 
"lt", 
"le", 
"substring_of"]:
 
   30                value = next((getattr(m, constraint) 
for m 
in self.
_field.metadata 
if hasattr(m, constraint)), 
None)
 
   32                    metadata[constraint] = value
 
 
   37    def annotation(self) -> typing.Type[typing.Any] | None:
 
   42        return self.
_field.is_required()
 
   53    A wrapper for pydantic BaseModel that implements the Schema interface. 
   55    __cached_fields__ = 
None 
   58    def fields(cls) -> typing.Dict[str, typing.Any]:
 
   59        if cls.__cached_fields__ 
is not None:
 
   60            return cls.__cached_fields__
 
 
   61        cls.__cached_fields__ = {k: 
FieldInfo(v) 
for k, v 
in cls.model_fields.items()}
 
   62        return cls.__cached_fields__
 
   65    def from_json(cls, _json: str) -> 
"ClassSchema":
 
 
   67        Create a ClassSchema from a JSON string. 
   69        return cls.model_validate_json(_json)
 
 
 
   72CallableT = typing.TypeVar(
'CallableT', bound=typing.Callable)
 
   75def callable_schema(func: CallableT, /, *, config: ConfigDict = 
None, validate_return: bool = 
False) -> CallableT:
 
   77    A decorator that wraps pydantic's validate_call. The decorated callable also implements the Schema interface. 
   80        func: The function to decorate. 
   81        config: The pydantic configuration of validate_call. 
   82        validate_return: Whether to validate the return value. 
   85        The decorated callable. 
   87    pydantic_wrapper = validate_call(config=config, validate_return=validate_return)(func)
 
   88    signature = inspect.signature(func, eval_str=
True)
 
 
   90    for k, p 
in signature.parameters.items():
 
   92        if p.default 
is not inspect.Signature.empty:
 
   94        actual_type = p.annotation
 
   96        if isinstance(p.default, pydantic.fields.FieldInfo):
 
   98        if typing.get_origin(p.annotation) 
is typing.Annotated:
 
   99            actual_type, *meta = typing.get_args(p.annotation)
 
  102                if isinstance(i, pydantic.fields.FieldInfo):
 
  106            if fieldinfo 
is not None:
 
  107                fields[k] = fieldinfo
 
 
  109                fields[k].default = default
 
  110                fields[k].annotation = actual_type
 
  111                fields[k].metadata.extend(metadata)
 
  113        if default 
is not None:
 
  114            fields[k] = Field(default)
 
  117        fields[k].annotation = actual_type
 
  118        fields[k].metadata.extend(metadata)
 
  122    def from_json(cls, json_str):
 
  123        json_data = json.loads(json_str)
 
  126        for k, p 
in signature.parameters.items():
 
  127            if p.kind == p.POSITIONAL_ONLY:
 
  128                positional_only.append(json_data[k])
 
  130                others[k] = json_data[k]
 
  131        return cls(*positional_only, **others)
 
  134        f
'{func.__qualname__}_PydanticSchema_{id(func)}',
 
  137            "_func": pydantic_wrapper,
 
  138            '__new__': 
lambda cls, *args, **kwargs: pydantic_wrapper(*args, **kwargs),
 
  139            '__call__': 
lambda *args, **kwargs: pydantic_wrapper(*args, **kwargs)  
 
  142    _class.from_json = classmethod(from_json)
 
  143    _class.fields = classmethod(
lambda cls: fields)