Skip to content

Commit

Permalink
meh
Browse files Browse the repository at this point in the history
  • Loading branch information
bartfeenstra committed Aug 13, 2024
1 parent 3652347 commit 716256f
Show file tree
Hide file tree
Showing 9 changed files with 372 additions and 315 deletions.
276 changes: 112 additions & 164 deletions betty/ancestry/__init__.py

Large diffs are not rendered by default.

13 changes: 9 additions & 4 deletions betty/json/linked_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

from __future__ import annotations

from abc import abstractmethod
from collections.abc import MutableSequence
from pathlib import Path
from typing import TYPE_CHECKING, cast, Self
from typing import TYPE_CHECKING, cast, Self, Generic, TypeVar

from betty.json.schema import Schema, FileBasedSchema
from betty.serde.dump import DumpMapping, Dump
Expand All @@ -16,7 +17,10 @@
from betty.ancestry import Link


class LinkedDataDumpable:
_SchemaT = TypeVar("_SchemaT", bound=Schema, covariant=True)


class LinkedDataDumpable(Generic[_SchemaT]):
"""
Describe an object that can be dumped to linked data.
"""
Expand All @@ -34,11 +38,12 @@ async def dump_linked_data(self, project: Project) -> DumpMapping[Dump]:
return dump

@classmethod
async def linked_data_schema(cls, project: Project) -> Schema:
@abstractmethod
async def linked_data_schema(cls, project: Project) -> _SchemaT:
"""
Define the `JSON Schema <https://json-schema.org/>`_ for :py:meth:`betty.json.linked_data.LinkedDataDumpable.dump_linked_data`.
"""
return Schema()
pass


def dump_context(dump: DumpMapping[Dump], **context_definitions: str) -> None:
Expand Down
187 changes: 155 additions & 32 deletions betty/json/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def __init__(
description: str | None = None,
):
self._def_name = def_name
self._schema = {}
self._schema: DumpMapping[Dump] = {}
if title:
self._schema["title"] = title
self._schema["description"] = description
Expand Down Expand Up @@ -105,6 +105,10 @@ class TypeSchema(Schema):
"""

class Type(Enum):
"""
A JSON Schema schema's ``type``.
"""

STRING = "string"
NUMBER = "number"
INTEGER = "integer"
Expand All @@ -126,7 +130,15 @@ def __init__(


class StringSchema(TypeSchema):
"""
A JSON Schema ``string`` type.
"""

class Format(Enum):
"""
A JSON Schema ``string`` type's ``format``.
"""

DATE_TIME = "date-time"
TIME = "time"
DATE = "date"
Expand Down Expand Up @@ -156,7 +168,7 @@ def __init__(
min_length: int | None = None,
max_length: int | None = None,
pattern: str | None = None,
format: Format | None = None,
format: Format | None = None, # noqa A002
):
super().__init__(
TypeSchema.Type.STRING,
Expand All @@ -174,15 +186,144 @@ def __init__(
self._schema["format"] = format.value


class ArraySchema(Schema):
class BooleanSchema(TypeSchema):
"""
A JSON Schema ``boolean`` type.
"""

def __init__(
self,
*,
def_name: str | None = None,
title: str | None = None,
description: str | None = None,
):
super().__init__(
TypeSchema.Type.BOOLEAN,
def_name=def_name,
title=title,
description=description,
)


class NumberSchema(TypeSchema):
"""
A JSON Schema ``number`` type.
"""

def __init__(
self,
*,
def_name: str | None = None,
title: str | None = None,
description: str | None = None,
):
super().__init__(
TypeSchema.Type.NUMBER,
def_name=def_name,
title=title,
description=description,
)


class NullSchema(TypeSchema):
"""
A JSON Schema ``null`` type.
"""

def __init__(
self,
*,
def_name: str | None = None,
title: str | None = None,
description: str | None = None,
):
super().__init__(
TypeSchema.Type.NULL,
def_name=def_name,
title=title,
description=description,
)


class ObjectSchema(TypeSchema):
"""
A JSON Schema ``object`` type.
"""

def __init__(
self,
*,
def_name: str | None = None,
title: str | None = None,
description: str | None = None,
):
super().__init__(
TypeSchema.Type.OBJECT,
def_name=def_name,
title=title,
description=description,
)
self._schema["properties"] = {}
self._schema["required"] = []

def add_property(
self,
property_name: str,
property_schema: Schema,
property_required: bool = True,
) -> None:
"""
Add a property to the object schema.
"""
self._schema["type"] = "object"
schema_properties = cast(
DumpMapping[Dump], self._schema.setdefault("properties", {})
)
schema_properties[property_name] = property_schema.embed(self)
if property_required:
schema_required = cast(
MutableSequence[str], self._schema.setdefault("required", [])
)
schema_required.append(property_name)


class ArraySchema(TypeSchema):
"""
A JSON Schema ``array`` type.
"""

def __init__(
self,
items: Schema,
*,
def_name: str | None = None,
title: str | None = None,
description: str | None = None,
):
super().__init__(
TypeSchema.Type.ARRAY,
def_name=def_name,
title=title,
description=description,
)
self._schema["items"] = items.embed(self)


class OneOf(Schema):
"""
A JSON Schema array.
A JSON Schema ``oneOf``.
"""

def __init__(self, items_schema: Schema, *, def_name: str | None = None):
super().__init__(def_name=def_name)
self._schema["type"] = "array"
self._schema["items"] = items_schema.embed(self)
def __init__(
self,
*items: Schema,
def_name: str | None = None,
title: str | None = None,
description: str | None = None,
):
super().__init__(def_name=def_name, title=title, description=description)
self._schema["oneOf"] = [item.embed(self) for item in items]


class Def(str):
Expand All @@ -208,28 +349,8 @@ class Ref(Schema):
"""

def __init__(self, def_name: str):
super().__init__(schema={"$ref": Def(def_name)})


def add_property(
into: Schema,
property_name: str,
property_schema: Schema,
property_required: bool = True,
) -> None:
"""
Add a property to an object schema.
"""
into._schema["type"] = "object"
schema_properties = cast(
DumpMapping[Dump], into._schema.setdefault("properties", {})
)
schema_properties[property_name] = property_schema.embed(into)
if property_required:
schema_required = cast(
MutableSequence[str], into._schema.setdefault("required", [])
)
schema_required.append(property_name)
super().__init__()
self._schema["$ref"] = Def(def_name)


class JsonSchemaReference(StringSchema):
Expand All @@ -241,7 +362,7 @@ def __init__(self):
super().__init__(
def_name="jsonSchemaReference",
format=StringSchema.Format.URI,
description="A JSON Schema URI."
description="A JSON Schema URI.",
)


Expand All @@ -257,7 +378,9 @@ async def new_for(cls, file_path: Path, *, name: str | None = None) -> Self:
"""
async with aiofiles.open(file_path) as f:
raw_schema = await f.read()
return cls(def_name=name, schema=loads(raw_schema))
schema = cls(def_name=name)
schema._schema = loads(raw_schema)
return schema


class JsonSchemaSchema(FileBasedSchema):
Expand Down
2 changes: 1 addition & 1 deletion betty/locale/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,5 +163,5 @@ class LocaleSchema(StringSchema):
def __init__(self):
super().__init__(
def_name="locale",
description="A BCP 47 locale identifier (https://www.ietf.org/rfc/bcp/bcp47.txt)."
description="A BCP 47 locale identifier (https://www.ietf.org/rfc/bcp/bcp47.txt).",
)
Loading

0 comments on commit 716256f

Please sign in to comment.