From a0288e34b49cff769f8afe5dd3a6d0213f1afc4c Mon Sep 17 00:00:00 2001 From: Antoine SEIN <142824551+asein-sinch@users.noreply.github.com> Date: Thu, 6 Feb 2025 10:52:34 +0100 Subject: [PATCH] Improve error management --- .../available/activate_number_endpoint.py | 9 +++-- .../available/search_for_number_endpoint.py | 8 +++-- .../numbers/endpoints/numbers_endpoint.py | 3 +- sinch/domains/numbers/exceptions.py | 3 ++ sinch/domains/numbers/models/numbers.py | 2 +- .../numbers/features/steps/numbers.steps.py | 34 ++++++++++++------- 6 files changed, 38 insertions(+), 21 deletions(-) diff --git a/sinch/domains/numbers/endpoints/available/activate_number_endpoint.py b/sinch/domains/numbers/endpoints/available/activate_number_endpoint.py index 6201c5dc..7c164d9b 100644 --- a/sinch/domains/numbers/endpoints/available/activate_number_endpoint.py +++ b/sinch/domains/numbers/endpoints/available/activate_number_endpoint.py @@ -1,6 +1,7 @@ from sinch.core.enums import HTTPAuthentication, HTTPMethods from sinch.core.models.http_response import HTTPResponse from sinch.domains.numbers.endpoints.numbers_endpoint import NumbersEndpoint +from sinch.domains.numbers.exceptions import NumberNotFoundException, NumbersException from sinch.domains.numbers.models.available.activate_number_request import ActivateNumberRequest from sinch.domains.numbers.models.available.activate_number_response import ActivateNumberResponse @@ -18,7 +19,9 @@ def __init__(self, project_id: str, request_data: ActivateNumberRequest): self.request_data = request_data def handle_response(self, response: HTTPResponse) -> ActivateNumberResponse: - error = super(ActivateNumberEndpoint, self).handle_response(response) - if error: - return error + try: + super(ActivateNumberEndpoint, self).handle_response(response) + except NumbersException as ex: + raise NumberNotFoundException(message=ex.args[0], response=ex.http_response, + is_from_server=ex.is_from_server) return self.process_response_model(response.body, ActivateNumberResponse) diff --git a/sinch/domains/numbers/endpoints/available/search_for_number_endpoint.py b/sinch/domains/numbers/endpoints/available/search_for_number_endpoint.py index 936b8f47..a6eed13c 100644 --- a/sinch/domains/numbers/endpoints/available/search_for_number_endpoint.py +++ b/sinch/domains/numbers/endpoints/available/search_for_number_endpoint.py @@ -1,6 +1,7 @@ from sinch.core.models.http_response import HTTPResponse from sinch.domains.numbers.endpoints.numbers_endpoint import NumbersEndpoint from sinch.core.enums import HTTPAuthentication, HTTPMethods +from sinch.domains.numbers.exceptions import NumberNotFoundException, NumbersException from sinch.domains.numbers.models.available.check_number_availability_response import CheckNumberAvailabilityResponse from sinch.domains.numbers.models.available.check_number_availability_request import CheckNumberAvailabilityRequest @@ -30,7 +31,8 @@ def handle_response(self, response: HTTPResponse) -> CheckNumberAvailabilityResp CheckNumberAvailabilityResponse: The response model containing the parsed response data of the requested phone number. """ - error = super(SearchForNumberEndpoint, self).handle_response(response) - if error: - return error + try: + super(SearchForNumberEndpoint, self).handle_response(response) + except NumbersException as e: + raise NumberNotFoundException(message=e.args[0], response=e.http_response, is_from_server=e.is_from_server) return self.process_response_model(response.body, CheckNumberAvailabilityResponse) diff --git a/sinch/domains/numbers/endpoints/numbers_endpoint.py b/sinch/domains/numbers/endpoints/numbers_endpoint.py index 4e1349ef..6012959b 100644 --- a/sinch/domains/numbers/endpoints/numbers_endpoint.py +++ b/sinch/domains/numbers/endpoints/numbers_endpoint.py @@ -54,7 +54,8 @@ def process_response_model(self, response_body: dict, response_model: Type[BM]) def handle_response(self, response: HTTPResponse): if response.status_code == 404: - return NotFoundError(**response.body['error']) + error = NotFoundError(**response.body['error']) + raise NumbersException(message=error, response=response, is_from_server=True) if response.status_code >= 400: raise NumbersException( diff --git a/sinch/domains/numbers/exceptions.py b/sinch/domains/numbers/exceptions.py index bb94f383..12009692 100644 --- a/sinch/domains/numbers/exceptions.py +++ b/sinch/domains/numbers/exceptions.py @@ -3,3 +3,6 @@ class NumbersException(SinchException): pass + +class NumberNotFoundException(NumbersException): + pass \ No newline at end of file diff --git a/sinch/domains/numbers/models/numbers.py b/sinch/domains/numbers/models/numbers.py index d7e363f8..6c64b5a3 100644 --- a/sinch/domains/numbers/models/numbers.py +++ b/sinch/domains/numbers/models/numbers.py @@ -134,7 +134,7 @@ def to_snake(string: str) -> str: class NotFoundError(BaseModelConfigResponse): code: StrictInt message: StrictStr - status: Literal['NOT_FOUND'] + status: StrictStr details: list[dict] model_config = ConfigDict(populate_by_name=True, alias_generator=to_snake) diff --git a/tests/e2e/numbers/features/steps/numbers.steps.py b/tests/e2e/numbers/features/steps/numbers.steps.py index 804ca5b7..cc535c5e 100644 --- a/tests/e2e/numbers/features/steps/numbers.steps.py +++ b/tests/e2e/numbers/features/steps/numbers.steps.py @@ -2,6 +2,7 @@ from behave import given, when, then from decimal import Decimal from sinch import SinchClient +from sinch.domains.numbers.exceptions import NumberNotFoundException from sinch.domains.numbers.models.available.activate_number_response import ActivateNumberResponse from sinch.domains.numbers.models.available.rent_any_number_response import RentAnyNumberResponse from sinch.domains.numbers.models.numbers import NotFoundError @@ -47,8 +48,12 @@ def step_check_number_properties(context): @when('I send a request to check the availability of the phone number "{phone_number}"') def step_check_number_availability(context, phone_number): - response = context.sinch.numbers.available.check_availability(phone_number) - context.response = response + try: + response = context.sinch.numbers.available.check_availability(phone_number) + context.response = response + except NumberNotFoundException as e: + context.error = e + @then('the response displays the phone number "{phone_number}" details') def step_validate_number_details(context, phone_number): @@ -57,7 +62,7 @@ def step_validate_number_details(context, phone_number): @then('the response contains an error about the number "{phone_number}" not being available') def step_check_unavailable_number(context, phone_number): - data: NotFoundError = context.response + data: NotFoundError = context.error.args[0] assert data.code == 404 assert data.status == 'NOT_FOUND' assert data.details[0]['resource_name'] == phone_number @@ -138,16 +143,19 @@ def step_validate_rented_specific_number(context, phone_number): @when('I send a request to rent the unavailable phone number "{phone_number}"') def step_rent_unavailable_number(context, phone_number): sinch_client: SinchClient = context.sinch - response = sinch_client.numbers.available.activate( - phone_number=phone_number, - sms_configuration={ - 'service_plan_id': 'SpaceMonkeySquadron', - }, - voice_configuration={ - 'app_id': 'sunshine-rain-drop-very-beautifulday' - } - ) - context.response = response + try: + response = sinch_client.numbers.available.activate( + phone_number=phone_number, + sms_configuration={ + 'service_plan_id': 'SpaceMonkeySquadron', + }, + voice_configuration={ + 'app_id': 'sunshine-rain-drop-very-beautifulday' + } + ) + context.response = response + except NumberNotFoundException as e: + context.error = e @when("I send a request to list the phone numbers") def step_when_list_phone_numbers(context):