Compile a Python model
To generate a canonical JSON Schema from a Pydantic model in softschema, use the compile_model function. This function transforms the model's structure into a YAML-formatted schema file, ensuring it includes a unique contract_id and a calculated schema_sha256 for integrity tracking.
The following example demonstrates how to define a model and compile it to a specific file path. The returned CompileResult provides access to the generated YAML content and the schema hash.
from pathlib import Path
from pydantic import BaseModel
from softschema.compile import compile_model
class UserProfile(BaseModel):
username: str
email: str
age: int | None = None
# Define the output path and compile the model
schema_file = Path("user_profile.schema.yaml")
result = compile_model(
UserProfile,
schema_file,
contract_id="example:UserProfile/v1"
)
# Inspect the compilation result
print(f"Schema written to: {result.out_path}")
print(f"SHA256 Hash: {result.schema_sha256}")
print(f"YAML Content Preview:\n{result.schema_yaml[:100]}")
Detecting Schema Drift
In CI/CD environments or linting workflows, you can use check_only=True to verify if the Pydantic model in your source code matches the schema file already committed to disk. When this flag is enabled, softschema does not write to the file; instead, it compares the generated schema against the existing file content.
The CompileResult object tracks differences through the drift and drift_diff attributes. If drift is True, the drift_diff attribute contains a string describing the specific changes detected between the model and the file.
from pathlib import Path
from pydantic import BaseModel
from softschema.compile import compile_model
class UserProfile(BaseModel):
username: str
email: str
# Adding a new field here would cause drift if the file isn't updated
is_active: bool = True
schema_file = Path("user_profile.schema.yaml")
# Check for drift without writing to the file
result = compile_model(
UserProfile,
schema_file,
contract_id="example:UserProfile/v1",
check_only=True
)
if result.drift:
print(f"Schema drift detected at {result.out_path}!")
print(f"Differences:\n{result.drift_diff}")
else:
print("Schema is up to date.")