usaspending-orm 0.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. usaspending/__init__.py +144 -0
  2. usaspending/cli/__init__.py +2 -0
  3. usaspending/cli/download_award.py +113 -0
  4. usaspending/client.py +550 -0
  5. usaspending/config.py +119 -0
  6. usaspending/download/__init__.py +8 -0
  7. usaspending/download/job.py +219 -0
  8. usaspending/download/manager.py +140 -0
  9. usaspending/exceptions.py +71 -0
  10. usaspending/logging_config.py +310 -0
  11. usaspending/models/__init__.py +86 -0
  12. usaspending/models/agency.py +631 -0
  13. usaspending/models/award.py +933 -0
  14. usaspending/models/award_factory.py +72 -0
  15. usaspending/models/award_types.py +114 -0
  16. usaspending/models/base_model.py +214 -0
  17. usaspending/models/contract.py +147 -0
  18. usaspending/models/district_spending.py +70 -0
  19. usaspending/models/download.py +74 -0
  20. usaspending/models/funding.py +182 -0
  21. usaspending/models/grant.py +147 -0
  22. usaspending/models/idv.py +165 -0
  23. usaspending/models/lazy_record.py +82 -0
  24. usaspending/models/loan.py +85 -0
  25. usaspending/models/location.py +125 -0
  26. usaspending/models/period_of_performance.py +43 -0
  27. usaspending/models/recipient.py +204 -0
  28. usaspending/models/recipient_business_categories.py +364 -0
  29. usaspending/models/recipient_spending.py +58 -0
  30. usaspending/models/spending.py +70 -0
  31. usaspending/models/state_spending.py +43 -0
  32. usaspending/models/subaward.py +270 -0
  33. usaspending/models/subtier_agency.py +98 -0
  34. usaspending/models/transaction.py +89 -0
  35. usaspending/queries/__init__.py +87 -0
  36. usaspending/queries/agencies_search.py +196 -0
  37. usaspending/queries/agency_award_summary.py +134 -0
  38. usaspending/queries/agency_query.py +102 -0
  39. usaspending/queries/award_query.py +40 -0
  40. usaspending/queries/awarding_agencies_search.py +16 -0
  41. usaspending/queries/awards_search.py +602 -0
  42. usaspending/queries/filters.py +437 -0
  43. usaspending/queries/funding_agencies_search.py +20 -0
  44. usaspending/queries/funding_search.py +180 -0
  45. usaspending/queries/query_builder.py +1430 -0
  46. usaspending/queries/recipient_query.py +66 -0
  47. usaspending/queries/recipients_search.py +167 -0
  48. usaspending/queries/single_resource_base.py +83 -0
  49. usaspending/queries/spending_search.py +261 -0
  50. usaspending/queries/sub_agency_query.py +177 -0
  51. usaspending/queries/subawards_search.py +196 -0
  52. usaspending/queries/transactions_search.py +213 -0
  53. usaspending/resources/__init__.py +17 -0
  54. usaspending/resources/agency_resource.py +105 -0
  55. usaspending/resources/award_resource.py +119 -0
  56. usaspending/resources/base_resource.py +31 -0
  57. usaspending/resources/download_resource.py +102 -0
  58. usaspending/resources/funding_resource.py +41 -0
  59. usaspending/resources/recipients_resource.py +104 -0
  60. usaspending/resources/spending_resource.py +45 -0
  61. usaspending/resources/subawards_resource.py +68 -0
  62. usaspending/resources/transactions_resource.py +39 -0
  63. usaspending/utils/__init__.py +6 -0
  64. usaspending/utils/formatter.py +550 -0
  65. usaspending/utils/rate_limit.py +135 -0
  66. usaspending/utils/retry.py +257 -0
  67. usaspending/utils/special_cases.yaml +155 -0
  68. usaspending_orm-0.6.0.dist-info/LICENSE +18 -0
  69. usaspending_orm-0.6.0.dist-info/METADATA +324 -0
  70. usaspending_orm-0.6.0.dist-info/RECORD +71 -0
  71. usaspending_orm-0.6.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,144 @@
1
+ """USASpending Python Wrapper - Simplified access to federal award data.
2
+
3
+ An opinionated Python client for the USAspending.gov API that simplifies
4
+ access to federal spending data through intuitive interfaces and smart defaults.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ # Version information
10
+ try:
11
+ from importlib.metadata import version
12
+
13
+ __version__ = version("usaspending")
14
+ except ImportError:
15
+ # Fallback for development/editable installs
16
+ __version__ = "2"
17
+
18
+ __author__ = "Casey Dreier"
19
+ __email__ = "casey.dreier@planetary.org"
20
+
21
+ # Core client and configuration
22
+ from .client import USASpendingClient
23
+ from .config import config
24
+
25
+ # Exception classes for error handling
26
+ from .exceptions import (
27
+ USASpendingError,
28
+ APIError,
29
+ HTTPError,
30
+ RateLimitError,
31
+ ValidationError,
32
+ ConfigurationError,
33
+ DownloadError,
34
+ )
35
+
36
+ # Model classes
37
+ from .models import (
38
+ Award,
39
+ Contract,
40
+ Grant,
41
+ IDV,
42
+ Loan,
43
+ Transaction,
44
+ Recipient,
45
+ Agency,
46
+ SubTierAgency,
47
+ Location,
48
+ PeriodOfPerformance,
49
+ SubAward,
50
+ Funding,
51
+ Spending,
52
+ RecipientSpending,
53
+ DistrictSpending,
54
+ StateSpending,
55
+ )
56
+
57
+ # Query builder classes
58
+ from .queries import (
59
+ AwardsSearch,
60
+ AgenciesSearch,
61
+ FundingAgenciesSearch,
62
+ AwardingAgenciesSearch,
63
+ RecipientsSearch,
64
+ TransactionsSearch,
65
+ SpendingSearch,
66
+ FundingSearch,
67
+ SubAwardsSearch,
68
+ )
69
+
70
+ # Filter classes for building queries
71
+ from .queries.filters import (
72
+ AgencyType,
73
+ AgencyTier,
74
+ LocationScope,
75
+ AwardDateType,
76
+ LocationSpec,
77
+ AgencyFilter,
78
+ AwardAmountFilter,
79
+ KeywordsFilter,
80
+ LocationFilter,
81
+ LocationScopeFilter,
82
+ TimePeriodFilter,
83
+ TreasuryAccountComponentsFilter,
84
+ )
85
+
86
+ # Public API exports
87
+ __all__ = [
88
+ # Version info
89
+ "__version__",
90
+ "__author__",
91
+ "__email__",
92
+ # Core
93
+ "USASpendingClient",
94
+ "config",
95
+ # Exceptions
96
+ "USASpendingError",
97
+ "APIError",
98
+ "HTTPError",
99
+ "RateLimitError",
100
+ "ValidationError",
101
+ "ConfigurationError",
102
+ "DownloadError",
103
+ # Models
104
+ "Award",
105
+ "Contract",
106
+ "Grant",
107
+ "IDV",
108
+ "Loan",
109
+ "Transaction",
110
+ "Recipient",
111
+ "Agency",
112
+ "SubTierAgency",
113
+ "Location",
114
+ "PeriodOfPerformance",
115
+ "SubAward",
116
+ "Funding",
117
+ "Spending",
118
+ "RecipientSpending",
119
+ "DistrictSpending",
120
+ "StateSpending",
121
+ # Query builders
122
+ "AwardsSearch",
123
+ "AgenciesSearch",
124
+ "FundingAgenciesSearch",
125
+ "AwardingAgenciesSearch",
126
+ "RecipientsSearch",
127
+ "TransactionsSearch",
128
+ "SpendingSearch",
129
+ "FundingSearch",
130
+ "SubAwardsSearch",
131
+ # Filters
132
+ "AgencyType",
133
+ "AgencyTier",
134
+ "LocationScope",
135
+ "AwardDateType",
136
+ "LocationSpec",
137
+ "AgencyFilter",
138
+ "AwardAmountFilter",
139
+ "KeywordsFilter",
140
+ "LocationFilter",
141
+ "LocationScopeFilter",
142
+ "TimePeriodFilter",
143
+ "TreasuryAccountComponentsFilter",
144
+ ]
@@ -0,0 +1,2 @@
1
+ # src/usaspending/cli/__init__.py
2
+ """Command Line Interface tools for USASpending API client."""
@@ -0,0 +1,113 @@
1
+ # src/usaspending/cli/download_award.py
2
+
3
+ import argparse
4
+ import sys
5
+ import os
6
+ from typing import List
7
+
8
+ # Helper to ensure the package root is in sys.path if running the script directly during development
9
+ if __name__ == "__main__":
10
+ # Adjust path relative to the script location (src/usaspending/cli)
11
+ project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
12
+ if project_root not in sys.path:
13
+ sys.path.insert(0, project_root)
14
+
15
+ # Import necessary components from the library
16
+ from usaspending.exceptions import DownloadError
17
+ from usaspending import USASpendingClient
18
+
19
+
20
+ def main():
21
+ parser = argparse.ArgumentParser(
22
+ description="Download detailed award data from USASpending.gov.",
23
+ epilog="This CLI tool queues a download job, waits for completion, downloads the zip file, and extracts the contents.",
24
+ )
25
+
26
+ parser.add_argument(
27
+ "award_id", help="The unique award identifier (e.g., PIIN/FAIN/etc.)"
28
+ )
29
+ parser.add_argument(
30
+ "-o",
31
+ "--output-dir",
32
+ help="The directory to save and extract the files (defaults to current directory).",
33
+ )
34
+ parser.add_argument(
35
+ "-f",
36
+ "--format",
37
+ choices=["csv", "tsv", "pstxt"],
38
+ default="csv",
39
+ help="The format of the files (default: csv).",
40
+ )
41
+ parser.add_argument(
42
+ "--timeout",
43
+ type=int,
44
+ default=1800,
45
+ help="Maximum time in seconds to wait (default: 1800s/30min).",
46
+ )
47
+ parser.add_argument(
48
+ "--poll-interval",
49
+ type=int,
50
+ default=30,
51
+ help="Interval in seconds between status checks (default: 30s).",
52
+ )
53
+ parser.add_argument(
54
+ "--no-cleanup", action="store_true", help="Keep the zip file after extraction."
55
+ )
56
+ parser.add_argument(
57
+ "-v", "--verbose", action="store_true", help="Enable verbose debug logging."
58
+ )
59
+
60
+ args = parser.parse_args()
61
+
62
+ # Configure logging (CLI scripts can configure logging since they are applications)
63
+ import logging
64
+
65
+ log_level = logging.DEBUG if args.verbose else logging.INFO
66
+ logging.basicConfig(
67
+ level=log_level, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
68
+ )
69
+ logger = logging.getLogger("usaspending.cli.download")
70
+
71
+ try:
72
+ # Initialize client (assuming default configuration handling)
73
+ client = USASpendingClient()
74
+
75
+ # Get award data
76
+ award = client.awards.find_by_award_id(args.award_id)
77
+
78
+ logger.info("--- Starting USASpending Award Download CLI ---")
79
+ logger.info(
80
+ f"Parameters: Award ID={args.award_id}, Type={award.category}, Format={args.format}"
81
+ )
82
+
83
+ job = award.download(file_format=args.format, destination_dir=args.output_dir)
84
+
85
+ logger.info(f"Job successfully queued. Tracking File: {job.file_name}")
86
+
87
+ # 2. Wait for completion (blocking operation)
88
+ extracted_files: List[str] = job.wait_for_completion(
89
+ timeout=args.timeout,
90
+ poll_interval=args.poll_interval,
91
+ cleanup_zip=not args.no_cleanup,
92
+ )
93
+
94
+ logger.info("--- Download and Extraction Complete ---")
95
+ # Determine the final extraction path
96
+ extract_subdir_name = os.path.splitext(job.file_name)[0]
97
+ final_path = os.path.join(job.destination_dir, extract_subdir_name)
98
+ logger.info(f"Data extracted to: {os.path.abspath(final_path)}")
99
+ logger.info(f"Total files extracted: {len(extracted_files)}")
100
+
101
+ except DownloadError as e:
102
+ logger.error(f"Download failed. Status: {e.status}. Message: {e}")
103
+ sys.exit(1)
104
+ except KeyboardInterrupt:
105
+ logger.warning("Download interrupted by user.")
106
+ sys.exit(1)
107
+ except Exception as e:
108
+ logger.exception(f"An unexpected error occurred: {e}")
109
+ sys.exit(1)
110
+
111
+
112
+ if __name__ == "__main__":
113
+ main()