I'd like to extend existing Pydantic types such as FilePath by f.i. adding a file type pattern for
- validation
- serialization to JSON schema.
Current approach
I'd f.i. like to define my custom type FilePathPattern extending FilePath by a pattern which is defined when using the custom type:
from typing import Annotated
from pydantic import Field, FilePath
def get_pattern(
field_data: dict[str, str]
) -> dict[str, str]:
return {"pattern", field_data["pattern"]}
FilePathPattern = Annotated[
FilePath,
Field(json_schema_extra=get_pattern),
]
class MySchema(BaseModel):
"""My schema."""
path_with_suffix: FilePathPattern = Field(
title="Path to CSV or TXT",
description="something",
default="my_data.csv",
pattern=r".*\.(csv|txt)$",
)
another_path: FilePathPattern = Field(
pattern="some_pattern",
)
Expected outcome
Which should
Use the validators provided by the base type
FilePathto check for existenceextend the validation by matching the regex pattern with
str(path_with_suffix)serialize the model to a JSON schema with
MySchema.model_json_schema()containing the additional keypattern(which is also included in the JSON schema standard):{ ... "properties": { "path_with_suffix": { "default": "my_data.csv", "description": "something", "format": "file-path", "pattern": ".*/struct.dat", "title": "Path to CSV or TXT" }, "another_path": {...} }, "title": "...", "type": "object" }
Problem
Unluckily this doesn't work, since
FilePathdoesn't seem to contain apattern, even if defined in theFieldof the derived custom typeFilePathPattern- Defining the pattern explicitly in
json_schema_extra={"pattern": r".*/struct\.dat"}will work, but this drastically reduces reusability of the custom type - Using
WithJsonSchemain theAnnotatedwill result in dropping all of the other schema keywords such asformat
How can I define a custom type extending existing types without overwriting any of the features provided by the existing type?