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

1"""Agency query implementation for retrieving single agency details.""" 

2 

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 

8 

9if TYPE_CHECKING: 

10 from ..models.agency import Agency 

11 

12logger = USASpendingLogger.get_logger(__name__) 

13 

14 

15class AgencyQuery(SingleResourceBase): 

16 """Retrieve a single agency from the USAspending API. 

17  

18 This query class handles fetching agency overview information for a  

19 specific fiscal year using the agency's toptier code. 

20 """ 

21 

22 def __init__(self, client: USASpending): 

23 """Initialize AgencyQuery with client. 

24  

25 Args: 

26 client: USASpending client instance 

27 """ 

28 super().__init__(client) 

29 logger.debug("AgencyQuery initialized with client: %s", client) 

30 

31 @property 

32 def _endpoint(self) -> str: 

33 """Base endpoint for single agency retrieval.""" 

34 return "/agency/" 

35 

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. 

38  

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) 

42  

43 Returns: 

44 Agency model instance with full details 

45  

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") 

52 

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 ) 

60 

61 logger.debug( 

62 "Fetching agency with toptier_code: %s, fiscal_year: %s", 

63 toptier_code, fiscal_year 

64 ) 

65 

66 # Make API request with optional fiscal_year parameter 

67 response = self._get_resource_with_params(toptier_code, fiscal_year) 

68 

69 # Create model instance 

70 from ..models.agency import Agency 

71 

72 return Agency(response, client=self._client) 

73 

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. 

78  

79 Args: 

80 toptier_code: The agency's toptier code 

81 fiscal_year: Optional fiscal year parameter 

82  

83 Returns: 

84 API response dictionary 

85 """ 

86 # Construct endpoint 

87 endpoint = self._construct_endpoint(toptier_code) 

88 

89 # Build params dict if fiscal_year provided 

90 params = {} 

91 if fiscal_year is not None: 

92 params["fiscal_year"] = fiscal_year 

93 

94 # Make API request with params 

95 response = self._client._make_request( 

96 "GET", 

97 endpoint, 

98 params=params if params else None 

99 ) 

100 

101 return response