Skip to content

Commit

Permalink
feat: validate schemas using pydantic_schemaorg (#69)
Browse files Browse the repository at this point in the history
Validates front matter as a pydantic_schemaorg schema, printing warnings
when schema validation errors are found.
  • Loading branch information
johnfraney authored Apr 11, 2024
1 parent ac36f48 commit 91702a2
Show file tree
Hide file tree
Showing 6 changed files with 448 additions and 7 deletions.
7 changes: 7 additions & 0 deletions blurry/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from jinja2 import select_autoescape
from livereload import Server
from rich import print
from rich.console import Console

from blurry.async_typer import AsyncTyper
from blurry.cli import print_blurry_name
Expand All @@ -25,6 +26,7 @@
from blurry.open_graph import open_graph_meta_tags
from blurry.plugins import discovered_html_plugins
from blurry.plugins import discovered_jinja_filter_plugins
from blurry.schema_validation import validate_front_matter_as_schema
from blurry.settings import get_build_directory
from blurry.settings import get_content_directory
from blurry.settings import get_templates_directory
Expand All @@ -46,6 +48,8 @@ def json_converter_with_dates(item: Any) -> None | str:
return item.strftime("%Y-%M-%D")


warning_console = Console(stderr=True, style="bold yellow")

print_blurry_name()
print_plugin_table()

Expand Down Expand Up @@ -147,6 +151,9 @@ async def write_html_file(
format_schema_data(schema_variables),
default=json_converter_with_dates,
)

validate_front_matter_as_schema(file_data.path, front_matter, warning_console)

schema_type_tag = f'<script type="application/ld+json">{schema_data}</script>'

template_context = {
Expand Down
58 changes: 58 additions & 0 deletions blurry/schema_validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import importlib
from collections.abc import MutableMapping
from pathlib import Path

from pydantic.v1 import ValidationError
from rich.console import Console

from blurry.settings import SETTINGS
from blurry.settings import update_settings


class Config:
extra = "forbid"


def validate_front_matter_as_schema(
path: Path, front_matter: MutableMapping, console: Console
):
"""
Validates schema data using pydantic_schemaorg, disallowing extra fields
"""
update_settings()

schema_type = front_matter["@type"]

# Import pydantic_schemaorg model
try:
pydantic_schemaorg_model_module = importlib.import_module(
f"pydantic_schemaorg.{schema_type}"
)
except ModuleNotFoundError:
console.print(
f"{path}: Could not find Schema type for {schema_type}. Skipping."
)
return

schema_model = getattr(pydantic_schemaorg_model_module, schema_type)

# Create new Pydantic model that forbids extra fields
class NonExtraSchemaModel(schema_model, extra="forbid"): # type: ignore
pass

# Validate model and print errors
try:
non_schema_variable_prefix = SETTINGS["FRONTMATTER_NON_SCHEMA_VARIABLE_PREFIX"]
schema_front_matter = {
k: v
for k, v in front_matter.items()
if not k.startswith(non_schema_variable_prefix)
}
NonExtraSchemaModel(**schema_front_matter)
except ValidationError as e:
for error in e.errors():
msg = error["msg"]
loc = error["loc"]
console.print(
f"{path}: {schema_type} schema validation error: {msg}: {loc}"
)
152 changes: 152 additions & 0 deletions docs/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 91702a2

Please sign in to comment.