Skip to content

Commit

Permalink
improve schema generation:
Browse files Browse the repository at this point in the history
- use oneOf instead of anyOf
- remove duplicated required strings automatically (not by hand)
  • Loading branch information
Totto16 committed Aug 7, 2023
1 parent 91d2fc2 commit a85951b
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 12 deletions.
2 changes: 1 addition & 1 deletion schema/content_list.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"type": "array",
"items": {
"anyOf": [
"oneOf": [
{
"$ref": "#/$defs/EpisodeContent"
},
Expand Down
4 changes: 0 additions & 4 deletions src/content/base_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,11 @@ class ContentDict(TypedDict):
scanned_file: ScannedFile




@dataclass(slots=True, repr=True)
class Content:
__type: ContentType = field(metadata=alias("type"))
__scanned_file: ScannedFile = field(metadata=alias("scanned_file"))


def summary(self: Self, _detailed: bool = False) -> Summary:
raise MissingOverrideError

Expand Down Expand Up @@ -66,7 +63,6 @@ def scan(
raise MissingOverrideError



def process_folder(
directory: Path,
callback: Callback[Content, ContentCharacteristic, Manager],
Expand Down
4 changes: 3 additions & 1 deletion src/content/collection_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
cast,
)

from apischema import alias
from apischema import alias, schema
from classifier import Classifier
from enlighten import Manager
from typing_extensions import override
Expand All @@ -27,6 +27,7 @@
NameParser,
ScannedFile,
Summary,
deduplicate_required,
)
from content.series_content import SeriesContent

Expand All @@ -36,6 +37,7 @@ class CollectionContentDict(ContentDict):
series: list[SeriesContent]


@schema(extra=deduplicate_required)
@dataclass(slots=True, repr=True)
class CollectionContent(Content):
__type: Literal[ContentType.collection] = field(metadata=alias("type"))
Expand Down
4 changes: 3 additions & 1 deletion src/content/episode_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Self,
)

from apischema import alias
from apischema import alias, schema
from classifier import Classifier, FileMetadataError, Language, WAVFile
from enlighten import Manager
from typing_extensions import override
Expand All @@ -22,6 +22,7 @@
NameParser,
ScannedFile,
Summary,
deduplicate_required,
)


Expand Down Expand Up @@ -50,6 +51,7 @@ def itr_print_percent() -> None:
print(f"{percent:.02f} %")


@schema(extra=deduplicate_required)
@dataclass(slots=True, repr=True)
class EpisodeContent(Content):
__type: Literal[ContentType.episode] = field(metadata=alias("type"))
Expand Down
9 changes: 9 additions & 0 deletions src/content/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,3 +488,12 @@ def safe_index(ls: list[SF], item: SF) -> Optional[int]:
return ls.index(item)
except ValueError:
return None


def deduplicate_required(schema: dict[str, Any]) -> None:
if schema.get("required") is not None and isinstance(schema["required"], list):
result: list[Any] = []
for element in schema["required"]:
if element not in result:
result.append(element)
schema["required"] = result
4 changes: 3 additions & 1 deletion src/content/season_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
cast,
)

from apischema import alias
from apischema import alias, schema
from classifier import Classifier
from enlighten import Manager
from typing_extensions import override
Expand All @@ -29,6 +29,7 @@
ScannedFile,
SeasonDescription,
Summary,
deduplicate_required,
)


Expand All @@ -37,6 +38,7 @@ class SeasonContentDict(ContentDict):
episodes: list[EpisodeContent]


@schema(extra=deduplicate_required)
@dataclass(slots=True, repr=True)
class SeasonContent(Content):
__type: Literal[ContentType.season] = field(metadata=alias("type")) # TODO: submit upstream path, to allow this: (to not add "type" in the required field twice)
Expand Down
4 changes: 3 additions & 1 deletion src/content/series_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
cast,
)

from apischema import alias
from apischema import alias, schema
from classifier import Classifier
from enlighten import Manager
from typing_extensions import override
Expand All @@ -28,6 +28,7 @@
ScannedFile,
SeriesDescription,
Summary,
deduplicate_required,
)
from content.season_content import SeasonContent

Expand All @@ -37,6 +38,7 @@ class SeriesContentDict(ContentDict):
seasons: list[SeasonContent]


@schema(extra=deduplicate_required)
@dataclass(slots=True, repr=True)
class SeriesContent(Content):
__type: Literal[ContentType.series] = field(metadata=alias("type"))
Expand Down
19 changes: 16 additions & 3 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import json
from os import makedirs
from pathlib import Path
from typing import TYPE_CHECKING, Any, Optional, Self, TypedDict
from typing import TYPE_CHECKING, Annotated, Any, Optional, Self, TypedDict

from apischema import deserialize, serialize
from apischema import deserialize, schema, serialize
from apischema.json_schema import (
deserialization_schema,
serialization_schema,
Expand Down Expand Up @@ -202,7 +202,20 @@ def __del__(self: Self) -> None:
self.__manager.stop()


AllContent = EpisodeContent | SeasonContent | SeriesContent | CollectionContent
# from: https://wyfo.github.io/apischema/0.18/json_schema/
# schema extra can be callable to modify the schema in place
def to_one_of(schema: dict[str, Any]) -> None:
if "anyOf" in schema:
schema["oneOf"] = schema.pop("anyOf")


OneOf = schema(extra=to_one_of)


AllContent = Annotated[
EpisodeContent | SeasonContent | SeriesContent | CollectionContent,
OneOf,
]


def load_from_file(file_path: Path) -> list[Content]:
Expand Down

0 comments on commit a85951b

Please sign in to comment.