usaspending-orm 0.8.0__tar.gz → 0.9.1__tar.gz
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_orm-0.8.0 → usaspending_orm-0.9.1}/.gitignore +1 -0
- usaspending_orm-0.9.1/.readthedocs.yaml +17 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/CHANGELOG.md +137 -7
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/LICENSE +1 -1
- usaspending_orm-0.9.1/PKG-INFO +153 -0
- usaspending_orm-0.9.1/README.md +124 -0
- usaspending_orm-0.9.1/docs/explanation/caching.md +115 -0
- usaspending_orm-0.9.1/docs/explanation/data-model.md +52 -0
- usaspending_orm-0.9.1/docs/explanation/query-execution.md +68 -0
- usaspending_orm-0.9.1/docs/getting-started/core-concepts.md +77 -0
- usaspending_orm-0.9.1/docs/getting-started/installation.md +47 -0
- usaspending_orm-0.9.1/docs/getting-started/quickstart.md +81 -0
- usaspending_orm-0.9.1/docs/guides/production.md +106 -0
- usaspending_orm-0.9.1/docs/guides/related-data.md +61 -0
- usaspending_orm-0.9.1/docs/guides/search-awards.md +166 -0
- usaspending_orm-0.9.1/docs/guides/search-transactions.md +71 -0
- usaspending_orm-0.9.1/docs/guides/spending-and-downloads.md +119 -0
- usaspending_orm-0.9.1/docs/index.md +56 -0
- usaspending_orm-0.9.1/docs/reference/client.md +41 -0
- usaspending_orm-0.9.1/docs/reference/configuration.md +60 -0
- usaspending_orm-0.9.1/docs/reference/models.md +48 -0
- usaspending_orm-0.9.1/docs/reference/queries.md +55 -0
- usaspending_orm-0.9.1/docs/usaspending-api/endpoint-mapping.md +54 -0
- usaspending_orm-0.9.1/docs/usaspending-api/limitations.md +59 -0
- usaspending_orm-0.9.1/docs/usaspending-api/terminology.md +55 -0
- usaspending_orm-0.9.1/mkdocs.yml +109 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/pyproject.toml +11 -2
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/__init__.py +2 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/client.py +17 -1
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/download/job.py +11 -3
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/__init__.py +2 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/agency.py +2 -39
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/award.py +5 -5
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/award_types.py +24 -1
- usaspending_orm-0.9.1/src/usaspending/models/def_code.py +36 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/download.py +6 -2
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/loan.py +3 -3
- usaspending_orm-0.9.1/src/usaspending/models/transaction.py +582 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/__init__.py +2 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/agencies_search.py +26 -7
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/agency_award_summary.py +5 -4
- usaspending_orm-0.8.0/src/usaspending/queries/transactions_search.py → usaspending_orm-0.9.1/src/usaspending/queries/award_transactions_search.py +24 -12
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/awards_search.py +8 -32
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/base_query.py +12 -1
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/client_side_query_builder.py +2 -18
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/filters.py +86 -11
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/mixins.py +32 -1
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/query_builder.py +162 -56
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/sub_agency_query.py +5 -1
- usaspending_orm-0.9.1/src/usaspending/queries/transactions_search.py +239 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/__init__.py +2 -0
- usaspending_orm-0.9.1/src/usaspending/resources/references_resource.py +21 -0
- usaspending_orm-0.9.1/src/usaspending/resources/transactions_resource.py +63 -0
- usaspending_orm-0.9.1/src/usaspending/utils/payloads.py +34 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/conftest.py +31 -31
- usaspending_orm-0.9.1/tests/fixtures/def_codes.json +29 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/public_api_surface.json +97 -5
- usaspending_orm-0.9.1/tests/fixtures/spending_by_transaction.json +214 -0
- usaspending_orm-0.9.1/tests/fixtures/spending_by_transaction_count.json +10 -0
- usaspending_orm-0.9.1/tests/fixtures/spending_by_transaction_mixed.json +210 -0
- usaspending_orm-0.9.1/tests/markdown_examples.py +86 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/mocks/README.md +3 -3
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/mocks/mock_client.py +3 -1
- usaspending_orm-0.8.0/tests/volatile_fields.py → usaspending_orm-0.9.1/tests/model_contracts.py +122 -65
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_category_registry.py +6 -4
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_common.py +1 -5
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_types.py +9 -0
- usaspending_orm-0.9.1/tests/models/test_def_code.py +52 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_lazy_load.py +19 -15
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_location.py +114 -57
- usaspending_orm-0.9.1/tests/models/test_model_field_contracts.py +159 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_recipient.py +25 -50
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_recipient_spending.py +28 -38
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_search_projection.py +47 -32
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_subaward.py +2 -9
- usaspending_orm-0.9.1/tests/models/test_transaction.py +300 -0
- usaspending_orm-0.9.1/tests/models/test_transaction_search_projection.py +456 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_agencies_search.py +123 -1
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_agency_award_summary.py +6 -4
- usaspending_orm-0.8.0/tests/queries/test_transactions_search.py → usaspending_orm-0.9.1/tests/queries/test_award_transactions_search.py +54 -37
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_count_respects_limits.py +5 -5
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_filters.py +87 -2
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_search_query_builder.py +111 -2
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_subawards_search.py +2 -9
- usaspending_orm-0.9.1/tests/queries/test_transactions_search.py +504 -0
- usaspending_orm-0.9.1/tests/resources/test_references_resource.py +92 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_transactions_resource.py +22 -3
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/snapshot_support.py +4 -6
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_client.py +0 -7
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_client_transactions.py +1 -1
- usaspending_orm-0.9.1/tests/test_documentation.py +246 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_download_resource.py +57 -4
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_integration.py +59 -5
- usaspending_orm-0.9.1/tests/test_live_contract_integration.py +286 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_readme_examples.py +11 -18
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/uv.lock +383 -1
- usaspending_orm-0.8.0/PKG-INFO +0 -519
- usaspending_orm-0.8.0/README.md +0 -490
- usaspending_orm-0.8.0/api-docs-links.md +0 -258
- usaspending_orm-0.8.0/src/usaspending/models/transaction.py +0 -150
- usaspending_orm-0.8.0/src/usaspending/resources/transactions_resource.py +0 -39
- usaspending_orm-0.8.0/tests/fixtures/golden/agency.json +0 -74
- usaspending_orm-0.8.0/tests/fixtures/golden/award_account_first_result.json +0 -29
- usaspending_orm-0.8.0/tests/fixtures/golden/award_contract.json +0 -190
- usaspending_orm-0.8.0/tests/fixtures/golden/award_contract_awarding_agency.json +0 -74
- usaspending_orm-0.8.0/tests/fixtures/golden/award_contract_period_of_performance.json +0 -15
- usaspending_orm-0.8.0/tests/fixtures/golden/award_contract_place_of_performance.json +0 -23
- usaspending_orm-0.8.0/tests/fixtures/golden/award_contract_recipient.json +0 -51
- usaspending_orm-0.8.0/tests/fixtures/golden/award_grant.json +0 -198
- usaspending_orm-0.8.0/tests/fixtures/golden/award_idv.json +0 -190
- usaspending_orm-0.8.0/tests/fixtures/golden/award_loan.json +0 -191
- usaspending_orm-0.8.0/tests/fixtures/golden/award_parent_of_contract.json +0 -136
- usaspending_orm-0.8.0/tests/fixtures/golden/funding_first_result.json +0 -35
- usaspending_orm-0.8.0/tests/fixtures/golden/idv_child_award_first_result.json +0 -192
- usaspending_orm-0.8.0/tests/fixtures/golden/recipient.json +0 -60
- usaspending_orm-0.8.0/tests/fixtures/golden/search_contract_first_result.json +0 -190
- usaspending_orm-0.8.0/tests/fixtures/golden/search_subaward_first_result.json +0 -91
- usaspending_orm-0.8.0/tests/fixtures/golden/spending_by_recipient_first_result.json +0 -68
- usaspending_orm-0.8.0/tests/fixtures/golden/spending_by_state_first_result.json +0 -17
- usaspending_orm-0.8.0/tests/fixtures/golden/transaction_first_result.json +0 -18
- usaspending_orm-0.8.0/tests/models/test_transaction.py +0 -249
- usaspending_orm-0.8.0/tests/models/test_volatile_field_mapping.py +0 -177
- usaspending_orm-0.8.0/tests/test_golden_master_integration.py +0 -707
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/cli/__init__.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/cli/download_award.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/config.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/download/__init__.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/download/manager.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/exceptions.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/logging_config.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/award_account.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/award_factory.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/award_identifier.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/base_model.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/contract.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/district_spending.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/federal_account.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/funding.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/grant.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/idv.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/lazy_record.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/location.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/period_of_performance.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/procurement_award.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/recipient.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/recipient_business_categories.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/recipient_spending.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/spending.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/state_spending.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/subaward.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/subtier_agency.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/treasury_account_symbol.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/agency_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/award_accounts_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/award_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/awarding_agencies_search.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/federal_accounts_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/filter_tree_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/funding_agencies_search.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/funding_search.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/idv_child_awards.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/recipient_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/recipients_search.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/single_resource_base.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/spending_search.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/subawards_search.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/tas_agencies_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/tas_codes_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/agency_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/award_accounts_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/award_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/base_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/download_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/funding_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/recipients_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/spending_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/subawards_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/tas_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/__init__.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/dates.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/numbers.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/rate_limit.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/retry.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/special_cases.yaml +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/textcase.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/validations.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/__init__.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/agency.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/agency_autocomplete.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/agency_award_summary.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/agency_subagencies.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/accounts.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/award_funding_grant.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/contract.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/grant.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/idv.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/idv_awards.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/loan.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/search_results_contracts.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/search_results_grants.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/search_results_idvs.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/search_results_subawards.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/transactions.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/download_assistance.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/download_search.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/download_status.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/recipient_university.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/recipients_search.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_award_contracts.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_district.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_recipient.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_state.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/tas_agencies.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/tas_codes.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/tas_federal_accounts.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/top_recipients_params.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/top_recipients_response.json +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/mocks/__init__.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/mocks/response_builder.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/mocks/test_mock_client.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/__init__.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_agency.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_agency_subagencies.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_agency_tas_integration.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_account.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_agency_integration.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_decimal_precision.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_factory.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_identifier.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_lazy_loading.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_office_integration.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_type_constants.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_base_model.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_district_spending.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_federal_account.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_funding.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_period_of_performance.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_recipient_business_categories.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_spending.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_state_spending.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_subtier_agency.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_treasury_account_symbol.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_agency_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_award_accounts_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_awards_search.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_client_side_query_builder.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_federal_accounts_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_funding_search.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_idv_child_awards.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_query_builder.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_query_builder_list_behavior.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_query_builder_pagination.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_recipient_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_recipients_search.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_single_resource_base.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_spending_search.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_spending_search_count.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_sub_agency_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_tas_agencies_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_tas_codes_query.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_agency_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_award_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_funding_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_recipients_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_spending_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_subawards_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_tas_resource.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_award_accounts_integration.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_cache_fallback.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_characterization.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_client_caching.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_client_funding.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_client_rate_limit.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_client_security.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_config.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_exceptions.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_logging_config.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_mock_client_example.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_public_api_surface.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_spending_integration.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/__init__.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/decimal_helpers.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_dates.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_doctests.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_numbers.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_rate_limit.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_retry.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_retry_session_reset.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_special_cases_data.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_textcase.py +0 -0
- {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_validations.py +0 -0
|
@@ -4,6 +4,137 @@ All notable changes to the USASpending ORM library are documented here.
|
|
|
4
4
|
The format loosely follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
5
5
|
and the project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [0.9.1] - 2026-08-27
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `client.references.def_codes()`: fetches the API's current Disaster Emergency
|
|
12
|
+
Fund Code reference data from `/api/v2/references/def_codes/` as `DefCode`
|
|
13
|
+
models. DEF codes change as legislation is enacted, so discover them at
|
|
14
|
+
runtime instead of maintaining a local list; the `def_codes(...)` search
|
|
15
|
+
filter itself remains network-free, and its docstring no longer carries a
|
|
16
|
+
hardcoded code list. `DefCode` moved to `usaspending/models/def_code.py` and
|
|
17
|
+
is exported from `usaspending.models`; the legacy
|
|
18
|
+
`usaspending.models.agency.DefCode` import path still resolves to the same
|
|
19
|
+
class.
|
|
20
|
+
- Client-side validation of classification-filter complexity, mirroring the
|
|
21
|
+
API's hard-coded bounds as reviewed against upstream on 2026-08-25.
|
|
22
|
+
`naics_codes()` rejects more than 200 combined require/exclude codes.
|
|
23
|
+
`psc_codes()` rejects more than 200 simple codes, more than 100 hierarchical
|
|
24
|
+
paths per side, more than 200 combined paths after upstream's PSC Tier-1
|
|
25
|
+
group expansion, and paths deeper than 10 levels. `tas_codes()` enforces the
|
|
26
|
+
same per-side, combined, and depth bounds. Oversized filters now raise
|
|
27
|
+
`ValidationError` at construction instead of failing at the API.
|
|
28
|
+
- MkDocs documentation site (getting-started guides, API reference, and the
|
|
29
|
+
upstream endpoint mapping) with Read the Docs configuration.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- `client.agencies.search()` now follows the shared collection semantics.
|
|
34
|
+
`page_size(n)` maps to the endpoint's `limit` parameter (default 100, capped
|
|
35
|
+
at 500) instead of a fixed internal limit of 100; the upstream limit applies
|
|
36
|
+
independently to the toptier, subtier, and office buckets, so one request can
|
|
37
|
+
return up to `3n` rows. `limit(n)` bounds the flattened result consistently
|
|
38
|
+
across `all()`, `count()`, `len()`, indexing, and slicing, and indexing reads
|
|
39
|
+
the single flattened response rather than translating indices into pages the
|
|
40
|
+
endpoint does not have. Zero bounds (`limit(0)`, `max_pages(0)`) resolve
|
|
41
|
+
without a request.
|
|
42
|
+
- `naics_codes()`, `psc_codes()`, and `tas_codes()` copy their inputs, so
|
|
43
|
+
mutating a caller-owned list after building a query no longer alters the
|
|
44
|
+
filter.
|
|
45
|
+
|
|
46
|
+
### Documentation
|
|
47
|
+
|
|
48
|
+
- Download failure text (`job.error_message`, `DownloadStatus.message`) is
|
|
49
|
+
documented as opaque server-provided text: it may be generic and can change
|
|
50
|
+
without notice, so application control flow should depend on `job.state`.
|
|
51
|
+
When a failed job carries no server message, `job.error_message` is
|
|
52
|
+
`"API reported failure."`.
|
|
53
|
+
|
|
54
|
+
## [0.9.0] - 2026-07-30
|
|
55
|
+
|
|
56
|
+
Adds the global transaction search: `client.transactions.search()` covers the
|
|
57
|
+
`/search/spending_by_transaction/` endpoint with the full fluent filter set,
|
|
58
|
+
mixed award-type categories, exact bucketed counts, and a `Transaction` model
|
|
59
|
+
that reads both of the API's row shapes.
|
|
60
|
+
|
|
61
|
+
**Breaking changes**
|
|
62
|
+
|
|
63
|
+
- `TransactionsSearch` is renamed to `AwardTransactionsSearch`. The freed name is
|
|
64
|
+
reused in this release for the new global `/search/spending_by_transaction/`
|
|
65
|
+
builder, so code importing `TransactionsSearch` directly keeps importing
|
|
66
|
+
cleanly but gets a different class rather than an `ImportError`. No
|
|
67
|
+
deprecation alias is provided. `client.transactions.award_id()` and
|
|
68
|
+
`award.transactions` are unchanged in both behavior and return value; only the
|
|
69
|
+
class and module names moved.
|
|
70
|
+
|
|
71
|
+
- `Transaction.transaction_amount` and its alias `amt` now return the first
|
|
72
|
+
nonzero of `federal_action_obligation`, `face_value_loan_guarantee` and
|
|
73
|
+
`original_loan_subsidy_cost`, and return the zero when every figure the row
|
|
74
|
+
carries is zero. Previously a zero obligation read as no value at all, so a
|
|
75
|
+
genuine zero-dollar transaction was indistinguishable from a row carrying no
|
|
76
|
+
amount, and a loan row, which reports a zero obligation with the real figure
|
|
77
|
+
in the loan fields, reported nothing. Negative figures such as deobligations
|
|
78
|
+
are preserved rather than skipped over. `amt is None` used to be true for
|
|
79
|
+
every zero-dollar transaction and is now true only for a row carrying none of
|
|
80
|
+
the three fields, so an `is None` check standing in for "no money moved"
|
|
81
|
+
needs `not amt` instead, and loan rows now report their face value, which
|
|
82
|
+
changes any total taken over a loan result set. Note that USAspending.gov's
|
|
83
|
+
own internal "pragmatic obligation" convention uses the subsidy cost, not
|
|
84
|
+
the face value, as a loan transaction's budgetary figure; this library
|
|
85
|
+
reports the face value the website displays, and
|
|
86
|
+
`original_loan_subsidy_cost` remains directly readable for budgetary totals.
|
|
87
|
+
|
|
88
|
+
### Added
|
|
89
|
+
|
|
90
|
+
- `client.transactions.search()`, returning the new `TransactionsSearch` query
|
|
91
|
+
builder over `/search/spending_by_transaction/`. It searches every
|
|
92
|
+
transaction the API holds rather than the transactions of one award, and
|
|
93
|
+
takes the same fluent filters the award search takes: `keywords()`,
|
|
94
|
+
`agency()`, `time_period()` and `fiscal_year()`, the location, code and
|
|
95
|
+
amount filters, plus `order_by()` over the endpoint's sort fields. An
|
|
96
|
+
`award_type_codes` filter is required, and unlike the award search this
|
|
97
|
+
endpoint accepts codes from more than one category at once, so
|
|
98
|
+
`.contracts().grants()` is a single valid query where the same chain on
|
|
99
|
+
`client.awards.search()` raises `ValidationError`. `count()` and `len()` read
|
|
100
|
+
`/search/spending_by_transaction_count/`, summing the buckets of the
|
|
101
|
+
categories the query selected. `TransactionsSearch` is exported from
|
|
102
|
+
`usaspending` and `usaspending.queries`.
|
|
103
|
+
|
|
104
|
+
- `Transaction` reads both row shapes the API sends: the snake_case keys of the
|
|
105
|
+
award-scoped `/transactions/` listing and the display-name keys of the global
|
|
106
|
+
search (`"Action Date"`, `"Transaction Amount"` and the rest). The existing
|
|
107
|
+
properties gained the second spelling, and the search rows carry fields the
|
|
108
|
+
award-scoped listing never had: `award_internal_id`,
|
|
109
|
+
`generated_unique_award_id`, `award_identifier`, `recipient_name`,
|
|
110
|
+
`recipient_uei`, `recipient_id`, the four agency-name properties,
|
|
111
|
+
`issued_date`, `last_date_to_order`, `naics_code`, `naics_description`,
|
|
112
|
+
`psc_code`, `psc_description`, `cfda_title`, `def_codes`,
|
|
113
|
+
`recipient_location` and `place_of_performance`. `id` is `None` for a global
|
|
114
|
+
search row, which identifies only the parent award, and
|
|
115
|
+
`transaction_description` is the preferred name for what `award_description`
|
|
116
|
+
has always returned. Every raw row key also has a getter under its
|
|
117
|
+
snake_cased name (`award_id`, `mod`, `award_type`, `loan_value`,
|
|
118
|
+
`subsidy_cost`, `description`, `primary_place_of_performance`, `amount`),
|
|
119
|
+
aliasing the normalized helpers, with the exceptions documented in the
|
|
120
|
+
model: agency names live under `*_agency_name`, dict-valued classifications
|
|
121
|
+
under their scalar helpers, and the server's award identifiers under
|
|
122
|
+
`award_internal_id` and `generated_unique_award_id`.
|
|
123
|
+
|
|
124
|
+
### Known limitations
|
|
125
|
+
|
|
126
|
+
- `TransactionsSearch` is bounded by the API's 50,000-row result window.
|
|
127
|
+
Iterating past that point raises `APIError` rather than truncating silently.
|
|
128
|
+
Narrow the filters, set `limit()`, or use `client.downloads` for larger
|
|
129
|
+
result sets; `count()` is not subject to the window.
|
|
130
|
+
|
|
131
|
+
- With a `program_activities()` filter set, `TransactionsSearch.count()` and
|
|
132
|
+
`len()` raise `ValidationError`: the count endpoint silently ignores that
|
|
133
|
+
filter while the search endpoint honors it, so passing it through would
|
|
134
|
+
report a confidently wrong count. `list(query)`, indexing and slicing
|
|
135
|
+
consult the count and so raise too; iteration, `all()`, `first()` and
|
|
136
|
+
`bool()` need no count and work regardless.
|
|
137
|
+
|
|
7
138
|
## [0.8.0] - 2026-07-28
|
|
8
139
|
|
|
9
140
|
Mostly refactoring internals to DRY the codebase and standardize the query interface.
|
|
@@ -262,7 +393,7 @@ truthiness agree under the bounds you set. Adding CI tests to verify compatabili
|
|
|
262
393
|
`q1 = search().keywords("alpha")` followed by `q2 = q1.keywords("beta")`
|
|
263
394
|
left `q1` sending `["alpha", "beta", "beta"]`. Affected chained `keywords`,
|
|
264
395
|
`award_type_codes`, simple `psc_codes` and `treasury_account_components`
|
|
265
|
-
filters.
|
|
396
|
+
filters.
|
|
266
397
|
|
|
267
398
|
- `client.recipients.find_by_recipient_id()` no longer addresses the wrong
|
|
268
399
|
record for a recipient ID carrying several levels, such as
|
|
@@ -274,7 +405,7 @@ truthiness agree under the bounds you set. Adding CI tests to verify compatabili
|
|
|
274
405
|
pass the suffix yourself (see `Recipient.recipient_level` under Added).
|
|
275
406
|
`client.spending.search().recipient_id()` also normalizes its argument now,
|
|
276
407
|
so a multi-level ID copied out of `raw` produces a filter the API can
|
|
277
|
-
match.
|
|
408
|
+
match.
|
|
278
409
|
|
|
279
410
|
- `award.transactions` no longer reports a count that disagrees with what it
|
|
280
411
|
yields. `since()` and `until()` filter in memory, but the count came from
|
|
@@ -282,7 +413,7 @@ truthiness agree under the bounds you set. Adding CI tests to verify compatabili
|
|
|
282
413
|
and `len()` said three where iteration yielded two, slices disagreed with
|
|
283
414
|
`len()`, and `query[-1]` raised `IndexError`. All of them now agree, and
|
|
284
415
|
`limit(1)` means one matching row rather than one row that may then be
|
|
285
|
-
discarded.
|
|
416
|
+
discarded.
|
|
286
417
|
|
|
287
418
|
- A `Recipient` built directly from an award search result now reports its
|
|
288
419
|
`uei` and `location`, which read only the nested spellings a detail
|
|
@@ -291,7 +422,7 @@ truthiness agree under the bounds you set. Adding CI tests to verify compatabili
|
|
|
291
422
|
not. `PeriodOfPerformance` had the same gap for `"Base Obligation Date"`.
|
|
292
423
|
Both models now read every spelling of their own fields, and `Award` hands
|
|
293
424
|
its payload over rather than reproducing the mapping; nested spellings
|
|
294
|
-
still take precedence where a payload carries both.
|
|
425
|
+
still take precedence where a payload carries both.
|
|
295
426
|
|
|
296
427
|
- Indexing and slicing an in-memory query now read the limited collection:
|
|
297
428
|
`agency.federal_accounts.limit(3)[:]` returned every account and
|
|
@@ -303,10 +434,10 @@ truthiness agree under the bounds you set. Adding CI tests to verify compatabili
|
|
|
303
434
|
fieldless `@dataclass` declaration generated an `__eq__` comparing empty
|
|
304
435
|
tuples, so any two transactions were equal and none was hashable. They now
|
|
305
436
|
compare by identity, like every other model, and can be used in sets and as
|
|
306
|
-
dict keys.
|
|
437
|
+
dict keys.
|
|
307
438
|
|
|
308
439
|
- `Recipient.parents` returns a fresh list on each read, so sorting or
|
|
309
|
-
popping the result no longer corrupts the model.
|
|
440
|
+
popping the result no longer corrupts the model.
|
|
310
441
|
|
|
311
442
|
- Iterating `idv.child_awards` no longer raises
|
|
312
443
|
`AttributeError: 'str' object has no attribute 'get'` when reading the four
|
|
@@ -344,7 +475,6 @@ truthiness agree under the bounds you set. Adding CI tests to verify compatabili
|
|
|
344
475
|
- `FederalAccount.count` no longer fires an API request when the count is
|
|
345
476
|
already in the response; the fallback was an eagerly evaluated default
|
|
346
477
|
argument, so every access paid for a request whose result was discarded.
|
|
347
|
-
|
|
348
478
|
|
|
349
479
|
- `query.limit(0).first()` returned a row, contradicting `.all()` and
|
|
350
480
|
`len()`. It now respects the zero, which is also what makes `__bool__`
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: usaspending-orm
|
|
3
|
+
Version: 0.9.1
|
|
4
|
+
Summary: A Python ORM wrapper for the USAspending.gov API with intuitive queries, automatic pagination, and smart caching
|
|
5
|
+
Project-URL: Homepage, https://github.com/planetary-society/usaspending-orm
|
|
6
|
+
Project-URL: Repository, https://github.com/planetary-society/usaspending-orm
|
|
7
|
+
Project-URL: Issues, https://github.com/planetary-society/usaspending-orm/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/planetary-society/usaspending-orm/blob/main/README.md
|
|
9
|
+
Author-email: Casey Dreier <casey.dreier@planetary.org>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: api-wrapper,contracts,federal-spending,government-data,grants,orm,usaspending
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Requires-Dist: cachier<5.0.0,>=4.1.0
|
|
25
|
+
Requires-Dist: pyyaml<7.0.0,>=6.0.2
|
|
26
|
+
Requires-Dist: requests<3.0.0,>=2.32.4
|
|
27
|
+
Requires-Dist: titlecase<3.0.0,>=2.4.1
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# USASpending ORM
|
|
31
|
+
|
|
32
|
+
[](https://github.com/planetary-society/usaspending-orm/actions/workflows/test.yml)
|
|
33
|
+
[](https://pypi.org/project/usaspending-orm/)
|
|
34
|
+
[](https://pypi.org/project/usaspending-orm/)
|
|
35
|
+
|
|
36
|
+
USASpending ORM is a typed, ORM-style Python interface to the
|
|
37
|
+
[USAspending.gov API](https://api.usaspending.gov/). It provides fluent query
|
|
38
|
+
builders and navigable models for federal awards, transactions, recipients,
|
|
39
|
+
agencies, spending summaries, Treasury Account Symbols, and bulk downloads.
|
|
40
|
+
|
|
41
|
+
The library is maintained by [The Planetary Society](https://www.planetary.org/).
|
|
42
|
+
|
|
43
|
+
## Why use it?
|
|
44
|
+
|
|
45
|
+
- Express complex USAspending searches through chainable Python methods.
|
|
46
|
+
- Work with normalized models, `date` values, and exact `Decimal` amounts.
|
|
47
|
+
- Navigate from awards to recipients, agencies, transactions, funding, accounts,
|
|
48
|
+
and subawards.
|
|
49
|
+
- Retain the original API response through each model's `.raw` property.
|
|
50
|
+
- Use built-in pagination, retries, rate limiting, optional caching, and result
|
|
51
|
+
safeguards.
|
|
52
|
+
|
|
53
|
+
No API key is required.
|
|
54
|
+
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
```console
|
|
58
|
+
python -m pip install usaspending-orm
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Requires Python 3.9 or newer.
|
|
62
|
+
|
|
63
|
+
## Quickstart
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from usaspending import USASpendingClient
|
|
67
|
+
|
|
68
|
+
with USASpendingClient() as client:
|
|
69
|
+
awards = (
|
|
70
|
+
client.awards.search()
|
|
71
|
+
.contracts()
|
|
72
|
+
.agency("National Aeronautics and Space Administration")
|
|
73
|
+
.recipient_search_text("Space Exploration Technologies")
|
|
74
|
+
.fiscal_year(2024)
|
|
75
|
+
.order_by("Award Amount", "desc")
|
|
76
|
+
.limit(5)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
for award in awards:
|
|
80
|
+
amount = award.total_obligation or 0
|
|
81
|
+
print(f"{award.award_identifier}: {award.recipient.name} - ${amount:,.2f}")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Queries are lazy. Building the chain makes no request; iteration, `.first()`,
|
|
85
|
+
`.all()`, `.count()`, `len(query)`, indexing, and truth-value testing execute
|
|
86
|
+
the appropriate USAspending operation.
|
|
87
|
+
|
|
88
|
+
## Documentation
|
|
89
|
+
|
|
90
|
+
The full documentation covers:
|
|
91
|
+
|
|
92
|
+
- [installation and core concepts](docs/getting-started/installation.md);
|
|
93
|
+
- [award and transaction searches](docs/guides/search-awards.md);
|
|
94
|
+
- [sessions, lazy loading, caching, and production use](docs/guides/production.md);
|
|
95
|
+
- [generated Python API reference](docs/reference/client.md);
|
|
96
|
+
- [mappings to canonical USAspending endpoints](docs/usaspending-api/endpoint-mapping.md);
|
|
97
|
+
- [known upstream limits and contract differences](docs/usaspending-api/limitations.md).
|
|
98
|
+
|
|
99
|
+
The repository includes Read the Docs configuration for the published site.
|
|
100
|
+
|
|
101
|
+
## Development
|
|
102
|
+
|
|
103
|
+
```console
|
|
104
|
+
git clone https://github.com/planetary-society/usaspending-orm.git
|
|
105
|
+
cd usaspending-orm
|
|
106
|
+
uv sync --locked --group docs
|
|
107
|
+
|
|
108
|
+
uv run pytest -q
|
|
109
|
+
uv run ruff check src/ tests/
|
|
110
|
+
uv run ruff format --check src/ tests/
|
|
111
|
+
uv run --group docs mkdocs build --strict
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Integration tests make live USAspending requests and run separately:
|
|
115
|
+
|
|
116
|
+
```console
|
|
117
|
+
uv run pytest -m integration -q
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Preview the documentation site locally with `uv run --group docs mkdocs serve`.
|
|
121
|
+
|
|
122
|
+
> **Note for contributors**
|
|
123
|
+
>
|
|
124
|
+
> Documentation examples are enforced, not just reviewed. `tests/test_documentation.py`
|
|
125
|
+
> compiles every fenced `python` block under `docs/`, checks that method names cited in
|
|
126
|
+
> prose exist on the public API, and executes most blocks against the live API under the
|
|
127
|
+
> `integration` marker. Adding or removing an example changes the runnable count, so
|
|
128
|
+
> update `_EXPECTED_RUNNABLE_BLOCKS` in the same change.
|
|
129
|
+
>
|
|
130
|
+
> The public API surface is snapshot-tested. When a deliberate change adds, removes, or
|
|
131
|
+
> alters a public callable, regenerate the fixture and review the diff:
|
|
132
|
+
>
|
|
133
|
+
> ```console
|
|
134
|
+
> USASPENDING_REGEN_API_SURFACE=1 uv run pytest tests/test_public_api_surface.py
|
|
135
|
+
> ```
|
|
136
|
+
>
|
|
137
|
+
> The published site builds from `.readthedocs.yaml`. To activate hosting: import
|
|
138
|
+
> `planetary-society/usaspending-orm` in Read the Docs, use `usaspending-orm` as the
|
|
139
|
+
> project slug, and enable pull-request builds. Keep `latest` as the default until a
|
|
140
|
+
> release tag contains the docs configuration, then make `stable` the default
|
|
141
|
+
> user-facing version while retaining `latest` for `main`.
|
|
142
|
+
|
|
143
|
+
## Project status
|
|
144
|
+
|
|
145
|
+
The project is in beta. USAspending itself changes over time, and live federal
|
|
146
|
+
data is revised as agencies submit corrections. Counts and values shown in
|
|
147
|
+
examples should not be treated as permanent fixtures.
|
|
148
|
+
|
|
149
|
+
See [CHANGELOG.md](CHANGELOG.md) for release history and compatibility notes.
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
USASpending ORM is released under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# USASpending ORM
|
|
2
|
+
|
|
3
|
+
[](https://github.com/planetary-society/usaspending-orm/actions/workflows/test.yml)
|
|
4
|
+
[](https://pypi.org/project/usaspending-orm/)
|
|
5
|
+
[](https://pypi.org/project/usaspending-orm/)
|
|
6
|
+
|
|
7
|
+
USASpending ORM is a typed, ORM-style Python interface to the
|
|
8
|
+
[USAspending.gov API](https://api.usaspending.gov/). It provides fluent query
|
|
9
|
+
builders and navigable models for federal awards, transactions, recipients,
|
|
10
|
+
agencies, spending summaries, Treasury Account Symbols, and bulk downloads.
|
|
11
|
+
|
|
12
|
+
The library is maintained by [The Planetary Society](https://www.planetary.org/).
|
|
13
|
+
|
|
14
|
+
## Why use it?
|
|
15
|
+
|
|
16
|
+
- Express complex USAspending searches through chainable Python methods.
|
|
17
|
+
- Work with normalized models, `date` values, and exact `Decimal` amounts.
|
|
18
|
+
- Navigate from awards to recipients, agencies, transactions, funding, accounts,
|
|
19
|
+
and subawards.
|
|
20
|
+
- Retain the original API response through each model's `.raw` property.
|
|
21
|
+
- Use built-in pagination, retries, rate limiting, optional caching, and result
|
|
22
|
+
safeguards.
|
|
23
|
+
|
|
24
|
+
No API key is required.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```console
|
|
29
|
+
python -m pip install usaspending-orm
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Requires Python 3.9 or newer.
|
|
33
|
+
|
|
34
|
+
## Quickstart
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from usaspending import USASpendingClient
|
|
38
|
+
|
|
39
|
+
with USASpendingClient() as client:
|
|
40
|
+
awards = (
|
|
41
|
+
client.awards.search()
|
|
42
|
+
.contracts()
|
|
43
|
+
.agency("National Aeronautics and Space Administration")
|
|
44
|
+
.recipient_search_text("Space Exploration Technologies")
|
|
45
|
+
.fiscal_year(2024)
|
|
46
|
+
.order_by("Award Amount", "desc")
|
|
47
|
+
.limit(5)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
for award in awards:
|
|
51
|
+
amount = award.total_obligation or 0
|
|
52
|
+
print(f"{award.award_identifier}: {award.recipient.name} - ${amount:,.2f}")
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Queries are lazy. Building the chain makes no request; iteration, `.first()`,
|
|
56
|
+
`.all()`, `.count()`, `len(query)`, indexing, and truth-value testing execute
|
|
57
|
+
the appropriate USAspending operation.
|
|
58
|
+
|
|
59
|
+
## Documentation
|
|
60
|
+
|
|
61
|
+
The full documentation covers:
|
|
62
|
+
|
|
63
|
+
- [installation and core concepts](docs/getting-started/installation.md);
|
|
64
|
+
- [award and transaction searches](docs/guides/search-awards.md);
|
|
65
|
+
- [sessions, lazy loading, caching, and production use](docs/guides/production.md);
|
|
66
|
+
- [generated Python API reference](docs/reference/client.md);
|
|
67
|
+
- [mappings to canonical USAspending endpoints](docs/usaspending-api/endpoint-mapping.md);
|
|
68
|
+
- [known upstream limits and contract differences](docs/usaspending-api/limitations.md).
|
|
69
|
+
|
|
70
|
+
The repository includes Read the Docs configuration for the published site.
|
|
71
|
+
|
|
72
|
+
## Development
|
|
73
|
+
|
|
74
|
+
```console
|
|
75
|
+
git clone https://github.com/planetary-society/usaspending-orm.git
|
|
76
|
+
cd usaspending-orm
|
|
77
|
+
uv sync --locked --group docs
|
|
78
|
+
|
|
79
|
+
uv run pytest -q
|
|
80
|
+
uv run ruff check src/ tests/
|
|
81
|
+
uv run ruff format --check src/ tests/
|
|
82
|
+
uv run --group docs mkdocs build --strict
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Integration tests make live USAspending requests and run separately:
|
|
86
|
+
|
|
87
|
+
```console
|
|
88
|
+
uv run pytest -m integration -q
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Preview the documentation site locally with `uv run --group docs mkdocs serve`.
|
|
92
|
+
|
|
93
|
+
> **Note for contributors**
|
|
94
|
+
>
|
|
95
|
+
> Documentation examples are enforced, not just reviewed. `tests/test_documentation.py`
|
|
96
|
+
> compiles every fenced `python` block under `docs/`, checks that method names cited in
|
|
97
|
+
> prose exist on the public API, and executes most blocks against the live API under the
|
|
98
|
+
> `integration` marker. Adding or removing an example changes the runnable count, so
|
|
99
|
+
> update `_EXPECTED_RUNNABLE_BLOCKS` in the same change.
|
|
100
|
+
>
|
|
101
|
+
> The public API surface is snapshot-tested. When a deliberate change adds, removes, or
|
|
102
|
+
> alters a public callable, regenerate the fixture and review the diff:
|
|
103
|
+
>
|
|
104
|
+
> ```console
|
|
105
|
+
> USASPENDING_REGEN_API_SURFACE=1 uv run pytest tests/test_public_api_surface.py
|
|
106
|
+
> ```
|
|
107
|
+
>
|
|
108
|
+
> The published site builds from `.readthedocs.yaml`. To activate hosting: import
|
|
109
|
+
> `planetary-society/usaspending-orm` in Read the Docs, use `usaspending-orm` as the
|
|
110
|
+
> project slug, and enable pull-request builds. Keep `latest` as the default until a
|
|
111
|
+
> release tag contains the docs configuration, then make `stable` the default
|
|
112
|
+
> user-facing version while retaining `latest` for `main`.
|
|
113
|
+
|
|
114
|
+
## Project status
|
|
115
|
+
|
|
116
|
+
The project is in beta. USAspending itself changes over time, and live federal
|
|
117
|
+
data is revised as agencies submit corrections. Counts and values shown in
|
|
118
|
+
examples should not be treated as permanent fixtures.
|
|
119
|
+
|
|
120
|
+
See [CHANGELOG.md](CHANGELOG.md) for release history and compatibility notes.
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
USASpending ORM is released under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Caching
|
|
2
|
+
|
|
3
|
+
Caching is off by default. When enabled, the client stores successful API
|
|
4
|
+
responses and serves repeat requests from the store instead of the network.
|
|
5
|
+
|
|
6
|
+
```python
|
|
7
|
+
from datetime import timedelta
|
|
8
|
+
|
|
9
|
+
from usaspending import USASpendingClient, config
|
|
10
|
+
|
|
11
|
+
config.configure(
|
|
12
|
+
cache_enabled=True,
|
|
13
|
+
cache_backend="file",
|
|
14
|
+
cache_ttl=timedelta(days=1),
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
with USASpendingClient() as client:
|
|
18
|
+
award = client.awards.find_by_award_id("80GSFC18C0008")
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Configure caching before creating a client. Settings are applied through an
|
|
22
|
+
observer, so a later `configure()` call rebuilds the cache wrapper rather than
|
|
23
|
+
leaving clients on stale settings.
|
|
24
|
+
|
|
25
|
+
## What gets cached
|
|
26
|
+
|
|
27
|
+
The unit of caching is one HTTP request, not one query. A cache entry is keyed
|
|
28
|
+
on the endpoint and the full request payload, so two searches that differ in any
|
|
29
|
+
filter, sort, or page are separate entries, and a repeat of the identical
|
|
30
|
+
request is a hit.
|
|
31
|
+
|
|
32
|
+
Because the unit is the request, caching covers everything the library sends:
|
|
33
|
+
search pages, count calls, award detail lookups, and the follow-up requests
|
|
34
|
+
behind lazy relationships. A loop that reads `award.recipient.location` for many
|
|
35
|
+
awards still issues one request per award the first time, but pays nothing on a
|
|
36
|
+
second pass over the same awards.
|
|
37
|
+
|
|
38
|
+
Two things are deliberately not stored:
|
|
39
|
+
|
|
40
|
+
- **Failures.** Errors are never cached, so a transient outage does not poison
|
|
41
|
+
the store. The next call re-issues the request.
|
|
42
|
+
- **Empty results.** A response the client could not interpret is not stored,
|
|
43
|
+
and the request falls back to the network.
|
|
44
|
+
|
|
45
|
+
## Cache misses are never fatal
|
|
46
|
+
|
|
47
|
+
Reading from the cache is best-effort. If the store is unreadable, locked, or
|
|
48
|
+
corrupt, the client logs a warning and issues the request normally. A broken
|
|
49
|
+
cache degrades performance, never correctness.
|
|
50
|
+
|
|
51
|
+
API errors are the exception to that fallback: `APIError`, `HTTPError`,
|
|
52
|
+
`RateLimitError`, and `ValidationError` propagate to the caller rather than
|
|
53
|
+
being retried uncached, because they describe the request rather than the cache.
|
|
54
|
+
|
|
55
|
+
## Backends
|
|
56
|
+
|
|
57
|
+
`cache_backend="memory"` keeps entries in the process and discards them on exit.
|
|
58
|
+
It suits tests and short scripts, and avoids writing anything to disk.
|
|
59
|
+
|
|
60
|
+
`cache_backend="file"` is the default and writes pickled responses under
|
|
61
|
+
`cache_dir`, which defaults to `$XDG_CACHE_HOME/usaspending` or
|
|
62
|
+
`~/.cache/usaspending`. Entries survive the process, so a later run reuses what
|
|
63
|
+
an earlier one fetched. That is what makes an interrupted batch job cheap to
|
|
64
|
+
restart, and what lets a script re-run during development stop paying for the
|
|
65
|
+
same pages.
|
|
66
|
+
|
|
67
|
+
Reuse depends on the request serializing identically each time. The library
|
|
68
|
+
sorts the values of match-any filters for that reason, so a filter built from a
|
|
69
|
+
Python set produces the same request, and therefore the same cache entry, on
|
|
70
|
+
every run.
|
|
71
|
+
|
|
72
|
+
!!! warning "The file backend unpickles data it reads"
|
|
73
|
+
|
|
74
|
+
Unpickling executes code, so the cache directory is a trust boundary. The
|
|
75
|
+
library creates it with `0700` permissions and restores those permissions if
|
|
76
|
+
they have been widened, but do not point `cache_dir` at a shared,
|
|
77
|
+
world-writable, or otherwise untrusted location, and do not use a directory
|
|
78
|
+
another user can write to.
|
|
79
|
+
|
|
80
|
+
## Expiry and namespaces
|
|
81
|
+
|
|
82
|
+
`cache_ttl` sets how long an entry stays fresh; the default is one week. An
|
|
83
|
+
entry older than the TTL is recomputed on next use. `configure()` accepts either
|
|
84
|
+
a `timedelta` or a number of seconds.
|
|
85
|
+
|
|
86
|
+
Federal spending data is revised after publication, so the TTL is a correctness
|
|
87
|
+
decision as much as a performance one. A long TTL on a reporting job can serve
|
|
88
|
+
figures that agencies have since corrected. Prefer hours or days for anything
|
|
89
|
+
whose numbers get published, and reserve a week for exploratory work.
|
|
90
|
+
|
|
91
|
+
`cache_namespace` is part of every key, so two projects sharing a `cache_dir` do
|
|
92
|
+
not read each other's entries. Change it to isolate a workload, or to abandon an
|
|
93
|
+
existing set of entries wholesale.
|
|
94
|
+
|
|
95
|
+
`cache_timeout` bounds how long a caller waits for another worker that is
|
|
96
|
+
already computing the same entry, which keeps concurrent callers from
|
|
97
|
+
stampeding the same request.
|
|
98
|
+
|
|
99
|
+
## Clearing the cache
|
|
100
|
+
|
|
101
|
+
There is no public API for clearing the cache. With the file backend, delete the
|
|
102
|
+
files under `cache_dir`; with the memory backend, ending the process is enough.
|
|
103
|
+
Changing `cache_namespace` also abandons the previous entries without deleting
|
|
104
|
+
them.
|
|
105
|
+
|
|
106
|
+
## Choosing a TTL
|
|
107
|
+
|
|
108
|
+
- Interactive analysis over a stable slice of history: hours to a day.
|
|
109
|
+
- Repeatedly re-running the same broad query while developing: a day or more,
|
|
110
|
+
since the point is to stop paying for the same pages.
|
|
111
|
+
- Anything producing published figures: short, or disabled, so a correction
|
|
112
|
+
upstream is not masked by a stale entry.
|
|
113
|
+
|
|
114
|
+
See [Production use](../guides/production.md) for how caching interacts with
|
|
115
|
+
rate limiting and long batch runs.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# USAspending data model
|
|
2
|
+
|
|
3
|
+
The library presents several related grains of federal spending data.
|
|
4
|
+
|
|
5
|
+
## Prime awards
|
|
6
|
+
|
|
7
|
+
An award is the durable agreement between the federal government and a
|
|
8
|
+
recipient: a contract, grant, loan, direct payment, other assistance, or
|
|
9
|
+
Indefinite Delivery Vehicle. An award accumulates financial activity over its
|
|
10
|
+
lifetime.
|
|
11
|
+
|
|
12
|
+
`Award` and its subclasses normalize the details endpoint and expose
|
|
13
|
+
relationships such as recipient, agencies, period of performance, place of
|
|
14
|
+
performance, transactions, accounts, funding records, and subawards.
|
|
15
|
+
|
|
16
|
+
## Transactions
|
|
17
|
+
|
|
18
|
+
A transaction is an action that changes or reports an award. Examples include
|
|
19
|
+
the initial obligation, a contract modification, an incremental funding
|
|
20
|
+
action, or a deobligation.
|
|
21
|
+
|
|
22
|
+
Transaction searches therefore have a different grain from award searches:
|
|
23
|
+
|
|
24
|
+
- award search returns one row per matching award;
|
|
25
|
+
- global transaction search returns one row per matching action;
|
|
26
|
+
- `award.transactions` returns actions belonging to one award.
|
|
27
|
+
|
|
28
|
+
Summing transaction amounts and reading an award's current total obligation are
|
|
29
|
+
different analytical operations.
|
|
30
|
+
|
|
31
|
+
## Subawards
|
|
32
|
+
|
|
33
|
+
A subaward records funding passed from a prime recipient to another
|
|
34
|
+
organization. Subawards are reported separately and do not share every field or
|
|
35
|
+
filter available for prime awards.
|
|
36
|
+
|
|
37
|
+
## Accounts and funding records
|
|
38
|
+
|
|
39
|
+
Federal accounts and Treasury Account Symbols describe the appropriations
|
|
40
|
+
accounts behind spending. Award funding records connect transactions to those
|
|
41
|
+
accounts and agencies. These records are useful when the question concerns
|
|
42
|
+
budget authority or the source of funds rather than only the recipient and
|
|
43
|
+
award.
|
|
44
|
+
|
|
45
|
+
## Aggregations
|
|
46
|
+
|
|
47
|
+
Spending-by-category endpoints return grouped totals by dimensions such as
|
|
48
|
+
recipient or geography. Their rows are summaries, not awards, and use dedicated
|
|
49
|
+
models.
|
|
50
|
+
|
|
51
|
+
See [Terminology](../usaspending-api/terminology.md) for links to canonical
|
|
52
|
+
USAspending definitions.
|