"""
Provide `JSON-LD <https://json-ld.org/>`_ utilities.
"""
from __future__ import annotations
from abc import abstractmethod
from collections.abc import MutableSequence
from pathlib import Path
from typing import TYPE_CHECKING, cast, Self, Generic, TypeVar
from betty.asyncio import wait_to_thread
from betty.json.schema import FileBasedSchema, Schema, Object
from betty.serde.dump import DumpMapping, Dump
if TYPE_CHECKING:
from betty.project import Project
from betty.ancestry.link import Link
_SchemaTypeT = TypeVar("_SchemaTypeT", bound=Schema, covariant=True)
[docs]
class LinkedDataDumpable(Generic[_SchemaTypeT]):
"""
Describe an object that can be dumped to linked data.
"""
[docs]
async def dump_linked_data(self, project: Project) -> DumpMapping[Dump]:
"""
Dump this instance to `JSON-LD <https://json-ld.org/>`_.
"""
from betty.project import ProjectSchema
dump: DumpMapping[Dump] = {}
schema = await self.linked_data_schema(project)
if schema.def_name:
dump["$schema"] = ProjectSchema.def_url(project, schema.def_name)
return dump
[docs]
@classmethod
@abstractmethod
async def linked_data_schema(cls, project: Project) -> _SchemaTypeT:
"""
Define the `JSON Schema <https://json-schema.org/>`_ for :py:meth:`betty.json.linked_data.LinkedDataDumpable.dump_linked_data`.
"""
pass
[docs]
def dump_context(dump: DumpMapping[Dump], **context_definitions: str) -> None:
"""
Add one or more contexts to a dump.
"""
context_dump = cast(DumpMapping[Dump], dump.setdefault("@context", {}))
for key, context_definition in context_definitions.items():
context_dump[key] = context_definition
[docs]
async def dump_link(dump: DumpMapping[Dump], project: Project, *links: Link) -> None:
"""
Add one or more links to a dump.
"""
link_dump = cast(MutableSequence[DumpMapping[Dump]], dump.setdefault("links", []))
for link in links:
link_dump.append(await link.dump_linked_data(project))
[docs]
class JsonLdSchema(FileBasedSchema):
"""
A `JSON-LD <https://json-ld.org/>`_ JSON Schema reference.
"""