tango-python 1.0.0__tar.gz → 1.1.0__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 (222) hide show
  1. tango_python-1.1.0/.github/workflows/lint.yml +96 -0
  2. {tango_python-1.0.0 → tango_python-1.1.0}/CHANGELOG.md +47 -0
  3. {tango_python-1.0.0 → tango_python-1.1.0}/PKG-INFO +5 -1
  4. {tango_python-1.0.0 → tango_python-1.1.0}/README.md +4 -0
  5. {tango_python-1.0.0 → tango_python-1.1.0}/pyproject.toml +1 -1
  6. {tango_python-1.0.0 → tango_python-1.1.0}/scripts/check_filter_shape_conformance.py +3 -0
  7. {tango_python-1.0.0 → tango_python-1.1.0}/tango/__init__.py +3 -1
  8. {tango_python-1.0.0 → tango_python-1.1.0}/tango/client.py +441 -12
  9. {tango_python-1.0.0 → tango_python-1.1.0}/tango/models.py +149 -10
  10. {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/explicit_schemas.py +7 -9
  11. {tango_python-1.0.0 → tango_python-1.1.0}/tango/webhooks/cli.py +2 -2
  12. tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_combined_filters_work_together +152 -0
  13. tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_contract_cursor_pagination +347 -0
  14. tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_contract_cursor_pagination → tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_contract_data_object_parsing +35 -35
  15. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestContractsIntegration.test_contract_field_types +97 -0
  16. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestContractsIntegration.test_filter_parameter_mappings[keyword-software] +87 -0
  17. tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_filter_parameter_mappings[psc_code-R425] +175 -0
  18. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestContractsIntegration.test_list_contracts_with_awarding_agency_filter +1 -1
  19. tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_date_range_filter +172 -0
  20. tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_flat +174 -0
  21. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestContractsIntegration.test_list_contracts_with_naics_code_filter +197 -0
  22. tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[custom-key,piid,recipient(display_name),total_contract_value,award_date] +162 -0
  23. tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[default-None] +174 -0
  24. tango_python-1.1.0/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 +203 -0
  25. tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[minimal-key,piid,award_date,recipient(display_name),description,total_contract_value] +174 -0
  26. tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_new_expiring_filters +173 -0
  27. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestContractsIntegration.test_new_fiscal_year_range_filters +89 -0
  28. tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_new_identifier_filters +152 -0
  29. tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_search_contracts_with_filters +172 -0
  30. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestContractsIntegration.test_search_filters_object_with_new_parameters +1 -1
  31. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestContractsIntegration.test_sort_and_order_mapped_to_ordering[asc-] +81 -0
  32. tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_sort_and_order_mapped_to_ordering[desc--] +174 -0
  33. tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_api_schema_stability_detection_contracts +172 -0
  34. tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_date_field_parsing_edge_cases +268 -0
  35. tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_decimal_field_parsing_edge_cases +252 -0
  36. tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_empty_list_responses +152 -0
  37. tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_flattened_responses_with_flat_lists +174 -0
  38. tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_parsing_nested_objects_with_missing_data +482 -0
  39. tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_parsing_null_missing_fields_in_contracts +252 -0
  40. tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_parsing_with_minimal_shape_sparse_data +172 -0
  41. tango_python-1.1.0/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[custom-key,piid,description] +164 -0
  42. tango_python-1.1.0/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[minimal-key,piid,award_date,recipient(display_name),description,total_contract_value] +174 -0
  43. tango_python-1.1.0/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[ultra_minimal-key,piid,recipient(display_name),total_contract_value] +162 -0
  44. {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_shapes.py +19 -0
  45. tango_python-1.0.0/.github/workflows/lint.yml +0 -43
  46. tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_combined_filters_work_together +0 -76
  47. tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_contract_data_object_parsing +0 -86
  48. tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_filter_parameter_mappings[psc_code-R425] +0 -86
  49. tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_date_range_filter +0 -86
  50. tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_flat +0 -86
  51. tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[custom-key,piid,recipient(display_name),total_contract_value,award_date] +0 -81
  52. tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[default-None] +0 -86
  53. tango_python-1.0.0/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 -100
  54. tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[minimal-key,piid,award_date,recipient(display_name),description,total_contract_value] +0 -86
  55. tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_new_expiring_filters +0 -86
  56. tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_new_identifier_filters +0 -76
  57. tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_search_contracts_with_filters +0 -86
  58. tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_sort_and_order_mapped_to_ordering[desc--] +0 -86
  59. tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_api_schema_stability_detection_contracts +0 -86
  60. tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_date_field_parsing_edge_cases +0 -131
  61. tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_decimal_field_parsing_edge_cases +0 -126
  62. tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_empty_list_responses +0 -76
  63. tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_flattened_responses_with_flat_lists +0 -86
  64. tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_parsing_nested_objects_with_missing_data +0 -224
  65. tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_parsing_null_missing_fields_in_contracts +0 -126
  66. tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_parsing_with_minimal_shape_sparse_data +0 -86
  67. tango_python-1.0.0/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[custom-key,piid,description] +0 -81
  68. tango_python-1.0.0/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[minimal-key,piid,award_date,recipient(display_name),description,total_contract_value] +0 -86
  69. tango_python-1.0.0/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[ultra_minimal-key,piid,recipient(display_name),total_contract_value] +0 -81
  70. {tango_python-1.0.0 → tango_python-1.1.0}/.github/workflows/docs-dispatch.yml +0 -0
  71. {tango_python-1.0.0 → tango_python-1.1.0}/.github/workflows/publish.yml +0 -0
  72. {tango_python-1.0.0 → tango_python-1.1.0}/.github/workflows/test.yml +0 -0
  73. {tango_python-1.0.0 → tango_python-1.1.0}/.gitignore +0 -0
  74. {tango_python-1.0.0 → tango_python-1.1.0}/LICENSE +0 -0
  75. {tango_python-1.0.0 → tango_python-1.1.0}/docs/API_REFERENCE.md +0 -0
  76. {tango_python-1.0.0 → tango_python-1.1.0}/docs/CLIENT.md +0 -0
  77. {tango_python-1.0.0 → tango_python-1.1.0}/docs/DYNAMIC_MODELS.md +0 -0
  78. {tango_python-1.0.0 → tango_python-1.1.0}/docs/ERRORS.md +0 -0
  79. {tango_python-1.0.0 → tango_python-1.1.0}/docs/PAGINATION.md +0 -0
  80. {tango_python-1.0.0 → tango_python-1.1.0}/docs/SHAPES.md +0 -0
  81. {tango_python-1.0.0 → tango_python-1.1.0}/docs/WEBHOOKS.md +0 -0
  82. {tango_python-1.0.0 → tango_python-1.1.0}/scripts/README.md +0 -0
  83. {tango_python-1.0.0 → tango_python-1.1.0}/scripts/fetch_api_schema.py +0 -0
  84. {tango_python-1.0.0 → tango_python-1.1.0}/scripts/generate_schemas_from_api.py +0 -0
  85. {tango_python-1.0.0 → tango_python-1.1.0}/scripts/pr_review.py +0 -0
  86. {tango_python-1.0.0 → tango_python-1.1.0}/scripts/smoke_api_parity.py +0 -0
  87. {tango_python-1.0.0 → tango_python-1.1.0}/scripts/test_production.py +0 -0
  88. {tango_python-1.0.0 → tango_python-1.1.0}/tango/exceptions.py +0 -0
  89. {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/__init__.py +0 -0
  90. {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/factory.py +0 -0
  91. {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/generator.py +0 -0
  92. {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/models.py +0 -0
  93. {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/parser.py +0 -0
  94. {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/schema.py +0 -0
  95. {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/types.py +0 -0
  96. {tango_python-1.0.0 → tango_python-1.1.0}/tango/webhooks/__init__.py +0 -0
  97. {tango_python-1.0.0 → tango_python-1.1.0}/tango/webhooks/receiver.py +0 -0
  98. {tango_python-1.0.0 → tango_python-1.1.0}/tango/webhooks/signing.py +0 -0
  99. {tango_python-1.0.0 → tango_python-1.1.0}/tango/webhooks/simulate.py +0 -0
  100. {tango_python-1.0.0 → tango_python-1.1.0}/tests/__init__.py +0 -0
  101. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestAgenciesIntegration.test_get_agency +0 -0
  102. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestAgenciesIntegration.test_list_agencies +0 -0
  103. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestBusinessTypesIntegration.test_business_type_field_type_validation +0 -0
  104. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestBusinessTypesIntegration.test_business_type_parsing_consistency +0 -0
  105. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestBusinessTypesIntegration.test_list_business_types +0 -0
  106. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEdgeCasesIntegration.test_api_schema_stability_detection_entities +0 -0
  107. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEdgeCasesIntegration.test_entity_parsing_with_various_address_formats +0 -0
  108. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEdgeCasesIntegration.test_list_field_parsing_consistency +0 -0
  109. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_entity_field_types +0 -0
  110. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_entity_location_parsing +0 -0
  111. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_entity_parsing_with_business_types +0 -0
  112. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_entity_with_various_identifiers +0 -0
  113. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_get_entity_by_uei +0 -0
  114. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_flat +0 -0
  115. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_search +0 -0
  116. {tango_python-1.0.0 → tango_python-1.1.0}/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 +0 -0
  117. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_shapes[custom-uei,legal_business_name,cage_code] +0 -0
  118. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_shapes[minimal-uei,legal_business_name,cage_code,business_types] +0 -0
  119. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_shapes[with_address-uei,legal_business_name,cage_code,business_types,physical_address] +0 -0
  120. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestForecastsIntegration.test_forecast_field_types +0 -0
  121. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestForecastsIntegration.test_list_forecasts_with_shapes[custom-id,title,anticipated_award_date] +0 -0
  122. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestForecastsIntegration.test_list_forecasts_with_shapes[default-None] +0 -0
  123. {tango_python-1.0.0 → tango_python-1.1.0}/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 -0
  124. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestForecastsIntegration.test_list_forecasts_with_shapes[minimal-id,title,anticipated_award_date,fiscal_year,naics_code,status] +0 -0
  125. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestGrantsIntegration.test_grant_field_types +0 -0
  126. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestGrantsIntegration.test_grant_pagination +0 -0
  127. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[custom-grant_id,title,opportunity_number] +0 -0
  128. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[default-None] +0 -0
  129. {tango_python-1.0.0 → tango_python-1.1.0}/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 -0
  130. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[minimal-grant_id,opportunity_number,title,status(-),agency_code] +0 -0
  131. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestIDVsIntegration.test_get_idv_uses_default_shape +0 -0
  132. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestIDVsIntegration.test_list_idv_awards_uses_default_shape +0 -0
  133. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestIDVsIntegration.test_list_idv_child_idvs_uses_default_shape +0 -0
  134. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestIDVsIntegration.test_list_idv_transactions +0 -0
  135. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestIDVsIntegration.test_list_idvs_uses_default_shape_and_keyset_params +0 -0
  136. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_agency_code +0 -0
  137. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_agency_name_text +0 -0
  138. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_cio_rating +0 -0
  139. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_cio_rating_max +0 -0
  140. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_performance_risk +0 -0
  141. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_type_of_investment +0 -0
  142. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_updated_time_range +0 -0
  143. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_funding_and_cio_evaluation_expansions +0 -0
  144. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_get_itdashboard_investment_by_uii +0 -0
  145. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_itdashboard_pagination +0 -0
  146. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_list_itdashboard_investments_with_search +0 -0
  147. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_list_itdashboard_investments_with_shapes[custom-uii,agency_name,investment_title,updated_time] +0 -0
  148. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_list_itdashboard_investments_with_shapes[default-None] +0 -0
  149. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_list_itdashboard_investments_with_shapes[minimal-uii,agency_name,bureau_name,investment_title,type_of_investment,part_of_it_portfolio,updated_time,url] +0 -0
  150. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestNaicsIntegration.test_list_naics +0 -0
  151. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestNoticesIntegration.test_list_notices_with_shapes[custom-notice_id,title,solicitation_number] +0 -0
  152. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestNoticesIntegration.test_list_notices_with_shapes[default-None] +0 -0
  153. {tango_python-1.0.0 → tango_python-1.1.0}/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(-)] +0 -0
  154. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestNoticesIntegration.test_list_notices_with_shapes[minimal-notice_id,title,solicitation_number,posted_date] +0 -0
  155. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestNoticesIntegration.test_notice_field_types +0 -0
  156. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestNoticesIntegration.test_notice_pagination +0 -0
  157. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestNoticesIntegration.test_notice_with_meta_fields +0 -0
  158. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOTAsIntegration.test_get_ota +0 -0
  159. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOTAsIntegration.test_list_otas +0 -0
  160. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOTIDVsIntegration.test_get_otidv +0 -0
  161. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOTIDVsIntegration.test_list_otidvs +0 -0
  162. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOfficesIntegration.test_get_office +0 -0
  163. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOfficesIntegration.test_list_offices +0 -0
  164. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOpportunitiesIntegration.test_list_opportunities_with_shapes[custom-opportunity_id,title,solicitation_number] +0 -0
  165. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOpportunitiesIntegration.test_list_opportunities_with_shapes[default-None] +0 -0
  166. {tango_python-1.0.0 → tango_python-1.1.0}/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 -0
  167. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOpportunitiesIntegration.test_list_opportunities_with_shapes[minimal-opportunity_id,title,solicitation_number,response_deadline,active] +0 -0
  168. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOpportunitiesIntegration.test_opportunity_field_types +0 -0
  169. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOrganizationsIntegration.test_get_organization +0 -0
  170. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOrganizationsIntegration.test_list_organizations +0 -0
  171. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestProtestsIntegration.test_get_protest_by_case_id +0 -0
  172. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestProtestsIntegration.test_list_protests_with_filter +0 -0
  173. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestProtestsIntegration.test_list_protests_with_shapes[custom-case_id,title,source_system,outcome] +0 -0
  174. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestProtestsIntegration.test_list_protests_with_shapes[default-None] +0 -0
  175. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestProtestsIntegration.test_list_protests_with_shapes[minimal-case_id,case_number,title,source_system,outcome,filed_date] +0 -0
  176. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestProtestsIntegration.test_list_protests_with_shapes[with_dockets-case_id,case_number,title,outcome,filed_date,dockets(docket_number,filed_date,outcome)] +0 -0
  177. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestProtestsIntegration.test_protest_pagination +0 -0
  178. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestSubawardsIntegration.test_list_subawards +0 -0
  179. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestTypeHintsIntegration.test_entities_dict_access[minimal-uei,legal_business_name,cage_code,business_types] +0 -0
  180. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestTypeHintsIntegration.test_entities_dict_access[with_address-uei,legal_business_name,cage_code,business_types,physical_address] +0 -0
  181. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestTypeHintsIntegration.test_notices_dict_access[detailed-notice_id,title,description,solicitation_number,posted_date,naics_code,set_aside,office(-),place_of_performance(-)] +0 -0
  182. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestTypeHintsIntegration.test_notices_dict_access[minimal-notice_id,title,solicitation_number,posted_date] +0 -0
  183. {tango_python-1.0.0 → tango_python-1.1.0}/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 -0
  184. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestTypeHintsIntegration.test_opportunities_dict_access[minimal-opportunity_id,title,solicitation_number,response_deadline,active] +0 -0
  185. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestVehiclesIntegration.test_get_vehicle_supports_joiner_and_flat_lists +0 -0
  186. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestVehiclesIntegration.test_get_vehicle_with_metrics_expansion +0 -0
  187. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestVehiclesIntegration.test_list_vehicle_awardees_uses_default_shape +0 -0
  188. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestVehiclesIntegration.test_list_vehicle_orders_uses_default_shape +0 -0
  189. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestVehiclesIntegration.test_list_vehicles_uses_default_shape_and_search +0 -0
  190. {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestVehiclesIntegration.test_list_vehicles_with_ordering +0 -0
  191. {tango_python-1.0.0 → tango_python-1.1.0}/tests/conftest.py +0 -0
  192. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/README.md +0 -0
  193. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/__init__.py +0 -0
  194. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/conftest.py +0 -0
  195. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_agencies_integration.py +0 -0
  196. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_contracts_integration.py +0 -0
  197. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_edge_cases_integration.py +0 -0
  198. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_entities_integration.py +0 -0
  199. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_forecasts_integration.py +0 -0
  200. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_grants_integration.py +0 -0
  201. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_itdashboard_integration.py +0 -0
  202. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_naics_integration.py +0 -0
  203. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_notices_integration.py +0 -0
  204. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_offices_integration.py +0 -0
  205. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_opportunities_integration.py +0 -0
  206. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_organizations_integration.py +0 -0
  207. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_otas_otidvs_integration.py +0 -0
  208. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_protests_integration.py +0 -0
  209. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_reference_data_integration.py +0 -0
  210. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_subawards_integration.py +0 -0
  211. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_vehicles_idvs_integration.py +0 -0
  212. {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/validation.py +0 -0
  213. {tango_python-1.0.0 → tango_python-1.1.0}/tests/production/__init__.py +0 -0
  214. {tango_python-1.0.0 → tango_python-1.1.0}/tests/production/conftest.py +0 -0
  215. {tango_python-1.0.0 → tango_python-1.1.0}/tests/production/test_production_smoke.py +0 -0
  216. {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_api_parity.py +0 -0
  217. {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_client.py +0 -0
  218. {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_models.py +0 -0
  219. {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_webhooks_cli.py +0 -0
  220. {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_webhooks_receiver.py +0 -0
  221. {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_webhooks_signing.py +0 -0
  222. {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_webhooks_simulate.py +0 -0
@@ -0,0 +1,96 @@
1
+ name: Linting
2
+
3
+ # Lint gate runs on every PR and push to main.
4
+ #
5
+ # - ruff format + ruff check are HARD gates (block the PR).
6
+ # - mypy is ADVISORY for now (continue-on-error): the package carries ~28
7
+ # pre-existing type errors that predate CI enforcement. Tracked for burn-down
8
+ # in makegov/tango-python; flip `continue-on-error` off once that's clear.
9
+ # - The SDK filter/shape conformance check needs the canonical manifest from the
10
+ # private makegov/tango repo, which requires a TANGO_API_REPO_ACCESS_TOKEN
11
+ # secret the public CI does not have. The conformance job SKIPS cleanly when
12
+ # the token is absent (rather than failing red) and becomes a real gate the
13
+ # moment the secret is configured.
14
+ on:
15
+ workflow_dispatch:
16
+ push:
17
+ branches: [ main ]
18
+ pull_request:
19
+ branches: [ main ]
20
+
21
+ jobs:
22
+ lint:
23
+ runs-on: ubuntu-latest
24
+
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+
28
+ - name: Install uv
29
+ uses: astral-sh/setup-uv@v4
30
+ with:
31
+ version: "latest"
32
+
33
+ - name: Set up Python
34
+ run: uv python install 3.12
35
+
36
+ - name: Install dependencies
37
+ run: uv sync --all-extras
38
+
39
+ - name: Check formatting with ruff
40
+ run: uv run ruff format --check tango/
41
+
42
+ - name: Lint with ruff
43
+ run: uv run ruff check tango/
44
+
45
+ - name: Type check with mypy (advisory)
46
+ continue-on-error: true
47
+ run: uv run mypy tango/
48
+
49
+ conformance:
50
+ # Requires the canonical filter_shape manifest from the private makegov/tango
51
+ # repo. When TANGO_API_REPO_ACCESS_TOKEN is not configured, every real step
52
+ # is skipped and the job passes (rather than failing on an empty token).
53
+ # Configure the secret to turn this into a hard gate automatically.
54
+ runs-on: ubuntu-latest
55
+
56
+ steps:
57
+ - name: Determine token availability
58
+ id: gate
59
+ env:
60
+ TANGO_API_REPO_ACCESS_TOKEN: ${{ secrets.TANGO_API_REPO_ACCESS_TOKEN }}
61
+ run: |
62
+ if [ -n "$TANGO_API_REPO_ACCESS_TOKEN" ]; then
63
+ echo "ready=true" >> "$GITHUB_OUTPUT"
64
+ else
65
+ echo "ready=false" >> "$GITHUB_OUTPUT"
66
+ echo "::notice::Skipping SDK conformance check — TANGO_API_REPO_ACCESS_TOKEN not configured."
67
+ fi
68
+
69
+ - uses: actions/checkout@v4
70
+ if: steps.gate.outputs.ready == 'true'
71
+
72
+ - name: Checkout tango API repo (manifest source)
73
+ if: steps.gate.outputs.ready == 'true'
74
+ uses: actions/checkout@v4
75
+ with:
76
+ repository: makegov/tango
77
+ path: tango-api
78
+ token: ${{ secrets.TANGO_API_REPO_ACCESS_TOKEN }}
79
+
80
+ - name: Install uv
81
+ if: steps.gate.outputs.ready == 'true'
82
+ uses: astral-sh/setup-uv@v4
83
+ with:
84
+ version: "latest"
85
+
86
+ - name: Set up Python
87
+ if: steps.gate.outputs.ready == 'true'
88
+ run: uv python install 3.12
89
+
90
+ - name: Install dependencies
91
+ if: steps.gate.outputs.ready == 'true'
92
+ run: uv sync --all-extras
93
+
94
+ - name: Check SDK filter/shape conformance
95
+ if: steps.gate.outputs.ready == 'true'
96
+ run: uv run python scripts/check_filter_shape_conformance.py --manifest tango-api/contracts/filter_shape_contract.json
@@ -7,6 +7,53 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.1.0] - 2026-05-29
11
+
12
+ ### Fixed
13
+ - `_parse_webhook_alert`: aligned the parser output with the `WebhookAlert`
14
+ type contract. Sparse server payloads now hydrate `query_type` and `filters`
15
+ as `""` / `{}` (matching their declared non-null types) rather than `None`,
16
+ and `status` is typed as the `Literal["active", "paused"]` the model promises.
17
+ Clears the four type-check errors this introduced; no change for full payloads.
18
+ - `Contract` model: removed dead fields (`id`, `award_id`, `recipient_name`,
19
+ `award_amount`, `awarding_agency`, `funding_agency`) and added the real API
20
+ fields (`key`, `piid`, `obligated`, `total_contract_value`,
21
+ `base_and_exercised_options_value`, `awarding_office`, `funding_office`,
22
+ `naics_code`, `psc_code`, `set_aside`, `solicitation_identifier`,
23
+ `parent_award`, `legislative_mandates`, `subawards_summary`,
24
+ `place_of_performance`). The deprecated fields remain declared with `None`
25
+ defaults for one minor cycle (they never returned data) and will be removed
26
+ in `2.0.0`. New `OrganizationOfficePayload` dataclass for the office fields.
27
+ (`Contract` is a documentation-only dataclass — not instantiated or exported
28
+ — so there is no runtime impact.)
29
+ - `list_contracts`: no longer sends `page=1` to the cursor-only `/api/contracts/`
30
+ endpoint. When no cursor is supplied, neither `page` nor `cursor` is sent and
31
+ the API returns the first page by default.
32
+ - Shape validation: registered the `ContractOrIDVCompetition` nested schema
33
+ (alias of `Competition`) so nested selections like
34
+ `competition(extent_competed,number_of_offers_received)` on contract / IDV
35
+ shapes validate instead of raising `ShapeValidationError`.
36
+
37
+ ### Added
38
+ - Budget accounts surface (tango v4.6.8): `list_budget_accounts`,
39
+ `get_budget_account`, `get_budget_account_quarters`,
40
+ `get_budget_account_recipients`. New `BudgetAccount` dataclass exported from
41
+ the top-level package, plus `ShapeConfig.BUDGET_ACCOUNTS_MINIMAL`.
42
+ - Singleton detail GETs: `get_contract`, `get_contract_subawards`,
43
+ `get_contract_transactions`, `get_forecast`, `get_grant`, `get_notice`,
44
+ `get_opportunity`, `get_subaward`.
45
+ - `get_entity_budget_flows(uei)` for `/api/entities/{uei}/budget-flows/`.
46
+ - `list_otidv_awards(key)` for `/api/otidvs/{key}/awards/` (parity with Node).
47
+ - `grant_id` filter kwarg on `list_grants` (supports multi-value OR via `|`).
48
+
49
+ ### CI
50
+ - Re-enabled `lint.yml` as a PR + push-to-main gate. `ruff format` and
51
+ `ruff check` are hard gates; `mypy` runs advisory (continue-on-error) pending
52
+ burn-down of ~28 pre-existing type errors. The filter/shape conformance check
53
+ is a separate job that skips cleanly until a `TANGO_API_REPO_ACCESS_TOKEN`
54
+ secret for the private manifest repo is configured, at which point it becomes
55
+ a hard gate.
56
+
10
57
  ## [1.0.0] - 2026-05-13
11
58
 
12
59
  > First stable release. `tango-python` is now at full API parity with the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tango-python
3
- Version: 1.0.0
3
+ Version: 1.1.0
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
@@ -57,6 +57,10 @@ Description-Content-Type: text/markdown
57
57
 
58
58
  # Tango Python SDK
59
59
 
60
+ [![PyPI](https://img.shields.io/pypi/v/tango-python.svg)](https://pypi.org/project/tango-python/)
61
+ [![Python Versions](https://img.shields.io/pypi/pyversions/tango-python.svg)](https://pypi.org/project/tango-python/)
62
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
63
+
60
64
  A modern Python SDK for the [Tango API](https://tango.makegov.com) by MakeGov, featuring dynamic response shaping and comprehensive type hints.
61
65
 
62
66
  ## Features
@@ -1,5 +1,9 @@
1
1
  # Tango Python SDK
2
2
 
3
+ [![PyPI](https://img.shields.io/pypi/v/tango-python.svg)](https://pypi.org/project/tango-python/)
4
+ [![Python Versions](https://img.shields.io/pypi/pyversions/tango-python.svg)](https://pypi.org/project/tango-python/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
+
3
7
  A modern Python SDK for the [Tango API](https://tango.makegov.com) by MakeGov, featuring dynamic response shaping and comprehensive type hints.
4
8
 
5
9
  ## Features
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "tango-python"
7
- version = "1.0.0"
7
+ version = "1.1.0"
8
8
  description = "Python SDK for the Tango API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -51,6 +51,7 @@ RESOURCE_TO_METHOD: dict[str, str] = {
51
51
  "naics": "list_naics",
52
52
  "gsa_elibrary_contracts": "list_gsa_elibrary_contracts",
53
53
  "itdashboard": "list_itdashboard_investments",
54
+ "budget_accounts": "list_budget_accounts",
54
55
  # Resources not yet implemented in SDK
55
56
  "offices": None,
56
57
  }
@@ -62,6 +63,7 @@ def get_shape_config_entries() -> list[tuple[str, str, type[Any]]]:
62
63
  IDV,
63
64
  OTA,
64
65
  OTIDV,
66
+ BudgetAccount,
65
67
  Contract,
66
68
  Entity,
67
69
  Forecast,
@@ -110,6 +112,7 @@ def get_shape_config_entries() -> list[tuple[str, str, type[Any]]]:
110
112
  ShapeConfig.ITDASHBOARD_INVESTMENTS_COMPREHENSIVE,
111
113
  ITDashboardInvestment,
112
114
  ),
115
+ ("BUDGET_ACCOUNTS_MINIMAL", ShapeConfig.BUDGET_ACCOUNTS_MINIMAL, BudgetAccount),
113
116
  ]
114
117
  for name, shape_str, model_cls in configs:
115
118
  entries.append((name, shape_str, model_cls))
@@ -9,6 +9,7 @@ from .exceptions import (
9
9
  TangoValidationError,
10
10
  )
11
11
  from .models import (
12
+ BudgetAccount,
12
13
  GsaElibraryContract,
13
14
  ITDashboardInvestment,
14
15
  PaginatedResponse,
@@ -43,7 +44,7 @@ from .webhooks import (
43
44
  )
44
45
  from .webhooks.receiver import Delivery, WebhookReceiver
45
46
 
46
- __version__ = "1.0.0"
47
+ __version__ = "1.1.0"
47
48
  __all__ = [
48
49
  "TangoClient",
49
50
  "TangoAPIError",
@@ -54,6 +55,7 @@ __all__ = [
54
55
  "RateLimitInfo",
55
56
  "ResolveCandidate",
56
57
  "ResolveResult",
58
+ "BudgetAccount",
57
59
  "GsaElibraryContract",
58
60
  "ITDashboardInvestment",
59
61
  "PaginatedResponse",