From 616cd94b50c97ef02734dea93a1fec35b6aeb14f Mon Sep 17 00:00:00 2001 From: take-kun <109226194+take-kun@users.noreply.github.com> Date: Sun, 8 Jan 2023 02:47:33 +0100 Subject: [PATCH 1/3] fix: Implement ResponseModel's mapping protocol recursively (#5) --- mercapi/models/base.py | 5 ++++- tests/models/__init__.py | 31 +++++++++++++++++++++++++++ tests/models/test_mapping_protocol.py | 16 +++++++++++++- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/mercapi/models/base.py b/mercapi/models/base.py index 5bec5a6..f733d81 100644 --- a/mercapi/models/base.py +++ b/mercapi/models/base.py @@ -48,7 +48,10 @@ def __getitem__(self, key): raise IndexError( f"{key} is not a valid member of {self.__class__.__name__}" ) - return getattr(self, key) + res = getattr(self, key) + if not issubclass(type(res), ResponseModel): + return res + return dict(res) @classmethod def from_dict(cls, d: dict) -> RM: diff --git a/tests/models/__init__.py b/tests/models/__init__.py index bf35ab2..bd8b096 100644 --- a/tests/models/__init__.py +++ b/tests/models/__init__.py @@ -15,3 +15,34 @@ def __init__(self, field_1: str, field_2: Optional[str]): super().__init__() self.field_1 = field_1 self.field_2 = field_2 + + +class ModelTestBNested(ResponseModel): + _required_properties = [ + ResponseProperty("field_a", "field_a", Extractors.get("field_a")), + ] + _optional_properties = [ + ResponseProperty("field_b", "field_b", Extractors.get("field_b")), + ] + + def __init__(self, field_a: str, field_b: Optional[str]): + super().__init__() + self.field_a = field_a + self.field_b = field_b + + +class ModelTestB(ResponseModel): + _required_properties = [ + ResponseProperty("field_1", "field_1", Extractors.get("field_1")), + ResponseProperty( + "field_nested", + "field_nested", + Extractors.get_as_model("field_nested", ModelTestBNested), + ), + ] + _optional_properties = [] + + def __init__(self, field_1: str, field_nested: ModelTestBNested): + super().__init__() + self.field_1 = field_1 + self.field_nested = field_nested diff --git a/tests/models/test_mapping_protocol.py b/tests/models/test_mapping_protocol.py index 4e40f72..3c8ac66 100644 --- a/tests/models/test_mapping_protocol.py +++ b/tests/models/test_mapping_protocol.py @@ -1,6 +1,6 @@ import pytest -from tests.models import ModelTest +from tests.models import ModelTest, ModelTestB, ModelTestBNested def test_retrieve_existing_required_field(): @@ -43,3 +43,17 @@ def test_unpack_class_as_kwargs(): "field_1": obj.field_1, "field_2": obj.field_2, } + + +def test_convert_nested_class_to_dict(): + obj_nested = ModelTestBNested("foo", "bar") + obj = ModelTestB("foo", obj_nested) + dict_obj = dict(obj) + + assert dict_obj == { + "field_1": obj.field_1, + "field_nested": { + "field_a": obj_nested.field_a, + "field_b": obj_nested.field_b, + }, + } From a7821ea49642beda846c7e515c63f02dbacdc180 Mon Sep 17 00:00:00 2001 From: take-kun <109226194+take-kun@users.noreply.github.com> Date: Sun, 8 Jan 2023 02:48:16 +0100 Subject: [PATCH 2/3] tests: Test retrieving empty optional from the model --- tests/models/test_mapping_protocol.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/models/test_mapping_protocol.py b/tests/models/test_mapping_protocol.py index 3c8ac66..b65d605 100644 --- a/tests/models/test_mapping_protocol.py +++ b/tests/models/test_mapping_protocol.py @@ -18,6 +18,12 @@ def test_retrieve_existing_optional_field(): assert obj["field_2"] == field_2 +def test_retrieve_existing_empty_optional_field(): + obj = ModelTest("foo", None) + + assert obj["field_2"] is None + + def test_retrieve_non_existent_field_throw_exception(): obj = ModelTest("foo", None) From 859eb3828eb0d4a62dd56720e1162c0482cc4b4d Mon Sep 17 00:00:00 2001 From: take-kun <109226194+take-kun@users.noreply.github.com> Date: Sun, 8 Jan 2023 03:03:45 +0100 Subject: [PATCH 3/3] chore: Version 0.2.0 -> 0.2.1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6d54ca6..e45a246 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "mercapi" -version = "0.2.0" +version = "0.2.1" description = "Python API for querying and browsing mercari.jp" authors = ["take-kun <109226194+take-kun@users.noreply.github.com>"] license = "MIT"