diff --git a/pyproject.toml b/pyproject.toml index c84807d..0b26c35 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "toadr3" -version = "0.28.0" +version = "0.29.0" description = "Tiny OpenADR 3 compatible client Python Library" authors = ["Jean-Paul Balabanian "] license = "Apache-2.0" diff --git a/tests/_common_test_utils.py b/tests/_common_test_utils.py index 78070a0..5f56675 100644 --- a/tests/_common_test_utils.py +++ b/tests/_common_test_utils.py @@ -50,7 +50,7 @@ def create_problem_response(title: str, status: int, detail: str) -> web.Respons detail=detail, ), status=status, - dumps=Problem.model_dump_json, + dumps=Problem.as_json, ) diff --git a/tests/test_event_payload_descriptor.py b/tests/test_event_payload_descriptor.py index bb0840e..627d700 100644 --- a/tests/test_event_payload_descriptor.py +++ b/tests/test_event_payload_descriptor.py @@ -54,6 +54,11 @@ def test_event_payload_descriptor_correct_object_type() -> None: assert payload_descriptor.units is None assert payload_descriptor.currency is None + json = payload_descriptor.as_json() + assert json == ( + '{"objectType":"EVENT_PAYLOAD_DESCRIPTOR","payloadType":"CONSUMPTION_POWER_LIMIT"}' + ) + json = payload_descriptor.model_dump_json() assert json == ( '{"objectType":"EVENT_PAYLOAD_DESCRIPTOR",' diff --git a/tests/test_exception.py b/tests/test_exception.py index 4a2cf40..8550cea 100644 --- a/tests/test_exception.py +++ b/tests/test_exception.py @@ -55,9 +55,7 @@ def test_toadr_error_from_problem_with_details() -> None: assert error.message == "title: detail" assert error.status_code == 500 assert error.json_response == { - "type": None, "title": "title", "status": 500, "detail": "detail", - "instance": None, } diff --git a/tests/test_interval.py b/tests/test_interval.py index ce59613..fcae8d3 100644 --- a/tests/test_interval.py +++ b/tests/test_interval.py @@ -136,5 +136,5 @@ def test_interval_to_json() -> None: interval = Interval.model_validate_json(json_data) - result = interval.model_dump_json() + result = interval.as_json() assert result == json_data diff --git a/tests/test_interval_periods.py b/tests/test_interval_periods.py index 453b51a..685a897 100644 --- a/tests/test_interval_periods.py +++ b/tests/test_interval_periods.py @@ -78,6 +78,9 @@ def test_interval_period_to_json() -> None: result = ip.model_dump_json(exclude_defaults=True) assert result == '{"start":"2024-09-24T01:02:03Z","duration":"P1DT2H"}' + result = ip.as_json() + assert result == '{"start":"2024-09-24T01:02:03Z","duration":"P1DT2H"}' + def test_interval_periods_sub_second_precision_in_json() -> None: """Test that the IntervalPeriod model can handle sub-second precision.""" diff --git a/tests/test_json_encoder.py b/tests/test_json_encoder.py index 4be1af6..4b134fa 100644 --- a/tests/test_json_encoder.py +++ b/tests/test_json_encoder.py @@ -21,7 +21,7 @@ def test_json_encoder_report() -> None: data = create_report() report = Report.model_validate(data) - result = Report.model_dump(report, exclude_none=True, exclude_unset=True) + result = Report.as_dict(report) # for comparison, we expect datetime objects and not strings data["createdDateTime"] = from_iso(data["createdDateTime"]) @@ -38,7 +38,7 @@ def test_json_encoder_event() -> None: data = create_event() event = Event.model_validate(data) - result = Event.model_dump(event, exclude_none=True, exclude_unset=True) + result = Event.as_dict(event) # for comparison, we expect datetime objects and not strings data["createdDateTime"] = from_iso(data["createdDateTime"]) @@ -63,7 +63,7 @@ def test_json_encode_as_expected(model_class: type[BaseModel], model_data: dict[ # 1. we expect only default values to be part of the final JSON # 2. we expect the 'objectType' field to be included in the final JSON instance = model_class.model_validate(model_data) - result = model_class.model_dump(instance, exclude_none=True, exclude_unset=True) + result = model_class.as_dict(instance) # type: ignore[attr-defined] assert "objectType" not in model_data assert "objectType" in result diff --git a/toadr3/exceptions.py b/toadr3/exceptions.py index 0aaf5b2..9ef247b 100644 --- a/toadr3/exceptions.py +++ b/toadr3/exceptions.py @@ -95,5 +95,5 @@ def from_problem(cls, problem: Problem, status_code: int | None = None) -> "Toad return ToadrError( message=message, status_code=status_code, - json_response=problem.model_dump(), + json_response=problem.as_dict(), ) diff --git a/toadr3/models/docstringbasemodel.py b/toadr3/models/docstringbasemodel.py index 83b7165..0a9c6c6 100644 --- a/toadr3/models/docstringbasemodel.py +++ b/toadr3/models/docstringbasemodel.py @@ -27,3 +27,11 @@ def model_post_init(self, _context: Any, /) -> None: # noqa: ANN401 def __str__(self) -> str: """Return a string representation of the object.""" return f"{self.__class__.__name__}({super().__str__()})" + + def as_dict(self) -> dict[str, Any]: + """Return the model as a dictionary.""" + return self.model_dump(exclude_unset=True, exclude_none=True) + + def as_json(self) -> str: + """Return the model as a JSON string.""" + return self.model_dump_json(exclude_unset=True, exclude_none=True) diff --git a/toadr3/programs.py b/toadr3/programs.py index 29d9972..0d301eb 100644 --- a/toadr3/programs.py +++ b/toadr3/programs.py @@ -230,7 +230,7 @@ async def put_program_by_id( if program is None: raise ValueError("program is required") - data = program.model_dump_json(exclude_none=True, exclude_unset=True) + data = program.as_json() if custom_headers is None: custom_headers = {} diff --git a/toadr3/reports.py b/toadr3/reports.py index 5b3a8cc..08c830a 100644 --- a/toadr3/reports.py +++ b/toadr3/reports.py @@ -64,7 +64,7 @@ async def post_report( vtn_url = vtn_url.rstrip("/") - data = report.model_dump_json(exclude_none=True, exclude_unset=True) + data = report.as_json() headers["Content-Type"] = "application/json" async with session.post(f"{vtn_url}/reports", headers=headers, data=data) as response: diff --git a/toadr3/subscriptions.py b/toadr3/subscriptions.py index aa77317..3fc6b82 100644 --- a/toadr3/subscriptions.py +++ b/toadr3/subscriptions.py @@ -157,7 +157,7 @@ async def post_subscription( vtn_url = vtn_url.rstrip("/") - data = subscription.model_dump_json(exclude_none=True, exclude_unset=True) + data = subscription.as_json() headers["Content-Type"] = "application/json" async with session.post(f"{vtn_url}/subscriptions", headers=headers, data=data) as response: @@ -314,7 +314,7 @@ async def put_subscription_by_id( if subscription is None: raise ValueError("subscription is required") - data = subscription.model_dump_json(exclude_none=True, exclude_unset=True) + data = subscription.as_json() if custom_headers is None: custom_headers = {}