Newer
Older
TIASDataHub / src / tiasdata / kinds / __init__.py
"""ファイルの種類・所見の種類の値の型.

種類の行(`kinds` 表)はマイグレーションで足し,所見の値の型はここに足す
(SPEC_02「拡張の例」).所見の値は目録に保存する前にここの型で検証する.
"""

import json
from typing import Any

from pydantic import BaseModel

from tiasdata.kinds.review import REVIEW_KIND, Review
from tiasdata.kinds.tongue_color import TongueColor

# 所見の種類名 → 値の型
ANNOTATION_VALUE_TYPES: dict[str, type[BaseModel]] = {
    REVIEW_KIND: Review,
    "tongue_color": TongueColor,
}


def annotation_value_type(kind: str) -> type[BaseModel]:
    """所見の種類名から値の型を引く.

    Args:
        kind: 所見の種類名(例: `tongue_color`).

    Returns:
        値の型(pydantic のモデル).

    Raises:
        ValueError: 値の型が定義されていない種類.
    """
    try:
        return ANNOTATION_VALUE_TYPES[kind]
    except KeyError:
        raise ValueError(f"所見の種類 '{kind}' の値の型が定義されていない") from None


def validate_annotation_value(kind: str, value: dict[str, Any]) -> BaseModel:
    """所見の値を種類の型で検証する.

    Args:
        kind: 所見の種類名.
        value: 値(JSON から読んだ辞書等).

    Returns:
        検証済みの値.

    Raises:
        ValueError: 値の型が定義されていない種類.
        pydantic.ValidationError: 値が型に合わない(未知のキー・未知の値・無効な組み合わせ).
    """
    return annotation_value_type(kind).model_validate(value)


def dump_annotation_value(value: BaseModel) -> str:
    """検証済みの所見の値を,目録に保存する JSON の文字列にする.

    キーの順を固定し空白を入れない(同じ値が常に同じ文字列になるようにするため).

    Args:
        value: 検証済みの値.

    Returns:
        JSON の文字列.
    """
    return json.dumps(value.model_dump(mode="json"), sort_keys=True, separators=(",", ":"))


__all__ = [
    "ANNOTATION_VALUE_TYPES",
    "REVIEW_KIND",
    "Review",
    "TongueColor",
    "annotation_value_type",
    "dump_annotation_value",
    "validate_annotation_value",
]