feat: Create the Random Choice Oracle
This commit is contained in:
parent
52f598c8b3
commit
d556159f2a
38
gm_assistant/oracle/random_choice.py
Normal file
38
gm_assistant/oracle/random_choice.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2025 2025
|
||||||
|
# SPDX-FileContributor: Gergely Polonkai
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
"""Random Choice Oracle"""
|
||||||
|
|
||||||
|
import random
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from .base import Oracle
|
||||||
|
|
||||||
|
|
||||||
|
class RandomChoiceOracle(Oracle):
|
||||||
|
"""An Oracle that can choose randomly from a list of possibilities"""
|
||||||
|
|
||||||
|
TYPE_MARKER = "random-choice"
|
||||||
|
|
||||||
|
def __init__(self, oracle_data: dict[str, Any]) -> None:
|
||||||
|
self.choices: list[str] | None = None
|
||||||
|
|
||||||
|
super().__init__(oracle_data)
|
||||||
|
|
||||||
|
def parse_and_validate(self, oracle_data: dict[str, Any]) -> None:
|
||||||
|
super().parse_and_validate(oracle_data)
|
||||||
|
|
||||||
|
if "choices" not in oracle_data:
|
||||||
|
raise KeyError("choices is missing from the data")
|
||||||
|
|
||||||
|
if not oracle_data["choices"]:
|
||||||
|
raise ValueError("Choice list cannot be empty")
|
||||||
|
|
||||||
|
if not isinstance(oracle_data["choices"], list):
|
||||||
|
raise TypeError("choices must be a list")
|
||||||
|
|
||||||
|
self.choices = oracle_data["choices"]
|
||||||
|
|
||||||
|
def generate(self) -> str:
|
||||||
|
return random.choice(self.choices or [])
|
65
tests/test_random_choice_oracle.py
Normal file
65
tests/test_random_choice_oracle.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2025 2025
|
||||||
|
# SPDX-FileContributor: Gergely Polonkai
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
"""Tests for the Random Choice Oracle"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
|
from gm_assistant.oracle.random_choice import RandomChoiceOracle
|
||||||
|
|
||||||
|
TEST_DATA = {
|
||||||
|
"type": "random-choice",
|
||||||
|
"name": "Test Oracle",
|
||||||
|
"source": "Test Source",
|
||||||
|
"choices": ["One", "Two", "Three"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_init_missing_choices() -> None:
|
||||||
|
"""Test initalising with missing choices"""
|
||||||
|
|
||||||
|
oracle_data = TEST_DATA.copy()
|
||||||
|
del oracle_data["choices"]
|
||||||
|
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
RandomChoiceOracle(oracle_data)
|
||||||
|
|
||||||
|
|
||||||
|
def test_init_empty_choices() -> None:
|
||||||
|
"""Test initialising with an empty choice list"""
|
||||||
|
|
||||||
|
oracle_data = TEST_DATA.copy()
|
||||||
|
oracle_data["choices"] = []
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
RandomChoiceOracle(oracle_data)
|
||||||
|
|
||||||
|
|
||||||
|
def test_init_nonlist_choices() -> None:
|
||||||
|
"""Test initialising with a choice list that is not a list"""
|
||||||
|
|
||||||
|
oracle_data = TEST_DATA.copy()
|
||||||
|
oracle_data["choices"] = {"a": "b"} # type: ignore[assignment]
|
||||||
|
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
RandomChoiceOracle(oracle_data)
|
||||||
|
|
||||||
|
|
||||||
|
def test_init() -> None:
|
||||||
|
"""Test initialisation"""
|
||||||
|
|
||||||
|
oracle = RandomChoiceOracle(TEST_DATA)
|
||||||
|
|
||||||
|
assert oracle.choices == ["One", "Two", "Three"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_generate(mocker: MockerFixture) -> None:
|
||||||
|
"""Test generate()"""
|
||||||
|
|
||||||
|
mocked_choice = mocker.patch("gm_assistant.oracle.random_choice.random.choice", return_value="Result")
|
||||||
|
oracle = RandomChoiceOracle(TEST_DATA)
|
||||||
|
|
||||||
|
assert oracle.generate() == "Result"
|
||||||
|
mocked_choice.assert_called_once_with(["One", "Two", "Three"])
|
Loading…
x
Reference in New Issue
Block a user