tango-python 1.7.0__tar.gz → 1.9.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.7.0 → tango_python-1.9.0}/CHANGELOG.md +21 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/PKG-INFO +10 -1
- {tango_python-1.7.0 → tango_python-1.9.0}/README.md +9 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/docs/API_REFERENCE.md +205 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/docs/WEBHOOKS.md +2 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/pyproject.toml +1 -1
- {tango_python-1.7.0 → tango_python-1.9.0}/scripts/check_filter_shape_conformance.py +2 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/scripts/check_shape_coverage.py +2 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/__init__.py +11 -1
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/client.py +416 -51
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/exceptions.py +10 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/models.py +188 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/shapes/explicit_schemas.py +171 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/shapes/generated_overlay.py +41 -19
- tango_python-1.9.0/tests/test_ebuy.py +322 -0
- tango_python-1.9.0/tests/test_federal_register.py +233 -0
- tango_python-1.9.0/tests/test_organization_scope.py +107 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/.gitignore +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/LICENSE +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/docs/CLIENT.md +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/docs/DYNAMIC_MODELS.md +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/docs/ERRORS.md +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/docs/PAGINATION.md +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/docs/SHAPES.md +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/scripts/README.md +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/scripts/fetch_api_schema.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/scripts/generate_schemas_from_api.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/scripts/generate_shape_overlay.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/scripts/pr_review.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/scripts/probe_shape_types.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/scripts/refresh_contract.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/scripts/smoke_api_parity.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/scripts/test_production.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/shapes/__init__.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/shapes/factory.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/shapes/generator.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/shapes/models.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/shapes/parser.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/shapes/schema.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/shapes/types.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/webhooks/__init__.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/webhooks/cli.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/webhooks/receiver.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/webhooks/signing.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tango/webhooks/simulate.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/__init__.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestAgenciesIntegration.test_get_agency +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestAgenciesIntegration.test_list_agencies +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestBusinessTypesIntegration.test_business_type_field_type_validation +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestBusinessTypesIntegration.test_business_type_parsing_consistency +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestBusinessTypesIntegration.test_list_business_types +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_combined_filters_work_together +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_contract_cursor_pagination +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_contract_data_object_parsing +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_contract_field_types +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_filter_parameter_mappings[keyword-software] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_filter_parameter_mappings[psc_code-R425] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_list_contracts_with_awarding_agency_filter +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_list_contracts_with_date_range_filter +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_list_contracts_with_flat +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_list_contracts_with_naics_code_filter +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[custom-key,piid,recipient(display_name),total_contract_value,award_date] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[default-None] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.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 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_list_contracts_with_shapes[minimal-key,piid,award_date,recipient(display_name),description,total_contract_value] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_new_expiring_filters +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_new_fiscal_year_range_filters +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_new_identifier_filters +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_search_contracts_with_filters +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_search_filters_object_with_new_parameters +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_sort_and_order_mapped_to_ordering[asc-] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestContractsIntegration.test_sort_and_order_mapped_to_ordering[desc--] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEdgeCasesIntegration.test_api_schema_stability_detection_contracts +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEdgeCasesIntegration.test_api_schema_stability_detection_entities +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEdgeCasesIntegration.test_date_field_parsing_edge_cases +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEdgeCasesIntegration.test_decimal_field_parsing_edge_cases +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEdgeCasesIntegration.test_empty_list_responses +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEdgeCasesIntegration.test_entity_parsing_with_various_address_formats +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEdgeCasesIntegration.test_flattened_responses_with_flat_lists +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEdgeCasesIntegration.test_list_field_parsing_consistency +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEdgeCasesIntegration.test_parsing_nested_objects_with_missing_data +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEdgeCasesIntegration.test_parsing_null_missing_fields_in_contracts +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEdgeCasesIntegration.test_parsing_with_minimal_shape_sparse_data +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEntitiesIntegration.test_entity_field_types +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEntitiesIntegration.test_entity_location_parsing +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEntitiesIntegration.test_entity_parsing_with_business_types +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEntitiesIntegration.test_entity_with_various_identifiers +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEntitiesIntegration.test_get_entity_budget_flows +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEntitiesIntegration.test_get_entity_by_uei +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_flat +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_search +0 -0
- {tango_python-1.7.0 → tango_python-1.9.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.7.0 → tango_python-1.9.0}/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_shapes[custom-uei,legal_business_name,cage_code] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestEntitiesIntegration.test_list_entities_with_shapes[minimal-uei,legal_business_name,cage_code,business_types] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.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.7.0 → tango_python-1.9.0}/tests/cassettes/TestForecastsIntegration.test_forecast_field_types +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestForecastsIntegration.test_list_forecasts_with_shapes[custom-id,title,anticipated_award_date] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestForecastsIntegration.test_list_forecasts_with_shapes[default-None] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.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.7.0 → tango_python-1.9.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.7.0 → tango_python-1.9.0}/tests/cassettes/TestGrantsIntegration.test_grant_field_types +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestGrantsIntegration.test_grant_pagination +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[custom-grant_id,title,opportunity_number] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[default-None] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.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.7.0 → tango_python-1.9.0}/tests/cassettes/TestGrantsIntegration.test_list_grants_with_shapes[minimal-grant_id,opportunity_number,title,status(-),agency_code] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestIDVsIntegration.test_get_idv_uses_default_shape +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestIDVsIntegration.test_list_idv_awards_uses_default_shape +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestIDVsIntegration.test_list_idv_child_idvs_uses_default_shape +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestIDVsIntegration.test_list_idv_transactions +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestIDVsIntegration.test_list_idvs_uses_default_shape_and_keyset_params +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_agency_code +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_agency_name_text +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_cio_rating +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_cio_rating_max +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_performance_risk +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_type_of_investment +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestITDashboardIntegration.test_filter_by_updated_time_range +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestITDashboardIntegration.test_funding_and_cio_evaluation_expansions +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestITDashboardIntegration.test_get_itdashboard_investment_by_uii +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestITDashboardIntegration.test_itdashboard_pagination +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestITDashboardIntegration.test_list_itdashboard_investments_with_search +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestITDashboardIntegration.test_list_itdashboard_investments_with_shapes[custom-uii,agency_name,investment_title,updated_time] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestITDashboardIntegration.test_list_itdashboard_investments_with_shapes[default-None] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.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.7.0 → tango_python-1.9.0}/tests/cassettes/TestNaicsIntegration.test_list_naics +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestNoticesIntegration.test_list_notices_with_shapes[custom-notice_id,title,solicitation_number] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestNoticesIntegration.test_list_notices_with_shapes[default-None] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.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.7.0 → tango_python-1.9.0}/tests/cassettes/TestNoticesIntegration.test_list_notices_with_shapes[minimal-notice_id,title,solicitation_number,posted_date] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestNoticesIntegration.test_notice_field_types +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestNoticesIntegration.test_notice_pagination +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestNoticesIntegration.test_notice_with_meta_fields +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestOTAsIntegration.test_get_ota +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestOTAsIntegration.test_list_otas +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestOTIDVsIntegration.test_get_otidv +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestOTIDVsIntegration.test_list_otidvs +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestOfficesIntegration.test_get_office +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestOfficesIntegration.test_list_offices +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestOpportunitiesIntegration.test_list_opportunities_with_shapes[custom-opportunity_id,title,solicitation_number] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestOpportunitiesIntegration.test_list_opportunities_with_shapes[default-None] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.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.7.0 → tango_python-1.9.0}/tests/cassettes/TestOpportunitiesIntegration.test_list_opportunities_with_shapes[minimal-opportunity_id,title,solicitation_number,response_deadline,active] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestOpportunitiesIntegration.test_opportunity_field_types +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestOrganizationsIntegration.test_get_organization +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestOrganizationsIntegration.test_list_organizations +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestProtestsIntegration.test_get_protest_by_case_id +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestProtestsIntegration.test_list_protests_with_filter +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestProtestsIntegration.test_list_protests_with_shapes[custom-case_id,title,source_system,outcome] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestProtestsIntegration.test_list_protests_with_shapes[default-None] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.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.7.0 → tango_python-1.9.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.7.0 → tango_python-1.9.0}/tests/cassettes/TestProtestsIntegration.test_protest_pagination +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestSubawardsIntegration.test_list_subawards +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[custom-key,piid,description] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[minimal-key,piid,award_date,recipient(display_name),description,total_contract_value] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestTypeHintsIntegration.test_contracts_dict_access[ultra_minimal-key,piid,recipient(display_name),total_contract_value] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestTypeHintsIntegration.test_entities_dict_access[minimal-uei,legal_business_name,cage_code,business_types] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.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.7.0 → tango_python-1.9.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.7.0 → tango_python-1.9.0}/tests/cassettes/TestTypeHintsIntegration.test_notices_dict_access[minimal-notice_id,title,solicitation_number,posted_date] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.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.7.0 → tango_python-1.9.0}/tests/cassettes/TestTypeHintsIntegration.test_opportunities_dict_access[minimal-opportunity_id,title,solicitation_number,response_deadline,active] +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestVehiclesIntegration.test_get_vehicle_supports_joiner_and_flat_lists +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestVehiclesIntegration.test_get_vehicle_with_metrics_expansion +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestVehiclesIntegration.test_list_vehicle_awardees_uses_default_shape +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestVehiclesIntegration.test_list_vehicle_orders_uses_default_shape +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestVehiclesIntegration.test_list_vehicles_uses_default_shape_and_search +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/cassettes/TestVehiclesIntegration.test_list_vehicles_with_ordering +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/conftest.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/README.md +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/__init__.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/conftest.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_agencies_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_contracts_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_edge_cases_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_entities_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_forecasts_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_grants_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_itdashboard_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_naics_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_notices_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_offices_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_opportunities_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_organizations_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_otas_otidvs_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_protests_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_reference_data_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_subawards_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/test_vehicles_idvs_integration.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/integration/validation.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/production/__init__.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/production/conftest.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/production/test_production_smoke.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/test_api_parity.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/test_client.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/test_contract_appeals.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/test_dibbs_exclusions_sbir.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/test_models.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/test_opportunity_attachments.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/test_shape_coverage_gate.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/test_shapes.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/test_sled.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/test_webhooks_cli.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/test_webhooks_receiver.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/test_webhooks_signing.py +0 -0
- {tango_python-1.7.0 → tango_python-1.9.0}/tests/test_webhooks_simulate.py +0 -0
|
@@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.9.0] - 2026-09-28
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **GSA eBuy requests** (Tango API 5.1.0). Four methods over the `/api/ebuy/` resource: `list_ebuy_requests()`, `get_ebuy_request()`, `get_ebuy_attachment_url()` and `get_ebuy_access()`, plus `EbuyRequest` / `EbuyAttachment` schemas, an `EbuyAccess` result type, and the `EBUY_REQUESTS_MINIMAL` / `EBUY_REQUESTS_COMPREHENSIVE` defaults. These are the RFQs, RFPs and RFIs posted to GSA eBuy. All fourteen of the API's filters are explicit named parameters, including `search` (which also matches attachment text), `reference_number`, `sin`, `agency` and `contract_number`.
|
|
14
|
+
|
|
15
|
+
Access is scoped to your account: you see only requests posted under the GSA schedule contracts linked to it, and the endpoints require the Pro tier or above. With no linked contract, `list_ebuy_requests()` returns an empty page rather than an error, so `get_ebuy_access()` reports whether access is enabled, why not (`tier_required` or `no_contract_grant`), and which contracts are linked. `status` is frozen at the last state a request was seen in, because a request that closes stops appearing rather than getting a final row; read `last_seen` for staleness. `get_ebuy_attachment_url()` returns the short-lived signed URL the API redirects to without downloading the document, and raises the new `TangoAttachmentLinkError` (a `TangoValidationError`) with the link on `.url` when the entry is an external link rather than a stored document. The `agency` filter requires Tango API 5.3.0.
|
|
16
|
+
- **`alerts.ebuy_request.match` is an alertable event type.** `create_webhook_alert(query_type="ebuy_request", ...)` works.
|
|
17
|
+
|
|
18
|
+
## [1.8.0] - 2026-09-28
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- **Federal Register documents** (Tango API 5.3.0). Two methods over the new `/api/federal_register/` resource: `list_federal_register_documents()` and `get_federal_register_document()`, plus a `FederalRegisterDocument` schema and the `FEDERAL_REGISTER_MINIMAL` / `FEDERAL_REGISTER_COMPREHENSIVE` defaults. These are the rules, proposed rules, notices and presidential documents published in the Federal Register since 1994. All seventeen of the API's filters are explicit named parameters, including `comments_open`, `cfr_title` / `cfr_part`, `rin`, and both `agency` (a Tango organization, including its sub-agencies) and `fr_agency` (the Federal Register's own agency slug).
|
|
22
|
+
|
|
23
|
+
`get_federal_register_document()` takes the document's `uuid`, not its `document_number`, because a document number is not unique on its own: the Federal Register reused some before 2016. Look a document up by number with `list_federal_register_documents(document_number=...)`. `full_text` is available on the detail method only when named in `shape`, and neither default shape includes it, since it can run to several MB. `ordering="rank"` requires a non-empty `search`, matching the API.
|
|
24
|
+
- **`alerts.federal_register.match` is an alertable event type.** `create_webhook_alert(query_type="federal_register", ...)` works.
|
|
25
|
+
- **`agency` filter on `list_budget_accounts()`, `list_exclusions()` and `list_itdashboard_investments()`** (Tango API 5.3.0). It takes a Tango agency name, abbreviation, code or organization key (e.g. `EPA`) and matches the whole organization subtree, so a department includes its sub-agencies; OR several with `|`. On exclusions it scopes by the excluding agency. On IT Dashboard it is available at every plan.
|
|
26
|
+
- **The `organization` expand is accepted on budget accounts, exclusions, SBIR topics and SBIR solicitations**, along with the `organization_id` field on budget accounts and exclusions. `organization(...)` carries `agency_code`, `agency_name`, `department_code`, `department_name`, `office_code`, `office_name` and `organization_id`. The SDK rejected these shapes client-side before. The default shapes are unchanged.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
- **`list_itdashboard_investments()` documents the API's current filter tiers.** `agency_name` is available at every plan, not Business+ only.
|
|
30
|
+
|
|
10
31
|
## [1.7.0] - 2026-09-23
|
|
11
32
|
|
|
12
33
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: tango-python
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.9.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
|
|
@@ -308,6 +308,15 @@ protests = client.list_protests(source_system="gao", outcome="Sustained", limit=
|
|
|
308
308
|
protest = client.get_protest("CASE_UUID")
|
|
309
309
|
```
|
|
310
310
|
|
|
311
|
+
### GSA eBuy
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
access = client.get_ebuy_access() # scoped to the schedule contracts linked to your account
|
|
315
|
+
requests = client.list_ebuy_requests(status="Open", sin="54151S", limit=25)
|
|
316
|
+
request = client.get_ebuy_request("RFQ1835158")
|
|
317
|
+
url = client.get_ebuy_attachment_url("RFQ1835158", doc_seq_num=1) # short-lived signed URL
|
|
318
|
+
```
|
|
319
|
+
|
|
311
320
|
### GSA eLibrary Contracts
|
|
312
321
|
|
|
313
322
|
```python
|
|
@@ -254,6 +254,15 @@ protests = client.list_protests(source_system="gao", outcome="Sustained", limit=
|
|
|
254
254
|
protest = client.get_protest("CASE_UUID")
|
|
255
255
|
```
|
|
256
256
|
|
|
257
|
+
### GSA eBuy
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
access = client.get_ebuy_access() # scoped to the schedule contracts linked to your account
|
|
261
|
+
requests = client.list_ebuy_requests(status="Open", sin="54151S", limit=25)
|
|
262
|
+
request = client.get_ebuy_request("RFQ1835158")
|
|
263
|
+
url = client.get_ebuy_attachment_url("RFQ1835158", doc_seq_num=1) # short-lived signed URL
|
|
264
|
+
```
|
|
265
|
+
|
|
257
266
|
### GSA eLibrary Contracts
|
|
258
267
|
|
|
259
268
|
```python
|
|
@@ -23,6 +23,8 @@ Complete reference for all Tango Python SDK methods and functionality.
|
|
|
23
23
|
- [GSA eLibrary Contracts](#gsa-elibrary-contracts)
|
|
24
24
|
- [Protests](#protests)
|
|
25
25
|
- [Contract Appeals](#contract-appeals)
|
|
26
|
+
- [Federal Register](#federal-register)
|
|
27
|
+
- [GSA eBuy](#gsa-ebuy)
|
|
26
28
|
- [Budget](#budget)
|
|
27
29
|
- [Business Types](#business-types)
|
|
28
30
|
- [NAICS](#naics)
|
|
@@ -1315,6 +1317,93 @@ appeal = client.get_contract_appeal(
|
|
|
1315
1317
|
|
|
1316
1318
|
---
|
|
1317
1319
|
|
|
1320
|
+
## Federal Register
|
|
1321
|
+
|
|
1322
|
+
Federal Register documents — rules, proposed rules, notices and presidential documents published since 1994.
|
|
1323
|
+
|
|
1324
|
+
A document is identified by `uuid`. `document_number` is not unique on its own: the Federal Register reused some numbers before 2016, so `document_number=` can return more than one document.
|
|
1325
|
+
|
|
1326
|
+
### list_federal_register_documents()
|
|
1327
|
+
|
|
1328
|
+
List documents with filtering and shaping.
|
|
1329
|
+
|
|
1330
|
+
```python
|
|
1331
|
+
documents = client.list_federal_register_documents(
|
|
1332
|
+
page=1,
|
|
1333
|
+
limit=25,
|
|
1334
|
+
shape=ShapeConfig.FEDERAL_REGISTER_MINIMAL,
|
|
1335
|
+
# Filter parameters (all optional)
|
|
1336
|
+
search=None,
|
|
1337
|
+
document_number=None,
|
|
1338
|
+
type=None,
|
|
1339
|
+
agency=None,
|
|
1340
|
+
fr_agency=None,
|
|
1341
|
+
publication_date_after=None,
|
|
1342
|
+
publication_date_before=None,
|
|
1343
|
+
effective_on_after=None,
|
|
1344
|
+
effective_on_before=None,
|
|
1345
|
+
comments_close_on_after=None,
|
|
1346
|
+
comments_close_on_before=None,
|
|
1347
|
+
comments_open=None,
|
|
1348
|
+
cfr_title=None,
|
|
1349
|
+
cfr_part=None,
|
|
1350
|
+
significant=None,
|
|
1351
|
+
rin=None,
|
|
1352
|
+
executive_order_number=None,
|
|
1353
|
+
ordering=None,
|
|
1354
|
+
)
|
|
1355
|
+
```
|
|
1356
|
+
|
|
1357
|
+
**Filter Parameters:**
|
|
1358
|
+
- `search` - Ranked full-text search over the title, abstract and action; wrap in double quotes for a phrase
|
|
1359
|
+
- `document_number` - Exact FR document number, e.g. `"2016-31922"`; OR several with `|`
|
|
1360
|
+
- `type` - `"Notice"`, `"Rule"`, `"Proposed Rule"`, `"Presidential Document"`, `"Correction"`, `"Sunshine Act Document"` or `"Uncategorized Document"` (case-insensitive); OR several with `|`. An unknown type is an error, not an empty page. Documents published before 2008 are mostly `Uncategorized Document`, so a type filter undercounts that era
|
|
1361
|
+
- `agency` - A Tango agency name, abbreviation, code or organization key, e.g. `"EPA"`. Matches a document when any agency it lists falls within that organization, so a department includes its sub-agencies; OR several with `|`
|
|
1362
|
+
- `fr_agency` - The Federal Register's own agency slug, e.g. `"environmental-protection-agency"`; OR several with `|`
|
|
1363
|
+
- `publication_date_after` / `publication_date_before` - Publication date range (`YYYY-MM-DD`)
|
|
1364
|
+
- `effective_on_after` / `effective_on_before` - Effective date range (`YYYY-MM-DD`)
|
|
1365
|
+
- `comments_close_on_after` / `comments_close_on_before` - Comment-deadline range (`YYYY-MM-DD`)
|
|
1366
|
+
- `comments_open` - `True` for documents whose comment period closes today or later, `False` for those already closed; documents with no comment deadline match neither
|
|
1367
|
+
- `cfr_title` - A CFR title number, e.g. `"40"`
|
|
1368
|
+
- `cfr_part` - A CFR part number, e.g. `"52"`. Requires `cfr_title`, and both must match the same CFR reference, so `cfr_title="40", cfr_part="52"` finds 40 CFR 52
|
|
1369
|
+
- `significant` - Significant under Executive Order 12866
|
|
1370
|
+
- `rin` - A Regulation Identifier Number, e.g. `"2060-AV16"`; OR several with `|`
|
|
1371
|
+
- `executive_order_number` - Exact executive order number
|
|
1372
|
+
- `ordering` - `publication_date` (the default, as `-publication_date`), `effective_on`, `comments_close_on`, `document_number` or `rank`. `rank` requires a non-empty `search`
|
|
1373
|
+
|
|
1374
|
+
**Returns:** [PaginatedResponse](#paginatedresponse) with document dictionaries
|
|
1375
|
+
|
|
1376
|
+
**Example:**
|
|
1377
|
+
```python
|
|
1378
|
+
documents = client.list_federal_register_documents(
|
|
1379
|
+
type="Proposed Rule",
|
|
1380
|
+
comments_open=True,
|
|
1381
|
+
agency="EPA",
|
|
1382
|
+
limit=25,
|
|
1383
|
+
)
|
|
1384
|
+
|
|
1385
|
+
for doc in documents.results:
|
|
1386
|
+
print(f"{doc['document_number']} ({doc['publication_date']}): {doc['title']}")
|
|
1387
|
+
print(f" comments close {doc['comments_close_on']}")
|
|
1388
|
+
```
|
|
1389
|
+
|
|
1390
|
+
### get_federal_register_document()
|
|
1391
|
+
|
|
1392
|
+
Get a single document by `uuid`. To look one up by its document number, use `list_federal_register_documents(document_number=...)`.
|
|
1393
|
+
|
|
1394
|
+
```python
|
|
1395
|
+
document = client.get_federal_register_document(
|
|
1396
|
+
"DOCUMENT_UUID",
|
|
1397
|
+
shape=ShapeConfig.FEDERAL_REGISTER_COMPREHENSIVE,
|
|
1398
|
+
)
|
|
1399
|
+
```
|
|
1400
|
+
|
|
1401
|
+
**Notes:**
|
|
1402
|
+
- `agencies`, `cfr_references`, `dockets` and `topics` are the Federal Register's own structures, served as published. `agencies` carries Federal Register agency slugs, not Tango organization keys.
|
|
1403
|
+
- `full_text`, the document's plain text, is available on this method only and only when named in `shape` (e.g. `shape="uuid,title,full_text"`). It can run to several MB, so neither default shape includes it.
|
|
1404
|
+
|
|
1405
|
+
---
|
|
1406
|
+
|
|
1318
1407
|
## State & Local (SLED)
|
|
1319
1408
|
|
|
1320
1409
|
State, local and education procurement — solicitations that never appear on SAM.gov because they were never federal. **Beta**: coverage is partial and grows one jurisdiction at a time.
|
|
@@ -1514,6 +1603,118 @@ forecast = client.get_sled_forecast("FORECAST_UUID")
|
|
|
1514
1603
|
|
|
1515
1604
|
---
|
|
1516
1605
|
|
|
1606
|
+
## GSA eBuy
|
|
1607
|
+
|
|
1608
|
+
GSA eBuy requests for quotes, proposals and information (RFQs, RFPs, RFIs), keyed by `rfq_id`.
|
|
1609
|
+
|
|
1610
|
+
**Access is scoped to your account.** You see only requests posted under the GSA schedule contracts linked to your account, and the endpoints require the Pro tier or above (below it they return 403). With no linked contract, `list_ebuy_requests()` returns an empty page rather than an error, and `get_ebuy_request()` raises `TangoNotFoundError` for a request outside your scope, the same as for an id that does not exist. Use `get_ebuy_access()` to tell "no access" from "no matches".
|
|
1611
|
+
|
|
1612
|
+
### list_ebuy_requests()
|
|
1613
|
+
|
|
1614
|
+
List requests with filtering and shaping.
|
|
1615
|
+
|
|
1616
|
+
```python
|
|
1617
|
+
requests = client.list_ebuy_requests(
|
|
1618
|
+
page=1,
|
|
1619
|
+
limit=25,
|
|
1620
|
+
shape=ShapeConfig.EBUY_REQUESTS_MINIMAL,
|
|
1621
|
+
# Filter parameters (all optional)
|
|
1622
|
+
search=None,
|
|
1623
|
+
rfq_id=None,
|
|
1624
|
+
reference_number=None,
|
|
1625
|
+
request_type=None,
|
|
1626
|
+
status=None,
|
|
1627
|
+
sin=None,
|
|
1628
|
+
schedule=None,
|
|
1629
|
+
buyer_agency=None,
|
|
1630
|
+
agency=None,
|
|
1631
|
+
contract_number=None,
|
|
1632
|
+
issue_date_after=None,
|
|
1633
|
+
issue_date_before=None,
|
|
1634
|
+
close_date_after=None,
|
|
1635
|
+
close_date_before=None,
|
|
1636
|
+
ordering=None,
|
|
1637
|
+
)
|
|
1638
|
+
```
|
|
1639
|
+
|
|
1640
|
+
**Filter Parameters:**
|
|
1641
|
+
- `search` - Full-text search over the title, description, reference number, request id and attachment text. Results rank by relevance unless `ordering` is given
|
|
1642
|
+
- `rfq_id` - Exact request id, e.g. `"RFQ1835158"`
|
|
1643
|
+
- `reference_number` - The buyer's own solicitation number; dashes are ignored
|
|
1644
|
+
- `request_type` - `"RFQ"`, `"RFP"` or `"RFI"`
|
|
1645
|
+
- `status` - `"Open"` or `"Cancelled"`, as last seen (see the note below)
|
|
1646
|
+
- `sin` - Special Item Number, e.g. `"54151S"`
|
|
1647
|
+
- `schedule` - GSA schedule
|
|
1648
|
+
- `buyer_agency` - The buyer agency as eBuy names it (free text)
|
|
1649
|
+
- `agency` - A Tango agency name, abbreviation, code or organization key, e.g. `"GSA"`. Matches the whole organization subtree, so a department includes its sub-agencies. Requires Tango API 5.3.0
|
|
1650
|
+
- `contract_number` - Narrow to requests posted under one of your own linked contracts. A contract not linked to your account returns an empty page, not an error
|
|
1651
|
+
- `issue_date_after` / `issue_date_before` - Issue date range (`YYYY-MM-DD`, inclusive)
|
|
1652
|
+
- `close_date_after` / `close_date_before` - Close date range (`YYYY-MM-DD`, inclusive)
|
|
1653
|
+
- `ordering` - `issue_date` (the default, as `-issue_date`), `close_date`, `last_seen` or `modified`; prefix `-` for descending
|
|
1654
|
+
|
|
1655
|
+
String filters accept several values joined with `|` (OR).
|
|
1656
|
+
|
|
1657
|
+
**Returns:** [PaginatedResponse](#paginatedresponse) with request dictionaries
|
|
1658
|
+
|
|
1659
|
+
**Example:**
|
|
1660
|
+
```python
|
|
1661
|
+
requests = client.list_ebuy_requests(status="Open", sin="54151S", ordering="close_date")
|
|
1662
|
+
|
|
1663
|
+
for req in requests.results:
|
|
1664
|
+
print(f"{req['rfq_id']} closes {req['close_date']}: {req['title']}")
|
|
1665
|
+
print(f" last seen {req['last_seen']}")
|
|
1666
|
+
```
|
|
1667
|
+
|
|
1668
|
+
**Notes:**
|
|
1669
|
+
- **`status` is frozen at the last state the request was seen in.** Only currently-active requests are carried, so a request that closes stops appearing rather than getting a final row. `Open` means "open the last time it was seen", not "open now"; read `last_seen` for staleness.
|
|
1670
|
+
- The contract number a request was posted under is never returned in any payload.
|
|
1671
|
+
- `buyer_agency_code` and some other buyer and contact fields are sparse on older requests.
|
|
1672
|
+
|
|
1673
|
+
### get_ebuy_request()
|
|
1674
|
+
|
|
1675
|
+
Get a single request by `rfq_id`.
|
|
1676
|
+
|
|
1677
|
+
```python
|
|
1678
|
+
request = client.get_ebuy_request(
|
|
1679
|
+
"RFQ1835158",
|
|
1680
|
+
shape=ShapeConfig.EBUY_REQUESTS_COMPREHENSIVE,
|
|
1681
|
+
)
|
|
1682
|
+
|
|
1683
|
+
for attachment in request["attachments"]:
|
|
1684
|
+
print(attachment["doc_seq_num"], attachment["doc_name"], attachment["is_link"])
|
|
1685
|
+
```
|
|
1686
|
+
|
|
1687
|
+
The default shape returns every field plus two expands: `organization` (the buyer office, with the same seven keys as other resources' `organization` expand) and `attachments`. Each attachment carries `doc_seq_num`, `doc_name`, `doc_type`, `doc_path`, `is_link` and `doc_session_date`. `is_link=True` means `doc_path` is an outbound URL with no stored document behind it. `amendments`, `line_items` and `addresses` are lists of objects, served as eBuy publishes them.
|
|
1688
|
+
|
|
1689
|
+
### get_ebuy_attachment_url()
|
|
1690
|
+
|
|
1691
|
+
Get a short-lived download URL for one stored attachment.
|
|
1692
|
+
|
|
1693
|
+
```python
|
|
1694
|
+
url = client.get_ebuy_attachment_url("RFQ1835158", doc_seq_num=1)
|
|
1695
|
+
```
|
|
1696
|
+
|
|
1697
|
+
**Returns:** The signed URL the API redirects to, as a string. The SDK reads the redirect without following it, so no document is downloaded. The URL expires after about five minutes: fetch it promptly, and call this again rather than storing it.
|
|
1698
|
+
|
|
1699
|
+
**Raises:**
|
|
1700
|
+
- `TangoAttachmentLinkError` (a `TangoValidationError`) - The entry is an external link (`is_link`), not a stored document. The link is on `error.url`
|
|
1701
|
+
- `TangoNotFoundError` - The request is unknown or outside your scope, the attachment does not exist, or its document has not been captured yet
|
|
1702
|
+
|
|
1703
|
+
### get_ebuy_access()
|
|
1704
|
+
|
|
1705
|
+
Check whether your account can read eBuy requests.
|
|
1706
|
+
|
|
1707
|
+
```python
|
|
1708
|
+
access = client.get_ebuy_access()
|
|
1709
|
+
if not access.enabled:
|
|
1710
|
+
print(access.reason) # "tier_required" or "no_contract_grant"
|
|
1711
|
+
print(access.contracts) # your own linked contracts, sorted
|
|
1712
|
+
```
|
|
1713
|
+
|
|
1714
|
+
**Returns:** `EbuyAccess` with `enabled` (bool), `reason` (`"tier_required"`, `"no_contract_grant"` or `None`; `tier_required` wins when both apply) and `contracts` (list of str).
|
|
1715
|
+
|
|
1716
|
+
---
|
|
1717
|
+
|
|
1517
1718
|
## Budget
|
|
1518
1719
|
|
|
1519
1720
|
Federal account × fiscal year budget rollups, covering the full budget lifecycle (requested → enacted → apportioned → obligated → outlayed), pre-computed ratios and trends, the contract / assistance / unlinked breakdown, and request-vs-actual spend.
|
|
@@ -2311,6 +2512,10 @@ entity = client.get_entity("UEI_KEY", shape=ShapeConfig.ENTITIES_COMPREHENSIVE)
|
|
|
2311
2512
|
| `PROTESTS_MINIMAL` | `list_protests` | case_id, case_number, title, source_system, outcome, filed_date |
|
|
2312
2513
|
| `CONTRACT_APPEALS_MINIMAL` | `list_contract_appeals` | uuid, board, docket_numbers, decision_date, appellant, judge, decision_type, url |
|
|
2313
2514
|
| `CONTRACT_APPEALS_COMPREHENSIVE` | `get_contract_appeal` | The list fields plus docket_raw, docket_source, decision_date_repaired, decision_type_raw, listing_year, first_listed_at, listed, text_status, text_char_count (omits `decision_text`, which needs an Enterprise plan) |
|
|
2515
|
+
| `FEDERAL_REGISTER_MINIMAL` | `list_federal_register_documents` | uuid, document_number, publication_date, type, subtype, title, abstract, action, agencies, cfr_references, citation, significant, comments_close_on, effective_on, html_url, pdf_url |
|
|
2516
|
+
| `FEDERAL_REGISTER_COMPREHENSIVE` | `get_federal_register_document` | The list fields plus dates, signing_date, start_page, end_page, volume, docket_ids, dockets, regulation_id_numbers, topics, correction_of, corrections, executive_order_number, presidential_document_number, proclamation_number, comment_url, regulations_dot_gov_url, raw_text_url, body_html_url (omits `full_text`) |
|
|
2517
|
+
| `EBUY_REQUESTS_MINIMAL` | `list_ebuy_requests` | rfq_id, request_type, title, schedule, sin, status, buyer_name, buyer_agency, buyer_agency_code, reference_number, issue_date, close_date, attachment_count, link_count, last_seen |
|
|
2518
|
+
| `EBUY_REQUESTS_COMPREHENSIVE` | `get_ebuy_request` | Every field, plus the `organization` and `attachments` expands |
|
|
2314
2519
|
| `BUDGET_ACCOUNTS_MINIMAL` | `list_budget_accounts`, `get_budget_account` | id, federal_account_symbol, fiscal_year, agency_code/name, bureau_name, account_title, bea_category, on_off_budget, subfunction_code, lifecycle (requested/enacted/apportioned/obligated/outlayed/unobligated), contract & assistance rollups, key ratios, next-year growth |
|
|
2315
2520
|
| `VEHICLE_ORDERS_MINIMAL` | `list_vehicle_orders` | key, piid, award_date, recipient(display_name,uei), total_contract_value, obligated |
|
|
2316
2521
|
| `ITDASHBOARD_INVESTMENTS_MINIMAL` | `list_itdashboard_investments` | Minimal IT Dashboard investment fields |
|
|
@@ -89,6 +89,8 @@ tango webhooks list-event-types
|
|
|
89
89
|
# alerts.dibbs_rfp.match DLA DIBBS RFP matched a saved alert
|
|
90
90
|
# alerts.sled_opportunity.match State/local/education solicitation matched a saved alert
|
|
91
91
|
# alerts.contract_appeal.match CBCA/ASBCA appeal decision matched a saved alert
|
|
92
|
+
# alerts.federal_register.match Federal Register document matched a saved alert
|
|
93
|
+
# alerts.ebuy_request.match GSA eBuy request matched a saved alert
|
|
92
94
|
```
|
|
93
95
|
|
|
94
96
|
This list is served by the API, so it is always current — the SDK does not hardcode
|
|
@@ -78,6 +78,8 @@ RESOURCE_TO_METHOD: dict[str, str | None] = {
|
|
|
78
78
|
"sled/forecasts": "list_sled_forecasts",
|
|
79
79
|
"protests": "list_protests",
|
|
80
80
|
"contract_appeals": "list_contract_appeals",
|
|
81
|
+
"federal_register": "list_federal_register_documents",
|
|
82
|
+
"ebuy/requests": "list_ebuy_requests",
|
|
81
83
|
"offices": "list_offices",
|
|
82
84
|
"psc": "list_psc",
|
|
83
85
|
"mas_sins": "list_mas_sins",
|
|
@@ -69,6 +69,8 @@ RESOURCE_TO_MODEL: dict[str, str] = {
|
|
|
69
69
|
"budget_accounts": "BudgetAccount",
|
|
70
70
|
"protests": "Protest",
|
|
71
71
|
"contract_appeals": "ContractAppeal",
|
|
72
|
+
"federal_register": "FederalRegisterDocument",
|
|
73
|
+
"ebuy/requests": "EbuyRequest",
|
|
72
74
|
"offices": "Office",
|
|
73
75
|
"assistance_listings": "AssistanceListing",
|
|
74
76
|
"business_types": "BusinessType",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from .client import TangoClient
|
|
4
4
|
from .exceptions import (
|
|
5
5
|
TangoAPIError,
|
|
6
|
+
TangoAttachmentLinkError,
|
|
6
7
|
TangoAuthError,
|
|
7
8
|
TangoNotFoundError,
|
|
8
9
|
TangoRateLimitError,
|
|
@@ -14,7 +15,11 @@ from .models import (
|
|
|
14
15
|
DibbsAward,
|
|
15
16
|
DibbsRfp,
|
|
16
17
|
DibbsRfq,
|
|
18
|
+
EbuyAccess,
|
|
19
|
+
EbuyAttachment,
|
|
20
|
+
EbuyRequest,
|
|
17
21
|
Exclusion,
|
|
22
|
+
FederalRegisterDocument,
|
|
18
23
|
GsaElibraryContract,
|
|
19
24
|
ITDashboardInvestment,
|
|
20
25
|
PaginatedResponse,
|
|
@@ -54,19 +59,24 @@ from .webhooks import (
|
|
|
54
59
|
)
|
|
55
60
|
from .webhooks.receiver import Delivery, WebhookReceiver
|
|
56
61
|
|
|
57
|
-
__version__ = "1.
|
|
62
|
+
__version__ = "1.9.0"
|
|
58
63
|
__all__ = [
|
|
59
64
|
"TangoClient",
|
|
60
65
|
"TangoAPIError",
|
|
61
66
|
"TangoAuthError",
|
|
62
67
|
"TangoNotFoundError",
|
|
63
68
|
"TangoValidationError",
|
|
69
|
+
"TangoAttachmentLinkError",
|
|
64
70
|
"TangoRateLimitError",
|
|
65
71
|
"RateLimitInfo",
|
|
66
72
|
"ResolveCandidate",
|
|
67
73
|
"ResolveResult",
|
|
68
74
|
"BudgetAccount",
|
|
69
75
|
"ContractAppeal",
|
|
76
|
+
"FederalRegisterDocument",
|
|
77
|
+
"EbuyAccess",
|
|
78
|
+
"EbuyAttachment",
|
|
79
|
+
"EbuyRequest",
|
|
70
80
|
"DibbsAward",
|
|
71
81
|
"DibbsRfp",
|
|
72
82
|
"DibbsRfq",
|