feat: Create the load_oracle_from_yaml helper

This commit is contained in:
Gergely Polonkai 2025-05-23 20:04:34 +02:00
parent 6d68faf73c
commit bf69d7463e
No known key found for this signature in database
GPG Key ID: 2D2885533B869ED4
2 changed files with 78 additions and 0 deletions

View File

@ -4,8 +4,11 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
"""Oracle classes and related functions""" """Oracle classes and related functions"""
from pathlib import Path
from typing import Any, Type from typing import Any, Type
import yaml
from .base import Oracle from .base import Oracle
from .object_generator import ObjectGeneratorOracle from .object_generator import ObjectGeneratorOracle
from .random_choice import RandomChoiceOracle from .random_choice import RandomChoiceOracle
@ -28,3 +31,23 @@ def generate_type_classes(class_list: dict[str, Any]) -> dict[str, Type[Oracle]]
ret[klass.TYPE_MARKER] = klass ret[klass.TYPE_MARKER] = klass
return ret return ret
TYPE_CLASSES: dict[str, Type[Oracle]] = generate_type_classes(globals())
def load_oracle_from_yaml(file_path: str | Path) -> Oracle:
"""Create an Oracle from a YAML file"""
with open(file_path, "r", encoding="utf-8") as fhand:
data = yaml.safe_load(fhand)
if not isinstance(data, dict):
raise TypeError("Oracle data must be a YAML object")
if (generator_type := data.get("type")) not in TYPE_CLASSES:
raise KeyError(f"No information on how to handle {generator_type} data")
handler_class = TYPE_CLASSES[generator_type]
return handler_class(data)

View File

@ -0,0 +1,55 @@
# SPDX-FileCopyrightText: 2025 2025
# SPDX-FileContributor: Gergely Polonkai
#
# SPDX-License-Identifier: GPL-3.0-or-later
"""Tests for the ``load_oracle_from_yaml`` function"""
import pytest
from pytest_mock import MockerFixture
from gm_assistant.oracle import load_oracle_from_yaml
from gm_assistant.oracle.random_choice import RandomChoiceOracle
def test_non_object(mocker: MockerFixture) -> None:
"""Test loading something that is not a YAML object"""
mocker.patch("gm_assistant.oracle.open")
mocker.patch("gm_assistant.oracle.yaml.safe_load", return_value=[])
with pytest.raises(TypeError) as ctx:
load_oracle_from_yaml("test_file")
assert str(ctx.value) == "Oracle data must be a YAML object"
# WARNING
#
# Tests below this line rely on specific classes getting loaded into gm_assistant.oracle.TYPE_CLASSES
def test_unknown_type(mocker: MockerFixture) -> None:
"""Test loading an oracle with an unknown type"""
mocker.patch("gm_assistant.oracle.open")
mocker.patch("gm_assistant.oracle.yaml.safe_load", return_value={"type": "something-non-existing"})
with pytest.raises(KeyError) as ctx:
load_oracle_from_yaml("test_file")
assert str(ctx.value) == "'No information on how to handle something-non-existing data'"
def test_load_oracle(mocker: MockerFixture) -> None:
"""Test loading a specific oracle"""
mocker.patch("gm_assistant.oracle.open")
mocker.patch(
"gm_assistant.oracle.yaml.safe_load",
return_value={"type": "random-choice", "name": "Test Oracle", "source": "Test Source", "choices": ["A", "B"]},
)
oracle = load_oracle_from_yaml("test_file")
assert isinstance(oracle, RandomChoiceOracle)
assert oracle.choices == ["A", "B"]