comicbox.validate.yaml_validator

[docs] module comicbox.validate.yaml_validator

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
"""Validate yaml with jsonchema."""

from pathlib import Path
from typing import Any

from glom import glom
from ruamel.yaml import YAML
from typing_extensions import override

from comicbox.constants import (
    COVER_DATE_KEY,
    COVER_DATE_KEYPATH,
    DATE_KEY,
    PAGES_KEY,
    PAGES_KEYPATH,
    ROOT_KEYPATH,
    STORE_DATE_KEY,
    STORE_DATE_KEYPATH,
    UPDATED_AT_KEY,
)
from comicbox.formats.base.fields.time_fields import DateField, DateTimeField
from comicbox.validate.json_validator import JsonValidator

_KEYPATH_PREFIX = ROOT_KEYPATH + "."
_FULL_UPDATED_AT_KEYPATH = _KEYPATH_PREFIX + UPDATED_AT_KEY
_FULL_COVER_DATE_KEYPATH = _KEYPATH_PREFIX + COVER_DATE_KEYPATH
_FULL_STORE_DATE_KEYPATH = _KEYPATH_PREFIX + STORE_DATE_KEYPATH


def _stringify_keys(data: Any) -> Any:
    """JSON requires string keys."""
    if pages := glom(data, PAGES_KEYPATH, default=None):
        pages = {str(key): value for key, value in pages.items()}
        # Glom can't assign to RumaelCommentMaps
        data[ROOT_KEYPATH][PAGES_KEY] = pages

    if updated_at := glom(data, _FULL_UPDATED_AT_KEYPATH, default=None):
        data[ROOT_KEYPATH][UPDATED_AT_KEY] = updated_at = DateTimeField()._serialize(  # noqa: SLF001
            updated_at, "", None
        )

    if cover_date := glom(data, _FULL_COVER_DATE_KEYPATH, default=None):
        data[ROOT_KEYPATH][DATE_KEY][COVER_DATE_KEY] = DateField()._serialize(  # noqa: SLF001
            cover_date, "", None
        )

    if store_date := glom(data, _FULL_STORE_DATE_KEYPATH, default=None):
        data[ROOT_KEYPATH][DATE_KEY][STORE_DATE_KEY] = DateField()._serialize(  # noqa: SLF001
            store_date, "", None
        )

    return data


class YamlValidator(JsonValidator):
    """Yaml Validator."""

    @override
    def validate(self, data: str | bytes | Path) -> None:
        """Validate source."""
        data = self.get_data_str(data)
        data = YAML().load(data)
        json_data = _stringify_keys(data)
        self._validator.validate(json_data)