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.
- tango_python-1.1.0/.github/workflows/lint.yml +96 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/CHANGELOG.md +47 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/PKG-INFO +5 -1
- {tango_python-1.0.0 → tango_python-1.1.0}/README.md +4 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/pyproject.toml +1 -1
- {tango_python-1.0.0 → tango_python-1.1.0}/scripts/check_filter_shape_conformance.py +3 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/__init__.py +3 -1
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/client.py +441 -12
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/models.py +149 -10
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/explicit_schemas.py +7 -9
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/webhooks/cli.py +2 -2
- tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_combined_filters_work_together +152 -0
- tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_contract_cursor_pagination +347 -0
- 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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestContractsIntegration.test_contract_field_types +97 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestContractsIntegration.test_filter_parameter_mappings[keyword-software] +87 -0
- tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_filter_parameter_mappings[psc_code-R425] +175 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestContractsIntegration.test_list_contracts_with_awarding_agency_filter +1 -1
- tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_date_range_filter +172 -0
- tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_flat +174 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestContractsIntegration.test_list_contracts_with_naics_code_filter +197 -0
- 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
- tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[default-None] +174 -0
- 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
- 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
- tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_new_expiring_filters +173 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestContractsIntegration.test_new_fiscal_year_range_filters +89 -0
- tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_new_identifier_filters +152 -0
- tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_search_contracts_with_filters +172 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestContractsIntegration.test_search_filters_object_with_new_parameters +1 -1
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestContractsIntegration.test_sort_and_order_mapped_to_ordering[asc-] +81 -0
- tango_python-1.1.0/tests/cassettes/TestContractsIntegration.test_sort_and_order_mapped_to_ordering[desc--] +174 -0
- tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_api_schema_stability_detection_contracts +172 -0
- tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_date_field_parsing_edge_cases +268 -0
- tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_decimal_field_parsing_edge_cases +252 -0
- tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_empty_list_responses +152 -0
- tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_flattened_responses_with_flat_lists +174 -0
- tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_parsing_nested_objects_with_missing_data +482 -0
- tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_parsing_null_missing_fields_in_contracts +252 -0
- tango_python-1.1.0/tests/cassettes/TestEdgeCasesIntegration.test_parsing_with_minimal_shape_sparse_data +172 -0
- tango_python-1.1.0/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[custom-key,piid,description] +164 -0
- 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
- tango_python-1.1.0/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[ultra_minimal-key,piid,recipient(display_name),total_contract_value] +162 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_shapes.py +19 -0
- tango_python-1.0.0/.github/workflows/lint.yml +0 -43
- tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_combined_filters_work_together +0 -76
- tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_contract_data_object_parsing +0 -86
- tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_filter_parameter_mappings[psc_code-R425] +0 -86
- tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_date_range_filter +0 -86
- tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_flat +0 -86
- 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
- tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[default-None] +0 -86
- 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
- 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
- tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_new_expiring_filters +0 -86
- tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_new_identifier_filters +0 -76
- tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_search_contracts_with_filters +0 -86
- tango_python-1.0.0/tests/cassettes/TestContractsIntegration.test_sort_and_order_mapped_to_ordering[desc--] +0 -86
- tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_api_schema_stability_detection_contracts +0 -86
- tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_date_field_parsing_edge_cases +0 -131
- tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_decimal_field_parsing_edge_cases +0 -126
- tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_empty_list_responses +0 -76
- tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_flattened_responses_with_flat_lists +0 -86
- tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_parsing_nested_objects_with_missing_data +0 -224
- tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_parsing_null_missing_fields_in_contracts +0 -126
- tango_python-1.0.0/tests/cassettes/TestEdgeCasesIntegration.test_parsing_with_minimal_shape_sparse_data +0 -86
- tango_python-1.0.0/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[custom-key,piid,description] +0 -81
- 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
- tango_python-1.0.0/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[ultra_minimal-key,piid,recipient(display_name),total_contract_value] +0 -81
- {tango_python-1.0.0 → tango_python-1.1.0}/.github/workflows/docs-dispatch.yml +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/.github/workflows/publish.yml +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/.github/workflows/test.yml +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/.gitignore +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/LICENSE +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/docs/API_REFERENCE.md +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/docs/CLIENT.md +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/docs/DYNAMIC_MODELS.md +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/docs/ERRORS.md +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/docs/PAGINATION.md +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/docs/SHAPES.md +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/docs/WEBHOOKS.md +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/scripts/README.md +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/scripts/fetch_api_schema.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/scripts/generate_schemas_from_api.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/scripts/pr_review.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/scripts/smoke_api_parity.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/scripts/test_production.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/exceptions.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/__init__.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/factory.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/generator.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/models.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/parser.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/schema.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/shapes/types.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/webhooks/__init__.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/webhooks/receiver.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/webhooks/signing.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tango/webhooks/simulate.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/__init__.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestAgenciesIntegration.test_get_agency +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestAgenciesIntegration.test_list_agencies +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestBusinessTypesIntegration.test_business_type_field_type_validation +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestBusinessTypesIntegration.test_business_type_parsing_consistency +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestBusinessTypesIntegration.test_list_business_types +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEdgeCasesIntegration.test_api_schema_stability_detection_entities +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEdgeCasesIntegration.test_entity_parsing_with_various_address_formats +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEdgeCasesIntegration.test_list_field_parsing_consistency +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_entity_field_types +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_entity_location_parsing +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_entity_parsing_with_business_types +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_entity_with_various_identifiers +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_get_entity_by_uei +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_flat +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_search +0 -0
- {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
- {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
- {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
- {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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestForecastsIntegration.test_forecast_field_types +0 -0
- {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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestForecastsIntegration.test_list_forecasts_with_shapes[default-None] +0 -0
- {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
- {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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestGrantsIntegration.test_grant_field_types +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestGrantsIntegration.test_grant_pagination +0 -0
- {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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[default-None] +0 -0
- {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
- {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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestIDVsIntegration.test_get_idv_uses_default_shape +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestIDVsIntegration.test_list_idv_awards_uses_default_shape +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestIDVsIntegration.test_list_idv_child_idvs_uses_default_shape +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestIDVsIntegration.test_list_idv_transactions +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestIDVsIntegration.test_list_idvs_uses_default_shape_and_keyset_params +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_agency_code +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_agency_name_text +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_cio_rating +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_cio_rating_max +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_performance_risk +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_type_of_investment +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_updated_time_range +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_funding_and_cio_evaluation_expansions +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_get_itdashboard_investment_by_uii +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_itdashboard_pagination +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_list_itdashboard_investments_with_search +0 -0
- {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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestITDashboardIntegration.test_list_itdashboard_investments_with_shapes[default-None] +0 -0
- {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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestNaicsIntegration.test_list_naics +0 -0
- {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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestNoticesIntegration.test_list_notices_with_shapes[default-None] +0 -0
- {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
- {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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestNoticesIntegration.test_notice_field_types +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestNoticesIntegration.test_notice_pagination +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestNoticesIntegration.test_notice_with_meta_fields +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOTAsIntegration.test_get_ota +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOTAsIntegration.test_list_otas +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOTIDVsIntegration.test_get_otidv +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOTIDVsIntegration.test_list_otidvs +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOfficesIntegration.test_get_office +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOfficesIntegration.test_list_offices +0 -0
- {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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOpportunitiesIntegration.test_list_opportunities_with_shapes[default-None] +0 -0
- {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
- {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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOpportunitiesIntegration.test_opportunity_field_types +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOrganizationsIntegration.test_get_organization +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestOrganizationsIntegration.test_list_organizations +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestProtestsIntegration.test_get_protest_by_case_id +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestProtestsIntegration.test_list_protests_with_filter +0 -0
- {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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestProtestsIntegration.test_list_protests_with_shapes[default-None] +0 -0
- {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
- {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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestProtestsIntegration.test_protest_pagination +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestSubawardsIntegration.test_list_subawards +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestVehiclesIntegration.test_get_vehicle_supports_joiner_and_flat_lists +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestVehiclesIntegration.test_get_vehicle_with_metrics_expansion +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestVehiclesIntegration.test_list_vehicle_awardees_uses_default_shape +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestVehiclesIntegration.test_list_vehicle_orders_uses_default_shape +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestVehiclesIntegration.test_list_vehicles_uses_default_shape_and_search +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/cassettes/TestVehiclesIntegration.test_list_vehicles_with_ordering +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/conftest.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/README.md +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/__init__.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/conftest.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_agencies_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_contracts_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_edge_cases_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_entities_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_forecasts_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_grants_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_itdashboard_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_naics_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_notices_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_offices_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_opportunities_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_organizations_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_otas_otidvs_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_protests_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_reference_data_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_subawards_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/test_vehicles_idvs_integration.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/integration/validation.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/production/__init__.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/production/conftest.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/production/test_production_smoke.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_api_parity.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_client.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_models.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_webhooks_cli.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_webhooks_receiver.py +0 -0
- {tango_python-1.0.0 → tango_python-1.1.0}/tests/test_webhooks_signing.py +0 -0
- {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.
|
|
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
|
+
[](https://pypi.org/project/tango-python/)
|
|
61
|
+
[](https://pypi.org/project/tango-python/)
|
|
62
|
+
[](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
|
+
[](https://pypi.org/project/tango-python/)
|
|
4
|
+
[](https://pypi.org/project/tango-python/)
|
|
5
|
+
[](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
|
|
@@ -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.
|
|
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",
|