From 869e0410c6b4bc69eea31002078782ef7817fd31 Mon Sep 17 00:00:00 2001 From: William Fawcett Date: Thu, 30 Apr 2026 09:40:00 +0100 Subject: [PATCH 1/2] docs: add CI, Python, and license badges to README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 193f67e..2799742 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # eve-api +[![CI](https://github.com/FrontierDevelopmentLab/eve-api/actions/workflows/main.yml/badge.svg)](https://github.com/FrontierDevelopmentLab/eve-api/actions/workflows/main.yml) +[![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue)](https://github.com/FrontierDevelopmentLab/eve-api) +[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE) + Minimal authenticated HTTP client for the EVE (Earth Virtual Expert) API. Provides login, automatic JWT token refresh, and generic HTTP methods that return plain dicts. No domain-specific wrappers or Pydantic models. From ead0fa27d52a085258b6923414ee3fa38c101a5f Mon Sep 17 00:00:00 2001 From: William Fawcett Date: Thu, 30 Apr 2026 09:40:05 +0100 Subject: [PATCH 2/2] fix: preserve server detail message in NotFoundError NotFoundError previously required (resource, resource_id) and the 404 branch in _handle_error passed hardcoded ("resource", "unknown"), discarding the parsed `detail` from the response body. Switch the constructor to accept a message + details (matching the other APIError subclasses) and forward the parsed message through. --- src/eve_api/client.py | 2 +- src/eve_api/exceptions.py | 15 ++++++++++----- tests/test_client.py | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/eve_api/client.py b/src/eve_api/client.py index 56cccbb..99bff05 100644 --- a/src/eve_api/client.py +++ b/src/eve_api/client.py @@ -356,7 +356,7 @@ def _handle_error(response: httpx.Response) -> None: message = response.text or f"HTTP {status}" if status == HTTPStatus.NOT_FOUND: - raise NotFoundError("resource", "unknown") + raise NotFoundError(message) if status == HTTPStatus.FORBIDDEN: raise ForbiddenError(message) if status == HTTPStatus.BAD_REQUEST: diff --git a/src/eve_api/exceptions.py b/src/eve_api/exceptions.py index 94af460..78cc0b3 100644 --- a/src/eve_api/exceptions.py +++ b/src/eve_api/exceptions.py @@ -58,17 +58,22 @@ def __init__( class NotFoundError(APIError): """Raised when a requested resource is not found (404).""" - def __init__(self, resource: str, resource_id: str) -> None: + def __init__( + self, + message: str = "Resource not found", + details: dict[str, Any] | None = None, + ) -> None: """Initialise the not found error. Args: - resource: Type of resource (e.g., 'conversation', 'document'). - resource_id: ID of the resource that was not found. + message: Human-readable error message (typically the server's + ``detail`` field). + details: Additional error details from the response body. """ super().__init__( - f"{resource.title()} not found: {resource_id}", + message, status_code=HTTPStatus.NOT_FOUND, - details={"resource": resource, "id": resource_id}, + details=details, ) diff --git a/tests/test_client.py b/tests/test_client.py index c39570f..32dad99 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -236,7 +236,7 @@ async def test_404_raises_not_found(mock_api, authenticated_client: EVEClient): ) ) - with pytest.raises(NotFoundError) as exc_info: + with pytest.raises(NotFoundError, match="Not found") as exc_info: await authenticated_client.get("/conversations/missing") assert exc_info.value.status_code == HTTPStatus.NOT_FOUND