Coverage for src/usaspending/queries/agency_query.py: 100%
30 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
1"""Agency query implementation for retrieving single agency details."""
3from typing import TYPE_CHECKING, Optional, Dict, Any
4from .single_resource_base import SingleResourceBase
5from ..exceptions import ValidationError
6from ..client import USASpending
7from ..logging_config import USASpendingLogger
9if TYPE_CHECKING:
10 from ..models.agency import Agency
12logger = USASpendingLogger.get_logger(__name__)
15class AgencyQuery(SingleResourceBase):
16 """Retrieve a single agency from the USAspending API.
18 This query class handles fetching agency overview information for a
19 specific fiscal year using the agency's toptier code.
20 """
22 def __init__(self, client: USASpending):
23 """Initialize AgencyQuery with client.
25 Args:
26 client: USASpending client instance
27 """
28 super().__init__(client)
29 logger.debug("AgencyQuery initialized with client: %s", client)
31 @property
32 def _endpoint(self) -> str:
33 """Base endpoint for single agency retrieval."""
34 return "/agency/"
36 def find_by_id(self, toptier_code: str, fiscal_year: Optional[int] = None) -> "Agency":
37 """Retrieve agency by toptier code and optional fiscal year.
39 Args:
40 toptier_code: The toptier code of an agency (3-4 digit string)
41 fiscal_year: Optional fiscal year for the data (defaults to current)
43 Returns:
44 Agency model instance with full details
46 Raises:
47 ValidationError: If toptier_code is invalid
48 APIError: If agency not found
49 """
50 if not toptier_code:
51 raise ValidationError("toptier_code is required")
53 # Validate toptier_code format (3-4 digit numeric string)
54 toptier_code = str(toptier_code).strip()
55 if not toptier_code.isdigit() or len(toptier_code) not in [3, 4]:
56 raise ValidationError(
57 f"Invalid toptier_code: {toptier_code}. "
58 "Must be a 3-4 digit numeric string"
59 )
61 logger.debug(
62 "Fetching agency with toptier_code: %s, fiscal_year: %s",
63 toptier_code, fiscal_year
64 )
66 # Make API request with optional fiscal_year parameter
67 response = self._get_resource_with_params(toptier_code, fiscal_year)
69 # Create model instance
70 from ..models.agency import Agency
72 return Agency(response, client=self._client)
74 def _get_resource_with_params(
75 self, toptier_code: str, fiscal_year: Optional[int] = None
76 ) -> Dict[str, Any]:
77 """Retrieve agency with optional query parameters.
79 Args:
80 toptier_code: The agency's toptier code
81 fiscal_year: Optional fiscal year parameter
83 Returns:
84 API response dictionary
85 """
86 # Construct endpoint
87 endpoint = self._construct_endpoint(toptier_code)
89 # Build params dict if fiscal_year provided
90 params = {}
91 if fiscal_year is not None:
92 params["fiscal_year"] = fiscal_year
94 # Make API request with params
95 response = self._client._make_request(
96 "GET",
97 endpoint,
98 params=params if params else None
99 )
101 return response