tango-python 0.4.1__tar.gz → 0.4.3__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 (235) hide show
  1. {tango_python-0.4.1 → tango_python-0.4.3}/.github/workflows/lint.yml +7 -4
  2. {tango_python-0.4.1 → tango_python-0.4.3}/CHANGELOG.md +26 -0
  3. {tango_python-0.4.1 → tango_python-0.4.3}/PKG-INFO +57 -29
  4. {tango_python-0.4.1 → tango_python-0.4.3}/README.md +56 -28
  5. {tango_python-0.4.1 → tango_python-0.4.3}/docs/API_REFERENCE.md +528 -26
  6. {tango_python-0.4.1 → tango_python-0.4.3}/docs/SHAPES.md +1 -1
  7. {tango_python-0.4.1 → tango_python-0.4.3}/docs/quick_start.ipynb +66 -51
  8. {tango_python-0.4.1 → tango_python-0.4.3}/pyproject.toml +1 -1
  9. {tango_python-0.4.1 → tango_python-0.4.3}/scripts/check_filter_shape_conformance.py +0 -1
  10. {tango_python-0.4.1 → tango_python-0.4.3}/scripts/pr_review.py +24 -5
  11. {tango_python-0.4.1 → tango_python-0.4.3}/tango/__init__.py +3 -1
  12. {tango_python-0.4.1 → tango_python-0.4.3}/tango/client.py +158 -68
  13. {tango_python-0.4.1 → tango_python-0.4.3}/tango/exceptions.py +28 -1
  14. {tango_python-0.4.1 → tango_python-0.4.3}/tango/models.py +46 -1
  15. {tango_python-0.4.1 → tango_python-0.4.3}/tango/shapes/explicit_schemas.py +53 -0
  16. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestAgenciesIntegration.test_get_agency +15 -23
  17. tango_python-0.4.3/tests/cassettes/TestAgenciesIntegration.test_list_agencies +89 -0
  18. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestBusinessTypesIntegration.test_business_type_field_type_validation +15 -17
  19. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestBusinessTypesIntegration.test_business_type_parsing_consistency +15 -17
  20. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestBusinessTypesIntegration.test_list_business_types +15 -17
  21. tango_python-0.4.1/tests/cassettes/TestOfficesIntegration.test_get_office → tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_combined_filters_work_together +16 -18
  22. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_contract_cursor_pagination +174 -0
  23. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_contract_data_object_parsing +86 -0
  24. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_contract_field_types +100 -0
  25. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_filter_parameter_mappings[keyword-software] +94 -0
  26. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_filter_parameter_mappings[psc_code-R425] +86 -0
  27. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_list_contracts_with_awarding_agency_filter +91 -0
  28. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_list_contracts_with_date_range_filter +86 -0
  29. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_list_contracts_with_flat +86 -0
  30. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_list_contracts_with_naics_code_filter +196 -0
  31. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[custom-key,piid,recipient(display_name),total_contract_value,award_date] +81 -0
  32. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[default-None] +86 -0
  33. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[detailed-key,piid,award_date,description,total_contract_value,obligated,fiscal_year,set_aside,recipient(display_name,uei),awarding_office(-),place_of_performa...ce114a3c47e2037aaa3c15d00b7031bd +100 -0
  34. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[minimal-key,piid,award_date,recipient(display_name),description,total_contract_value] +86 -0
  35. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_new_expiring_filters +86 -0
  36. tango_python-0.4.1/tests/cassettes/TestAssistanceIntegration.test_list_assistance → tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_new_fiscal_year_range_filters +11 -11
  37. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestContractsIntegration.test_new_identifier_filters +13 -15
  38. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_search_contracts_with_filters +86 -0
  39. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_search_filters_object_with_new_parameters +89 -0
  40. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_sort_and_order_mapped_to_ordering[asc-] +86 -0
  41. tango_python-0.4.3/tests/cassettes/TestContractsIntegration.test_sort_and_order_mapped_to_ordering[desc--] +86 -0
  42. tango_python-0.4.3/tests/cassettes/TestEdgeCasesIntegration.test_api_schema_stability_detection_contracts +86 -0
  43. tango_python-0.4.3/tests/cassettes/TestEdgeCasesIntegration.test_api_schema_stability_detection_entities +141 -0
  44. tango_python-0.4.3/tests/cassettes/TestEdgeCasesIntegration.test_date_field_parsing_edge_cases +131 -0
  45. tango_python-0.4.3/tests/cassettes/TestEdgeCasesIntegration.test_decimal_field_parsing_edge_cases +126 -0
  46. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestEdgeCasesIntegration.test_empty_list_responses +13 -15
  47. tango_python-0.4.3/tests/cassettes/TestEdgeCasesIntegration.test_entity_parsing_with_various_address_formats +217 -0
  48. tango_python-0.4.3/tests/cassettes/TestEdgeCasesIntegration.test_flattened_responses_with_flat_lists +86 -0
  49. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestEdgeCasesIntegration.test_list_field_parsing_consistency +73 -91
  50. tango_python-0.4.3/tests/cassettes/TestEdgeCasesIntegration.test_parsing_nested_objects_with_missing_data +224 -0
  51. tango_python-0.4.3/tests/cassettes/TestEdgeCasesIntegration.test_parsing_null_missing_fields_in_contracts +126 -0
  52. tango_python-0.4.3/tests/cassettes/TestEdgeCasesIntegration.test_parsing_with_minimal_shape_sparse_data +86 -0
  53. tango_python-0.4.3/tests/cassettes/TestEntitiesIntegration.test_entity_field_types +217 -0
  54. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestEntitiesIntegration.test_entity_location_parsing +73 -91
  55. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestEntitiesIntegration.test_entity_parsing_with_business_types +73 -91
  56. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestEntitiesIntegration.test_entity_with_various_identifiers +59 -77
  57. tango_python-0.4.3/tests/cassettes/TestEntitiesIntegration.test_get_entity_by_uei +231 -0
  58. tango_python-0.4.3/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_flat +86 -0
  59. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_search +22 -20
  60. tango_python-0.4.3/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_shapes[comprehensive-uei,legal_business_name,dba_name,cage_code,business_types,primary_naics,naics_codes,psc_codes,email_address,entity_url,description,capabilities,ke...1603a7d52e211cf2b3bc7d32080238aa +116 -0
  61. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_shapes[custom-uei,legal_business_name,cage_code] +17 -20
  62. tango_python-0.4.3/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_shapes[minimal-uei,legal_business_name,cage_code,business_types] +99 -0
  63. tango_python-0.4.3/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_shapes[with_address-uei,legal_business_name,cage_code,business_types,physical_address] +105 -0
  64. tango_python-0.4.3/tests/cassettes/TestForecastsIntegration.test_forecast_field_types +86 -0
  65. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestForecastsIntegration.test_list_forecasts_with_shapes[custom-id,title,anticipated_award_date] +17 -19
  66. tango_python-0.4.1/tests/cassettes/TestForecastsIntegration.test_list_forecasts_with_shapes[minimal-id,title,anticipated_award_date,fiscal_year,naics_code,status] → tango_python-0.4.3/tests/cassettes/TestForecastsIntegration.test_list_forecasts_with_shapes[default-None] +16 -18
  67. tango_python-0.4.3/tests/cassettes/TestForecastsIntegration.test_list_forecasts_with_shapes[detailed-id,source_system,external_id,title,description,anticipated_award_date,fiscal_year,naics_code,status,is_active] +140 -0
  68. tango_python-0.4.1/tests/cassettes/TestForecastsIntegration.test_list_forecasts_with_shapes[default-None] → tango_python-0.4.3/tests/cassettes/TestForecastsIntegration.test_list_forecasts_with_shapes[minimal-id,title,anticipated_award_date,fiscal_year,naics_code,status] +17 -19
  69. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestGrantsIntegration.test_grant_field_types +13 -15
  70. tango_python-0.4.3/tests/cassettes/TestGrantsIntegration.test_grant_pagination +160 -0
  71. tango_python-0.4.3/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[custom-grant_id,title,opportunity_number] +81 -0
  72. tango_python-0.4.3/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[default-None] +81 -0
  73. tango_python-0.4.3/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[detailed-grant_id,opportunity_number,title,status(-),agency_code,description,last_updated,cfda_numbers(number,title),applicant_types(-),funding_categories(-)] +244 -0
  74. tango_python-0.4.3/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[minimal-grant_id,opportunity_number,title,status(-),agency_code] +81 -0
  75. tango_python-0.4.3/tests/cassettes/TestIDVsIntegration.test_get_idv_uses_default_shape +174 -0
  76. tango_python-0.4.3/tests/cassettes/TestIDVsIntegration.test_list_idv_awards_uses_default_shape +155 -0
  77. tango_python-0.4.3/tests/cassettes/TestIDVsIntegration.test_list_idv_child_idvs_uses_default_shape +155 -0
  78. tango_python-0.4.3/tests/cassettes/TestIDVsIntegration.test_list_idv_transactions +159 -0
  79. tango_python-0.4.3/tests/cassettes/TestIDVsIntegration.test_list_idvs_uses_default_shape_and_keyset_params +96 -0
  80. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestNaicsIntegration.test_list_naics +15 -15
  81. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestNoticesIntegration.test_list_notices_with_shapes[custom-notice_id,title,solicitation_number] +12 -14
  82. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestNoticesIntegration.test_list_notices_with_shapes[default-None] +12 -14
  83. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestNoticesIntegration.test_list_notices_with_shapes[detailed-notice_id,title,description,solicitation_number,posted_date,naics_code,set_aside,office(-),place_of_performance(-)] +12 -14
  84. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestNoticesIntegration.test_list_notices_with_shapes[minimal-notice_id,title,solicitation_number,posted_date] +12 -14
  85. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestNoticesIntegration.test_notice_field_types +12 -14
  86. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestNoticesIntegration.test_notice_pagination +24 -28
  87. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestNoticesIntegration.test_notice_with_meta_fields +24 -26
  88. tango_python-0.4.3/tests/cassettes/TestOTAsIntegration.test_get_ota +154 -0
  89. tango_python-0.4.3/tests/cassettes/TestOTAsIntegration.test_list_otas +87 -0
  90. tango_python-0.4.3/tests/cassettes/TestOTIDVsIntegration.test_get_otidv +154 -0
  91. tango_python-0.4.3/tests/cassettes/TestOTIDVsIntegration.test_list_otidvs +88 -0
  92. tango_python-0.4.3/tests/cassettes/TestOfficesIntegration.test_get_office +154 -0
  93. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestOfficesIntegration.test_list_offices +15 -15
  94. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestOpportunitiesIntegration.test_list_opportunities_with_shapes[custom-opportunity_id,title,solicitation_number] +17 -18
  95. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestOpportunitiesIntegration.test_list_opportunities_with_shapes[default-None] +17 -18
  96. tango_python-0.4.3/tests/cassettes/TestOpportunitiesIntegration.test_list_opportunities_with_shapes[detailed-opportunity_id,title,description,solicitation_number,response_deadline,first_notice_date,last_notice_date,active,naics_code,psc_code,set_asid...23b6b4502ddd665b7184afcff6c6d8d9 +138 -0
  97. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestOpportunitiesIntegration.test_list_opportunities_with_shapes[minimal-opportunity_id,title,solicitation_number,response_deadline,active] +17 -18
  98. tango_python-0.4.3/tests/cassettes/TestOpportunitiesIntegration.test_opportunity_field_types +87 -0
  99. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestOrganizationsIntegration.test_get_organization +30 -30
  100. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestOrganizationsIntegration.test_list_organizations +22 -22
  101. tango_python-0.4.3/tests/cassettes/TestProtestsIntegration.test_get_protest_by_case_id +152 -0
  102. tango_python-0.4.3/tests/cassettes/TestProtestsIntegration.test_list_protests_with_filter +81 -0
  103. tango_python-0.4.3/tests/cassettes/TestProtestsIntegration.test_list_protests_with_shapes[custom-case_id,title,source_system,outcome] +81 -0
  104. tango_python-0.4.3/tests/cassettes/TestProtestsIntegration.test_list_protests_with_shapes[default-None] +81 -0
  105. tango_python-0.4.3/tests/cassettes/TestProtestsIntegration.test_list_protests_with_shapes[minimal-case_id,case_number,title,source_system,outcome,filed_date] +81 -0
  106. tango_python-0.4.3/tests/cassettes/TestProtestsIntegration.test_list_protests_with_shapes[with_dockets-case_id,case_number,title,outcome,filed_date,dockets(docket_number,filed_date,outcome)] +81 -0
  107. tango_python-0.4.3/tests/cassettes/TestProtestsIntegration.test_protest_pagination +160 -0
  108. tango_python-0.4.3/tests/cassettes/TestSubawardsIntegration.test_list_subawards +95 -0
  109. tango_python-0.4.3/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[custom-key,piid,description] +81 -0
  110. tango_python-0.4.3/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[minimal-key,piid,award_date,recipient(display_name),description,total_contract_value] +86 -0
  111. tango_python-0.4.3/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[ultra_minimal-key,piid,recipient(display_name),total_contract_value] +81 -0
  112. tango_python-0.4.3/tests/cassettes/TestTypeHintsIntegration.test_entities_dict_access[minimal-uei,legal_business_name,cage_code,business_types] +99 -0
  113. tango_python-0.4.3/tests/cassettes/TestTypeHintsIntegration.test_entities_dict_access[with_address-uei,legal_business_name,cage_code,business_types,physical_address] +105 -0
  114. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestTypeHintsIntegration.test_notices_dict_access[detailed-notice_id,title,description,solicitation_number,posted_date,naics_code,set_aside,office(-),place_of_performance(-)] +12 -14
  115. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestTypeHintsIntegration.test_notices_dict_access[minimal-notice_id,title,solicitation_number,posted_date] +12 -14
  116. tango_python-0.4.3/tests/cassettes/TestTypeHintsIntegration.test_opportunities_dict_access[detailed-opportunity_id,title,description,solicitation_number,response_deadline,first_notice_date,last_notice_date,active,naics_code,psc_code,set_aside,sam_url,office(-),place_of_performance(-)] +138 -0
  117. {tango_python-0.4.1 → tango_python-0.4.3}/tests/cassettes/TestTypeHintsIntegration.test_opportunities_dict_access[minimal-opportunity_id,title,solicitation_number,response_deadline,active] +17 -18
  118. tango_python-0.4.3/tests/cassettes/TestVehiclesIntegration.test_get_vehicle_supports_joiner_and_flat_lists +152 -0
  119. tango_python-0.4.3/tests/cassettes/TestVehiclesIntegration.test_list_vehicle_awardees_uses_default_shape +169 -0
  120. tango_python-0.4.3/tests/cassettes/TestVehiclesIntegration.test_list_vehicles_uses_default_shape_and_search +86 -0
  121. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/conftest.py +20 -20
  122. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_contracts_integration.py +13 -5
  123. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_edge_cases_integration.py +12 -4
  124. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_entities_integration.py +0 -1
  125. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_grants_integration.py +0 -1
  126. tango_python-0.4.3/tests/integration/test_protests_integration.py +214 -0
  127. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_vehicles_idvs_integration.py +3 -76
  128. {tango_python-0.4.1 → tango_python-0.4.3}/tests/production/test_production_smoke.py +0 -21
  129. {tango_python-0.4.1 → tango_python-0.4.3}/tests/test_client.py +86 -29
  130. {tango_python-0.4.1 → tango_python-0.4.3}/uv.lock +1 -1
  131. tango_python-0.4.1/tests/cassettes/TestAgenciesIntegration.test_list_agencies +0 -98
  132. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_combined_filters_work_together +0 -92
  133. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_contract_cursor_pagination +0 -169
  134. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_contract_data_object_parsing +0 -92
  135. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_contract_field_types +0 -102
  136. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_filter_parameter_mappings[keyword-software] +0 -180
  137. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_filter_parameter_mappings[psc_code-R425] +0 -180
  138. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_list_contracts_with_awarding_agency_filter +0 -182
  139. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_list_contracts_with_date_range_filter +0 -174
  140. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_list_contracts_with_flat +0 -92
  141. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_list_contracts_with_naics_code_filter +0 -408
  142. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[custom-key,piid,recipient(display_name),total_contract_value,award_date] +0 -83
  143. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[default-None] +0 -92
  144. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[detailed-key,piid,award_date,description,total_contract_value,obligated,fiscal_year,set_aside,recipient(display_name,uei),awarding_office(-),place_of_performa...ce114a3c47e2037aaa3c15d00b7031bd +0 -218
  145. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[minimal-key,piid,award_date,recipient(display_name),description,total_contract_value] +0 -92
  146. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_new_expiring_filters +0 -88
  147. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_new_fiscal_year_range_filters +0 -88
  148. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_search_contracts_with_filters +0 -174
  149. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_search_filters_object_with_new_parameters +0 -88
  150. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_sort_and_order_mapped_to_ordering[asc-] +0 -88
  151. tango_python-0.4.1/tests/cassettes/TestContractsIntegration.test_sort_and_order_mapped_to_ordering[desc--] +0 -92
  152. tango_python-0.4.1/tests/cassettes/TestEdgeCasesIntegration.test_api_schema_stability_detection_contracts +0 -88
  153. tango_python-0.4.1/tests/cassettes/TestEdgeCasesIntegration.test_api_schema_stability_detection_entities +0 -142
  154. tango_python-0.4.1/tests/cassettes/TestEdgeCasesIntegration.test_date_field_parsing_edge_cases +0 -143
  155. tango_python-0.4.1/tests/cassettes/TestEdgeCasesIntegration.test_decimal_field_parsing_edge_cases +0 -128
  156. tango_python-0.4.1/tests/cassettes/TestEdgeCasesIntegration.test_entity_parsing_with_various_address_formats +0 -228
  157. tango_python-0.4.1/tests/cassettes/TestEdgeCasesIntegration.test_flattened_responses_with_flat_lists +0 -92
  158. tango_python-0.4.1/tests/cassettes/TestEdgeCasesIntegration.test_parsing_nested_objects_with_missing_data +0 -289
  159. tango_python-0.4.1/tests/cassettes/TestEdgeCasesIntegration.test_parsing_null_missing_fields_in_contracts +0 -128
  160. tango_python-0.4.1/tests/cassettes/TestEdgeCasesIntegration.test_parsing_with_minimal_shape_sparse_data +0 -88
  161. tango_python-0.4.1/tests/cassettes/TestEntitiesIntegration.test_entity_field_types +0 -228
  162. tango_python-0.4.1/tests/cassettes/TestEntitiesIntegration.test_get_entity_by_uei +0 -254
  163. tango_python-0.4.1/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_flat +0 -90
  164. tango_python-0.4.1/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_shapes[comprehensive-uei,legal_business_name,dba_name,cage_code,business_types,primary_naics,naics_codes,psc_codes,email_address,entity_url,description,capabilities,ke...95fcff7efcf320ecc846393dd484321d +0 -115
  165. tango_python-0.4.1/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_shapes[minimal-uei,legal_business_name,cage_code,business_types] +0 -102
  166. tango_python-0.4.1/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_shapes[with_address-uei,legal_business_name,cage_code,business_types,physical_address] +0 -107
  167. tango_python-0.4.1/tests/cassettes/TestForecastsIntegration.test_forecast_field_types +0 -88
  168. tango_python-0.4.1/tests/cassettes/TestForecastsIntegration.test_list_forecasts_with_shapes[detailed-id,source_system,external_id,title,description,anticipated_award_date,fiscal_year,naics_code,status,is_active] +0 -107
  169. tango_python-0.4.1/tests/cassettes/TestGrantsIntegration.test_grant_pagination +0 -171
  170. tango_python-0.4.1/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[custom-grant_id,title,opportunity_number] +0 -87
  171. tango_python-0.4.1/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[default-None] +0 -87
  172. tango_python-0.4.1/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[detailed-grant_id,opportunity_number,title,status(-),agency_code,description,last_updated,cfda_numbers(number,title),applicant_types(-),funding_categories(-)] +0 -179
  173. tango_python-0.4.1/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[minimal-grant_id,opportunity_number,title,status(-),agency_code] +0 -87
  174. tango_python-0.4.1/tests/cassettes/TestIDVsIntegration.test_get_idv_summary +0 -252
  175. tango_python-0.4.1/tests/cassettes/TestIDVsIntegration.test_get_idv_uses_default_shape +0 -494
  176. tango_python-0.4.1/tests/cassettes/TestIDVsIntegration.test_list_idv_awards_uses_default_shape +0 -302
  177. tango_python-0.4.1/tests/cassettes/TestIDVsIntegration.test_list_idv_child_idvs_uses_default_shape +0 -302
  178. tango_python-0.4.1/tests/cassettes/TestIDVsIntegration.test_list_idv_summary_awards +0 -256
  179. tango_python-0.4.1/tests/cassettes/TestIDVsIntegration.test_list_idv_transactions +0 -304
  180. tango_python-0.4.1/tests/cassettes/TestIDVsIntegration.test_list_idvs_uses_default_shape_and_keyset_params +0 -284
  181. tango_python-0.4.1/tests/cassettes/TestOTAsIntegration.test_get_ota +0 -306
  182. tango_python-0.4.1/tests/cassettes/TestOTAsIntegration.test_list_otas +0 -170
  183. tango_python-0.4.1/tests/cassettes/TestOTIDVsIntegration.test_get_otidv +0 -310
  184. tango_python-0.4.1/tests/cassettes/TestOTIDVsIntegration.test_list_otidvs +0 -176
  185. tango_python-0.4.1/tests/cassettes/TestOpportunitiesIntegration.test_list_opportunities_with_shapes[detailed-opportunity_id,title,description,solicitation_number,response_deadline,first_notice_date,last_notice_date,active,naics_code,psc_code,set_asid...23b6b4502ddd665b7184afcff6c6d8d9 +0 -129
  186. tango_python-0.4.1/tests/cassettes/TestOpportunitiesIntegration.test_opportunity_field_types +0 -83
  187. tango_python-0.4.1/tests/cassettes/TestProductionSmokeWithCassettes.test_contract_cursor_pagination +0 -169
  188. tango_python-0.4.1/tests/cassettes/TestSubawardsIntegration.test_list_subawards +0 -95
  189. tango_python-0.4.1/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[custom-key,piid,description] +0 -87
  190. tango_python-0.4.1/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[minimal-key,piid,award_date,recipient(display_name),description,total_contract_value] +0 -92
  191. tango_python-0.4.1/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[ultra_minimal-key,piid,recipient(display_name),total_contract_value] +0 -83
  192. tango_python-0.4.1/tests/cassettes/TestTypeHintsIntegration.test_entities_dict_access[minimal-uei,legal_business_name,cage_code,business_types] +0 -102
  193. tango_python-0.4.1/tests/cassettes/TestTypeHintsIntegration.test_entities_dict_access[with_address-uei,legal_business_name,cage_code,business_types,physical_address] +0 -107
  194. tango_python-0.4.1/tests/cassettes/TestTypeHintsIntegration.test_opportunities_dict_access[detailed-opportunity_id,title,description,solicitation_number,response_deadline,first_notice_date,last_notice_date,active,naics_code,psc_code,set_aside,sam_url,office(-),place_of_performance(-)] +0 -129
  195. tango_python-0.4.1/tests/cassettes/TestVehiclesIntegration.test_get_vehicle_supports_joiner_and_flat_lists +0 -1352
  196. tango_python-0.4.1/tests/cassettes/TestVehiclesIntegration.test_list_vehicle_awardees_uses_default_shape +0 -1505
  197. tango_python-0.4.1/tests/cassettes/TestVehiclesIntegration.test_list_vehicles_uses_default_shape_and_search +0 -812
  198. tango_python-0.4.1/tests/integration/test_assistance_integration.py +0 -46
  199. {tango_python-0.4.1 → tango_python-0.4.3}/.env.example +0 -0
  200. {tango_python-0.4.1 → tango_python-0.4.3}/.github/workflows/publish.yml +0 -0
  201. {tango_python-0.4.1 → tango_python-0.4.3}/.github/workflows/test.yml +0 -0
  202. {tango_python-0.4.1 → tango_python-0.4.3}/.gitignore +0 -0
  203. {tango_python-0.4.1 → tango_python-0.4.3}/LICENSE +0 -0
  204. {tango_python-0.4.1 → tango_python-0.4.3}/ROADMAP.md +0 -0
  205. {tango_python-0.4.1 → tango_python-0.4.3}/docs/DEVELOPERS.md +0 -0
  206. {tango_python-0.4.1 → tango_python-0.4.3}/scripts/README.md +0 -0
  207. {tango_python-0.4.1 → tango_python-0.4.3}/scripts/fetch_api_schema.py +0 -0
  208. {tango_python-0.4.1 → tango_python-0.4.3}/scripts/generate_schemas_from_api.py +0 -0
  209. {tango_python-0.4.1 → tango_python-0.4.3}/scripts/test_production.py +0 -0
  210. {tango_python-0.4.1 → tango_python-0.4.3}/tango/shapes/__init__.py +0 -0
  211. {tango_python-0.4.1 → tango_python-0.4.3}/tango/shapes/factory.py +0 -0
  212. {tango_python-0.4.1 → tango_python-0.4.3}/tango/shapes/generator.py +0 -0
  213. {tango_python-0.4.1 → tango_python-0.4.3}/tango/shapes/models.py +0 -0
  214. {tango_python-0.4.1 → tango_python-0.4.3}/tango/shapes/parser.py +0 -0
  215. {tango_python-0.4.1 → tango_python-0.4.3}/tango/shapes/schema.py +0 -0
  216. {tango_python-0.4.1 → tango_python-0.4.3}/tango/shapes/types.py +0 -0
  217. {tango_python-0.4.1 → tango_python-0.4.3}/tests/__init__.py +0 -0
  218. {tango_python-0.4.1 → tango_python-0.4.3}/tests/conftest.py +0 -0
  219. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/README.md +0 -0
  220. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/__init__.py +0 -0
  221. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_agencies_integration.py +0 -0
  222. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_forecasts_integration.py +0 -0
  223. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_naics_integration.py +0 -0
  224. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_notices_integration.py +0 -0
  225. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_offices_integration.py +0 -0
  226. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_opportunities_integration.py +0 -0
  227. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_organizations_integration.py +0 -0
  228. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_otas_otidvs_integration.py +0 -0
  229. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_reference_data_integration.py +0 -0
  230. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/test_subawards_integration.py +0 -0
  231. {tango_python-0.4.1 → tango_python-0.4.3}/tests/integration/validation.py +0 -0
  232. {tango_python-0.4.1 → tango_python-0.4.3}/tests/production/__init__.py +0 -0
  233. {tango_python-0.4.1 → tango_python-0.4.3}/tests/production/conftest.py +0 -0
  234. {tango_python-0.4.1 → tango_python-0.4.3}/tests/test_models.py +0 -0
  235. {tango_python-0.4.1 → tango_python-0.4.3}/tests/test_shapes.py +0 -0
@@ -1,10 +1,13 @@
1
1
  name: Linting
2
2
 
3
+ # Disabled: requires checkout of private makegov/tango repo for filter_shape conformance check.
4
+ # Re-enable when that repo is accessible (e.g. add TANGO_API_REPO_ACCESS_TOKEN secret).
3
5
  on:
4
- push:
5
- branches: [ main, develop ]
6
- pull_request:
7
- branches: [ main, develop ]
6
+ workflow_dispatch:
7
+ # push:
8
+ # branches: [ main, develop ]
9
+ # pull_request:
10
+ # branches: [ main, develop ]
8
11
 
9
12
  jobs:
10
13
  lint:
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.4.3] - 2026-03-21
11
+
12
+ ### Added
13
+ - `TangoRateLimitError` now exposes `wait_in_seconds`, `detail`, and `limit_type` properties parsed from the API's 429 response body.
14
+ - `RateLimitInfo` dataclass for structured access to rate limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`, and per-window daily/burst variants).
15
+ - `TangoClient.rate_limit_info` property returns rate limit info from the most recent API response.
16
+
17
+ ### Changed
18
+ - `_request` now passes the full 429 response body to `TangoRateLimitError` (previously discarded), enabling callers to access `wait_in_seconds` and the specific limit type that was exceeded.
19
+
20
+ ## [0.4.2] - 2026-03-04
21
+
22
+ ### Added
23
+ - Protests endpoints: `list_protests`, `get_protest` with shaping and filter params (`source_system`, `outcome`, `case_type`, `agency`, `case_number`, `solicitation_number`, `protester`, `filed_date_after`, `filed_date_before`, `decision_date_after`, `decision_date_before`, `search`).
24
+
25
+ ### Changed
26
+ - Lint CI workflow disabled for push/PR (runs only on manual trigger) until the private `makegov/tango` repo is accessible to the workflow.
27
+ - Updated documents to reflect changes since v0.4.0
28
+ - Entities: `ENTITIES_COMPREHENSIVE` now uses `federal_obligations(*)` expansion; the API treats federal obligations as an expansion rather than a plain shape field.
29
+ - Docs: `SHAPES.md` documents `federal_obligations(*)` as an expansion for entity shaping.
30
+ - Integration tests: `test_parsing_nested_objects_with_missing_data` accepts award office fields (`office_code`, `agency_code`, `department_code`) and empty nested objects when the API returns partial data.
31
+
32
+ ### Removed
33
+ - Assistance: `list_assistance` endpoint and all related tests, docs, and references.
34
+ - IDV summaries: `get_idv_summary` and `list_idv_summary_awards` endpoints and related integration tests, cassettes, and API reference section.
35
+
10
36
  ## [0.4.1] - 2026-03-03
11
37
 
12
38
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tango-python
3
- Version: 0.4.1
3
+ Version: 0.4.3
4
4
  Summary: Python SDK for the Tango API
5
5
  Project-URL: Homepage, https://github.com/makegov/tango-python
6
6
  Project-URL: Documentation, https://docs.makegov.com/tango-python
@@ -61,7 +61,7 @@ A modern Python SDK for the [Tango API](https://tango.makegov.com) by MakeGov, f
61
61
 
62
62
  - **Dynamic Response Shaping** - Request only the fields you need, reducing payload sizes by 60-80%
63
63
  - **Full Type Safety** - Runtime-generated TypedDict types with accurate type hints for IDE autocomplete
64
- - **Comprehensive API Coverage** - All major Tango API endpoints (contracts, entities, forecasts, opportunities, notices, grants, webhooks) [Note: the current version does NOT implement all endpoints, we will be adding them incrementally]
64
+ - **Comprehensive API Coverage** - All major Tango API endpoints (contracts, IDVs, OTAs, entities, forecasts, opportunities, notices, grants, protests, webhooks, and more)
65
65
  - **Flexible Data Access** - Dictionary-based response objects with validation
66
66
  - **Modern Python** - Built for Python 3.12+ using modern async-ready patterns
67
67
  - **Production-Ready** - Comprehensive test suite with VCR.py-based integration tests
@@ -207,14 +207,33 @@ contracts = client.list_contracts(
207
207
  **Response Options:**
208
208
  - `shape`, `flat`, `flat_lists` - Response shaping options
209
209
 
210
+ ### IDVs, OTAs, OTIDVs
211
+
212
+ ```python
213
+ # List IDVs (keyset pagination)
214
+ idvs = client.list_idvs(limit=25, awarding_agency="4700")
215
+
216
+ # Get single IDV with shaping
217
+ idv = client.get_idv("IDV_KEY", shape=ShapeConfig.IDVS_COMPREHENSIVE)
218
+
219
+ # OTAs and OTIDVs follow the same pattern
220
+ otas = client.list_otas(limit=25)
221
+ otidvs = client.list_otidvs(limit=25)
222
+ ```
223
+
224
+ ### Vehicles
225
+
226
+ ```python
227
+ vehicles = client.list_vehicles(search="GSA schedule", shape=ShapeConfig.VEHICLES_MINIMAL)
228
+ vehicle = client.get_vehicle("UUID", shape=ShapeConfig.VEHICLES_COMPREHENSIVE)
229
+ awardees = client.list_vehicle_awardees("UUID")
230
+ ```
231
+
210
232
  ### Entities (Vendors/Recipients)
211
233
 
212
234
  ```python
213
- # List entities
214
- entities = client.list_entities(
215
- page=1,
216
- limit=25
217
- )
235
+ # List entities with filters
236
+ entities = client.list_entities(search="Booz Allen", state="VA", limit=25)
218
237
 
219
238
  # Get specific entity by UEI or CAGE code
220
239
  entity = client.get_entity("ZQGGHJH74DW7")
@@ -223,47 +242,49 @@ entity = client.get_entity("ZQGGHJH74DW7")
223
242
  ### Forecasts
224
243
 
225
244
  ```python
226
- # List contract forecasts
227
- forecasts = client.list_forecasts(
228
- agency="GSA",
229
- limit=25
230
- )
245
+ forecasts = client.list_forecasts(agency="GSA", fiscal_year=2025, limit=25)
231
246
  ```
232
247
 
233
248
  ### Opportunities
234
249
 
235
250
  ```python
236
- # List opportunities/solicitations
237
- opportunities = client.list_opportunities(
238
- agency="DOD",
239
- limit=25
240
- )
251
+ opportunities = client.list_opportunities(agency="DOD", active=True, limit=25)
241
252
  ```
242
253
 
243
254
  ### Notices
244
255
 
245
256
  ```python
246
- # List contract notices
247
- notices = client.list_notices(
248
- agency="DOD",
249
- limit=25
250
- )
257
+ notices = client.list_notices(agency="DOD", notice_type="award", limit=25)
251
258
  ```
252
259
 
253
260
  ### Grants
254
261
 
255
262
  ```python
256
- # List grant opportunities
257
- grants = client.list_grants(
258
- agency_code="HHS",
259
- limit=25
260
- )
263
+ grants = client.list_grants(agency="HHS", status="forecasted", limit=25)
264
+ ```
265
+
266
+ ### Protests
267
+
268
+ ```python
269
+ protests = client.list_protests(source_system="gao", outcome="Sustained", limit=25)
270
+ protest = client.get_protest("CASE_UUID")
271
+ ```
272
+
273
+ ### GSA eLibrary Contracts
274
+
275
+ ```python
276
+ contracts = client.list_gsa_elibrary_contracts(schedule="MAS", limit=25)
277
+ contract = client.get_gsa_elibrary_contract("UUID")
261
278
  ```
262
279
 
263
- ### Business Types
280
+ ### Reference Data
264
281
 
265
282
  ```python
266
- # List business types
283
+ # Offices, organizations, NAICS, subawards, business types
284
+ offices = client.list_offices(search="acquisitions")
285
+ organizations = client.list_organizations(level=1)
286
+ naics = client.list_naics(search="software")
287
+ subawards = client.list_subawards(prime_uei="UEI123")
267
288
  business_types = client.list_business_types()
268
289
  ```
269
290
 
@@ -476,9 +497,16 @@ tango-python/
476
497
  │ ├── test_entities_integration.py
477
498
  │ ├── test_forecasts_integration.py
478
499
  │ ├── test_grants_integration.py
500
+ │ ├── test_naics_integration.py
479
501
  │ ├── test_notices_integration.py
502
+ │ ├── test_offices_integration.py
480
503
  │ ├── test_opportunities_integration.py
504
+ │ ├── test_organizations_integration.py
505
+ │ ├── test_otas_otidvs_integration.py
506
+ │ ├── test_protests_integration.py
481
507
  │ ├── test_reference_data_integration.py
508
+ │ ├── test_subawards_integration.py
509
+ │ ├── test_vehicles_idvs_integration.py
482
510
  │ └── test_edge_cases_integration.py
483
511
  ├── docs/ # Documentation
484
512
  │ ├── API_REFERENCE.md # Complete API reference
@@ -6,7 +6,7 @@ A modern Python SDK for the [Tango API](https://tango.makegov.com) by MakeGov, f
6
6
 
7
7
  - **Dynamic Response Shaping** - Request only the fields you need, reducing payload sizes by 60-80%
8
8
  - **Full Type Safety** - Runtime-generated TypedDict types with accurate type hints for IDE autocomplete
9
- - **Comprehensive API Coverage** - All major Tango API endpoints (contracts, entities, forecasts, opportunities, notices, grants, webhooks) [Note: the current version does NOT implement all endpoints, we will be adding them incrementally]
9
+ - **Comprehensive API Coverage** - All major Tango API endpoints (contracts, IDVs, OTAs, entities, forecasts, opportunities, notices, grants, protests, webhooks, and more)
10
10
  - **Flexible Data Access** - Dictionary-based response objects with validation
11
11
  - **Modern Python** - Built for Python 3.12+ using modern async-ready patterns
12
12
  - **Production-Ready** - Comprehensive test suite with VCR.py-based integration tests
@@ -152,14 +152,33 @@ contracts = client.list_contracts(
152
152
  **Response Options:**
153
153
  - `shape`, `flat`, `flat_lists` - Response shaping options
154
154
 
155
+ ### IDVs, OTAs, OTIDVs
156
+
157
+ ```python
158
+ # List IDVs (keyset pagination)
159
+ idvs = client.list_idvs(limit=25, awarding_agency="4700")
160
+
161
+ # Get single IDV with shaping
162
+ idv = client.get_idv("IDV_KEY", shape=ShapeConfig.IDVS_COMPREHENSIVE)
163
+
164
+ # OTAs and OTIDVs follow the same pattern
165
+ otas = client.list_otas(limit=25)
166
+ otidvs = client.list_otidvs(limit=25)
167
+ ```
168
+
169
+ ### Vehicles
170
+
171
+ ```python
172
+ vehicles = client.list_vehicles(search="GSA schedule", shape=ShapeConfig.VEHICLES_MINIMAL)
173
+ vehicle = client.get_vehicle("UUID", shape=ShapeConfig.VEHICLES_COMPREHENSIVE)
174
+ awardees = client.list_vehicle_awardees("UUID")
175
+ ```
176
+
155
177
  ### Entities (Vendors/Recipients)
156
178
 
157
179
  ```python
158
- # List entities
159
- entities = client.list_entities(
160
- page=1,
161
- limit=25
162
- )
180
+ # List entities with filters
181
+ entities = client.list_entities(search="Booz Allen", state="VA", limit=25)
163
182
 
164
183
  # Get specific entity by UEI or CAGE code
165
184
  entity = client.get_entity("ZQGGHJH74DW7")
@@ -168,47 +187,49 @@ entity = client.get_entity("ZQGGHJH74DW7")
168
187
  ### Forecasts
169
188
 
170
189
  ```python
171
- # List contract forecasts
172
- forecasts = client.list_forecasts(
173
- agency="GSA",
174
- limit=25
175
- )
190
+ forecasts = client.list_forecasts(agency="GSA", fiscal_year=2025, limit=25)
176
191
  ```
177
192
 
178
193
  ### Opportunities
179
194
 
180
195
  ```python
181
- # List opportunities/solicitations
182
- opportunities = client.list_opportunities(
183
- agency="DOD",
184
- limit=25
185
- )
196
+ opportunities = client.list_opportunities(agency="DOD", active=True, limit=25)
186
197
  ```
187
198
 
188
199
  ### Notices
189
200
 
190
201
  ```python
191
- # List contract notices
192
- notices = client.list_notices(
193
- agency="DOD",
194
- limit=25
195
- )
202
+ notices = client.list_notices(agency="DOD", notice_type="award", limit=25)
196
203
  ```
197
204
 
198
205
  ### Grants
199
206
 
200
207
  ```python
201
- # List grant opportunities
202
- grants = client.list_grants(
203
- agency_code="HHS",
204
- limit=25
205
- )
208
+ grants = client.list_grants(agency="HHS", status="forecasted", limit=25)
209
+ ```
210
+
211
+ ### Protests
212
+
213
+ ```python
214
+ protests = client.list_protests(source_system="gao", outcome="Sustained", limit=25)
215
+ protest = client.get_protest("CASE_UUID")
216
+ ```
217
+
218
+ ### GSA eLibrary Contracts
219
+
220
+ ```python
221
+ contracts = client.list_gsa_elibrary_contracts(schedule="MAS", limit=25)
222
+ contract = client.get_gsa_elibrary_contract("UUID")
206
223
  ```
207
224
 
208
- ### Business Types
225
+ ### Reference Data
209
226
 
210
227
  ```python
211
- # List business types
228
+ # Offices, organizations, NAICS, subawards, business types
229
+ offices = client.list_offices(search="acquisitions")
230
+ organizations = client.list_organizations(level=1)
231
+ naics = client.list_naics(search="software")
232
+ subawards = client.list_subawards(prime_uei="UEI123")
212
233
  business_types = client.list_business_types()
213
234
  ```
214
235
 
@@ -421,9 +442,16 @@ tango-python/
421
442
  │ ├── test_entities_integration.py
422
443
  │ ├── test_forecasts_integration.py
423
444
  │ ├── test_grants_integration.py
445
+ │ ├── test_naics_integration.py
424
446
  │ ├── test_notices_integration.py
447
+ │ ├── test_offices_integration.py
425
448
  │ ├── test_opportunities_integration.py
449
+ │ ├── test_organizations_integration.py
450
+ │ ├── test_otas_otidvs_integration.py
451
+ │ ├── test_protests_integration.py
426
452
  │ ├── test_reference_data_integration.py
453
+ │ ├── test_subawards_integration.py
454
+ │ ├── test_vehicles_idvs_integration.py
427
455
  │ └── test_edge_cases_integration.py
428
456
  ├── docs/ # Documentation
429
457
  │ ├── API_REFERENCE.md # Complete API reference