From bbc4e26cad9d70d4da439b8cf49e221c5fc93267 Mon Sep 17 00:00:00 2001 From: Melvin <31448155+melvio@users.noreply.github.com> Date: Mon, 23 Sep 2024 21:24:35 +0200 Subject: [PATCH 1/2] support graceful degr --- src/hopla/cli/feed_all.py | 5 ++-- src/hopla/hoplalib/hoplaversion.py | 2 +- src/hopla/hoplalib/zoo/zoomodels.py | 15 ++++++++--- src/tests/cli/test_feed_all.py | 4 ++- src/tests/hoplalib/zoo/test_zoomodels.py | 33 +++++++++++++++++++++--- 5 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/hopla/cli/feed_all.py b/src/hopla/cli/feed_all.py index be3314d..6790846 100644 --- a/src/hopla/cli/feed_all.py +++ b/src/hopla/cli/feed_all.py @@ -24,7 +24,7 @@ def __get_feed_plan_or_exit() -> Union[NoReturn, FeedPlan]: """Get the user and build the feed plan""" user: HabiticaUser = HabiticaUserRequest().request_user_data_or_exit() stockpile: FoodStockpile = FoodStockpileBuilder().user(user).build() - zoo: Zoo = ZooBuilder(user).build() + zoo: Zoo = ZooBuilder(user).build(skip_unsupported_pets=True) algorithm = FeedAlgorithm(zoo=zoo, stockpile=stockpile) return algorithm.make_plan() @@ -100,7 +100,8 @@ def feed_all(no_interactive: bool) -> None: click.echo( "The feed plan is empty. Reasons for this could be:\n" "1. There is insufficient food available to turn pets into mounts.\n" - "2. You don't have any feedable pets." + "2. You don't have any feedable pets\n" + "3. You do have feedable pets, but they are not supported yet by hopla\n" ) sys.exit(0) diff --git a/src/hopla/hoplalib/hoplaversion.py b/src/hopla/hoplalib/hoplaversion.py index 486cb09..77ad679 100644 --- a/src/hopla/hoplalib/hoplaversion.py +++ b/src/hopla/hoplalib/hoplaversion.py @@ -7,7 +7,7 @@ MAJOR_VERSION: Final[int] = 0 MINOR_VERSION: Final[int] = 0 -PATCH_VERSION: Final[int] = 43 +PATCH_VERSION: Final[int] = 44 PRE_RELEASE: Final[Optional[str]] = "alpha" diff --git a/src/hopla/hoplalib/zoo/zoomodels.py b/src/hopla/hoplalib/zoo/zoomodels.py index f34a67d..b49e6dc 100644 --- a/src/hopla/hoplalib/zoo/zoomodels.py +++ b/src/hopla/hoplalib/zoo/zoomodels.py @@ -2,11 +2,13 @@ """ Module with models for collections of pets and mounts. """ +import logging from typing import Callable, Dict from dataclasses import dataclass from hopla.cli.groupcmds.get_user import HabiticaUser from hopla.hoplalib.zoo.foodmodels import FeedStatus +from hopla.hoplalib.zoo.petdata import PetData from hopla.hoplalib.zoo.petmodels import Mount, Pet, PetMountPair Zoo = Dict[str, PetMountPair] @@ -73,13 +75,20 @@ def __init__(self, user: HabiticaUser): def __repr__(self): return self.__class__.__name__ + f"({self.__dict__})" - def build(self) -> Zoo: - """Create the Zoo. Return the Zoo in case of success""" + def build(self, skip_unsupported_pets: bool = False) -> Zoo: + """ Build the Zoo. + + :param skip_unsupported_pets: if True, skips pets that are not supported (mounts are always included) + :return: the Zoo in case of success + """ # loop through the pets for pet_name, feed_status in self.pets.items(): - pet = Pet(pet_name, feed_status=FeedStatus(feed_status)) + if skip_unsupported_pets and (pet_name not in PetData.pet_names): + logging.error(f"{pet_name=} not supported yet: skipping {pet_name} in the feed plan") + continue + pet = Pet(pet_name, feed_status=FeedStatus(feed_status)) if self.mounts.get(pet_name) is not None: mount = Mount( mount_name=pet_name, diff --git a/src/tests/cli/test_feed_all.py b/src/tests/cli/test_feed_all.py index c4dfa2e..7bc354b 100644 --- a/src/tests/cli/test_feed_all.py +++ b/src/tests/cli/test_feed_all.py @@ -144,7 +144,9 @@ def test_feed_released_pets(self, mock_user_request: MagicMock, expected_msg = ("The feed plan is empty. Reasons for this could be:\n" "1. There is insufficient food available to turn pets into mounts.\n" - "2. You don't have any feedable pets.") + "2. You don't have any feedable pets\n" + "3. You do have feedable pets, but they are not supported yet by hopla\n") + assert expected_msg in result.stdout @pytest.fixture diff --git a/src/tests/hoplalib/zoo/test_zoomodels.py b/src/tests/hoplalib/zoo/test_zoomodels.py index 0b5d0f5..e15593b 100644 --- a/src/tests/hoplalib/zoo/test_zoomodels.py +++ b/src/tests/hoplalib/zoo/test_zoomodels.py @@ -1,7 +1,9 @@ #!/usr/bin/env python3 +import pytest + from hopla.cli.groupcmds.get_user import HabiticaUser from hopla.hoplalib.zoo.foodmodels import FeedStatus -from hopla.hoplalib.zoo.petmodels import Pet, PetMountPair +from hopla.hoplalib.zoo.petmodels import Pet, PetMountPair, InvalidPet from hopla.hoplalib.zoo.zoomodels import Zoo, ZooBuilder, ZooHelper from tests.testutils.user_test_utils import UserTestUtil @@ -39,9 +41,6 @@ def test_build_empty_zoo(self): assert zoo == {} - def test_build_released_zoo(self): - pass - def test_build_raised_pets(self): animal_name = "BearCub-Shadow" feed_status = -1 # i.e. No pet, just mount @@ -84,6 +83,32 @@ def test_build_yes_pet_no_mount(self): assert result_pair.mount_available() is False assert result_pair.pet_available() + def test_build_not_supported_pets_fails(self): + animal_name_supported = "Dragon-Skeleton" + animal_name_not_supported = "Dragon-NOTSUPPORTED" + user = UserTestUtil.user_with_zoo(pets={animal_name_supported: 5, animal_name_not_supported: 5}) + + with pytest.raises(InvalidPet) as exc: + ZooBuilder(user).build() + + assert animal_name_not_supported in str(exc.value) + assert animal_name_supported not in str(exc.value) + + def test_build_not_supported_pets_success(self): + animal_name_supported = "Dragon-Skeleton" + animal_name_not_supported = "Dragon-NOTSUPPORTED" + feed_status = 5 + user = UserTestUtil.user_with_zoo(pets={animal_name_supported: feed_status, + animal_name_not_supported: feed_status}) + + zoo: Zoo = ZooBuilder(user).build(skip_unsupported_pets=True) + + assert len(zoo) == 1 + result_pair: PetMountPair = zoo[animal_name_supported] + assert result_pair.pet.name == animal_name_supported + assert result_pair.pet.feed_status == FeedStatus(feed_status) + assert result_pair.mount_available() is False + class TestZooHelper: def test_filter_on_pet_mount_pair(self): From ad374b1320f63af749d06c903467a84294e7b2b1 Mon Sep 17 00:00:00 2001 From: Melvin <31448155+melvio@users.noreply.github.com> Date: Mon, 23 Sep 2024 21:27:52 +0200 Subject: [PATCH 2/2] linting --- src/hopla/hoplalib/zoo/zoomodels.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hopla/hoplalib/zoo/zoomodels.py b/src/hopla/hoplalib/zoo/zoomodels.py index b49e6dc..0308126 100644 --- a/src/hopla/hoplalib/zoo/zoomodels.py +++ b/src/hopla/hoplalib/zoo/zoomodels.py @@ -78,14 +78,14 @@ def __repr__(self): def build(self, skip_unsupported_pets: bool = False) -> Zoo: """ Build the Zoo. - :param skip_unsupported_pets: if True, skips pets that are not supported (mounts are always included) + :param skip_unsupported_pets: if True, skip unsupported pets (excludes mounts) :return: the Zoo in case of success """ # loop through the pets for pet_name, feed_status in self.pets.items(): if skip_unsupported_pets and (pet_name not in PetData.pet_names): - logging.error(f"{pet_name=} not supported yet: skipping {pet_name} in the feed plan") + logging.error(f"{pet_name=} not supported yet: skipped {pet_name}") continue pet = Pet(pet_name, feed_status=FeedStatus(feed_status))