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.
- usaspending/__init__.py +144 -0
- usaspending/cli/__init__.py +2 -0
- usaspending/cli/download_award.py +113 -0
- usaspending/client.py +550 -0
- usaspending/config.py +119 -0
- usaspending/download/__init__.py +8 -0
- usaspending/download/job.py +219 -0
- usaspending/download/manager.py +140 -0
- usaspending/exceptions.py +71 -0
- usaspending/logging_config.py +310 -0
- usaspending/models/__init__.py +86 -0
- usaspending/models/agency.py +631 -0
- usaspending/models/award.py +933 -0
- usaspending/models/award_factory.py +72 -0
- usaspending/models/award_types.py +114 -0
- usaspending/models/base_model.py +214 -0
- usaspending/models/contract.py +147 -0
- usaspending/models/district_spending.py +70 -0
- usaspending/models/download.py +74 -0
- usaspending/models/funding.py +182 -0
- usaspending/models/grant.py +147 -0
- usaspending/models/idv.py +165 -0
- usaspending/models/lazy_record.py +82 -0
- usaspending/models/loan.py +85 -0
- usaspending/models/location.py +125 -0
- usaspending/models/period_of_performance.py +43 -0
- usaspending/models/recipient.py +204 -0
- usaspending/models/recipient_business_categories.py +364 -0
- usaspending/models/recipient_spending.py +58 -0
- usaspending/models/spending.py +70 -0
- usaspending/models/state_spending.py +43 -0
- usaspending/models/subaward.py +270 -0
- usaspending/models/subtier_agency.py +98 -0
- usaspending/models/transaction.py +89 -0
- usaspending/queries/__init__.py +87 -0
- usaspending/queries/agencies_search.py +196 -0
- usaspending/queries/agency_award_summary.py +134 -0
- usaspending/queries/agency_query.py +102 -0
- usaspending/queries/award_query.py +40 -0
- usaspending/queries/awarding_agencies_search.py +16 -0
- usaspending/queries/awards_search.py +602 -0
- usaspending/queries/filters.py +437 -0
- usaspending/queries/funding_agencies_search.py +20 -0
- usaspending/queries/funding_search.py +180 -0
- usaspending/queries/query_builder.py +1430 -0
- usaspending/queries/recipient_query.py +66 -0
- usaspending/queries/recipients_search.py +167 -0
- usaspending/queries/single_resource_base.py +83 -0
- usaspending/queries/spending_search.py +261 -0
- usaspending/queries/sub_agency_query.py +177 -0
- usaspending/queries/subawards_search.py +196 -0
- usaspending/queries/transactions_search.py +213 -0
- usaspending/resources/__init__.py +17 -0
- usaspending/resources/agency_resource.py +105 -0
- usaspending/resources/award_resource.py +119 -0
- usaspending/resources/base_resource.py +31 -0
- usaspending/resources/download_resource.py +102 -0
- usaspending/resources/funding_resource.py +41 -0
- usaspending/resources/recipients_resource.py +104 -0
- usaspending/resources/spending_resource.py +45 -0
- usaspending/resources/subawards_resource.py +68 -0
- usaspending/resources/transactions_resource.py +39 -0
- usaspending/utils/__init__.py +6 -0
- usaspending/utils/formatter.py +550 -0
- usaspending/utils/rate_limit.py +135 -0
- usaspending/utils/retry.py +257 -0
- usaspending/utils/special_cases.yaml +155 -0
- usaspending_orm-0.6.0.dist-info/LICENSE +18 -0
- usaspending_orm-0.6.0.dist-info/METADATA +324 -0
- usaspending_orm-0.6.0.dist-info/RECORD +71 -0
- usaspending_orm-0.6.0.dist-info/WHEEL +4 -0
usaspending/__init__.py
ADDED
|
@@ -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,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()
|