Skip to content

Conversation

da1910
Copy link
Collaborator

@da1910 da1910 commented Apr 15, 2025

Closes #757

This PR adds deserialization for exceptions if models are defined in the type map. A new property exception_model will be present on an ApiException object which will be populated with the return type if it's defined.

I considered just returning the model without throwing, but that might be a surprising outcome for users, and would break the pattern of "everything was OK because I got a response and not an exception". This is an additive change to handle_response and to the exception type, existing users of that code should continue to see the same behaviour as before.

@github-actions github-actions bot added the enhancement New features or code improvements label Apr 15, 2025
Copy link

codecov bot commented Apr 15, 2025

Codecov Report

Attention: Patch coverage is 95.83333% with 1 line in your changes missing coverage. Please review.

Project coverage is 94.28%. Comparing base (3d4264f) to head (adc720f).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/ansys/openapi/common/_exceptions.py 83.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #778      +/-   ##
==========================================
- Coverage   94.40%   94.28%   -0.12%     
==========================================
  Files           7        7              
  Lines         804      805       +1     
==========================================
  Hits          759      759              
- Misses         45       46       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@Andy-Grigg Andy-Grigg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly minor changes, naming and re-ordering. Overall, this looks good, and should help consumers of packages that depend on this handle specific exceptions more flexibly.

Provides the exception to raise when the remote server returns an unsuccessful response.
For more information about the failure, inspect ``.status_code`` and ``.reason_phrase``.
For more information about the failure, inspect ``.status_code``, ``.reason_phrase``, and if the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
For more information about the failure, inspect ``.status_code``, ``.reason_phrase``, and if the
For more information about the failure, inspect ``.status_code`` and ``.reason_phrase``. If the

For more information about the failure, inspect ``.status_code`` and ``.reason_phrase``.
For more information about the failure, inspect ``.status_code``, ``.reason_phrase``, and if the
server defines a custom exception model, ``.exception_model``.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
server defines a custom exception model, ``.exception_model``.
server defines a custom exception model, ``.exception_model`` contains the deserialized response.

def handle_response(response: requests.Response) -> requests.Response:
def handle_response(
response: requests.Response, response_model: DeserializedType = None
) -> requests.Response:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is kind of weird. It no longer needs to return anything, so really all it's doing is encapsulating the "if not 2xx then raise" logic.

Maybe we just delete the function and include the if-check in __call_api?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about that, but it's not a private function, so there's a low but non-zero chance someone is relying on it.

If we think that risk is low enough then yes it can be removed and replaced with a check in the one place it's used

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so. As you say, it's not a private function, but it's also not documented. For me this falls into a grey area, and I'm happy to take the chance that either no one's using it, or if they are, they can easily work around this change.

_response_type = response_type_map.get(response_data.status_code, None)

return_data = self.deserialize(response_data, _response_type)
deserialized_response = return_data
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is all a bit weird. We define a variable called return_data, which is a union of both the request response type and our deserialized type, and initially contains the raw request response.

We then maybe overwrite that with the deserialized response, and then write that to a different variable deserialized_response.

I realize that return_data needs to be the union of the types eventually, but it might be cleaner if that union happens closer to the end of the function.

assert headers["Content-Type"] == "text/plain"

def test_get_model_returns_defined_exception(self):
"""This test getting an object from a server which returns a defined exception object when the requested id does
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""This test getting an object from a server which returns a defined exception object when the requested id does
"""This test gets an object from a server which returns a defined exception object when the requested id does

assert exception_model.stack_trace == stack_trace

def test_get_model_throws_if_no_defined_exception_type(self):
"""This test getting an object from a server which returns a defined exception object when the requested id does
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""This test getting an object from a server which returns a defined exception object when the requested id does
"""This test gets an object from a server which returns a defined exception object when the requested id does

assert "Content-Type" in headers
assert headers["Content-Type"] == "text/plain"

def test_get_model_returns_defined_exception(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def test_get_model_returns_defined_exception(self):
def test_get_model_raises_exception_with_deserialized_response(self):

assert exception_model.exception_code == exception_code
assert exception_model.stack_trace == stack_trace

def test_get_model_throws_if_no_defined_exception_type(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def test_get_model_throws_if_no_defined_exception_type(self):
def test_get_model_raises_exception_with_no_deserialized_response(self):

@da1910 da1910 force-pushed the feat/deserialize_exception_models branch from 132db2c to da24ed9 Compare April 22, 2025 09:54
@da1910 da1910 added this pull request to the merge queue Apr 22, 2025
Merged via the queue into main with commit 2d82e92 Apr 22, 2025
31 of 32 checks passed
@da1910 da1910 deleted the feat/deserialize_exception_models branch April 22, 2025 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New features or code improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deserialize exception responses

4 participants