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.
Files changed (291) hide show
  1. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/.gitignore +1 -0
  2. usaspending_orm-0.9.1/.readthedocs.yaml +17 -0
  3. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/CHANGELOG.md +137 -7
  4. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/LICENSE +1 -1
  5. usaspending_orm-0.9.1/PKG-INFO +153 -0
  6. usaspending_orm-0.9.1/README.md +124 -0
  7. usaspending_orm-0.9.1/docs/explanation/caching.md +115 -0
  8. usaspending_orm-0.9.1/docs/explanation/data-model.md +52 -0
  9. usaspending_orm-0.9.1/docs/explanation/query-execution.md +68 -0
  10. usaspending_orm-0.9.1/docs/getting-started/core-concepts.md +77 -0
  11. usaspending_orm-0.9.1/docs/getting-started/installation.md +47 -0
  12. usaspending_orm-0.9.1/docs/getting-started/quickstart.md +81 -0
  13. usaspending_orm-0.9.1/docs/guides/production.md +106 -0
  14. usaspending_orm-0.9.1/docs/guides/related-data.md +61 -0
  15. usaspending_orm-0.9.1/docs/guides/search-awards.md +166 -0
  16. usaspending_orm-0.9.1/docs/guides/search-transactions.md +71 -0
  17. usaspending_orm-0.9.1/docs/guides/spending-and-downloads.md +119 -0
  18. usaspending_orm-0.9.1/docs/index.md +56 -0
  19. usaspending_orm-0.9.1/docs/reference/client.md +41 -0
  20. usaspending_orm-0.9.1/docs/reference/configuration.md +60 -0
  21. usaspending_orm-0.9.1/docs/reference/models.md +48 -0
  22. usaspending_orm-0.9.1/docs/reference/queries.md +55 -0
  23. usaspending_orm-0.9.1/docs/usaspending-api/endpoint-mapping.md +54 -0
  24. usaspending_orm-0.9.1/docs/usaspending-api/limitations.md +59 -0
  25. usaspending_orm-0.9.1/docs/usaspending-api/terminology.md +55 -0
  26. usaspending_orm-0.9.1/mkdocs.yml +109 -0
  27. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/pyproject.toml +11 -2
  28. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/__init__.py +2 -0
  29. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/client.py +17 -1
  30. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/download/job.py +11 -3
  31. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/__init__.py +2 -0
  32. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/agency.py +2 -39
  33. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/award.py +5 -5
  34. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/award_types.py +24 -1
  35. usaspending_orm-0.9.1/src/usaspending/models/def_code.py +36 -0
  36. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/download.py +6 -2
  37. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/loan.py +3 -3
  38. usaspending_orm-0.9.1/src/usaspending/models/transaction.py +582 -0
  39. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/__init__.py +2 -0
  40. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/agencies_search.py +26 -7
  41. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/agency_award_summary.py +5 -4
  42. 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
  43. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/awards_search.py +8 -32
  44. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/base_query.py +12 -1
  45. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/client_side_query_builder.py +2 -18
  46. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/filters.py +86 -11
  47. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/mixins.py +32 -1
  48. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/query_builder.py +162 -56
  49. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/sub_agency_query.py +5 -1
  50. usaspending_orm-0.9.1/src/usaspending/queries/transactions_search.py +239 -0
  51. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/__init__.py +2 -0
  52. usaspending_orm-0.9.1/src/usaspending/resources/references_resource.py +21 -0
  53. usaspending_orm-0.9.1/src/usaspending/resources/transactions_resource.py +63 -0
  54. usaspending_orm-0.9.1/src/usaspending/utils/payloads.py +34 -0
  55. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/conftest.py +31 -31
  56. usaspending_orm-0.9.1/tests/fixtures/def_codes.json +29 -0
  57. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/public_api_surface.json +97 -5
  58. usaspending_orm-0.9.1/tests/fixtures/spending_by_transaction.json +214 -0
  59. usaspending_orm-0.9.1/tests/fixtures/spending_by_transaction_count.json +10 -0
  60. usaspending_orm-0.9.1/tests/fixtures/spending_by_transaction_mixed.json +210 -0
  61. usaspending_orm-0.9.1/tests/markdown_examples.py +86 -0
  62. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/mocks/README.md +3 -3
  63. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/mocks/mock_client.py +3 -1
  64. usaspending_orm-0.8.0/tests/volatile_fields.py → usaspending_orm-0.9.1/tests/model_contracts.py +122 -65
  65. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_category_registry.py +6 -4
  66. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_common.py +1 -5
  67. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_types.py +9 -0
  68. usaspending_orm-0.9.1/tests/models/test_def_code.py +52 -0
  69. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_lazy_load.py +19 -15
  70. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_location.py +114 -57
  71. usaspending_orm-0.9.1/tests/models/test_model_field_contracts.py +159 -0
  72. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_recipient.py +25 -50
  73. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_recipient_spending.py +28 -38
  74. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_search_projection.py +47 -32
  75. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_subaward.py +2 -9
  76. usaspending_orm-0.9.1/tests/models/test_transaction.py +300 -0
  77. usaspending_orm-0.9.1/tests/models/test_transaction_search_projection.py +456 -0
  78. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_agencies_search.py +123 -1
  79. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_agency_award_summary.py +6 -4
  80. 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
  81. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_count_respects_limits.py +5 -5
  82. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_filters.py +87 -2
  83. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_search_query_builder.py +111 -2
  84. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_subawards_search.py +2 -9
  85. usaspending_orm-0.9.1/tests/queries/test_transactions_search.py +504 -0
  86. usaspending_orm-0.9.1/tests/resources/test_references_resource.py +92 -0
  87. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_transactions_resource.py +22 -3
  88. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/snapshot_support.py +4 -6
  89. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_client.py +0 -7
  90. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_client_transactions.py +1 -1
  91. usaspending_orm-0.9.1/tests/test_documentation.py +246 -0
  92. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_download_resource.py +57 -4
  93. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_integration.py +59 -5
  94. usaspending_orm-0.9.1/tests/test_live_contract_integration.py +286 -0
  95. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_readme_examples.py +11 -18
  96. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/uv.lock +383 -1
  97. usaspending_orm-0.8.0/PKG-INFO +0 -519
  98. usaspending_orm-0.8.0/README.md +0 -490
  99. usaspending_orm-0.8.0/api-docs-links.md +0 -258
  100. usaspending_orm-0.8.0/src/usaspending/models/transaction.py +0 -150
  101. usaspending_orm-0.8.0/src/usaspending/resources/transactions_resource.py +0 -39
  102. usaspending_orm-0.8.0/tests/fixtures/golden/agency.json +0 -74
  103. usaspending_orm-0.8.0/tests/fixtures/golden/award_account_first_result.json +0 -29
  104. usaspending_orm-0.8.0/tests/fixtures/golden/award_contract.json +0 -190
  105. usaspending_orm-0.8.0/tests/fixtures/golden/award_contract_awarding_agency.json +0 -74
  106. usaspending_orm-0.8.0/tests/fixtures/golden/award_contract_period_of_performance.json +0 -15
  107. usaspending_orm-0.8.0/tests/fixtures/golden/award_contract_place_of_performance.json +0 -23
  108. usaspending_orm-0.8.0/tests/fixtures/golden/award_contract_recipient.json +0 -51
  109. usaspending_orm-0.8.0/tests/fixtures/golden/award_grant.json +0 -198
  110. usaspending_orm-0.8.0/tests/fixtures/golden/award_idv.json +0 -190
  111. usaspending_orm-0.8.0/tests/fixtures/golden/award_loan.json +0 -191
  112. usaspending_orm-0.8.0/tests/fixtures/golden/award_parent_of_contract.json +0 -136
  113. usaspending_orm-0.8.0/tests/fixtures/golden/funding_first_result.json +0 -35
  114. usaspending_orm-0.8.0/tests/fixtures/golden/idv_child_award_first_result.json +0 -192
  115. usaspending_orm-0.8.0/tests/fixtures/golden/recipient.json +0 -60
  116. usaspending_orm-0.8.0/tests/fixtures/golden/search_contract_first_result.json +0 -190
  117. usaspending_orm-0.8.0/tests/fixtures/golden/search_subaward_first_result.json +0 -91
  118. usaspending_orm-0.8.0/tests/fixtures/golden/spending_by_recipient_first_result.json +0 -68
  119. usaspending_orm-0.8.0/tests/fixtures/golden/spending_by_state_first_result.json +0 -17
  120. usaspending_orm-0.8.0/tests/fixtures/golden/transaction_first_result.json +0 -18
  121. usaspending_orm-0.8.0/tests/models/test_transaction.py +0 -249
  122. usaspending_orm-0.8.0/tests/models/test_volatile_field_mapping.py +0 -177
  123. usaspending_orm-0.8.0/tests/test_golden_master_integration.py +0 -707
  124. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/cli/__init__.py +0 -0
  125. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/cli/download_award.py +0 -0
  126. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/config.py +0 -0
  127. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/download/__init__.py +0 -0
  128. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/download/manager.py +0 -0
  129. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/exceptions.py +0 -0
  130. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/logging_config.py +0 -0
  131. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/award_account.py +0 -0
  132. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/award_factory.py +0 -0
  133. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/award_identifier.py +0 -0
  134. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/base_model.py +0 -0
  135. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/contract.py +0 -0
  136. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/district_spending.py +0 -0
  137. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/federal_account.py +0 -0
  138. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/funding.py +0 -0
  139. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/grant.py +0 -0
  140. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/idv.py +0 -0
  141. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/lazy_record.py +0 -0
  142. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/location.py +0 -0
  143. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/period_of_performance.py +0 -0
  144. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/procurement_award.py +0 -0
  145. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/recipient.py +0 -0
  146. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/recipient_business_categories.py +0 -0
  147. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/recipient_spending.py +0 -0
  148. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/spending.py +0 -0
  149. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/state_spending.py +0 -0
  150. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/subaward.py +0 -0
  151. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/subtier_agency.py +0 -0
  152. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/models/treasury_account_symbol.py +0 -0
  153. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/agency_query.py +0 -0
  154. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/award_accounts_query.py +0 -0
  155. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/award_query.py +0 -0
  156. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/awarding_agencies_search.py +0 -0
  157. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/federal_accounts_query.py +0 -0
  158. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/filter_tree_query.py +0 -0
  159. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/funding_agencies_search.py +0 -0
  160. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/funding_search.py +0 -0
  161. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/idv_child_awards.py +0 -0
  162. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/recipient_query.py +0 -0
  163. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/recipients_search.py +0 -0
  164. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/single_resource_base.py +0 -0
  165. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/spending_search.py +0 -0
  166. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/subawards_search.py +0 -0
  167. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/tas_agencies_query.py +0 -0
  168. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/queries/tas_codes_query.py +0 -0
  169. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/agency_resource.py +0 -0
  170. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/award_accounts_resource.py +0 -0
  171. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/award_resource.py +0 -0
  172. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/base_resource.py +0 -0
  173. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/download_resource.py +0 -0
  174. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/funding_resource.py +0 -0
  175. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/recipients_resource.py +0 -0
  176. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/spending_resource.py +0 -0
  177. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/subawards_resource.py +0 -0
  178. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/resources/tas_resource.py +0 -0
  179. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/__init__.py +0 -0
  180. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/dates.py +0 -0
  181. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/numbers.py +0 -0
  182. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/rate_limit.py +0 -0
  183. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/retry.py +0 -0
  184. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/special_cases.yaml +0 -0
  185. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/textcase.py +0 -0
  186. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/src/usaspending/utils/validations.py +0 -0
  187. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/__init__.py +0 -0
  188. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/agency.json +0 -0
  189. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/agency_autocomplete.json +0 -0
  190. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/agency_award_summary.json +0 -0
  191. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/agency_subagencies.json +0 -0
  192. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/accounts.json +0 -0
  193. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/award_funding_grant.json +0 -0
  194. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/contract.json +0 -0
  195. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/grant.json +0 -0
  196. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/idv.json +0 -0
  197. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/idv_awards.json +0 -0
  198. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/loan.json +0 -0
  199. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/search_results_contracts.json +0 -0
  200. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/search_results_grants.json +0 -0
  201. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/search_results_idvs.json +0 -0
  202. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/search_results_subawards.json +0 -0
  203. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/awards/transactions.json +0 -0
  204. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/download_assistance.json +0 -0
  205. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/download_search.json +0 -0
  206. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/download_status.json +0 -0
  207. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/recipient_university.json +0 -0
  208. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/recipients_search.json +0 -0
  209. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_award_contracts.json +0 -0
  210. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_district.json +0 -0
  211. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_recipient.json +0 -0
  212. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/spending_by_state.json +0 -0
  213. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/tas_agencies.json +0 -0
  214. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/tas_codes.json +0 -0
  215. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/tas_federal_accounts.json +0 -0
  216. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/top_recipients_params.json +0 -0
  217. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/fixtures/top_recipients_response.json +0 -0
  218. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/mocks/__init__.py +0 -0
  219. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/mocks/response_builder.py +0 -0
  220. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/mocks/test_mock_client.py +0 -0
  221. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/__init__.py +0 -0
  222. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_agency.py +0 -0
  223. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_agency_subagencies.py +0 -0
  224. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_agency_tas_integration.py +0 -0
  225. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_account.py +0 -0
  226. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_agency_integration.py +0 -0
  227. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_decimal_precision.py +0 -0
  228. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_factory.py +0 -0
  229. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_identifier.py +0 -0
  230. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_lazy_loading.py +0 -0
  231. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_office_integration.py +0 -0
  232. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_award_type_constants.py +0 -0
  233. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_base_model.py +0 -0
  234. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_district_spending.py +0 -0
  235. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_federal_account.py +0 -0
  236. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_funding.py +0 -0
  237. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_period_of_performance.py +0 -0
  238. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_recipient_business_categories.py +0 -0
  239. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_spending.py +0 -0
  240. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_state_spending.py +0 -0
  241. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_subtier_agency.py +0 -0
  242. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/models/test_treasury_account_symbol.py +0 -0
  243. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_agency_query.py +0 -0
  244. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_award_accounts_query.py +0 -0
  245. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_awards_search.py +0 -0
  246. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_client_side_query_builder.py +0 -0
  247. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_federal_accounts_query.py +0 -0
  248. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_funding_search.py +0 -0
  249. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_idv_child_awards.py +0 -0
  250. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_query_builder.py +0 -0
  251. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_query_builder_list_behavior.py +0 -0
  252. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_query_builder_pagination.py +0 -0
  253. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_recipient_query.py +0 -0
  254. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_recipients_search.py +0 -0
  255. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_single_resource_base.py +0 -0
  256. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_spending_search.py +0 -0
  257. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_spending_search_count.py +0 -0
  258. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_sub_agency_query.py +0 -0
  259. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_tas_agencies_query.py +0 -0
  260. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/queries/test_tas_codes_query.py +0 -0
  261. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_agency_resource.py +0 -0
  262. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_award_resource.py +0 -0
  263. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_funding_resource.py +0 -0
  264. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_recipients_resource.py +0 -0
  265. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_spending_resource.py +0 -0
  266. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_subawards_resource.py +0 -0
  267. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/resources/test_tas_resource.py +0 -0
  268. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_award_accounts_integration.py +0 -0
  269. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_cache_fallback.py +0 -0
  270. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_characterization.py +0 -0
  271. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_client_caching.py +0 -0
  272. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_client_funding.py +0 -0
  273. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_client_rate_limit.py +0 -0
  274. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_client_security.py +0 -0
  275. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_config.py +0 -0
  276. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_exceptions.py +0 -0
  277. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_logging_config.py +0 -0
  278. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_mock_client_example.py +0 -0
  279. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_public_api_surface.py +0 -0
  280. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/test_spending_integration.py +0 -0
  281. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/__init__.py +0 -0
  282. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/decimal_helpers.py +0 -0
  283. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_dates.py +0 -0
  284. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_doctests.py +0 -0
  285. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_numbers.py +0 -0
  286. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_rate_limit.py +0 -0
  287. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_retry.py +0 -0
  288. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_retry_session_reset.py +0 -0
  289. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_special_cases_data.py +0 -0
  290. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_textcase.py +0 -0
  291. {usaspending_orm-0.8.0 → usaspending_orm-0.9.1}/tests/utils/test_validations.py +0 -0
@@ -4,6 +4,7 @@ __pycache__
4
4
  .*_cache
5
5
  repomix*
6
6
  dist/
7
+ site/
7
8
  .claude/
8
9
  /~/
9
10
  .coverage
@@ -0,0 +1,17 @@
1
+ version: 2
2
+
3
+ build:
4
+ os: ubuntu-24.04
5
+ tools:
6
+ python: "3.13"
7
+
8
+ python:
9
+ install:
10
+ - method: uv
11
+ command: sync
12
+ groups:
13
+ - docs
14
+
15
+ mkdocs:
16
+ configuration: mkdocs.yml
17
+ fail_on_warning: true
@@ -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__`
@@ -1,4 +1,4 @@
1
- Copyright 2025 Casey Dreier
1
+ Copyright 2025 Casey Dreier/The Planetary Society
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the “Software”), to deal
@@ -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
+ [![Tests](https://github.com/planetary-society/usaspending-orm/actions/workflows/test.yml/badge.svg)](https://github.com/planetary-society/usaspending-orm/actions/workflows/test.yml)
33
+ [![PyPI](https://img.shields.io/pypi/v/usaspending-orm.svg)](https://pypi.org/project/usaspending-orm/)
34
+ [![Python](https://img.shields.io/pypi/pyversions/usaspending-orm.svg)](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
+ [![Tests](https://github.com/planetary-society/usaspending-orm/actions/workflows/test.yml/badge.svg)](https://github.com/planetary-society/usaspending-orm/actions/workflows/test.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/usaspending-orm.svg)](https://pypi.org/project/usaspending-orm/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/usaspending-orm.svg)](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.