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..0308126 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, 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(): - 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: skipped {pet_name}") + 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):