usaspending-orm 0.9.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.9.0 → usaspending_orm-0.9.1}/.gitignore +1 -0
- usaspending_orm-0.9.1/.readthedocs.yaml +17 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/CHANGELOG.md +47 -0
- {usaspending_orm-0.9.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.9.0 → usaspending_orm-0.9.1}/pyproject.toml +11 -2
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/client.py +17 -1
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/download/job.py +11 -3
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/__init__.py +2 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/agency.py +2 -39
- usaspending_orm-0.9.1/src/usaspending/models/def_code.py +36 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/download.py +6 -2
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/loan.py +3 -3
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/agencies_search.py +26 -7
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/agency_award_summary.py +5 -4
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/awards_search.py +2 -1
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/base_query.py +12 -1
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/client_side_query_builder.py +2 -18
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/filters.py +86 -11
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/mixins.py +32 -1
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/query_builder.py +55 -41
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/sub_agency_query.py +5 -1
- {usaspending_orm-0.9.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/utils/payloads.py +34 -0
- {usaspending_orm-0.9.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.9.0 → usaspending_orm-0.9.1}/tests/fixtures/public_api_surface.json +14 -0
- usaspending_orm-0.9.1/tests/markdown_examples.py +86 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/mocks/README.md +3 -3
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/mocks/mock_client.py +3 -1
- usaspending_orm-0.9.0/tests/volatile_fields.py → usaspending_orm-0.9.1/tests/model_contracts.py +122 -65
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_award_category_registry.py +6 -4
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_award_common.py +1 -5
- {usaspending_orm-0.9.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.9.0 → usaspending_orm-0.9.1}/tests/models/test_lazy_load.py +19 -15
- {usaspending_orm-0.9.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.9.0 → usaspending_orm-0.9.1}/tests/models/test_recipient.py +25 -50
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_recipient_spending.py +28 -38
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_search_projection.py +47 -32
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_subaward.py +2 -9
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_transaction.py +85 -75
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_agencies_search.py +123 -1
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_agency_award_summary.py +6 -4
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_filters.py +87 -2
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_search_query_builder.py +111 -2
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_subawards_search.py +2 -9
- usaspending_orm-0.9.1/tests/resources/test_references_resource.py +92 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/snapshot_support.py +4 -6
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_client.py +0 -7
- usaspending_orm-0.9.1/tests/test_documentation.py +246 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_download_resource.py +57 -4
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_integration.py +7 -5
- usaspending_orm-0.9.1/tests/test_live_contract_integration.py +286 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_readme_examples.py +11 -18
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/uv.lock +383 -1
- usaspending_orm-0.9.0/PKG-INFO +0 -586
- usaspending_orm-0.9.0/README.md +0 -557
- usaspending_orm-0.9.0/api-docs-links.md +0 -276
- usaspending_orm-0.9.0/tests/fixtures/golden/agency.json +0 -74
- usaspending_orm-0.9.0/tests/fixtures/golden/award_account_first_result.json +0 -29
- usaspending_orm-0.9.0/tests/fixtures/golden/award_contract.json +0 -190
- usaspending_orm-0.9.0/tests/fixtures/golden/award_contract_awarding_agency.json +0 -74
- usaspending_orm-0.9.0/tests/fixtures/golden/award_contract_period_of_performance.json +0 -15
- usaspending_orm-0.9.0/tests/fixtures/golden/award_contract_place_of_performance.json +0 -23
- usaspending_orm-0.9.0/tests/fixtures/golden/award_contract_recipient.json +0 -51
- usaspending_orm-0.9.0/tests/fixtures/golden/award_grant.json +0 -198
- usaspending_orm-0.9.0/tests/fixtures/golden/award_idv.json +0 -190
- usaspending_orm-0.9.0/tests/fixtures/golden/award_loan.json +0 -191
- usaspending_orm-0.9.0/tests/fixtures/golden/award_parent_of_contract.json +0 -136
- usaspending_orm-0.9.0/tests/fixtures/golden/funding_first_result.json +0 -35
- usaspending_orm-0.9.0/tests/fixtures/golden/idv_child_award_first_result.json +0 -192
- usaspending_orm-0.9.0/tests/fixtures/golden/recipient.json +0 -60
- usaspending_orm-0.9.0/tests/fixtures/golden/search_contract_first_result.json +0 -190
- usaspending_orm-0.9.0/tests/fixtures/golden/search_subaward_first_result.json +0 -91
- usaspending_orm-0.9.0/tests/fixtures/golden/spending_by_recipient_first_result.json +0 -68
- usaspending_orm-0.9.0/tests/fixtures/golden/spending_by_state_first_result.json +0 -17
- usaspending_orm-0.9.0/tests/fixtures/golden/transaction_first_result.json +0 -18
- usaspending_orm-0.9.0/tests/models/test_volatile_field_mapping.py +0 -177
- usaspending_orm-0.9.0/tests/test_golden_master_integration.py +0 -707
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/__init__.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/cli/__init__.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/cli/download_award.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/config.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/download/__init__.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/download/manager.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/exceptions.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/logging_config.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/award.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/award_account.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/award_factory.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/award_identifier.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/award_types.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/base_model.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/contract.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/district_spending.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/federal_account.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/funding.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/grant.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/idv.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/lazy_record.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/location.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/period_of_performance.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/procurement_award.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/recipient.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/recipient_business_categories.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/recipient_spending.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/spending.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/state_spending.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/subaward.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/subtier_agency.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/transaction.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/models/treasury_account_symbol.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/__init__.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/agency_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/award_accounts_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/award_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/award_transactions_search.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/awarding_agencies_search.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/federal_accounts_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/filter_tree_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/funding_agencies_search.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/funding_search.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/idv_child_awards.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/recipient_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/recipients_search.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/single_resource_base.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/spending_search.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/subawards_search.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/tas_agencies_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/tas_codes_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/queries/transactions_search.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/resources/agency_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/resources/award_accounts_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/resources/award_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/resources/base_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/resources/download_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/resources/funding_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/resources/recipients_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/resources/spending_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/resources/subawards_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/resources/tas_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/resources/transactions_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/utils/__init__.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/utils/dates.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/utils/numbers.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/utils/rate_limit.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/utils/retry.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/utils/special_cases.yaml +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/utils/textcase.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/src/usaspending/utils/validations.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/__init__.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/agency.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/agency_autocomplete.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/agency_award_summary.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/agency_subagencies.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/accounts.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/award_funding_grant.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/contract.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/grant.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/idv.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/idv_awards.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/loan.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/search_results_contracts.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/search_results_grants.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/search_results_idvs.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/search_results_subawards.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/transactions.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/download_assistance.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/download_search.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/download_status.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/recipient_university.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/recipients_search.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_award_contracts.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_district.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_recipient.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_state.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_transaction.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_transaction_count.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_transaction_mixed.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/tas_agencies.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/tas_codes.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/tas_federal_accounts.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/top_recipients_params.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/fixtures/top_recipients_response.json +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/mocks/__init__.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/mocks/response_builder.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/mocks/test_mock_client.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/__init__.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_agency.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_agency_subagencies.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_agency_tas_integration.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_award_account.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_award_agency_integration.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_award_decimal_precision.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_award_factory.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_award_identifier.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_award_lazy_loading.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_award_office_integration.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_award_type_constants.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_base_model.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_district_spending.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_federal_account.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_funding.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_period_of_performance.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_recipient_business_categories.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_spending.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_state_spending.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_subtier_agency.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_transaction_search_projection.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/models/test_treasury_account_symbol.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_agency_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_award_accounts_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_award_transactions_search.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_awards_search.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_client_side_query_builder.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_count_respects_limits.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_federal_accounts_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_funding_search.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_idv_child_awards.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_query_builder.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_query_builder_list_behavior.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_query_builder_pagination.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_recipient_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_recipients_search.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_single_resource_base.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_spending_search.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_spending_search_count.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_sub_agency_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_tas_agencies_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_tas_codes_query.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/queries/test_transactions_search.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/resources/test_agency_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/resources/test_award_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/resources/test_funding_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/resources/test_recipients_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/resources/test_spending_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/resources/test_subawards_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/resources/test_tas_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/resources/test_transactions_resource.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_award_accounts_integration.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_cache_fallback.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_characterization.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_client_caching.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_client_funding.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_client_rate_limit.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_client_security.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_client_transactions.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_config.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_exceptions.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_logging_config.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_mock_client_example.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_public_api_surface.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/test_spending_integration.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/utils/__init__.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/utils/decimal_helpers.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/utils/test_dates.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/utils/test_doctests.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/utils/test_numbers.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/utils/test_rate_limit.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/utils/test_retry.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/utils/test_retry_session_reset.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/utils/test_special_cases_data.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/utils/test_textcase.py +0 -0
- {usaspending_orm-0.9.0 → usaspending_orm-0.9.1}/tests/utils/test_validations.py +0 -0
|
@@ -4,6 +4,53 @@ 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
|
+
|
|
7
54
|
## [0.9.0] - 2026-07-30
|
|
8
55
|
|
|
9
56
|
Adds the global transaction search: `client.transactions.search()` covers the
|
|
@@ -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.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Query execution
|
|
2
|
+
|
|
3
|
+
Query builders separate request construction from execution.
|
|
4
|
+
|
|
5
|
+
## Lazy construction
|
|
6
|
+
|
|
7
|
+
Filter, sort, and limit calls modify the builder without making an HTTP
|
|
8
|
+
request:
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
query = (
|
|
12
|
+
client.awards.search()
|
|
13
|
+
.contracts()
|
|
14
|
+
.agency("National Aeronautics and Space Administration")
|
|
15
|
+
.fiscal_year(2024)
|
|
16
|
+
.limit(25)
|
|
17
|
+
)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The request begins when code:
|
|
21
|
+
|
|
22
|
+
- iterates over the query;
|
|
23
|
+
- calls `.all()`, `.first()`, or `.count()`;
|
|
24
|
+
- calls `len(query)`;
|
|
25
|
+
- indexes or slices the query;
|
|
26
|
+
- evaluates its truth value.
|
|
27
|
+
|
|
28
|
+
## Pagination
|
|
29
|
+
|
|
30
|
+
Iteration requests pages as needed and stops when the API is exhausted or a
|
|
31
|
+
configured bound is reached. Query builders expose list-like operations, but
|
|
32
|
+
they do not pre-load the entire result set.
|
|
33
|
+
|
|
34
|
+
`.all()` materializes the bounded query into a list. Prefer iteration when
|
|
35
|
+
streaming pages is sufficient.
|
|
36
|
+
|
|
37
|
+
## Count consistency
|
|
38
|
+
|
|
39
|
+
`count()` uses a companion endpoint when USAspending provides one. Library
|
|
40
|
+
limits are applied to the reported value so these expressions agree for a
|
|
41
|
+
bounded query:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
query = client.awards.search().contracts().fiscal_year(2024).limit(10)
|
|
45
|
+
|
|
46
|
+
query.count()
|
|
47
|
+
len(query)
|
|
48
|
+
len(query.all())
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Some upstream search and count endpoints accept different filters. When a
|
|
52
|
+
correct count cannot be requested, the library raises `ValidationError` rather
|
|
53
|
+
than returning a misleading number.
|
|
54
|
+
|
|
55
|
+
## Immutable chaining
|
|
56
|
+
|
|
57
|
+
Fluent methods return a clone with the new filter, sort, or bound. A partly
|
|
58
|
+
built query can therefore be used as an immutable template:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
base = client.awards.search().contracts().fiscal_year(2024)
|
|
62
|
+
california = base.place_of_performance_locations(
|
|
63
|
+
{"country_code": "USA", "state_code": "CA"}
|
|
64
|
+
)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
After this call, `base` remains unchanged and `california` carries the added
|
|
68
|
+
location filter.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Core concepts
|
|
2
|
+
|
|
3
|
+
## Client
|
|
4
|
+
|
|
5
|
+
`USASpendingClient` owns the HTTP session, retry behavior, rate limiter, and
|
|
6
|
+
resource entry points. Prefer a `with` block so the session closes reliably.
|
|
7
|
+
|
|
8
|
+
```python
|
|
9
|
+
from usaspending import USASpendingClient
|
|
10
|
+
|
|
11
|
+
with USASpendingClient() as client:
|
|
12
|
+
award = client.awards.find_by_award_id("80GSFC18C0008")
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Resources
|
|
16
|
+
|
|
17
|
+
Client properties group related upstream operations:
|
|
18
|
+
|
|
19
|
+
| Resource | Typical purpose |
|
|
20
|
+
| --------------------- | -------------------------------------------------- |
|
|
21
|
+
| `client.awards` | Find and search prime awards |
|
|
22
|
+
| `client.transactions` | Search transactions globally or for one award |
|
|
23
|
+
| `client.subawards` | Search subawards |
|
|
24
|
+
| `client.recipients` | Find and search recipient organizations |
|
|
25
|
+
| `client.agencies` | Agency summaries, subagencies, and office searches |
|
|
26
|
+
| `client.references` | Current API reference data, including DEF codes |
|
|
27
|
+
| `client.spending` | Aggregated spending by recipient or geography |
|
|
28
|
+
| `client.tas` | Treasury Account Symbol hierarchy |
|
|
29
|
+
| `client.downloads` | Queue server-side bulk exports |
|
|
30
|
+
|
|
31
|
+
## Query builders
|
|
32
|
+
|
|
33
|
+
Calling `.search()` returns a fluent builder. Filter methods clone it and return
|
|
34
|
+
a new query, so a shared base query can safely feed consumers that need
|
|
35
|
+
different filters.
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
query = (
|
|
39
|
+
client.awards.search()
|
|
40
|
+
.contracts()
|
|
41
|
+
.agency("National Aeronautics and Space Administration")
|
|
42
|
+
.fiscal_year(2024)
|
|
43
|
+
.limit(25)
|
|
44
|
+
)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Query builders handle pagination and expose a list-like interface, but they are
|
|
48
|
+
not in-memory lists. Some operations make separate API requests; see
|
|
49
|
+
[Query execution](../explanation/query-execution.md).
|
|
50
|
+
|
|
51
|
+
## Models
|
|
52
|
+
|
|
53
|
+
Results are model objects such as `Award`, `Transaction`, `Recipient`, and
|
|
54
|
+
`Agency`. Models provide:
|
|
55
|
+
|
|
56
|
+
- normalized snake-case properties;
|
|
57
|
+
- parsed dates and decimal amounts;
|
|
58
|
+
- `.raw` access to the original response;
|
|
59
|
+
- related objects or query builders where the upstream data supports them.
|
|
60
|
+
|
|
61
|
+
Optional fields return `None` when the API does not report a value. A real
|
|
62
|
+
zero-dollar amount remains `Decimal("0.00")`.
|
|
63
|
+
|
|
64
|
+
## Lazy loading and sessions
|
|
65
|
+
|
|
66
|
+
Some relationships require another API request. Access them while the creating
|
|
67
|
+
client is open. A model can be reattached to a new client when later lazy loads
|
|
68
|
+
are required:
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
with USASpendingClient() as client:
|
|
72
|
+
award = client.awards.find_by_award_id("80GSFC18C0008")
|
|
73
|
+
|
|
74
|
+
with USASpendingClient() as new_client:
|
|
75
|
+
award.reattach(new_client, recursive=True)
|
|
76
|
+
print(award.transactions.count())
|
|
77
|
+
```
|