Coverage for src/usaspending/queries/single_resource_base.py: 90%
29 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-03 17:15 -0700
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-03 17:15 -0700
1from ..exceptions import ValidationError
2from ..client import USASpending
3from typing import Any
4from abc import ABC, abstractmethod
5from ..logging_config import USASpendingLogger
7logger = USASpendingLogger.get_logger(__name__)
10class SingleResourceBase(ABC):
11 """
12 Base class for retrieving single resources like awards or recipients,
13 anything with a simple GET request, generally.
14 """
16 def __init__(self, client: USASpending):
17 self._client = client
19 @property
20 @abstractmethod
21 def _endpoint(self) -> str:
22 """Base endpoint for single resource retrieval."""
23 pass
25 @abstractmethod
26 def find_by_id(self, resource_id: str) -> Any:
27 """Filter by unique resource identifier."""
28 pass
30 def _get_resource(self, resource_id: str) -> dict:
31 """Retrieve a single resource by ID."""
32 if not resource_id or not isinstance(resource_id, str) or not resource_id.strip():
33 raise ValidationError("A non-empty resource_id string is required")
35 # Clean recipient ID
36 cleaned_resource_id = self._clean_resource_id(resource_id)
38 if not cleaned_resource_id:
39 raise ValidationError(
40 "No resource id found after cleaning. Original: %s. Cleaned: %s",
41 resource_id,
42 cleaned_resource_id,
43 )
45 # Construct valid endpoint
46 endpoint = self._construct_endpoint(cleaned_resource_id)
48 # Make API request
49 response = self._client._make_request("GET", endpoint)
51 return response
53 def _construct_endpoint(self, resource_id: str) -> str:
54 """Construct the full endpoint URL for a specific resource ID."""
55 return f"{self._endpoint}{resource_id}/"
57 def _clean_resource_id(self, resource_id: str) -> str:
58 """Very basic resource ID cleaning.
60 More complex logic is implemented in specific resource classes.
62 Args:
63 resource_id: The raw resource ID string
65 Returns:
66 Cleaned resource ID string
67 """
68 return str(resource_id).strip()