From a2f3a5f16f7f2f4f49fac218f170e135f40733ce Mon Sep 17 00:00:00 2001 From: Danglewood <85772166+deeleeramone@users.noreply.github.com> Date: Wed, 23 Sep 2026 12:00:10 -0700 Subject: [PATCH] [V5] `openbb-eia`: Refactor for V5 + Add Full API Implementation (#7584) * eia refactor for v5 * add test and publish workflows * data browser state * fix workflows * more workflow test items * temp files in tests * more fixes * more browsers * fix codeql issues * fix mer state and ensure multi-user capability * uv lock * table bridge * fix electricity browser state * convert HTML widgets to iFrame * fix recursion error in workspace mcp --- .github/workflows/publish-openbb-us-eia.yml | 201 + .github/workflows/test-unit-openbb-us-eia.yml | 164 + openbb_platform/providers/eia/.gitignore | 1 + openbb_platform/providers/eia/README.md | 115 +- openbb_platform/providers/eia/hatch_build.py | 103 + .../providers/eia/openbb_us_eia/__init__.py | 13 +- .../eia/openbb_us_eia/assets/__init__.py | 1 + .../eia/openbb_us_eia/assets/apps.json | 197 + .../openbb_us_eia/assets/data_browser.html | 738 +++ .../openbb_us_eia/assets/proxy/article.css | 1 + .../openbb_us_eia/assets/proxy/asset_fix.js | 1 + .../eia/openbb_us_eia/assets/proxy/chrome.css | 1 + .../eia/openbb_us_eia/assets/proxy/dark.css | 1 + .../assets/proxy/dialog_clamp.js | 1 + .../assets/proxy/international.css | 1 + .../assets/proxy/map_contrast.css | 1 + .../openbb_us_eia/assets/proxy/map_layout.css | 1 + .../openbb_us_eia/assets/proxy/nav_guard.js | 1 + .../openbb_us_eia/assets/proxy/ngqs_grid.css | 1 + .../eia/openbb_us_eia/assets/proxy/states.css | 1 + .../assets/proxy/table_bridge.js | 744 +++ .../openbb_us_eia/assets/proxy/view_bridge.js | 1 + .../assets/proxy/view_select_sync.js | 1 + .../eia/openbb_us_eia/assets/proxy/xhr_tag.js | 154 + .../eia/openbb_us_eia/assets/rss_feed.html | 555 ++ .../providers/eia/openbb_us_eia/browsers.py | 2172 ++++++++ .../providers/eia/openbb_us_eia/eia_mcp.py | 400 ++ .../providers/eia/openbb_us_eia/eia_router.py | 580 ++ .../providers/eia/openbb_us_eia/models/aeo.py | 290 + .../eia/openbb_us_eia/models/coal/__init__.py | 1 + .../models/coal/aggregate_production.py | 205 + .../models/coal/by_mine_by_plant.py | 271 + .../models/coal/consumption_and_quality.py | 219 + .../coal/exports_imports_quantity_price.py | 193 + .../models/coal/market_sales_price.py | 166 + .../models/coal/mine_aggregates.py | 173 + .../models/coal/mine_production.py | 365 ++ .../models/coal/mine_state_aggregates.py | 188 + .../models/coal/plant_aggregates.py | 175 + .../models/coal/plant_state_aggregates.py | 195 + .../models/coal/price_by_rank.py | 157 + .../eia/openbb_us_eia/models/coal/receipts.py | 494 ++ .../models/coal/reserves_capacity.py | 177 + .../openbb_us_eia/models/crude_oil_imports.py | 246 + .../eia/openbb_us_eia/models/data_browser.py | 218 + .../models/densified_biomass/__init__.py | 1 + .../densified_biomass/capacity_by_region.py | 106 + .../characteristics_by_region.py | 133 + .../export_sales_and_price.py | 86 + .../densified_biomass/feedstocks_and_costs.py | 112 + .../inventories_by_region.py | 117 + .../densified_biomass/production_by_region.py | 117 + .../sales_and_price_by_region.py | 102 + .../wood_pellet_plant_capacity.py | 187 + .../models/electricity/__init__.py | 1 + .../electricity/electric_power_operations.py | 331 ++ ..._operations_for_individual_power_plants.py | 341 ++ ...electricity_sales_to_ultimate_customers.py | 200 + .../inventory_of_operable_generators.py | 554 ++ .../models/electricity_grid/__init__.py | 1 + .../models/electricity_grid/demand.py | 211 + .../electricity_grid/demand_by_subregion.py | 222 + .../electricity_grid/generation_by_fuel.py | 227 + .../models/electricity_grid/interchange.py | 297 + .../providers/eia/openbb_us_eia/models/ieo.py | 268 + .../eia/openbb_us_eia/models/international.py | 182 + .../models/natural_gas/__init__.py | 1 + .../associated_dissolved_proved_reserves.py | 170 + ...epth_of_crude_oil_and_natural_gas_wells.py | 153 + .../models/natural_gas/coalbed_methane.py | 164 + .../natural_gas/coalbed_methane_production.py | 200 + ...crude_oil_and_natural_gas_wells_drilled.py | 152 + ...e_oil_and_natural_gas_drilling_activity.py | 158 + ...l_gas_exploratory_and_development_wells.py | 162 + .../crude_oil_plus_lease_condensate.py | 170 + .../dry_natural_gas_proved_reserves.py | 169 + ...ffshore_gulf_of_america_proved_reserves.py | 178 + ...led_for_crude_oil_and_natural_gas_wells.py | 153 + ..._of_america_federal_offshore_production.py | 176 + .../heat_content_of_natural_gas_consumed.py | 236 + ...state_movements_of_natural_gas_by_state.py | 143 + .../models/natural_gas/lease_condensate.py | 164 + .../lease_condensate_production.py | 197 + .../lng_storage_additions_and_withdrawals.py | 178 + .../maximum_us_active_seismic_crew_counts.py | 150 + ..._gas_annual_supply_disposition_by_state.py | 185 + .../natural_gas_consumption_by_end_use.py | 198 + ...gas_delivered_for_the_account_of_others.py | 192 + ...al_gas_gross_withdrawals_and_production.py | 186 + .../natural_gas_liquids_proved_reserves.py | 167 + .../natural_gas_plant_liquids_production.py | 199 + .../natural_gas_plant_processing.py | 186 + .../models/natural_gas/natural_gas_prices.py | 200 + ...ved_reserves_wet_after_lease_separation.py | 174 + ...tural_gas_reserves_summary_as_of_dec_31.py | 172 + .../natural_gas_spot_and_futures_prices.py | 147 + .../models/natural_gas/natural_gas_summary.py | 233 + ..._wellhead_value_and_marketed_production.py | 215 + .../nonassociated_proved_reserves.py | 170 + .../number_of_gas_producing_oil_wells.py | 198 + .../number_of_natural_gas_consumers.py | 196 + .../number_of_producing_gas_wells.py | 200 + ...fshore_gross_withdrawals_of_natural_gas.py | 138 + .../plant_liquids_in_proved_reserves.py | 201 + .../proved_nonproducing_reserves.py | 178 + ...l_and_commercial_prices_selected_states.py | 175 + .../models/natural_gas/shale_gas.py | 159 + .../natural_gas/shale_gas_production.py | 192 + ...l_us_natural_gas_delivered_to_consumers.py | 192 + .../natural_gas/supplemental_gas_supplies.py | 113 + ...nd_natural_gas_storage_by_all_operators.py | 180 + ...nderground_natural_gas_storage_capacity.py | 173 + ...l_gas_exports_and_re_exports_by_country.py | 202 + ...exports_and_re_exports_by_point_of_exit.py | 141 + .../us_natural_gas_imports_by_country.py | 225 + ...s_natural_gas_imports_by_point_of_entry.py | 139 + ...us_natural_gas_imports_exports_by_state.py | 135 + ..._monthly_supply_and_disposition_balance.py | 154 + ...und_natural_gas_storage_by_storage_type.py | 170 + ...ekly_working_gas_in_underground_storage.py | 144 + .../models/nuclear_outages/__init__.py | 1 + .../facility_level_nuclear_outages.py | 173 + .../generator_level_nuclear_outages.py | 186 + .../nuclear_outages/us_nuclear_outages.py | 90 + .../models/petroleum/__init__.py | 1 + ..._fuel_oil_and_kerosene_sales_by_end_use.py | 235 + ...sales_of_distillate_fuel_oil_by_end_use.py | 216 + .../adjusted_sales_of_kerosene_by_end_use.py | 199 + ...d_sales_of_residual_fuel_oil_by_end_use.py | 201 + ...epth_of_crude_oil_and_natural_gas_wells.py | 153 + .../biofuels_operable_production_capacity.py | 134 + .../models/petroleum/blender_net_input.py | 166 + .../petroleum/blender_net_production.py | 160 + ...crude_oil_and_natural_gas_wells_drilled.py | 152 + ..._first_purchase_prices_selected_streams.py | 158 + ...se_condensate_production_by_api_gravity.py | 269 + ...e_oil_and_natural_gas_drilling_activity.py | 158 + ...l_gas_exploratory_and_development_wells.py | 162 + .../petroleum/crude_oil_input_qualities.py | 174 + .../models/petroleum/crude_oil_production.py | 261 + ...eserves_reserves_changes_and_production.py | 175 + ...rude_oil_stocks_at_tank_farms_pipelines.py | 146 + ...e_plus_lease_condensate_proved_reserves.py | 170 + ..._fuel_oil_and_kerosene_sales_by_end_use.py | 232 + ...il_first_purchase_prices_by_api_gravity.py | 147 + ...crude_oil_first_purchase_prices_by_area.py | 209 + ...pacity_of_operable_petroleum_refineries.py | 220 + ...wnstream_processing_of_fresh_feed_input.py | 213 + .../openbb_us_eia/models/petroleum/exports.py | 179 + .../petroleum/exports_by_destination.py | 173 + ...cks_consumed_for_production_of_biofuels.py | 182 + ...ts_of_imported_crude_oil_by_api_gravity.py | 146 + ...fob_costs_of_imported_crude_oil_by_area.py | 142 + ...ed_crude_oil_for_selected_crude_streams.py | 173 + ...led_for_crude_oil_and_natural_gas_wells.py | 153 + .../fuel_consumed_at_biofuels_plants.py | 151 + .../petroleum/fuel_consumed_at_refineries.py | 232 + ..._prices_by_formulation_grade_sales_type.py | 230 + ..._of_america_federal_offshore_production.py | 176 + .../petroleum/imports_by_area_of_entry.py | 214 + .../petroleum/imports_by_processing_area.py | 207 + .../petroleum/imports_of_residual_fuel.py | 182 + ..._costs_of_imported_crude_by_api_gravity.py | 146 + .../landed_costs_of_imported_crude_by_area.py | 143 + ...ported_crude_for_selected_crude_streams.py | 202 + .../maximum_us_active_seismic_crew_counts.py | 150 + .../movements_between_pad_districts.py | 196 + ...ments_by_pipeline_between_pad_districts.py | 175 + ...movements_by_rail_between_pad_districts.py | 146 + ..._tanker_and_barge_between_pad_districts.py | 200 + ...crude_oil_and_selected_products_by_rail.py | 157 + .../natural_gas_feedstock_for_hydrogen.py | 138 + .../natural_gas_plant_field_production.py | 145 + .../petroleum/natural_gas_plant_stocks.py | 149 + .../net_receipts_between_pad_districts.py | 212 + .../no2_distillate_prices_by_sales_type.py | 191 + ...er_and_capacity_of_petroleum_refineries.py | 221 + .../models/petroleum/nymex_futures_prices.py | 173 + .../models/petroleum/oxygenate_production.py | 204 + .../pad_district_exports_by_destination.py | 172 + ...d_district_imports_by_country_of_origin.py | 193 + ...total_imported_crude_oil_by_api_gravity.py | 149 + .../prices_sales_volumes_stocks_by_state.py | 234 + .../petroleum/prime_supplier_sales_volumes.py | 230 + .../models/petroleum/product_supplied.py | 191 + ...pacity_of_operable_petroleum_refineries.py | 201 + .../petroleum/propane_prices_by_sales_type.py | 230 + .../petroleum/proved_nonproducing_reserves.py | 178 + .../refiner_acquisition_cost_of_crude_oil.py | 161 + ...gasoline_prices_by_grade_and_sales_type.py | 219 + .../refiner_motor_gasoline_sales_volumes.py | 219 + ..._petroleum_product_prices_by_sales_type.py | 226 + ...ual_fuel_oil_and_no4_fuel_sales_volumes.py | 239 + ...les_volumes_of_other_petroleum_products.py | 221 + .../petroleum/refinery_blender_net_input.py | 175 + .../refinery_blender_net_production.py | 186 + ...l_and_natural_gas_plant_stocks_by_state.py | 212 + .../models/petroleum/refinery_net_input.py | 177 + .../petroleum/refinery_net_production.py | 192 + ...f_crude_oil_by_method_of_transportation.py | 160 + .../models/petroleum/refinery_stocks.py | 203 + .../refinery_utilization_and_capacity.py | 225 + .../models/petroleum/refinery_yield.py | 144 + .../residual_fuel_oil_prices_by_sales_type.py | 211 + ...sales_of_distillate_fuel_oil_by_end_use.py | 214 + .../petroleum/sales_of_kerosene_by_end_use.py | 199 + .../sales_of_residual_fuel_oil_by_end_use.py | 201 + ...storage_capacity_at_operable_refineries.py | 167 + .../models/petroleum/spot_prices.py | 151 + .../models/petroleum/stocks_by_type.py | 231 + .../petroleum/stocks_of_selected_products.py | 220 + .../petroleum/supply_and_disposition.py | 213 + ...el_production_capacity_sales_and_stocks.py | 198 + .../us_crude_oil_supply_disposition.py | 188 + .../us_imports_by_country_of_origin.py | 185 + .../petroleum/us_net_imports_by_country.py | 181 + ..._prices_by_formulation_grade_sales_type.py | 236 + .../petroleum/us_weekly_product_supplied.py | 146 + .../weekly_blender_net_production.py | 175 + .../weekly_crude_imports_by_top_10_origins.py | 170 + .../weekly_ethanol_plant_production.py | 137 + .../weekly_heating_oil_and_propane_prices.py | 194 + .../petroleum/weekly_imports_exports.py | 182 + .../petroleum/weekly_inputs_utilization.py | 221 + .../weekly_refiner_blender_net_production.py | 178 + .../weekly_refiner_net_production.py | 177 + ...eekly_retail_gasoline_and_diesel_prices.py | 181 + .../models/petroleum/weekly_stocks.py | 183 + .../petroleum/weekly_supply_estimates.py | 224 + ...storage_capacity_at_operable_refineries.py | 167 + .../models/petroleum_status_report.py | 25 +- .../eia/openbb_us_eia/models/registry.py | 779 +++ .../eia/openbb_us_eia/models/seds.py | 151 + .../models/short_term_energy_outlook.py | 55 +- .../state_electricity_profiles/__init__.py | 1 + .../advanced_metering_infrastructure.py | 188 + ...savings_from_energy_efficiency_programs.py | 219 + ...ity_net_metering_customers_and_capacity.py | 136 + .../emissions_by_state_by_fuel.py | 194 + .../generating_capacity.py | 209 + .../state_rankings_for_key_statistics.py | 325 ++ .../supply_and_disposition_of_electricity.py | 258 + .../eia/openbb_us_eia/models/total_energy.py | 86 + .../providers/eia/openbb_us_eia/py.typed | 0 .../providers/eia/openbb_us_eia/rss.py | 74 + .../eia/openbb_us_eia/utils/api_query.py | 465 ++ .../eia/openbb_us_eia/utils/catalog.py | 595 ++ .../eia/openbb_us_eia/utils/constants.py | 64 +- .../openbb_us_eia/utils/generate_catalog.py | 1264 +++++ .../eia/openbb_us_eia/utils/helpers.py | 102 +- .../providers/eia/openbb_us_eia/utils/rss.py | 363 ++ .../openbb_us_eia/utils/total_energy_map.json | 982 ---- openbb_platform/providers/eia/poetry.lock | 2018 ------- openbb_platform/providers/eia/pyproject.toml | 123 +- .../test_eia_aeo_fetcher_urllib3_v2.yaml | 64 + ...gregate_production_fetcher_urllib3_v2.yaml | 66 + ...l_by_mine_by_plant_fetcher_urllib3_v2.yaml | 66 + ...mption_and_quality_fetcher_urllib3_v2.yaml | 68 + ...rts_quantity_price_fetcher_urllib3_v2.yaml | 64 + ...market_sales_price_fetcher_urllib3_v2.yaml | 64 + ...al_mine_aggregates_fetcher_urllib3_v2.yaml | 66 + ...al_mine_production_fetcher_urllib3_v2.yaml | 70 + ...e_state_aggregates_fetcher_urllib3_v2.yaml | 65 + ...l_plant_aggregates_fetcher_urllib3_v2.yaml | 65 + ...t_state_aggregates_fetcher_urllib3_v2.yaml | 65 + ...coal_price_by_rank_fetcher_urllib3_v2.yaml | 63 + ..._eia_coal_receipts_fetcher_urllib3_v2.yaml | 69 + ..._reserves_capacity_fetcher_urllib3_v2.yaml | 64 + ..._crude_oil_imports_fetcher_urllib3_v2.yaml | 65 + ...t_eia_data_browser_fetcher_urllib3_v2.yaml | 129 + ...capacity_by_region_fetcher_urllib3_v2.yaml | 63 + ...eristics_by_region_fetcher_urllib3_v2.yaml | 65 + ...rt_sales_and_price_fetcher_urllib3_v2.yaml | 63 + ...edstocks_and_costs_fetcher_urllib3_v2.yaml | 63 + ...entories_by_region_fetcher_urllib3_v2.yaml | 63 + ...oduction_by_region_fetcher_urllib3_v2.yaml | 63 + ...nd_price_by_region_fetcher_urllib3_v2.yaml | 63 + ...let_plant_capacity_fetcher_urllib3_v2.yaml | 65 + ...c_power_operations_fetcher_urllib3_v2.yaml | 71 + ...idual_power_plants_fetcher_urllib3_v2.yaml | 63 + ...ultimate_customers_fetcher_urllib3_v2.yaml | 66 + ...emand_by_subregion_fetcher_urllib3_v2.yaml | 65 + ...ricity_grid_demand_fetcher_urllib3_v2.yaml | 65 + ...generation_by_fuel_fetcher_urllib3_v2.yaml | 64 + ...y_grid_interchange_fetcher_urllib3_v2.yaml | 65 + ...perable_generators_fetcher_urllib3_v2.yaml | 64 + .../test_eia_ieo_fetcher_urllib3_v2.yaml | 64 + ..._eia_international_fetcher_urllib3_v2.yaml | 64 + ...ed_proved_reserves_fetcher_urllib3_v2.yaml | 64 + ..._natural_gas_wells_fetcher_urllib3_v2.yaml | 63 + ...as_coalbed_methane_fetcher_urllib3_v2.yaml | 63 + ...methane_production_fetcher_urllib3_v2.yaml | 63 + ..._gas_wells_drilled_fetcher_urllib3_v2.yaml | 64 + ..._drilling_activity_fetcher_urllib3_v2.yaml | 64 + ..._development_wells_fetcher_urllib3_v2.yaml | 63 + ...s_lease_condensate_fetcher_urllib3_v2.yaml | 63 + ...as_proved_reserves_fetcher_urllib3_v2.yaml | 63 + ...ca_proved_reserves_fetcher_urllib3_v2.yaml | 63 + ..._natural_gas_wells_fetcher_urllib3_v2.yaml | 64 + ...ffshore_production_fetcher_urllib3_v2.yaml | 63 + ...tural_gas_consumed_fetcher_urllib3_v2.yaml | 63 + ...tural_gas_by_state_fetcher_urllib3_v2.yaml | 63 + ...s_lease_condensate_fetcher_urllib3_v2.yaml | 64 + ...densate_production_fetcher_urllib3_v2.yaml | 64 + ...ns_and_withdrawals_fetcher_urllib3_v2.yaml | 63 + ...eismic_crew_counts_fetcher_urllib3_v2.yaml | 63 + ...sposition_by_state_fetcher_urllib3_v2.yaml | 63 + ...umption_by_end_use_fetcher_urllib3_v2.yaml | 64 + ..._account_of_others_fetcher_urllib3_v2.yaml | 64 + ...als_and_production_fetcher_urllib3_v2.yaml | 63 + ...ds_proved_reserves_fetcher_urllib3_v2.yaml | 64 + ...liquids_production_fetcher_urllib3_v2.yaml | 64 + ...s_plant_processing_fetcher_urllib3_v2.yaml | 63 + ...natural_gas_prices_fetcher_urllib3_v2.yaml | 64 + ...r_lease_separation_fetcher_urllib3_v2.yaml | 65 + ...ummary_as_of_dec31_fetcher_urllib3_v2.yaml | 63 + ...and_futures_prices_fetcher_urllib3_v2.yaml | 64 + ...atural_gas_summary_fetcher_urllib3_v2.yaml | 64 + ...arketed_production_fetcher_urllib3_v2.yaml | 63 + ...ed_proved_reserves_fetcher_urllib3_v2.yaml | 64 + ...roducing_oil_wells_fetcher_urllib3_v2.yaml | 63 + ...ural_gas_consumers_fetcher_urllib3_v2.yaml | 64 + ...roducing_gas_wells_fetcher_urllib3_v2.yaml | 63 + ...als_of_natural_gas_fetcher_urllib3_v2.yaml | 63 + ...in_proved_reserves_fetcher_urllib3_v2.yaml | 64 + ...producing_reserves_fetcher_urllib3_v2.yaml | 64 + ...es_selected_states_fetcher_urllib3_v2.yaml | 64 + ...ural_gas_shale_gas_fetcher_urllib3_v2.yaml | 63 + ...ale_gas_production_fetcher_urllib3_v2.yaml | 63 + ...vered_to_consumers_fetcher_urllib3_v2.yaml | 63 + ...ental_gas_supplies_fetcher_urllib3_v2.yaml | 63 + ...e_by_all_operators_fetcher_urllib3_v2.yaml | 63 + ...s_storage_capacity_fetcher_urllib3_v2.yaml | 63 + ...exports_by_country_fetcher_urllib3_v2.yaml | 63 + ...s_by_point_of_exit_fetcher_urllib3_v2.yaml | 63 + ...imports_by_country_fetcher_urllib3_v2.yaml | 63 + ..._by_point_of_entry_fetcher_urllib3_v2.yaml | 63 + ...s_exports_by_state_fetcher_urllib3_v2.yaml | 63 + ...isposition_balance_fetcher_urllib3_v2.yaml | 63 + ...ge_by_storage_type_fetcher_urllib3_v2.yaml | 63 + ...nderground_storage_fetcher_urllib3_v2.yaml | 63 + ...el_nuclear_outages_fetcher_urllib3_v2.yaml | 127 + ...el_nuclear_outages_fetcher_urllib3_v2.yaml | 64 + ...us_nuclear_outages_fetcher_urllib3_v2.yaml | 64 + ...e_sales_by_end_use_fetcher_urllib3_v2.yaml | 63 + ...uel_oil_by_end_use_fetcher_urllib3_v2.yaml | 64 + ...erosene_by_end_use_fetcher_urllib3_v2.yaml | 63 + ...uel_oil_by_end_use_fetcher_urllib3_v2.yaml | 64 + ..._natural_gas_wells_fetcher_urllib3_v2.yaml | 63 + ...roduction_capacity_fetcher_urllib3_v2.yaml | 63 + ..._blender_net_input_fetcher_urllib3_v2.yaml | 64 + ...der_net_production_fetcher_urllib3_v2.yaml | 64 + ..._gas_wells_drilled_fetcher_urllib3_v2.yaml | 64 + ...s_selected_streams_fetcher_urllib3_v2.yaml | 63 + ...ion_by_api_gravity_fetcher_urllib3_v2.yaml | 63 + ..._drilling_activity_fetcher_urllib3_v2.yaml | 64 + ..._development_wells_fetcher_urllib3_v2.yaml | 64 + ...il_input_qualities_fetcher_urllib3_v2.yaml | 63 + ...ude_oil_production_fetcher_urllib3_v2.yaml | 63 + ...ges_and_production_fetcher_urllib3_v2.yaml | 63 + ...nk_farms_pipelines_fetcher_urllib3_v2.yaml | 64 + ...te_proved_reserves_fetcher_urllib3_v2.yaml | 63 + ...e_sales_by_end_use_fetcher_urllib3_v2.yaml | 64 + ...ces_by_api_gravity_fetcher_urllib3_v2.yaml | 63 + ...ase_prices_by_area_fetcher_urllib3_v2.yaml | 63 + ...troleum_refineries_fetcher_urllib3_v2.yaml | 64 + ...f_fresh_feed_input_fetcher_urllib3_v2.yaml | 63 + ...rts_by_destination_fetcher_urllib3_v2.yaml | 63 + ..._petroleum_exports_fetcher_urllib3_v2.yaml | 63 + ...uction_of_biofuels_fetcher_urllib3_v2.yaml | 63 + ...oil_by_api_gravity_fetcher_urllib3_v2.yaml | 63 + ..._crude_oil_by_area_fetcher_urllib3_v2.yaml | 63 + ...cted_crude_streams_fetcher_urllib3_v2.yaml | 63 + ..._natural_gas_wells_fetcher_urllib3_v2.yaml | 64 + ...at_biofuels_plants_fetcher_urllib3_v2.yaml | 64 + ...umed_at_refineries_fetcher_urllib3_v2.yaml | 63 + ...n_grade_sales_type_fetcher_urllib3_v2.yaml | 63 + ...ffshore_production_fetcher_urllib3_v2.yaml | 63 + ...s_by_area_of_entry_fetcher_urllib3_v2.yaml | 63 + ...by_processing_area_fetcher_urllib3_v2.yaml | 64 + ...s_of_residual_fuel_fetcher_urllib3_v2.yaml | 63 + ...ude_by_api_gravity_fetcher_urllib3_v2.yaml | 63 + ...rted_crude_by_area_fetcher_urllib3_v2.yaml | 63 + ...cted_crude_streams_fetcher_urllib3_v2.yaml | 63 + ...eismic_crew_counts_fetcher_urllib3_v2.yaml | 63 + ...ween_pad_districts_fetcher_urllib3_v2.yaml | 64 + ...ween_pad_districts_fetcher_urllib3_v2.yaml | 64 + ...ween_pad_districts_fetcher_urllib3_v2.yaml | 64 + ...ween_pad_districts_fetcher_urllib3_v2.yaml | 64 + ...d_products_by_rail_fetcher_urllib3_v2.yaml | 63 + ...stock_for_hydrogen_fetcher_urllib3_v2.yaml | 64 + ...t_field_production_fetcher_urllib3_v2.yaml | 63 + ...l_gas_plant_stocks_fetcher_urllib3_v2.yaml | 63 + ...ween_pad_districts_fetcher_urllib3_v2.yaml | 64 + ...ices_by_sales_type_fetcher_urllib3_v2.yaml | 63 + ...troleum_refineries_fetcher_urllib3_v2.yaml | 64 + ...mex_futures_prices_fetcher_urllib3_v2.yaml | 63 + ...ygenate_production_fetcher_urllib3_v2.yaml | 63 + ...rts_by_destination_fetcher_urllib3_v2.yaml | 63 + ..._country_of_origin_fetcher_urllib3_v2.yaml | 64 + ...oil_by_api_gravity_fetcher_urllib3_v2.yaml | 65 + ...es_stocks_by_state_fetcher_urllib3_v2.yaml | 64 + ...lier_sales_volumes_fetcher_urllib3_v2.yaml | 64 + ...m_product_supplied_fetcher_urllib3_v2.yaml | 63 + ...troleum_refineries_fetcher_urllib3_v2.yaml | 64 + ...ices_by_sales_type_fetcher_urllib3_v2.yaml | 63 + ...producing_reserves_fetcher_urllib3_v2.yaml | 64 + ..._cost_of_crude_oil_fetcher_urllib3_v2.yaml | 63 + ...ade_and_sales_type_fetcher_urllib3_v2.yaml | 64 + ...line_sales_volumes_fetcher_urllib3_v2.yaml | 64 + ...ices_by_sales_type_fetcher_urllib3_v2.yaml | 64 + ...fuel_sales_volumes_fetcher_urllib3_v2.yaml | 64 + ...petroleum_products_fetcher_urllib3_v2.yaml | 64 + ..._blender_net_input_fetcher_urllib3_v2.yaml | 63 + ...der_net_production_fetcher_urllib3_v2.yaml | 63 + ...nt_stocks_by_state_fetcher_urllib3_v2.yaml | 64 + ...refinery_net_input_fetcher_urllib3_v2.yaml | 63 + ...ery_net_production_fetcher_urllib3_v2.yaml | 63 + ..._of_transportation_fetcher_urllib3_v2.yaml | 64 + ...um_refinery_stocks_fetcher_urllib3_v2.yaml | 64 + ...ation_and_capacity_fetcher_urllib3_v2.yaml | 63 + ...eum_refinery_yield_fetcher_urllib3_v2.yaml | 63 + ...ices_by_sales_type_fetcher_urllib3_v2.yaml | 64 + ...uel_oil_by_end_use_fetcher_urllib3_v2.yaml | 63 + ...erosene_by_end_use_fetcher_urllib3_v2.yaml | 63 + ...uel_oil_by_end_use_fetcher_urllib3_v2.yaml | 63 + ...perable_refineries_fetcher_urllib3_v2.yaml | 63 + ...roleum_spot_prices_fetcher_urllib3_v2.yaml | 63 + ...eum_stocks_by_type_fetcher_urllib3_v2.yaml | 63 + ..._selected_products_fetcher_urllib3_v2.yaml | 63 + ...ly_and_disposition_fetcher_urllib3_v2.yaml | 63 + ...y_sales_and_stocks_fetcher_urllib3_v2.yaml | 63 + ...supply_disposition_fetcher_urllib3_v2.yaml | 63 + ..._country_of_origin_fetcher_urllib3_v2.yaml | 63 + ...imports_by_country_fetcher_urllib3_v2.yaml | 63 + ...n_grade_sales_type_fetcher_urllib3_v2.yaml | 64 + ...y_product_supplied_fetcher_urllib3_v2.yaml | 63 + ...der_net_production_fetcher_urllib3_v2.yaml | 64 + ...s_by_top10_origins_fetcher_urllib3_v2.yaml | 63 + ...l_plant_production_fetcher_urllib3_v2.yaml | 63 + ...and_propane_prices_fetcher_urllib3_v2.yaml | 63 + ...ly_imports_exports_fetcher_urllib3_v2.yaml | 63 + ...inputs_utilization_fetcher_urllib3_v2.yaml | 63 + ...der_net_production_fetcher_urllib3_v2.yaml | 64 + ...ner_net_production_fetcher_urllib3_v2.yaml | 64 + ..._and_diesel_prices_fetcher_urllib3_v2.yaml | 63 + ...leum_weekly_stocks_fetcher_urllib3_v2.yaml | 63 + ...y_supply_estimates_fetcher_urllib3_v2.yaml | 63 + ...perable_refineries_fetcher_urllib3_v2.yaml | 63 + .../test_eia_seds_fetcher_urllib3_v2.yaml | 66 + ...erm_energy_outlook_fetcher_urllib3_v2.yaml | 200 +- ...ing_infrastructure_fetcher_urllib3_v2.yaml | 66 + ...fficiency_programs_fetcher_urllib3_v2.yaml | 66 + ...omers_and_capacity_fetcher_urllib3_v2.yaml | 64 + ...s_by_state_by_fuel_fetcher_urllib3_v2.yaml | 69 + ...enerating_capacity_fetcher_urllib3_v2.yaml | 63 + ...for_key_statistics_fetcher_urllib3_v2.yaml | 67 + ...ion_of_electricity_fetcher_urllib3_v2.yaml | 62 + ...t_eia_total_energy_fetcher_urllib3_v2.yaml | 67 + .../providers/eia/tests/test_api_models.py | 357 ++ .../providers/eia/tests/test_api_query.py | 382 ++ .../providers/eia/tests/test_browsers.py | 2784 ++++++++++ .../providers/eia/tests/test_catalog.py | 365 ++ .../providers/eia/tests/test_data_browser.py | 173 + .../providers/eia/tests/test_eia_fetchers.py | 3803 ++++++++++++- .../providers/eia/tests/test_eia_mcp.py | 883 +++ .../providers/eia/tests/test_eia_router.py | 290 + .../eia/tests/test_generate_catalog.py | 800 +++ .../providers/eia/tests/test_helpers.py | 90 + .../eia/tests/test_proxy_transport.py | 303 ++ .../providers/eia/tests/test_raw_tables.py | 877 +++ .../providers/eia/tests/test_report_models.py | 298 + .../providers/eia/tests/test_rss.py | 381 ++ openbb_platform/providers/eia/uv.lock | 4775 +++++++++++++++++ 474 files changed, 78393 insertions(+), 3274 deletions(-) create mode 100644 .github/workflows/publish-openbb-us-eia.yml create mode 100644 .github/workflows/test-unit-openbb-us-eia.yml create mode 100644 openbb_platform/providers/eia/.gitignore create mode 100644 openbb_platform/providers/eia/hatch_build.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/__init__.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/apps.json create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/data_browser.html create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/article.css create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/asset_fix.js create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/chrome.css create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/dark.css create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/dialog_clamp.js create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/international.css create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/map_contrast.css create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/map_layout.css create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/nav_guard.js create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/ngqs_grid.css create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/states.css create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/table_bridge.js create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/view_bridge.js create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/view_select_sync.js create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/proxy/xhr_tag.js create mode 100644 openbb_platform/providers/eia/openbb_us_eia/assets/rss_feed.html create mode 100644 openbb_platform/providers/eia/openbb_us_eia/browsers.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/eia_mcp.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/eia_router.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/aeo.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/coal/__init__.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/coal/aggregate_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/coal/by_mine_by_plant.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/coal/consumption_and_quality.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/coal/exports_imports_quantity_price.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/coal/market_sales_price.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/coal/mine_aggregates.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/coal/mine_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/coal/mine_state_aggregates.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/coal/plant_aggregates.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/coal/plant_state_aggregates.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/coal/price_by_rank.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/coal/receipts.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/coal/reserves_capacity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/crude_oil_imports.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/data_browser.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/__init__.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/capacity_by_region.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/characteristics_by_region.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/export_sales_and_price.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/feedstocks_and_costs.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/inventories_by_region.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/production_by_region.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/sales_and_price_by_region.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/wood_pellet_plant_capacity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/electricity/__init__.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/electricity/electric_power_operations.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/electricity/electric_power_operations_for_individual_power_plants.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/electricity/electricity_sales_to_ultimate_customers.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/electricity/inventory_of_operable_generators.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/__init__.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/demand.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/demand_by_subregion.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/generation_by_fuel.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/interchange.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/ieo.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/international.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/__init__.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/associated_dissolved_proved_reserves.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/average_depth_of_crude_oil_and_natural_gas_wells.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/coalbed_methane.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/coalbed_methane_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/costs_of_crude_oil_and_natural_gas_wells_drilled.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/crude_oil_and_natural_gas_drilling_activity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/crude_oil_and_natural_gas_exploratory_and_development_wells.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/crude_oil_plus_lease_condensate.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/dry_natural_gas_proved_reserves.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/federal_offshore_gulf_of_america_proved_reserves.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/footage_drilled_for_crude_oil_and_natural_gas_wells.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/gulf_of_america_federal_offshore_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/heat_content_of_natural_gas_consumed.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/international_interstate_movements_of_natural_gas_by_state.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/lease_condensate.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/lease_condensate_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/lng_storage_additions_and_withdrawals.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/maximum_us_active_seismic_crew_counts.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_annual_supply_disposition_by_state.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_consumption_by_end_use.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_delivered_for_the_account_of_others.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_gross_withdrawals_and_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_liquids_proved_reserves.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_plant_liquids_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_plant_processing.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_prices.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_proved_reserves_wet_after_lease_separation.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_reserves_summary_as_of_dec_31.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_spot_and_futures_prices.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_summary.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_wellhead_value_and_marketed_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/nonassociated_proved_reserves.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/number_of_gas_producing_oil_wells.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/number_of_natural_gas_consumers.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/number_of_producing_gas_wells.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/offshore_gross_withdrawals_of_natural_gas.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/plant_liquids_in_proved_reserves.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/proved_nonproducing_reserves.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/residential_and_commercial_prices_selected_states.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/shale_gas.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/shale_gas_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/share_of_total_us_natural_gas_delivered_to_consumers.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/supplemental_gas_supplies.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/underground_natural_gas_storage_by_all_operators.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/underground_natural_gas_storage_capacity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_exports_and_re_exports_by_country.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_exports_and_re_exports_by_point_of_exit.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_imports_by_country.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_imports_by_point_of_entry.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_imports_exports_by_state.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_monthly_supply_and_disposition_balance.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_underground_natural_gas_storage_by_storage_type.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/weekly_working_gas_in_underground_storage.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/__init__.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/facility_level_nuclear_outages.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/generator_level_nuclear_outages.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/us_nuclear_outages.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/__init__.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_distillate_fuel_oil_and_kerosene_sales_by_end_use.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_sales_of_distillate_fuel_oil_by_end_use.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_sales_of_kerosene_by_end_use.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_sales_of_residual_fuel_oil_by_end_use.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/average_depth_of_crude_oil_and_natural_gas_wells.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/biofuels_operable_production_capacity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/blender_net_input.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/blender_net_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/costs_of_crude_oil_and_natural_gas_wells_drilled.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_first_purchase_prices_selected_streams.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_and_lease_condensate_production_by_api_gravity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_and_natural_gas_drilling_activity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_and_natural_gas_exploratory_and_development_wells.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_input_qualities.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_proved_reserves_reserves_changes_and_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_stocks_at_tank_farms_pipelines.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_plus_lease_condensate_proved_reserves.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/distillate_fuel_oil_and_kerosene_sales_by_end_use.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/domestic_crude_oil_first_purchase_prices_by_api_gravity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/domestic_crude_oil_first_purchase_prices_by_area.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/downstream_charge_capacity_of_operable_petroleum_refineries.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/downstream_processing_of_fresh_feed_input.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/exports.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/exports_by_destination.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/feedstocks_consumed_for_production_of_biofuels.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fob_costs_of_imported_crude_oil_by_api_gravity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fob_costs_of_imported_crude_oil_by_area.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fob_costs_of_imported_crude_oil_for_selected_crude_streams.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/footage_drilled_for_crude_oil_and_natural_gas_wells.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fuel_consumed_at_biofuels_plants.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fuel_consumed_at_refineries.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/gasoline_prices_by_formulation_grade_sales_type.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/gulf_of_america_federal_offshore_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/imports_by_area_of_entry.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/imports_by_processing_area.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/imports_of_residual_fuel.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/landed_costs_of_imported_crude_by_api_gravity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/landed_costs_of_imported_crude_by_area.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/landed_costs_of_imported_crude_for_selected_crude_streams.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/maximum_us_active_seismic_crew_counts.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_between_pad_districts.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_by_pipeline_between_pad_districts.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_by_rail_between_pad_districts.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_by_tanker_and_barge_between_pad_districts.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_of_crude_oil_and_selected_products_by_rail.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/natural_gas_feedstock_for_hydrogen.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/natural_gas_plant_field_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/natural_gas_plant_stocks.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/net_receipts_between_pad_districts.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/no2_distillate_prices_by_sales_type.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/number_and_capacity_of_petroleum_refineries.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/nymex_futures_prices.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/oxygenate_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/pad_district_exports_by_destination.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/pad_district_imports_by_country_of_origin.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/percentages_of_total_imported_crude_oil_by_api_gravity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/prices_sales_volumes_stocks_by_state.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/prime_supplier_sales_volumes.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/product_supplied.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/production_capacity_of_operable_petroleum_refineries.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/propane_prices_by_sales_type.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/proved_nonproducing_reserves.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_acquisition_cost_of_crude_oil.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_gasoline_prices_by_grade_and_sales_type.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_motor_gasoline_sales_volumes.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_petroleum_product_prices_by_sales_type.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_residual_fuel_oil_and_no4_fuel_sales_volumes.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_sales_volumes_of_other_petroleum_products.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_blender_net_input.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_blender_net_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_bulk_terminal_and_natural_gas_plant_stocks_by_state.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_net_input.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_net_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_receipts_of_crude_oil_by_method_of_transportation.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_stocks.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_utilization_and_capacity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_yield.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/residual_fuel_oil_prices_by_sales_type.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/sales_of_distillate_fuel_oil_by_end_use.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/sales_of_kerosene_by_end_use.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/sales_of_residual_fuel_oil_by_end_use.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/shell_storage_capacity_at_operable_refineries.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/spot_prices.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/stocks_by_type.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/stocks_of_selected_products.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/supply_and_disposition.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_biodiesel_production_capacity_sales_and_stocks.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_crude_oil_supply_disposition.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_imports_by_country_of_origin.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_net_imports_by_country.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_refiner_gasoline_prices_by_formulation_grade_sales_type.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_weekly_product_supplied.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_blender_net_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_crude_imports_by_top_10_origins.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_ethanol_plant_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_heating_oil_and_propane_prices.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_imports_exports.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_inputs_utilization.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_refiner_blender_net_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_refiner_net_production.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_retail_gasoline_and_diesel_prices.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_stocks.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_supply_estimates.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/petroleum/working_storage_capacity_at_operable_refineries.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/registry.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/seds.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/__init__.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/advanced_metering_infrastructure.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/costs_and_savings_from_energy_efficiency_programs.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/electricity_net_metering_customers_and_capacity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/emissions_by_state_by_fuel.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/generating_capacity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/state_rankings_for_key_statistics.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/supply_and_disposition_of_electricity.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/models/total_energy.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/py.typed create mode 100644 openbb_platform/providers/eia/openbb_us_eia/rss.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/utils/api_query.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/utils/catalog.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/utils/generate_catalog.py create mode 100644 openbb_platform/providers/eia/openbb_us_eia/utils/rss.py delete mode 100644 openbb_platform/providers/eia/openbb_us_eia/utils/total_energy_map.json delete mode 100644 openbb_platform/providers/eia/poetry.lock create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_aeo_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_aggregate_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_by_mine_by_plant_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_consumption_and_quality_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_exports_imports_quantity_price_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_market_sales_price_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_mine_aggregates_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_mine_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_mine_state_aggregates_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_plant_aggregates_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_plant_state_aggregates_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_price_by_rank_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_receipts_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_reserves_capacity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_crude_oil_imports_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_data_browser_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_capacity_by_region_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_characteristics_by_region_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_export_sales_and_price_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_feedstocks_and_costs_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_inventories_by_region_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_production_by_region_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_sales_and_price_by_region_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_wood_pellet_plant_capacity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_electric_power_operations_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_electric_power_operations_for_individual_power_plants_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_electricity_sales_to_ultimate_customers_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_demand_by_subregion_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_demand_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_generation_by_fuel_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_interchange_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_inventory_of_operable_generators_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_ieo_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_international_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_associated_dissolved_proved_reserves_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_average_depth_of_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_coalbed_methane_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_coalbed_methane_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_costs_of_crude_oil_and_natural_gas_wells_drilled_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_crude_oil_and_natural_gas_drilling_activity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_crude_oil_and_natural_gas_exploratory_and_development_wells_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_crude_oil_plus_lease_condensate_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_dry_natural_gas_proved_reserves_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_federal_offshore_gulf_of_america_proved_reserves_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_footage_drilled_for_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_gulf_of_america_federal_offshore_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_heat_content_of_natural_gas_consumed_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_international_interstate_movements_of_natural_gas_by_state_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_lease_condensate_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_lease_condensate_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_lng_storage_additions_and_withdrawals_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_maximum_us_active_seismic_crew_counts_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_annual_supply_disposition_by_state_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_consumption_by_end_use_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_delivered_for_the_account_of_others_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_gross_withdrawals_and_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_liquids_proved_reserves_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_plant_liquids_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_plant_processing_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_prices_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_proved_reserves_wet_after_lease_separation_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_reserves_summary_as_of_dec31_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_spot_and_futures_prices_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_summary_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_wellhead_value_and_marketed_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_nonassociated_proved_reserves_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_number_of_gas_producing_oil_wells_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_number_of_natural_gas_consumers_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_number_of_producing_gas_wells_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_offshore_gross_withdrawals_of_natural_gas_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_plant_liquids_in_proved_reserves_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_proved_nonproducing_reserves_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_residential_and_commercial_prices_selected_states_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_shale_gas_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_shale_gas_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_share_of_total_us_natural_gas_delivered_to_consumers_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_supplemental_gas_supplies_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_underground_natural_gas_storage_by_all_operators_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_underground_natural_gas_storage_capacity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_exports_and_re_exports_by_country_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_exports_and_re_exports_by_point_of_exit_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_imports_by_country_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_imports_by_point_of_entry_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_imports_exports_by_state_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_monthly_supply_and_disposition_balance_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_underground_natural_gas_storage_by_storage_type_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_weekly_working_gas_in_underground_storage_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_nuclear_outages_facility_level_nuclear_outages_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_nuclear_outages_generator_level_nuclear_outages_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_nuclear_outages_us_nuclear_outages_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_distillate_fuel_oil_and_kerosene_sales_by_end_use_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_sales_of_distillate_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_sales_of_kerosene_by_end_use_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_sales_of_residual_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_average_depth_of_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_biofuels_operable_production_capacity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_blender_net_input_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_blender_net_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_costs_of_crude_oil_and_natural_gas_wells_drilled_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_first_purchase_prices_selected_streams_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_and_lease_condensate_production_by_api_gravity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_and_natural_gas_drilling_activity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_and_natural_gas_exploratory_and_development_wells_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_input_qualities_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_proved_reserves_reserves_changes_and_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_stocks_at_tank_farms_pipelines_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_plus_lease_condensate_proved_reserves_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_distillate_fuel_oil_and_kerosene_sales_by_end_use_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_domestic_crude_oil_first_purchase_prices_by_api_gravity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_domestic_crude_oil_first_purchase_prices_by_area_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_downstream_charge_capacity_of_operable_petroleum_refineries_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_downstream_processing_of_fresh_feed_input_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_exports_by_destination_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_exports_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_feedstocks_consumed_for_production_of_biofuels_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fob_costs_of_imported_crude_oil_by_api_gravity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fob_costs_of_imported_crude_oil_by_area_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fob_costs_of_imported_crude_oil_for_selected_crude_streams_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_footage_drilled_for_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fuel_consumed_at_biofuels_plants_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fuel_consumed_at_refineries_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_gasoline_prices_by_formulation_grade_sales_type_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_gulf_of_america_federal_offshore_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_imports_by_area_of_entry_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_imports_by_processing_area_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_imports_of_residual_fuel_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_landed_costs_of_imported_crude_by_api_gravity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_landed_costs_of_imported_crude_by_area_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_landed_costs_of_imported_crude_for_selected_crude_streams_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_maximum_us_active_seismic_crew_counts_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_between_pad_districts_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_by_pipeline_between_pad_districts_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_by_rail_between_pad_districts_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_by_tanker_and_barge_between_pad_districts_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_of_crude_oil_and_selected_products_by_rail_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_natural_gas_feedstock_for_hydrogen_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_natural_gas_plant_field_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_natural_gas_plant_stocks_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_net_receipts_between_pad_districts_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_no2_distillate_prices_by_sales_type_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_number_and_capacity_of_petroleum_refineries_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_nymex_futures_prices_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_oxygenate_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_pad_district_exports_by_destination_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_pad_district_imports_by_country_of_origin_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_percentages_of_total_imported_crude_oil_by_api_gravity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_prices_sales_volumes_stocks_by_state_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_prime_supplier_sales_volumes_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_product_supplied_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_production_capacity_of_operable_petroleum_refineries_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_propane_prices_by_sales_type_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_proved_nonproducing_reserves_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_acquisition_cost_of_crude_oil_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_gasoline_prices_by_grade_and_sales_type_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_motor_gasoline_sales_volumes_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_petroleum_product_prices_by_sales_type_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_residual_fuel_oil_and_no4_fuel_sales_volumes_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_sales_volumes_of_other_petroleum_products_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_blender_net_input_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_blender_net_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_bulk_terminal_and_natural_gas_plant_stocks_by_state_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_net_input_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_net_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_receipts_of_crude_oil_by_method_of_transportation_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_stocks_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_utilization_and_capacity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_yield_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_residual_fuel_oil_prices_by_sales_type_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_sales_of_distillate_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_sales_of_kerosene_by_end_use_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_sales_of_residual_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_shell_storage_capacity_at_operable_refineries_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_spot_prices_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_stocks_by_type_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_stocks_of_selected_products_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_supply_and_disposition_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_biodiesel_production_capacity_sales_and_stocks_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_crude_oil_supply_disposition_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_imports_by_country_of_origin_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_net_imports_by_country_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_refiner_gasoline_prices_by_formulation_grade_sales_type_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_weekly_product_supplied_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_blender_net_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_crude_imports_by_top10_origins_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_ethanol_plant_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_heating_oil_and_propane_prices_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_imports_exports_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_inputs_utilization_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_refiner_blender_net_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_refiner_net_production_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_retail_gasoline_and_diesel_prices_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_stocks_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_supply_estimates_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_working_storage_capacity_at_operable_refineries_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_seds_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_advanced_metering_infrastructure_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_costs_and_savings_from_energy_efficiency_programs_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_electricity_net_metering_customers_and_capacity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_emissions_by_state_by_fuel_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_generating_capacity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_state_rankings_for_key_statistics_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_supply_and_disposition_of_electricity_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_total_energy_fetcher_urllib3_v2.yaml create mode 100644 openbb_platform/providers/eia/tests/test_api_models.py create mode 100644 openbb_platform/providers/eia/tests/test_api_query.py create mode 100644 openbb_platform/providers/eia/tests/test_browsers.py create mode 100644 openbb_platform/providers/eia/tests/test_catalog.py create mode 100644 openbb_platform/providers/eia/tests/test_data_browser.py create mode 100644 openbb_platform/providers/eia/tests/test_eia_mcp.py create mode 100644 openbb_platform/providers/eia/tests/test_eia_router.py create mode 100644 openbb_platform/providers/eia/tests/test_generate_catalog.py create mode 100644 openbb_platform/providers/eia/tests/test_helpers.py create mode 100644 openbb_platform/providers/eia/tests/test_proxy_transport.py create mode 100644 openbb_platform/providers/eia/tests/test_raw_tables.py create mode 100644 openbb_platform/providers/eia/tests/test_report_models.py create mode 100644 openbb_platform/providers/eia/tests/test_rss.py create mode 100644 openbb_platform/providers/eia/uv.lock diff --git a/.github/workflows/publish-openbb-us-eia.yml b/.github/workflows/publish-openbb-us-eia.yml new file mode 100644 index 00000000000..d0ca02963cd --- /dev/null +++ b/.github/workflows/publish-openbb-us-eia.yml @@ -0,0 +1,201 @@ +name: 📦 publish openbb-us-eia + +# Triggers exclusively on the merge of a ``release/openbb-us-eia-v*`` branch +# into ``develop``. No push / tag triggers. Four sequential jobs — check the +# version is bumped, build once against a freshly crawled catalog, test the +# built artifact across the full cross-platform matrix, and only publish to +# PyPI if the entire matrix is green. + +on: + pull_request: + types: [closed] + branches: [develop, v5] + workflow_dispatch: + +permissions: + contents: read + +jobs: + version-check: + name: Verify version bump + if: ${{ (github.event_name == 'pull_request' && github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/openbb-us-eia-v')) || github.event_name == 'workflow_dispatch' }} + runs-on: ubuntu-latest + outputs: + version: ${{ steps.parse.outputs.version }} + defaults: + run: + shell: bash + working-directory: openbb_platform/providers/eia + steps: + - uses: actions/checkout@v6 + with: + ref: develop + + - name: Parse [project].version from pyproject.toml + id: parse + run: | + VERSION=$(grep -m1 -E '^version[[:space:]]*=' pyproject.toml | sed -E 's/^version[[:space:]]*=[[:space:]]*"([^"]+)".*/\1/') + if [ -z "$VERSION" ]; then + echo "::error::Could not parse [project].version from pyproject.toml." + exit 1 + fi + echo "Local version: $VERSION" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Fail if version already exists on PyPI + env: + VERSION: ${{ steps.parse.outputs.version }} + run: | + STATUS=$(curl -sS -o /dev/null -w "%{http_code}" "https://pypi.org/pypi/openbb-us-eia/${VERSION}/json") + case "$STATUS" in + 200) + echo "::error::openbb-us-eia ${VERSION} is already published on PyPI." + echo "Bump openbb_platform/providers/eia/pyproject.toml [project].version and re-merge a fresh release branch." + exit 1 + ;; + 404) + echo "openbb-us-eia ${VERSION} is not yet on PyPI — proceeding." + ;; + *) + echo "::error::Unexpected status $STATUS from PyPI JSON API. Aborting to avoid a silent skip." + exit 1 + ;; + esac + + - name: Verify release branch name matches pyproject version + if: github.event_name == 'pull_request' + env: + VERSION: ${{ steps.parse.outputs.version }} + BRANCH: ${{ github.event.pull_request.head.ref }} + run: | + EXPECTED="release/openbb-us-eia-v${VERSION}" + if [ "$BRANCH" != "$EXPECTED" ]; then + echo "::error::Release branch '${BRANCH}' does not match pyproject version '${VERSION}'." + echo "Expected branch name: '${EXPECTED}'." + echo "Either rename the release branch or update [project].version in pyproject.toml so they agree." + exit 1 + fi + echo "Branch '${BRANCH}' matches pyproject version '${VERSION}'." + + build: + name: Build sdist + wheel + needs: version-check + runs-on: ubuntu-latest + defaults: + run: + shell: bash + working-directory: openbb_platform/providers/eia + steps: + - uses: actions/checkout@v6 + with: + ref: develop + + - uses: actions/setup-python@v6 + with: + python-version: "3.11" + + - run: python -m pip install --upgrade pip uv + + - name: Install the build backend and openbb-core + run: | + uv pip install --system "hatchling>=1.25" "requests>=2.31" + uv pip install --system ../../core + + - name: Save the freshly crawled catalog (warming pool for the PR workflow) + uses: actions/cache@v4 + with: + path: openbb_platform/providers/eia/openbb_us_eia/assets/eia_catalog.json.xz + key: eia-catalog-${{ hashFiles('openbb_platform/providers/eia/openbb_us_eia/utils/generate_catalog.py') }} + + - name: Build sdist (fresh EIA catalog) + env: + OPENBB_EIA_FORCE_CATALOG_REBUILD: "1" + EIA_API_KEY: ${{ secrets.EIA_API_KEY }} + run: uv build --sdist --no-sources --no-build-isolation --python "$(which python)" + + - name: Build wheel + env: + OPENBB_EIA_FORCE_CATALOG_REBUILD: "0" + run: uv build --wheel --no-sources --no-build-isolation --python "$(which python)" + + - uses: actions/upload-artifact@v4 + with: + name: openbb-us-eia-dist + path: openbb_platform/providers/eia/dist/ + if-no-files-found: error + retention-days: 7 + + test: + name: Test (${{ matrix.os }} / Python ${{ matrix.python_version }}) + needs: build + strategy: + fail-fast: false + matrix: + include: + # Linux: full sweep across every released Python. + - { os: ubuntu-latest, python_version: "3.10" } + - { os: ubuntu-latest, python_version: "3.11" } + - { os: ubuntu-latest, python_version: "3.12" } + - { os: ubuntu-latest, python_version: "3.13" } + - { os: ubuntu-latest, python_version: "3.14" } + # macOS + Windows: min and max supported. + - { os: macos-latest, python_version: "3.10" } + - { os: macos-latest, python_version: "3.14" } + - { os: windows-latest, python_version: "3.10" } + - { os: windows-latest, python_version: "3.14" } + runs-on: ${{ matrix.os }} + defaults: + run: + shell: bash + working-directory: openbb_platform/providers/eia + steps: + - uses: actions/checkout@v6 + with: + ref: develop + + - uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python_version }} + allow-prereleases: true + + - uses: actions/download-artifact@v4 + with: + name: openbb-us-eia-dist + path: openbb_platform/providers/eia/dist + + - run: python -m pip install --upgrade pip uv + + - name: Install dependencies then openbb-us-eia wheel + # ``openbb-core>=2.0.0`` isn't on PyPI yet — install it from the + # sibling source tree first so the wheel's pinned deps resolve. + # ``--group dev`` brings in pytest / pytest-asyncio / pytest-cov / + # pytest-recorder / ruff / ty. + run: | + uv pip install --system ../../core + uv pip install --system --group dev + uv pip install --system dist/openbb_us_eia-*.whl + + - name: Test the installed wheel + # Remove the local ``openbb_us_eia/`` source so pytest imports the + # package from site-packages — i.e., the EXACT wheel that's about to + # be uploaded to PyPI. This is a release pipeline; the source tree + # can't be allowed to shadow the artifact. + run: | + rm -rf openbb_us_eia + pytest tests --cov=openbb_us_eia --cov-report=term-missing --cov-fail-under=100 + + publish: + name: Publish to PyPI + needs: test + runs-on: ubuntu-latest + permissions: + id-token: write # required for PyPI OIDC trusted publishing + steps: + - uses: actions/download-artifact@v4 + with: + name: openbb-us-eia-dist + path: dist + + - uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist diff --git a/.github/workflows/test-unit-openbb-us-eia.yml b/.github/workflows/test-unit-openbb-us-eia.yml new file mode 100644 index 00000000000..428c6d71885 --- /dev/null +++ b/.github/workflows/test-unit-openbb-us-eia.yml @@ -0,0 +1,164 @@ +name: 🧪 test openbb-us-eia + + +on: + pull_request: + branches: [develop, main, v5] + paths: + - "openbb_platform/providers/eia/**" + - ".github/workflows/test-unit-openbb-us-eia.yml" + workflow_dispatch: + inputs: + force_catalog_rebuild: + description: "Force the build hook to regenerate the EIA catalog from the live APIv2 metadata tree (ignores actions/cache)." + type: boolean + default: false + +permissions: + contents: read + +concurrency: + # Cancel in-flight matrix runs when a new commit lands on the same PR. + group: test-openbb-us-eia-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + build: + name: Build sdist + wheel + runs-on: ubuntu-latest + defaults: + run: + shell: bash + working-directory: openbb_platform/providers/eia + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-python@v6 + with: + python-version: "3.11" + + - run: python -m pip install --upgrade pip uv + + - name: Install the build backend and openbb-core + run: | + uv pip install --system "hatchling>=1.25" "requests>=2.31" + uv pip install --system ../../core + + - name: Restore EIA catalog + # ``eia_catalog.json.xz`` is gitignored. On a cache hit the build hook + # reuses it; on a miss it crawls api.eia.gov, which needs EIA_API_KEY. + id: eia-cache + uses: actions/cache@v5 + with: + path: openbb_platform/providers/eia/openbb_us_eia/assets/eia_catalog.json.xz + key: eia-catalog-${{ hashFiles('openbb_platform/providers/eia/openbb_us_eia/utils/generate_catalog.py') }} + restore-keys: | + eia-catalog- + + - name: Build sdist + env: + OPENBB_EIA_FORCE_CATALOG_REBUILD: ${{ inputs.force_catalog_rebuild == true && '1' || '0' }} + EIA_API_KEY: ${{ secrets.EIA_API_KEY }} + run: uv build --sdist --no-sources --no-build-isolation --python "$(which python)" + + - name: Build wheel + env: + OPENBB_EIA_FORCE_CATALOG_REBUILD: "0" + run: uv build --wheel --no-sources --no-build-isolation --python "$(which python)" + + - uses: actions/upload-artifact@v5 + with: + name: openbb-us-eia-dist + path: openbb_platform/providers/eia/dist/ + if-no-files-found: error + retention-days: 7 + + lint: + name: Lint (ruff + ty) + needs: build + runs-on: ubuntu-latest + defaults: + run: + shell: bash + working-directory: openbb_platform/providers/eia + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-python@v6 + with: + python-version: "3.11" + + - run: python -m pip install --upgrade pip uv + + - uses: actions/download-artifact@v5 + with: + name: openbb-us-eia-dist + path: openbb_platform/providers/eia/dist + + - name: Install dependencies then openbb-us-eia wheel + run: | + uv pip install --system ../../core + uv pip install --system --group dev + uv pip install --system dist/openbb_us_eia-*.whl + + - name: ruff check + run: ruff check openbb_us_eia tests hatch_build.py + + - name: ruff format --check + run: ruff format --check openbb_us_eia tests hatch_build.py + + - name: ty check + run: ty check openbb_us_eia + + test: + name: Test (${{ matrix.os }} / Python ${{ matrix.python_version }}) + needs: build + strategy: + fail-fast: false + matrix: + include: + # Linux: full sweep across every released Python. + - { os: ubuntu-latest, python_version: "3.10" } + - { os: ubuntu-latest, python_version: "3.11" } + - { os: ubuntu-latest, python_version: "3.12" } + - { os: ubuntu-latest, python_version: "3.13" } + - { os: ubuntu-latest, python_version: "3.14" } + # macOS + Windows: min and max supported. + - { os: macos-latest, python_version: "3.10" } + - { os: macos-latest, python_version: "3.14" } + - { os: windows-latest, python_version: "3.10" } + - { os: windows-latest, python_version: "3.14" } + runs-on: ${{ matrix.os }} + defaults: + run: + shell: bash + working-directory: openbb_platform/providers/eia + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python_version }} + allow-prereleases: true + + - uses: actions/download-artifact@v5 + with: + name: openbb-us-eia-dist + path: openbb_platform/providers/eia/dist + + - run: python -m pip install --upgrade pip uv + + - name: Install dependencies then openbb-us-eia wheel + run: | + uv pip install --system ../../core + uv pip install --system --group dev + uv pip install --system dist/openbb_us_eia-*.whl + + - name: Test the installed wheel + # Remove the local ``openbb_us_eia/`` source so pytest imports the + # package from site-packages — the exact wheel that was just built. + # The HTTP fetchers replay from tests/record cassettes, so no EIA + # credential is needed here. + run: | + rm -rf openbb_us_eia + pytest tests --cov=openbb_us_eia --cov-report=term-missing --cov-fail-under=100 diff --git a/openbb_platform/providers/eia/.gitignore b/openbb_platform/providers/eia/.gitignore new file mode 100644 index 00000000000..d8e8e0b2707 --- /dev/null +++ b/openbb_platform/providers/eia/.gitignore @@ -0,0 +1 @@ +openbb_us_eia/assets/eia_catalog.json.xz diff --git a/openbb_platform/providers/eia/README.md b/openbb_platform/providers/eia/README.md index 4ff4156d3b4..2e14dd166ff 100644 --- a/openbb_platform/providers/eia/README.md +++ b/openbb_platform/providers/eia/README.md @@ -1,6 +1,9 @@ # OpenBB EIA Provider Extension -This module integrates the [EIA](https://eia.gov) data provider into the OpenBB Platform. +This module integrates the [EIA](https://eia.gov) data provider into the OpenBB Platform, +exposing the [EIA Open Data APIv2](https://www.eia.gov/opendata/) as a set of typed router +endpoints under `obb.eia`, plus the Weekly Petroleum Status Report and Short Term Energy +Outlook models. ## Installation @@ -28,9 +31,6 @@ pip install -e . Functions calling the EIA's API require free registration and an API key, obtained [here](https://www.eia.gov/opendata/register.php). -### OpenBB Hub - -Add the key as "eia_api_key" in the OpenBB Hub Credentials page, [here](https://my.openbb.co/app/platform/credentials) ### `user_settings.json` @@ -56,68 +56,63 @@ obb.user.credentials.eia_api_key = "REPLACE_WITH_YOUR_KEY" ## Coverage -### Endpoints +### API Dataset Endpoints -- `obb.commodity.petroleum_status_report` (API key not required.) -- `obb.commodity.short_term_energy_outlook` (API key required.) +Every dataset published through the EIA APIv2 browser is one command, mirroring the API +browser's route hierarchy: sub-router menus per source, EIA category sub-menus for +petroleum and natural gas, and one parameterized command per dataset. Each command +exposes only that dataset's frequencies, data columns, and filter (facet) parameters; +filter values are validated against the dataset's vocabulary with the valid `code = label` +choices listed on error. Requests paginate automatically until every matching row is +returned; use `limit` to cap the row count. -### Weekly Petroluem Status Report +- `obb.eia.coal.*` - 13 datasets, e.g. `coal.receipts`, `coal.exports_imports_quantity_price` +- `obb.eia.petroleum..*` - 105 datasets in 7 categories, e.g. `petroleum.prices.spot_prices` +- `obb.eia.natural_gas..*` - 53 datasets in 7 categories, e.g. `natural_gas.storage.weekly_working_gas_in_underground_storage` +- `obb.eia.electricity.*` - 4 power operations, generator, and retail sales datasets +- `obb.eia.electricity_grid.*` - hourly/daily grid monitor: demand, generation, interchange +- `obb.eia.state_electricity_profiles.*` - 7 annual state profile datasets +- `obb.eia.densified_biomass.*` - 8 wood pellet datasets +- `obb.eia.nuclear_outages.*` - 3 daily outage datasets +- `obb.eia.crude_oil_imports` - imports by origin, destination, and grade +- `obb.eia.international` - country/region energy statistics +- `obb.eia.seds` - State Energy Data System annual estimates +- `obb.eia.total_energy` - Monthly Energy Review series by MSN mnemonic +- `obb.eia.aeo` / `obb.eia.ieo` - Annual and International Energy Outlook projections by release +- `obb.eia.data_browser` - query any APIv2 route directly by path with raw facet filters -The WPSR is comprised of thirteen (excludes discontinued series) high-level categories with each containing a subset of tables. Data is from the static Excel files published [here](https://www.eia.gov/petroleum/supply/weekly/), and each file represents a single category. +### Discovery Endpoints -All data from a single category is returned by supplying "all" to the `table` parameter of the WPSR endpoint. +- `obb.eia.datasets` - the full dataset catalog: routes, frequencies, data columns, and filters +- `obb.eia.facet_options` - valid values for one filter of a dataset, fetched live -Tables from the WPSR are returned in a flat format in the same order as presented in the Excel files. The response is suitable for pivot tables and SQL storage. +### Reports -Category choices are defined as: +- `petroleum_status_report` (API key not required) and `short_term_energy_outlook` are + exposed under `obb.commodity` when `openbb-commodity` is installed, and under `obb.eia` + otherwise. -```text -balance_sheet -inputs_and_production -refiner_and_blender_net_production -crude_petroleum_stocks -gasoline_fuel_stocks -total_gasoline_by_sub_padd -distillate_fuel_oil_stocks -imports -imports_by_country -weekly_estimates -spot_prices_crude_gas_heating -spot_prices_diesel_jet_fuel_propane -retail_prices +## The Metadata Cache and Generated Models + +The metadata cache (`openbb_us_eia/assets/eia_catalog.json.xz`) is gitignored and +materialized during the package build by the `hatch_build.py` hook, so wheels and sdists +ship a self-contained artifact - just like the other provider caches. The build hook +reuses an existing local cache; set `OPENBB_EIA_FORCE_CATALOG_REBUILD=1` to force a fresh +crawl at build time. The crawl needs an API key from `EIA_API_KEY` or the OpenBB +`eia_api_key` credential. + +The per-dataset model modules (`openbb_us_eia/models//`) and the fetcher registry +(`openbb_us_eia/models/registry.py`) are checked-in source built from the same metadata +tree: every dataset is one complete model module with readable value slugs, Literal +types, a fully-declared data model with typed columns and units, and a standard Fetcher. +To refresh everything after EIA publishes new routes or facets: + +```sh +generate-eia-catalog ``` -### Short Term Energy Outlook - -The Short Term Energy Outlook (STEO) is curated by table, and relies on the EIA V2 API. Tables are defined by their alphanumeric code, and return in the same format as the WPSR tables. - -```text -01: US Energy Markets Summary -02: Nominal Energy Prices -03a: World Petroleum and Other Liquid Fuels Production, Consumption, and Inventories -03b: Non-OPEC Petroleum and Other Liquid Fuels Production -03c: World Petroleum and Other Liquid Fuels Production -03d: World Crude Oil Production -03e: World Petroleum and Other Liquid Fuels Consumption -04a: US Petroleum and Other Liquid Fuels Supply, Consumption, and Inventories -04b: US Hydrocarbon Gas Liquids (HGL) and Petroleum Refinery Balances -04c: US Regional Motor Gasoline Prices and Inventories -04d: US Biofuel Supply, Consumption, and Inventories -05a: US Natural Gas Supply, Consumption, and Inventories -05b: US Regional Natural Gas Prices -06: US Coal Supply, Consumption, and Inventories -07a: US Electricity Industry Overview -07b: US Regional Electricity Retail Sales -07c: US Regional Electricity Prices -07d1: US Regional Electricity Generation, Electric Power Sector -07d2: US Regional Electricity Generation, Electric Power Sector, continued -07e: US Electricity Generating Capacity -08: US Renewable Energy Consumption -09a: US Macroeconomic Indicators and CO2 Emissions -09b: US Regional Macroeconomic Data -09c: US Regional Weather Data -10a: Drilling Productivity Metrics -10b: Crude Oil and Natural Gas Production from Shale and Tight Formations -``` - -A "symbol" parameter allows lookup by individual series ID(s) within the dataset. +The command crawls the API, rewrites the cache and model source deterministically, +and gates its own output: emitted modules are passed through `ruff check --fix` and +`ruff format`, and the package is verified with `ty check` before the run reports +success. Pass `--tree path/to/crawl.json` to rebuild from a saved crawl, or +`--asset-only` to rewrite just the cache (what the build hook does). diff --git a/openbb_platform/providers/eia/hatch_build.py b/openbb_platform/providers/eia/hatch_build.py new file mode 100644 index 00000000000..6f64c3fb1c4 --- /dev/null +++ b/openbb_platform/providers/eia/hatch_build.py @@ -0,0 +1,103 @@ +"""Hatchling build hook for ``openbb_us_eia/assets/eia_catalog.json.xz``.""" + +from __future__ import annotations + +import os +import subprocess +import sys +from contextlib import suppress +from pathlib import Path +from typing import TextIO + +from hatchling.builders.hooks.plugin.interface import ( # ty: ignore[unresolved-import] + BuildHookInterface, +) + +_ROOT = Path(__file__).resolve().parent +_CATALOG_PATH = _ROOT / "openbb_us_eia" / "assets" / "eia_catalog.json.xz" +_GENERATE_CATALOG = _ROOT / "openbb_us_eia" / "utils" / "generate_catalog.py" +_FORCE_ENV = "OPENBB_EIA_FORCE_CATALOG_REBUILD" + + +def _open_tty() -> TextIO | None: + """Open ``/dev/tty`` for direct terminal output.""" + with suppress(OSError): + return open("/dev/tty", "w", buffering=1, encoding="utf-8") # noqa: SIM115 + return None + + +class EiaCatalogBuildHook(BuildHookInterface): + """Materialize ``eia_catalog.json.xz`` before packaging.""" + + PLUGIN_NAME = "eia-catalog" + + _generated_this_session: bool = False + + def initialize(self, version: str, build_data: dict) -> None: + """Generate or reuse the catalog, then mark it for inclusion.""" + tty = _open_tty() + + def _say(msg: str) -> None: + """Emit ``msg`` to ``/dev/tty`` and stderr.""" + line = msg if msg.endswith("\n") else msg + "\n" + if tty is not None: + with suppress(OSError): + tty.write(line) + tty.flush() + sys.stderr.write(line) + sys.stderr.flush() + + cls = type(self) + + force = ( + os.environ.get(_FORCE_ENV, "").lower() in {"1", "true", "yes"} + and not cls._generated_this_session + ) + try: + if _CATALOG_PATH.exists() and not force: + reuse_reason = ( + "this build session already regenerated it" + if cls._generated_this_session + else f"set {_FORCE_ENV}=1 to rebuild" + ) + _say(f"eia-catalog: reusing {_CATALOG_PATH.name} ({reuse_reason})") + else: + _say( + "eia-catalog: regenerating from the EIA APIv2 metadata tree" + " (api.eia.gov/v2, requires EIA_API_KEY or the OpenBB" + " 'eia_api_key' credential)..." + ) + env = {**os.environ, "PYTHONUNBUFFERED": "1"} + proc = subprocess.Popen( # noqa: S603 + [sys.executable, str(_GENERATE_CATALOG), "--asset-only"], + cwd=str(_ROOT), + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + bufsize=1, + ) + assert proc.stdout is not None # noqa: S101 + for line in proc.stdout: + if tty is not None: + with suppress(OSError): + tty.write(line) + tty.flush() + sys.stderr.write(line) + sys.stderr.flush() + returncode = proc.wait() + + if returncode != 0 or not _CATALOG_PATH.exists(): + self.app.abort( + "eia-catalog: failed to generate eia_catalog.json.xz " + f"(exit code {returncode})." + ) + + cls._generated_this_session = True + finally: + if tty is not None: + tty.close() + + rel = _CATALOG_PATH.relative_to(_ROOT).as_posix() + build_data.setdefault("force_include", {})[str(_CATALOG_PATH)] = rel + build_data.setdefault("artifacts", []).append(rel) diff --git a/openbb_platform/providers/eia/openbb_us_eia/__init__.py b/openbb_platform/providers/eia/openbb_us_eia/__init__.py index 3d9502cf1cd..7c1fc23e6a9 100644 --- a/openbb_platform/providers/eia/openbb_us_eia/__init__.py +++ b/openbb_platform/providers/eia/openbb_us_eia/__init__.py @@ -1,23 +1,30 @@ """OpenBB EIA Provider Module.""" +from importlib.util import find_spec + from openbb_core.provider.abstract.provider import Provider + +from openbb_us_eia.models.data_browser import EiaDataBrowserFetcher from openbb_us_eia.models.petroleum_status_report import EiaPetroleumStatusReportFetcher +from openbb_us_eia.models.registry import DATASET_FETCHERS from openbb_us_eia.models.short_term_energy_outlook import ( EiaShortTermEnergyOutlookFetcher, ) +COMMODITY_INSTALLED = find_spec("openbb_commodity") is not None + eia_provider = Provider( name="eia", website="https://eia.gov/", description="The U.S. Energy Information Administration is committed to its free and open data" + " by making it available through an Application Programming Interface (API) and its open data tools." + " See https://www.eia.gov/opendata/ for more information.", - credentials=[ - "api_key" - ], # This is not required for the Weekly Petroleum Status Report + credentials=["api_key"], fetcher_dict={ + "EiaDataBrowser": EiaDataBrowserFetcher, "PetroleumStatusReport": EiaPetroleumStatusReportFetcher, "ShortTermEnergyOutlook": EiaShortTermEnergyOutlookFetcher, + **DATASET_FETCHERS, }, repr_name="U.S. Energy Information Administration (EIA) Open Data and API", instructions="""Credentials are required for functions calling the EIA's API. diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/__init__.py b/openbb_platform/providers/eia/openbb_us_eia/assets/__init__.py new file mode 100644 index 00000000000..6b97b1a953f --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/__init__.py @@ -0,0 +1 @@ +"""OpenBB EIA provider assets.""" diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/apps.json b/openbb_platform/providers/eia/openbb_us_eia/assets/apps.json new file mode 100644 index 00000000000..34b40f16c47 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/apps.json @@ -0,0 +1,197 @@ +[ + { + "name": "U.S. Energy Information Administration", + "img": "https://substackcdn.com/image/fetch/$s_!tfyf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F825cfbf6-d16d-4efd-b4ec-8c8954f9d421_814x526.png", + "img_dark": "", + "img_light": "", + "description": "Official U.S. energy statistics from the Energy Information Administration: electricity, coal, total energy, the Short-Term and Annual Energy Outlooks, international energy, petroleum imports, natural gas, state energy profiles, and oil and natural gas maps, plus EIA's news and data-release feeds.", + "allowCustomization": true, + "tabs": { + "electricity": { + "id": "electricity", + "name": "Electricity Browser", + "layout": [ + { + "i": "eia_electricity_browser_us_eia_obb", + "x": 0, + "y": 0, + "w": 40, + "h": 24, + "state": { + "params": {} + } + } + ] + }, + "coal": { + "id": "coal", + "name": "Coal Browser", + "layout": [ + { + "i": "eia_coal_browser_us_eia_obb", + "x": 0, + "y": 0, + "w": 40, + "h": 24, + "state": { + "params": {} + } + } + ] + }, + "total-energy": { + "id": "total-energy", + "name": "Total Energy (MER) Browser", + "layout": [ + { + "i": "eia_total_energy_browser_us_eia_obb", + "x": 0, + "y": 0, + "w": 40, + "h": 24, + "state": { + "params": {} + } + } + ] + }, + "steo": { + "id": "steo", + "name": "Short-Term Energy Outlook Browser", + "layout": [ + { + "i": "eia_steo_browser_us_eia_obb", + "x": 0, + "y": 0, + "w": 40, + "h": 24, + "state": { + "params": {} + } + } + ] + }, + "aeo": { + "id": "aeo", + "name": "Annual Energy Outlook Browser", + "layout": [ + { + "i": "eia_aeo_browser_us_eia_obb", + "x": 0, + "y": 0, + "w": 40, + "h": 24, + "state": { + "params": {} + } + } + ] + }, + "international": { + "id": "international", + "name": "International Browser", + "layout": [ + { + "i": "eia_international_browser_us_eia_obb", + "x": 0, + "y": 0, + "w": 40, + "h": 24, + "state": { + "params": {} + } + } + ] + }, + "petroleum-imports": { + "id": "petroleum-imports", + "name": "Petroleum Imports Browser", + "layout": [ + { + "i": "eia_petroleum_imports_browser_us_eia_obb", + "x": 0, + "y": 0, + "w": 40, + "h": 24, + "state": { + "params": {} + } + } + ] + }, + "natural-gas-query": { + "id": "natural-gas-query", + "name": "Natural Gas Annual Respondent Query System Browser", + "layout": [ + { + "i": "eia_natural_gas_query_browser_us_eia_obb", + "x": 0, + "y": 0, + "w": 40, + "h": 24, + "state": { + "params": {} + } + } + ] + }, + "states": { + "id": "states", + "name": "State Energy Profiles Browser", + "layout": [ + { + "i": "eia_states_browser_us_eia_obb", + "x": 0, + "y": 0, + "w": 40, + "h": 24, + "state": { + "params": {} + } + } + ] + }, + "maps": { + "id": "maps", + "name": "Oil & Natural Gas Maps Browser", + "layout": [ + { + "i": "eia_maps_browser_us_eia_obb", + "x": 0, + "y": 0, + "w": 40, + "h": 24, + "state": { + "params": {} + } + } + ] + }, + "news-and-feeds": { + "id": "news-and-feeds", + "name": "News & Feeds", + "layout": [ + { + "i": "eia_rss_feeds_us_eia_obb", + "x": 0, + "y": 0, + "w": 40, + "h": 22, + "state": { + "params": { + "feed": "today_in_energy" + } + } + } + ] + } + }, + "groups": [], + "prompts": [ + "Summarize the latest Today in Energy articles.", + "What were the most recent EIA press releases about?", + "Show me U.S. electricity net generation by fuel in the electricity browser.", + "What are the latest retail gasoline and diesel prices from the fuel-price feed?" + ] + } +] \ No newline at end of file diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/data_browser.html b/openbb_platform/providers/eia/openbb_us_eia/assets/data_browser.html new file mode 100644 index 00000000000..d5b33360970 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/data_browser.html @@ -0,0 +1,738 @@ + + + + + +EIA Data Browser + + + + + + + diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/article.css b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/article.css new file mode 100644 index 00000000000..e3f71209d8e --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/article.css @@ -0,0 +1 @@ +.l-row.header,.title-banner,.sub-navigation,#page-sub-nav,.tie-archive-section{display:none!important} \ No newline at end of file diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/asset_fix.js b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/asset_fix.js new file mode 100644 index 00000000000..3f641bc079b --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/asset_fix.js @@ -0,0 +1 @@ +(function(){var parts=location.pathname.split('/eia_proxy/');if(parts.length<2)return;var prefix=parts[0]+'/eia_proxy';function fix(el){var raw=el.getAttribute('src');if(!raw||raw.charAt(0)!=='/'||raw.charAt(1)==='/')return;if(raw.indexOf(prefix+'/')===0)return;el.setAttribute('src',prefix+raw);}function scan(root){if(!root.querySelectorAll)return;var els=root.querySelectorAll('img[src^="/"]');for(var i=0;i.title{display:none!important}html,body{margin:0!important;padding:0!important;background:#fff!important}section{margin:0!important}.l-outer-wrapper,.l-inner-wrapper{width:100%!important;max-width:none!important;margin:0!important}.l-outer-wrapper .l-inner-wrapper{padding:8px 12px 12px!important}.fancybox__content{max-height:100%!important}.fancybox__content .customize_window_container{display:flex!important;flex-direction:column!important;min-height:0!important}.fancybox__content .customize_window_container>.green_top{display:flex!important;flex:1 1 auto!important;min-height:0!important}.fancybox__content .customize_window_container .customize_options{flex:1 1 auto!important;min-height:0!important;overflow-y:auto!important}.fancybox__content .customize_window_container .fancybox_buttons{position:static!important} \ No newline at end of file diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/dark.css b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/dark.css new file mode 100644 index 00000000000..cddd87225ab --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/dark.css @@ -0,0 +1 @@ +html{filter:invert(0.92) hue-rotate(180deg);background:#fff!important;min-height:100%!important}body{background:#fff!important;min-height:100vh!important}img,video,embed,object,iframe{filter:invert(1) hue-rotate(180deg)}img[src*=".png"],img[src*=".svg"],img[src*=".gif"]{filter:none}img[src*="flags/"],.rankFlag img,.country-flag img,.highcharts-tooltip svg{filter:invert(1) hue-rotate(180deg)}*{scrollbar-width:thin;scrollbar-color:#c3cbdd transparent}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{background:#c3cbdd;border-radius:6px}::-webkit-scrollbar-thumb:hover{background:#a8b3cc}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-corner{background:transparent}html{scrollbar-color:#3a4150 transparent}html::-webkit-scrollbar-thumb{background:#3a4150}html::-webkit-scrollbar-thumb:hover{background:#4c556a} \ No newline at end of file diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/dialog_clamp.js b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/dialog_clamp.js new file mode 100644 index 00000000000..bb2e6eb184d --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/dialog_clamp.js @@ -0,0 +1 @@ +(function(){var SEL='#analysis_dialog,#download_dialog,#visualization_dialog,#filter_dialog';function clamp(){var box=document.getElementById('simplemodal-container');if(!box)return;var el=box.querySelector(SEL)||box.firstElementChild;if(!el)return;var pad=6,r=el.getBoundingClientRect(),w=document.documentElement.clientWidth,cur=parseFloat(getComputedStyle(el).left)||0,dx=0;if(r.leftw-pad)dx=Math.max(w-pad-r.right,pad-r.left);if(dx)el.style.left=(cur+dx)+'px';}new MutationObserver(clamp).observe(document.documentElement,{childList:true,subtree:true});window.addEventListener('resize',clamp);})(); \ No newline at end of file diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/international.css b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/international.css new file mode 100644 index 00000000000..051345624ce --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/international.css @@ -0,0 +1 @@ +app-other-resources,#other-resources{display:none!important} \ No newline at end of file diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/map_contrast.css b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/map_contrast.css new file mode 100644 index 00000000000..d50b7e9e4b7 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/map_contrast.css @@ -0,0 +1 @@ +.highcharts-map-series .highcharts-null-point{fill:#dde2e8!important}.highcharts-map-series .highcharts-point{stroke:#98a2b0!important;stroke-width:0.7px!important} \ No newline at end of file diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/map_layout.css b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/map_layout.css new file mode 100644 index 00000000000..17fcdf7f354 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/map_layout.css @@ -0,0 +1 @@ +#map{position:relative!important;max-width:920px!important} \ No newline at end of file diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/nav_guard.js b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/nav_guard.js new file mode 100644 index 00000000000..75d27db27f2 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/nav_guard.js @@ -0,0 +1 @@ +(function(){var parts=location.pathname.split('/eia_proxy/');if(parts.length<2)return;var prefix=parts[0]+'/eia_proxy';var spa=parts[1].indexOf('international/')===0||parts[1].indexOf('states/')===0;var cur=new URLSearchParams(location.search),keep=[];['obb_theme','obb_user'].forEach(function(k){if(cur.has(k))keep.push([k,cur.get(k)]);});function ensure(sp){var added=false;keep.forEach(function(pr){if(!sp.has(pr[0])){sp.set(pr[0],pr[1]);added=true;}});return added;}function proxied(raw){if(!raw)return null;var a=document.createElement('a');a.href=raw;if(a.protocol!=='http:'&&a.protocol!=='https:')return null;var mine=a.origin===location.origin;if(!mine&&a.hostname!=='www.eia.gov'&&a.hostname!=='eia.gov')return null;var p=a.pathname||'/',sp=new URLSearchParams(a.search);if(mine&&p.indexOf(prefix+'/')===0){if(spa||!ensure(sp))return null;var q0=sp.toString();return a.origin+p+(q0?'?'+q0:'')+a.hash;}ensure(sp);var q=sp.toString();return prefix+p+(q?'?'+q:'')+a.hash;}window.__eiaProxied=proxied;document.addEventListener('click',function(e){var a=e.target&&e.target.closest?e.target.closest('a[href]'):null;if(!a)return;var u=proxied(a.href);if(!u)return;e.preventDefault();var up=window.parent&&window.parent!==window?window.parent:null;if(up&&/\.pdf(\?|#|$)/i.test(a.href)){var abs=u.charAt(0)==='/'?location.origin+u:u;up.postMessage({type:'eia:pdf',src:abs},'*');return;}location.href=u;},true);document.addEventListener('change',function(e){var s=e.target;if(!s||s.tagName!=='SELECT')return;if((s.getAttribute('onchange')||'').indexOf('location')<0)return;var u=proxied(s.value);if(!u)return;e.preventDefault();e.stopPropagation();location.href=u;},true);document.addEventListener('submit',function(e){var f=e.target;if(!f||!f.getAttribute)return;var u=proxied(f.getAttribute('action')||'');if(!u)return;f.setAttribute('action',u);},true);})(); \ No newline at end of file diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/ngqs_grid.css b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/ngqs_grid.css new file mode 100644 index 00000000000..f32ea89803f --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/ngqs_grid.css @@ -0,0 +1 @@ +#agGrid{width:100%!important} \ No newline at end of file diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/states.css b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/states.css new file mode 100644 index 00000000000..da4de332f6a --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/states.css @@ -0,0 +1 @@ +h3.dashboard-title{top:0!important}.dashboard-controls-container{top:33px!important} \ No newline at end of file diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/table_bridge.js b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/table_bridge.js new file mode 100644 index 00000000000..6930433bbdd --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/table_bridge.js @@ -0,0 +1,744 @@ +(function () { + var parts = location.pathname.split('/eia_proxy/'); + if (parts.length < 2) return; + + var sink = parts[0] + '/eia_table'; + var stateSink = parts[0] + '/eia_state'; + var browser = '__OBB_BROWSER__'; + function hash16(s) { + var h1 = 0x811c9dc5; + var h2 = 0x9e3779b9; + for (var i = 0; i < s.length; i++) { + var c = s.charCodeAt(i); + h1 ^= c; + h1 = (h1 + ((h1 << 1) + (h1 << 4) + (h1 << 7) + (h1 << 8) + (h1 << 24))) >>> 0; + h2 = (h2 ^ ((c << 1) >>> 0)) >>> 0; + h2 = (h2 + 0x6d2b79f5) >>> 0; + } + function hex(n) { + return ('00000000' + (n >>> 0).toString(16)).slice(-8); + } + return hex(h1) + hex(h2); + } + function sanitizeUser(v) { + if (v === null || v === undefined) return ''; + var s = String(v); + if (!s) return ''; + return s.indexOf('@') >= 0 ? hash16(s) : s; + } + var user='__OBB_USER__'; + user=sanitizeUser(user); + + try { + var _uq = new URLSearchParams(location.search).get('obb_user'); + if (_uq) { + user = sanitizeUser(_uq); + if (user) sessionStorage.setItem('obb_user', user); + } else { + var _us = sessionStorage.getItem('obb_user'); + if (_us) user = sanitizeUser(_us); + } + } catch (e) {} + + var up = window.parent && window.parent !== window ? window.parent : null; + + function stripObbUser(query) { + var p = new URLSearchParams(query || ''); + p.delete('obb_user'); + var s = p.toString(); + return s ? '?' + s : ''; + } + + function stripObbUserInHash(hash) { + var raw = hash || ''; + if (!raw) return ''; + if (raw.charAt(0) === '#') raw = raw.slice(1); + var i = raw.indexOf('?'); + if (i < 0) return '#' + raw; + var head = raw.slice(0, i); + var qs = raw.slice(i + 1); + var p = new URLSearchParams(qs); + p.delete('obb_user'); + var tail = p.toString(); + return '#' + head + (tail ? '?' + tail : ''); + } + + function view() { + var p = location.pathname.split('/eia_proxy/')[1] || ''; + return p + stripObbUser(location.search) + stripObbUserInHash(location.hash); + } + + function txt(el) { + return ((el.innerText || el.textContent || '').replace(/\s+/g, ' ')).trim(); + } + + function cell(v) { + if (v === null || v === undefined) return null; + if (typeof v === 'number') return isFinite(v) ? v : null; + if (typeof v === 'object') { + if ('value' in v) return cell(v.value); + if ('v' in v) return cell(v.v); + if ('y' in v) return cell(v.y); + return null; + } + var s = String(v) + .replace(/<[^>]*>/g, ' ') + .replace(/ /g, ' ') + .replace(/\s+/g, ' ') + .trim(); + if (s === '' || s === '--' || s === '-' || s === '\u2013' || s === '\u2014') { + return null; + } + var n = s.replace(/,/g, ''); + if (/^-?\d*\.?\d+$/.test(n)) return parseFloat(n); + return s; + } + + function records(head, body) { + var names = []; + var used = {}; + for (var i = 0; i < head.length; i++) { + var h = String(head[i] || '').trim(); + if (!h) h = 'category'; + if (/^\d+$/.test(h)) h = h + ' '; + if (used[h]) { + used[h]++; + h = h + ' (' + used[h] + ')'; + } else { + used[h] = 1; + } + names.push(h); + } + var out = []; + for (var r = 0; r < body.length; r++) { + var row = {}; + for (var c = 0; c < names.length; c++) row[names[c]] = cell(body[r][c]); + if (Object.keys(row).length) out.push(row); + } + return out; + } + + var grids = []; + + function resolve(field, item) { + if (!field) return undefined; + var path = String(field).split('.'); + var v = item; + for (var i = 0; i < path.length; i++) { + if (v === null || v === undefined) return undefined; + v = v[path[i]]; + } + return v; + } + + function extract(grid, item, col) { + var o = grid.getOptions ? grid.getOptions() : null; + if (o && typeof o.dataItemColumnValueExtractor === 'function') { + try { + return o.dataItemColumnValueExtractor(item, col); + } catch (e) {} + } + return resolve(col.field, item); + } + + function value(grid, item, col, r, c) { + var raw = extract(grid, item, col); + if (typeof raw === 'number' && isFinite(raw)) return raw; + var fn = col.outputFormatter || col.dataFormatter || col.formatter; + if (typeof fn === 'function') { + try { + var out = fn.call(grid, r, c, raw, col, item); + if (out !== undefined && out !== null) return out; + } catch (e) {} + } + return raw === undefined ? null : raw; + } + + function node(g) { + try { + return g.getContainerNode ? g.getContainerNode() : null; + } catch (e) { + return null; + } + } + + function dead(g) { + var n = node(g); + return !!n && !n.querySelector('.slick-viewport'); + } + + function live(g) { + var n = node(g); + if (!n) return true; + if (!n.ownerDocument || !n.ownerDocument.contains(n)) return false; + if (!n.querySelector('.slick-viewport')) return false; + return !!(n.offsetParent || n.getClientRects().length); + } + + function fromSlick() { + var best = null; + var rows = 0; + var keep = []; + for (var i = 0; i < grids.length; i++) { + var g = grids[i]; + if (dead(g)) continue; + keep.push(g); + if (!live(g)) continue; + try { + var n = g.getDataLength(); + if (n > rows) { + rows = n; + best = g; + } + } catch (e) {} + } + grids = keep; + if (!best || !rows) return null; + + var all = best.getColumns() || []; + if (!all.length) return null; + + var cols = []; + var head = []; + for (var c = 0; c < all.length; c++) { + var col = all[c]; + if (col.output === false || col.display === false || col.id === 'spacer' || col.iconClass) { + continue; + } + var h = col.name === undefined || col.name === null ? '' : String(col.name); + cols.push(col); + head.push(h.replace(/<[^>]*>/g, ' ')); + } + if (!cols.length) return null; + + function period(i) { + var id = cols[i].id; + id = id === null || id === undefined ? '' : String(id); + return /^\d{4}(Q[1-4]|\d{2}|\d{4})?$/.test(id) ? id : null; + } + + var order = []; + for (var oi = 0; oi < cols.length; oi++) order.push(oi); + order.sort(function (a, b) { + var pa = period(a); + var pb = period(b); + if (pa === null && pb === null) return a - b; + if (pa === null) return -1; + if (pb === null) return 1; + return pa < pb ? -1 : pa > pb ? 1 : a - b; + }); + + var scols = []; + var shead = []; + for (var oj = 0; oj < order.length; oj++) { + scols.push(cols[order[oj]]); + shead.push(head[order[oj]]); + } + cols = scols; + head = shead; + + var body = []; + for (var r = 0; r < rows; r++) { + var item = best.getDataItem(r); + if (!item) continue; + var row = []; + for (var f = 0; f < cols.length; f++) row.push(value(best, item, cols[f], r, f)); + body.push(row); + } + return body.length ? records(head, body) : null; + } + + function wrapGrid() { + var S = window.Slick; + if (!S || typeof S.Grid !== 'function' || S.Grid.__obb) return; + var G = S.Grid; + function W() { + var g = Object.create(G.prototype || Object.prototype); + var r = G.apply(g, arguments); + var inst = r && typeof r === 'object' ? r : g; + try { + grids.push(inst); + if (inst.onRendered && inst.onRendered.subscribe) inst.onRendered.subscribe(schedule); + schedule(); + } catch (e) {} + return inst; + } + W.prototype = G.prototype; + W.__obb = 1; + for (var k in G) { + try { + W[k] = G[k]; + } catch (e) {} + } + try { + S.Grid = W; + } catch (e) {} + } + + setInterval(wrapGrid, 20); + + var apis = []; + + function keep(api) { + if (!api || typeof api.forEachNodeAfterFilterAndSort !== 'function') return; + for (var i = 0; i < apis.length; i++) if (apis[i] === api) return; + apis.push(api); + schedule(); + } + + function wrapAg() { + var A = window.agGrid; + if (!A || A.__obb) return; + if (typeof A.createGrid === 'function') { + var create = A.createGrid; + A.createGrid = function () { + var api = create.apply(this, arguments); + try { + keep(api); + } catch (e) {} + return api; + }; + } + if (typeof A.Grid === 'function') { + var G = A.Grid; + function W(el, opts) { + var g = Object.create(G.prototype || Object.prototype); + var r = G.apply(g, arguments); + var inst = r && typeof r === 'object' ? r : g; + try { + keep(opts && opts.api); + keep(inst && inst.gridOptions && inst.gridOptions.api); + } catch (e) {} + return inst; + } + W.prototype = G.prototype; + for (var k in G) { + try { + W[k] = G[k]; + } catch (e) {} + } + try { + A.Grid = W; + } catch (e) {} + } + try { + A.__obb = 1; + } catch (e) {} + } + + setInterval(wrapAg, 20); + + function unwrap(v) { + if (!v) return null; + var seen = [ + v, + v.api, + v.gridApi, + v.gridOptions && v.gridOptions.api, + v.gridOptions && v.gridOptions.gridApi, + ]; + for (var i = 0; i < seen.length; i++) { + var a = seen[i]; + if (a && typeof a.forEachNodeAfterFilterAndSort === 'function') return a; + } + return null; + } + + function domApi() { + var nodes = document.querySelectorAll('ag-grid-angular,.ag-root-wrapper,.ag-root,.ag-body'); + for (var i = 0; i < nodes.length; i++) { + var el = nodes[i]; + for (var d = 0; d < 4 && el && el.getAttribute; d++, el = el.parentNode) { + var a = unwrap(el.__ag_grid_instance); + if (a) return a; + for (var k in el) { + try { + var got = unwrap(el[k]); + if (got) return got; + } catch (e) {} + } + } + } + return null; + } + + function gridApi() { + var best = null; + var rows = -1; + for (var i = 0; i < apis.length; i++) { + var a = apis[i]; + try { + if (a.isDestroyed && a.isDestroyed()) continue; + var n = 0; + a.forEachNodeAfterFilterAndSort(function () { + n++; + }); + if (n > rows) { + rows = n; + best = a; + } + } catch (e) {} + } + return best || domApi(); + } + + function fromGrid() { + var api = gridApi(); + if (!api || !api.getAllDisplayedColumns) return null; + var cols = api.getAllDisplayedColumns() || []; + if (!cols.length) return null; + + var head = []; + var fields = []; + var defs = []; + for (var i = 0; i < cols.length; i++) { + var def = cols[i].getColDef ? cols[i].getColDef() : {}; + var id = cols[i].getColId ? cols[i].getColId() : ''; + var h = + def.headerName !== undefined && def.headerName !== null ? String(def.headerName) : String(id); + if (h.toLowerCase() === 'pin' || h.toLowerCase() === 'api') continue; + head.push(h); + fields.push(def.field || id); + defs.push(def); + } + if (!fields.length) return null; + + var body = []; + api.forEachNodeAfterFilterAndSort(function (node) { + if (!node || !node.data) return; + var row = []; + for (var j = 0; j < fields.length; j++) { + var v = resolve(fields[j], node.data); + if ((v === undefined || v === null) && typeof defs[j].valueGetter === 'function') { + try { + v = defs[j].valueGetter({ data: node.data, node: node, colDef: defs[j] }); + } catch (e) {} + } + row.push(v === undefined ? null : v); + } + body.push(row); + }); + return body.length ? records(head, body) : null; + } + + function fromHighcharts() { + var H = window.Highcharts; + if (!H || !H.charts || !H.charts.length) return null; + + var best = null; + var bestPoints = 0; + + for (var i = 0; i < H.charts.length; i++) { + var chart = H.charts[i]; + if (!chart || !chart.renderTo) continue; + if (!(chart.renderTo.offsetParent || chart.renderTo.getClientRects().length)) continue; + var series = chart.series || []; + var visible = []; + var maxLen = 0; + for (var s = 0; s < series.length; s++) { + var sr = series[s]; + if (!sr || sr.visible === false || !sr.data || !sr.data.length) continue; + visible.push(sr); + if (sr.data.length > maxLen) maxLen = sr.data.length; + } + if (!visible.length || maxLen <= 0) continue; + if (maxLen > bestPoints) { + bestPoints = maxLen; + best = { chart: chart, series: visible, rows: maxLen }; + } + } + + if (!best) return null; + + var cats = []; + try { + cats = (best.chart.xAxis && best.chart.xAxis[0] && best.chart.xAxis[0].categories) || []; + } catch (e) { + cats = []; + } + + var head = ['category']; + for (var h = 0; h < best.series.length; h++) { + head.push(best.series[h].name || 'series_' + (h + 1)); + } + + var body = []; + for (var r = 0; r < best.rows; r++) { + var row = []; + var p0 = best.series[0].data[r]; + var cat = cats[r]; + if (cat === undefined || cat === null) { + if (p0 && p0.category !== undefined) cat = p0.category; + else if (p0 && p0.x !== undefined) cat = p0.x; + else cat = r; + } + row.push(cat); + for (var s2 = 0; s2 < best.series.length; s2++) { + var pt = best.series[s2].data[r]; + row.push(pt ? (pt.y !== undefined ? pt.y : pt) : null); + } + body.push(row); + } + + return body.length ? records(head, body) : null; + } + + function fromEcharts() { + var E = window.echarts; + if (!E || typeof E.getInstanceByDom !== 'function') return null; + + var nodes = document.querySelectorAll('[data-zr-dom-id],.echarts,.echarts-for-react,canvas'); + var best = null; + var bestPoints = 0; + + for (var i = 0; i < nodes.length; i++) { + var inst = null; + try { + inst = E.getInstanceByDom(nodes[i]); + } catch (e) {} + if (!inst) continue; + + var option = null; + try { + option = inst.getOption ? inst.getOption() : null; + } catch (e) {} + if (!option || !option.series || !option.series.length) continue; + + var series = option.series; + var maxLen = 0; + for (var s = 0; s < series.length; s++) { + var d = series[s] && series[s].data; + if (d && d.length && d.length > maxLen) maxLen = d.length; + } + if (maxLen > bestPoints) { + bestPoints = maxLen; + best = option; + } + } + + if (!best || !best.series || !best.series.length) return null; + + var cats = []; + var xAxis = best.xAxis; + if (xAxis && xAxis.length && xAxis[0] && xAxis[0].data) cats = xAxis[0].data; + + var head = ['category']; + for (var h = 0; h < best.series.length; h++) { + head.push(best.series[h].name || 'series_' + (h + 1)); + } + + var rows = 0; + for (var s2 = 0; s2 < best.series.length; s2++) { + var d2 = best.series[s2] && best.series[s2].data; + if (d2 && d2.length > rows) rows = d2.length; + } + + var body = []; + for (var r = 0; r < rows; r++) { + var row = []; + row.push(cats[r] !== undefined ? cats[r] : r); + for (var s3 = 0; s3 < best.series.length; s3++) { + var dd = best.series[s3] && best.series[s3].data ? best.series[s3].data[r] : null; + row.push(dd && dd.value !== undefined ? dd.value : dd); + } + body.push(row); + } + + return body.length ? records(head, body) : null; + } + + function fromTable() { + var all = document.querySelectorAll('table'); + var best = null; + for (var i = 0; i < all.length; i++) { + var t = all[i]; + if (t.rows.length < 2 || !t.offsetParent) continue; + if (!best || t.rows.length > best.rows.length) best = t; + } + if (!best) return null; + + var head = []; + var body = []; + var first = best.rows[0]; + for (var c = 0; c < first.cells.length; c++) head.push(txt(first.cells[c])); + for (var r = 1; r < best.rows.length; r++) { + var cells = best.rows[r].cells; + var row = []; + for (var k2 = 0; k2 < cells.length; k2++) row.push(txt(cells[k2])); + body.push(row); + } + return body.length ? records(head, body) : null; + } + + function stateUrl(v, seq) { + return ( + stateSink + + '?obb_browser=' + + encodeURIComponent(browser) + + '&obb_user=' + + encodeURIComponent(user) + + '&obb_view=' + + encodeURIComponent(v) + + '&obb_seq=' + + String(seq) + ); + } + + function controlKey(el, index) { + return String(el.name || el.id || el.getAttribute('data-name') || el.getAttribute('aria-label') || index); + } + + function controlVal(el) { + var tag = (el.tagName || '').toLowerCase(); + if (tag === 'select') { + var selected = []; + for (var i = 0; i < el.options.length; i++) { + if (el.options[i].selected) selected.push(el.options[i].value || el.options[i].text || ''); + } + return el.multiple ? selected : selected[0] || ''; + } + if (tag === 'input') { + var type = (el.type || '').toLowerCase(); + if (type === 'checkbox' || type === 'radio') return !!el.checked; + return el.value; + } + if (tag === 'textarea') return el.value; + if ((el.getAttribute('role') || '').toLowerCase() === 'slider') { + return el.getAttribute('aria-valuenow') || el.getAttribute('value') || ''; + } + if (el.classList && el.classList.contains('ui-slider-handle')) { + return el.getAttribute('aria-valuenow') || el.style.left || ''; + } + return el.value !== undefined ? el.value : txt(el); + } + + function activeLabels(selectors, cap) { + var out = []; + var nodes = document.querySelectorAll(selectors); + for (var i = 0; i < nodes.length && out.length < cap; i++) { + var label = txt(nodes[i]); + if (label) out.push(label); + } + return out; + } + + function stateSnapshot(v) { + var controls = {}; + var nodes = document.querySelectorAll('input,select,textarea,[role="slider"],.ui-slider-handle'); + for (var i = 0; i < nodes.length && i < 500; i++) { + var key = controlKey(nodes[i], i); + if (!key) continue; + controls[key] = controlVal(nodes[i]); + } + var nav = activeLabels('.tab.selected,.tab.active,li.active,[aria-selected="true"]', 100); + return { + path: location.pathname, + search: location.search, + hash: location.hash, + view: v, + title: document.title || '', + controls: controls, + active: nav, + }; + } + + var last = ''; + var lastState = ''; + var canTrackState = typeof document.addEventListener === 'function'; + + function pushState(v, seq) { + if (!canTrackState) return; + var state = stateSnapshot(v); + var body = JSON.stringify(state); + var stamp = v + '|' + body; + if (stamp === lastState) return; + lastState = stamp; + fetch(stateUrl(v, seq), { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: body, + }).catch(function () {}); + } + + function grab() { + var v = view(); + var seq = Date.now(); + pushState(v, seq); + + var rows = null; + try { + rows = fromSlick(); + } catch (e) {} + if (!rows) { + try { + rows = fromGrid(); + } catch (e) {} + } + if (!rows) { + try { + rows = fromHighcharts(); + } catch (e) {} + } + if (!rows) { + try { + rows = fromEcharts(); + } catch (e) {} + } + if (!rows) { + try { + rows = fromTable(); + } catch (e) {} + } + if (!rows || !rows.length) return; + + var body = JSON.stringify(rows); + var stamp = v + '|' + body; + if (stamp === last) return; + last = stamp; + + if (up) up.postMessage({ type: 'eia:table', rows: rows }, '*'); + + var q = + sink + + '?obb_browser=' + + encodeURIComponent(browser) + + '&obb_user=' + + encodeURIComponent(user) + + '&obb_view=' + + encodeURIComponent(v) + + '&obb_seq=' + + String(seq); + + fetch(q, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: body, + }).catch(function () {}); + } + + var timer = null; + + function schedule() { + clearTimeout(timer); + timer = setTimeout(grab, 500); + } + + new MutationObserver(schedule).observe(document.documentElement, { + childList: true, + subtree: true, + characterData: true, + }); + + setInterval(grab, 2000); + if (canTrackState) { + document.addEventListener('click', schedule, true); + document.addEventListener('change', schedule, true); + document.addEventListener('input', schedule, true); + document.addEventListener('mouseup', schedule, true); + document.addEventListener('keyup', schedule, true); + } + window.addEventListener('load', schedule); + window.addEventListener('hashchange', schedule); + window.addEventListener('popstate', schedule); + schedule(); +})(); \ No newline at end of file diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/view_bridge.js b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/view_bridge.js new file mode 100644 index 00000000000..2cd217fcb2e --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/view_bridge.js @@ -0,0 +1 @@ +(function(){if(location.pathname.indexOf('/eia_proxy/')<0)return;var up=window.parent&&window.parent!==window?window.parent:null;if(!up)return;var last=null,ready=false;function report(){var v=location.pathname+location.search+location.hash;if(v===last)return;last=v;up.postMessage({type:'eia:nav',pathname:location.pathname,search:location.search,hash:location.hash},'*');}function hook(m){var o=history[m];if(o)history[m]=function(){var r=o.apply(this,arguments);setTimeout(report,0);return r;};}hook('pushState');hook('replaceState');function checkReady(){if(ready)return;if(document.readyState!=='complete')return;if(document.querySelector('.loadmask,.loadmask-msg'))return;ready=true;up.postMessage({type:'eia:ready'},'*');}window.addEventListener('hashchange',report);window.addEventListener('popstate',report);var iv=setInterval(function(){checkReady();if(ready)clearInterval(iv);},250);window.addEventListener('load',function(){report();checkReady();});report();})(); \ No newline at end of file diff --git a/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/view_select_sync.js b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/view_select_sync.js new file mode 100644 index 00000000000..f171dce9892 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/assets/proxy/view_select_sync.js @@ -0,0 +1 @@ +(function(){var parts=location.pathname.split('/eia_proxy/');if(parts.length<2)return;var dir=parts[0]+'/eia_proxy/'+parts[1];var map=null,loading=false,tries=0;function trim(v){return String(v==null?'':v).replace(/~+$/,'');}function loadConfig(){if(loading||map!==null||tries>=8)return;loading=true;tries++;fetch(dir+'data/index.php?method=getConfig',{credentials:'same-origin'}).then(function(r){return r.json();}).then(function(cfg){var out={},views=(cfg&&cfg.views)||[];for(var i=0;i>>0; + h2=(h2^((c<<1)>>>0))>>>0; h2=(h2+0x6d2b79f5)>>>0; + } + function hex(n){return ('00000000'+(n>>>0).toString(16)).slice(-8);} + return hex(h1)+hex(h2); + } + function sanitizeUser(v){ + if(v===null||v===undefined)return ''; + var s=String(v); + if(!s)return ''; + return s.indexOf('@')>=0?hash16(s):s; + } + var user='__OBB_USER__'; + user=sanitizeUser(user); + var authHeaders={}; + var beacon=parts[0]+'/eia_view'; + var mine=[parts[0]+'/eia_table',parts[0]+'/eia_view']; + try{ + var qUser=new URLSearchParams(location.search).get('obb_user'); + if(qUser){ + user=sanitizeUser(qUser); + if(user)sessionStorage.setItem('obb_user',user); + }else{ + var storedUser=sessionStorage.getItem('obb_user'); + if(storedUser)user=sanitizeUser(storedUser); + } + }catch(e){} + function mergeHeaders(base){ + var out={}; + if(base&&typeof base==='object'){ + var keys=Object.keys(base); + for(var i=0;i + + + + +EIA RSS Feed + + + +
+
+

+

+
+
+
+ +
+ +
+ +
+
+ +
Loading…
+
+
+ + + + + diff --git a/openbb_platform/providers/eia/openbb_us_eia/browsers.py b/openbb_platform/providers/eia/openbb_us_eia/browsers.py new file mode 100644 index 00000000000..76187997081 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/browsers.py @@ -0,0 +1,2172 @@ +"""EIA data-browser widgets.""" + +import re +import threading +from collections.abc import AsyncIterator +from contextlib import asynccontextmanager +from pathlib import Path +from typing import Annotated, Any + +from fastapi import Depends, Request +from fastapi.responses import ( + HTMLResponse, + JSONResponse, + RedirectResponse, + Response, +) +from openbb_core.app.router import Router + + +async def request_info(request: Request) -> dict: + """Extract deepcopy-safe request fields for the widget/proxy endpoints.""" + body = b"" + if request.method == "POST": + try: + body = await request.body() + except Exception: # noqa: BLE001 + body = b"" + return { + "url": str(request.url).split("?", 1)[0], + "query": request.url.query, + "path": request.url.path, + "method": request.method, + "body": body, + "content_type": request.headers.get("Content-Type", ""), + "referer": request.headers.get("Referer", ""), + "user": _user_key(request.headers.get("X-OpenBB-User", "")), + } + + +def _user_key(identity: str) -> str: + """Return a stable, non-identifying key that isolates one user's widget state.""" + from hashlib import sha256 + + return sha256(identity.encode("utf-8")).hexdigest()[:16] if identity else "" + + +def _mcp_url() -> str: + """Return this same server's dedicated EIA MCP endpoint, for iframe auto-connect. + + The route is registered on this very API process (see ``eia_router.py``), + which reverse-proxies to the EIA MCP subprocess, so the URL the Workspace + connects to shares the exact host/port ``openbb-platform-api`` itself is + bound to. The ``eia`` extension name is applied as a path prefix by the + core router loader, so the served path is ``.../eia/eia_mcp``. + """ + import os + + from openbb_core.app.service.system_service import SystemService + + host = os.environ.get("OPENBB_API_HOST", "127.0.0.1") + port = os.environ.get("OPENBB_API_PORT", "6900") + prefix = SystemService().system_settings.api_settings.prefix + return f"http://{host}:{port}{prefix}/eia/eia_mcp" + + +router = Router(prefix="", description="EIA interactive data browsers.") + +_TEMPLATE = Path(__file__).parent / "assets" / "data_browser.html" +_EIA_ORIGIN = "https://www.eia.gov" + +_PROXY_ASSETS = Path(__file__).parent / "assets" / "proxy" + + +def _style(name: str) -> str: + """Return a proxy stylesheet wrapped in a ``style`` tag.""" + return f"" + + +def _script(name: str) -> str: + """Return a proxy script wrapped in a ``script`` tag.""" + return f"" + + +_CHROME_CSS = _style("chrome.css") +_DARK_CSS = _style("dark.css") +_MAP_LAYOUT_CSS = _style("map_layout.css") +_MAP_CONTRAST_CSS = _style("map_contrast.css") +_NGQS_GRID_CSS = _style("ngqs_grid.css") +_STATES_CSS = _style("states.css") +_INTERNATIONAL_CSS = _style("international.css") +_ARTICLE_CSS = _style("article.css") +_VIEW_BRIDGE_TEMPLATE = _script("view_bridge.js") + + +def _view_bridge_js() -> str: + """Render the bridge that reports the iframe's view path/hash and ready state.""" + return _VIEW_BRIDGE_TEMPLATE + + +_TABLE_BRIDGE_TEMPLATE = _script("table_bridge.js") + + +def _table_bridge_js(browser: str, user: str = "") -> str: + """Render the bridge that publishes the browser's rendered table.""" + return _TABLE_BRIDGE_TEMPLATE.replace("__OBB_BROWSER__", browser).replace( + "__OBB_USER__", user + ) + + +_XHR_TAG_TEMPLATE = _script("xhr_tag.js") + + +def _xhr_tag_js(browser: str, user: str = "") -> str: + """Render the request tagger that binds each proxied request to its view.""" + return _XHR_TAG_TEMPLATE.replace("__OBB_BROWSER__", browser).replace( + "__OBB_USER__", user + ) + + +_DIALOG_CLAMP_JS = _script("dialog_clamp.js") +_VIEW_SELECT_SYNC_JS = _script("view_select_sync.js") +_ASSET_FIX_JS = _script("asset_fix.js") +_NAV_GUARD_JS = _script("nav_guard.js") +_DEAD_SCRIPTS = re.compile( + r"""]*\bsrc=["'][^"']*""" + r"""(?:googletagmanager|gtag/js|ga-file-downloads|/akam/|akamaihd""" + r"""|remote\.loader|/sayt)""" + r"""[^"']*["'][^>]*>\s*""", + re.I, +) +_ABS_EIA_RE = re.compile(r"(?:https?:)?//www\.eia\.gov(?=/)", re.I) +_ESCAPED_EIA_RE = re.compile(r"(?:https?:)?\\/\\/www\.eia\.gov(?=\\/)", re.I) +_AKAMAI_INLINE = re.compile( + r"]*>(?:(?!).)*?" + r"(?:aksb|akamaihd|bazadebezolkohpepadr)" + r"(?:(?!).)*?", + re.I | re.S, +) +_AKAMAI_NOSCRIPT = re.compile( + r").)*?/akam/(?:(?!).)*?", + re.I | re.S, +) +_SEARCH_INLINE = re.compile( + r"]*>(?:(?!).)*?" + r"(?:remote\.loader|search\.usa\.gov)" + r"(?:(?!).)*?", + re.I | re.S, +) +_ARTICLE_DEAD_SCRIPTS = re.compile( + r"""]*\bsrc=["'][^"']*""" + r"""(?:highcharts|jquery[.-]ui|touch-punch)[^"']*["'][^>]*>\s*""", + re.I, +) +_ARTICLE_PATHS = ("todayinenergy/", "pressroom/") +_SPA_PATHS = ("international/", "states/") +_ROOT_PATH_RE = re.compile(r"""(["'])/(?!/)""") +_ESCAPED_ROOT_RE = re.compile(r"""(["'])\\/(?!\\?/)""") +_JS_ROOT_RE = re.compile( + r"""(["'])/(about|api|coal|dnav|electricity|global|international|maps""" + r"""|naturalgas|opendata|outlooks|petroleum|realtime|rss|states|totalenergy)""" + r"""(?=[/"'])""" +) +_SPA_ROOT_RE = re.compile(r"""(["'])/(states|state|international)(?=[/"'])""") + +EIA_DATA_BROWSERS: dict[str, dict[str, str]] = { + "electricity": { + "description": "U.S. electric power statistics: net generation, consumption, retail sales, revenue and average retail price, fuel receipts, costs and quality, and plant-level operations - by state, sector, and fuel, monthly through annual.", + "label": "Electricity", + "path": "electricity/data/browser/", + "hash": "#/topic/0?agg=2,0,1&fuel=vtvv&geo=g&sec=g&freq=M&start=200101" + "&end=202604&ctype=linechart<ype=pin&linechart=ELEC.GEN.ALL-US-99.M" + "~ELEC.GEN.COW-US-99.M~ELEC.GEN.NG-US-99.M~ELEC.GEN.NUC-US-99.M" + "~ELEC.GEN.HYC-US-99.M~ELEC.GEN.WND-US-99.M~ELEC.GEN.TSN-US-99.M", + }, + "coal": { + "description": "U.S. coal statistics: production, consumption and quality, prices by rank, recoverable reserves and mine capacity, exports and imports, and mine- and plant-level shipments - by state, region, mine type, and coal rank.", + "label": "Coal", + "path": "coal/data/browser/", + "hash": "", + }, + "total_energy": { + "description": "The Monthly Energy Review: recent and historical U.S. energy statistics, including total energy production, consumption, stocks, and trade; energy prices; overviews of petroleum, natural gas, coal, electricity, nuclear energy, renewable energy, and carbon dioxide emissions; and energy unit conversion values.", + "label": "Total Energy (MER)", + "path": "totalenergy/data/browser/", + "hash": "", + }, + "steo": { + "description": "The Short-Term Energy Outlook: EIA's monthly 18-month forecast of energy supply, demand, prices, and inventories - crude oil and liquid fuels, natural gas, electricity, coal, renewables, and energy-related carbon dioxide emissions - for the United States and the world.", + "label": "Short-Term Energy Outlook", + "path": "outlooks/steo/data/browser/", + "hash": "", + }, + "aeo": { + "description": "The Annual Energy Outlook: EIA's long-term projections of U.S. energy production, consumption, trade, prices, and emissions through 2050, in the Reference case and alternative side cases covering economic growth, oil prices, and technology.", + "label": "Annual Energy Outlook", + "path": "outlooks/aeo/data/browser/", + "hash": "", + }, + "international": { + "description": "International energy statistics for more than 200 countries and regions: production, consumption, imports, exports, reserves, and carbon dioxide emissions for petroleum and other liquids, natural gas, coal, electricity, nuclear, and renewables.", + "label": "International", + "path": "international/overview/world", + "hash": "", + }, + "petroleum_imports": { + "description": "Company-level U.S. crude oil and petroleum product imports (Form EIA-814): volumes by country of origin, port and PAD District of entry, processing refinery and company, crude grade, and API gravity - monthly and annual.", + "label": "Petroleum Imports", + "path": "petroleum/imports/browser/", + "hash": "#/?vs=PET_IMPORTS.WORLD-US-ALL.A", + }, + "natural_gas_query": { + "description": "The Natural Gas Annual Respondent Query System (Form EIA-176): company- and state-level natural gas volumes and prices, covering production, deliveries by consuming sector, underground and LNG storage, and supplemental supplies.", + "label": "Natural Gas Annual Respondent Query System", + "path": "naturalgas/ngqs/", + "hash": "#?report=RP2", + }, + "states": { + "description": "State Energy Profiles: energy production, consumption, prices, expenditures, and cross-state rankings for coal, natural gas, petroleum, electricity, nuclear, and renewables, for every U.S. state and territory.", + "label": "State Energy Profiles", + "path": "states/overview", + "hash": "", + }, + "maps": { + "description": "EIA's oil and natural gas maps: shale plays and sedimentary basins, pipelines and infrastructure, refineries, and production regions - as PDF and image maps.", + "label": "Oil & Natural Gas Maps", + "path": "maps/oil-naturalgas.php", + "hash": "", + }, +} + +_BROWSER_PATHS = frozenset(spec["path"] for spec in EIA_DATA_BROWSERS.values()) + + +def _app_root(path: str) -> str: + """Return the leading path segment(s) that identify a browser's app.""" + segments = path.split("/") + if segments[0] == "outlooks" and len(segments) > 1: + return f"{segments[0]}/{segments[1]}/" + return f"{segments[0]}/" + + +_APP_ROOT_TO_BROWSER = { + _app_root(spec["path"]): spec["path"] for spec in EIA_DATA_BROWSERS.values() +} + + +def _derive_browser(path: str) -> str: + """Map a proxied resource path to the browser whose app owns it.""" + for root, browser in _APP_ROOT_TO_BROWSER.items(): + if path.startswith(root): + return browser + return "" + + +MAPS_PAGE = "maps/oil-naturalgas.php" + + +_TABLE_ROWS: dict[tuple[str, str, str], tuple[list, float]] = {} +_NOT_TABLE_RE = re.compile( + r"method=getConfig" + r"|method=getImportExportConfigJSON" + r"|method=getRowMetadata" + r"|method=getMapData" + r"|type=config" + r"|type=defaults" + r"|type=mapData" + r"|/status\.json" + r"|/release_dates\.json" + r"|/ngqs/data/(?:version|report|items|sortby)(?:\?|$)" + r"|/international/api/(?:activities|configurations|countries|country_groups" + r"|fips_groups|frequencies|max_min_periods|political_groups|product_activities" + r"|products|selection_trees|unit_groups|unit_groups_assoc|units|views)/data" + r"|/international/api/articles/" + r"|/international/(?:content|api/analysis|api/other-groups\.json)" + r"|/states/api/Projects/States/Json/" + r"|/states/rankings/getRankingCategories" + r"|/states/content/(?:facts|tie|resources|l2articles" + r"|getRegionsOrganizations|getOtherWebsites)" + r"|/geo\.json", + re.I, +) + + +def is_data_response(target: str, content_type: str) -> bool: + """Return ``True`` for a proxied response carrying a browser's table data.""" + if "/global/" in target or "json" not in content_type: + return False + return not _NOT_TABLE_RE.search(target) + + +_LAST_DATA: dict[tuple[str, str], tuple[dict, float]] = {} +_VIEW_DATA: dict[tuple[str, str, str], tuple[dict, float]] = {} +_CURRENT_VIEW: dict[tuple[str, str], tuple[str, float]] = {} +_WIDGET_STATE: dict[tuple[str, str], tuple[dict, float]] = {} +_PAGE_CONTINUATION_RE = re.compile(r"[?&]offset=(?!0(?:&|$))\d") + + +def view_key(view: str) -> str: + """Strip a view's query string, keeping any hash the classic browsers use.""" + head, marker, fragment = view.partition("#") + head = head.partition("?")[0] + return f"{head}#{fragment}" if marker else head + + +def _put(store: dict, key, value, seq: float) -> None: + """Store ``value`` unless a later-issued one is already there.""" + existing = store.get(key) + if existing is not None and existing[1] > seq: + return + store[key] = (value, seq) + + +def _freshest_any_user(store: dict, *rest: str) -> tuple | None: + """Return the freshest ``(value, seq)`` entry for ``(any_user, *rest)``. + + A caller reading state (the MCP tool in particular) has no way to + guarantee its own identity hash matches the one a widget's iframe used + when it reported state, so the real source of truth is whichever widget + instance most recently reported this exact state -- regardless of whose + user hash it was filed under. + """ + best = None + for key, entry in store.items(): + if key[1:] == rest and (best is None or entry[1] > best[1]): + best = entry + return best + + +def set_current_view(browser: str, view: str, seq: float = 0.0, user: str = "") -> None: + """Record the view a browser is displaying for one user.""" + _put(_CURRENT_VIEW, (user, browser), view, seq) + + +def get_current_view(browser: str, user: str = "") -> str: + """Return the view a browser is displaying for one user. + + Falls back to the anonymous bucket when a user-scoped entry is missing, so + a beacon that could not resolve a user hash still lands on the state a + prior (or concurrent) anonymous beacon recorded for the same browser. + """ + entry = _CURRENT_VIEW.get((user, browser)) + if entry is None and user: + entry = _CURRENT_VIEW.get(("", browser)) + return entry[0] if entry is not None else "" + + +def set_data_target( + browser: str, view: str, request: dict, seq: float = 0.0, user: str = "" +) -> None: + """Record the data request a browser issued, keyed by the view that issued it.""" + _put(_LAST_DATA, (user, browser), request, seq) + if view: + _put(_VIEW_DATA, (user, browser, view_key(view)), request, seq) + + +def get_data_target(browser: str, user: str = "") -> dict | None: + """Return the data request behind the view a browser is currently displaying.""" + view = view_key(get_current_view(browser, user)) + if view: + entry = _VIEW_DATA.get((user, browser, view)) + if entry is None and user: + entry = _VIEW_DATA.get(("", browser, view)) + if entry is not None: + return entry[0] + entry = _LAST_DATA.get((user, browser)) + if entry is None and user: + entry = _LAST_DATA.get(("", browser)) + return entry[0] if entry is not None else None + + +def set_table_rows( + browser: str, rows: list, seq: float = 0.0, user: str = "", view: str = "" +) -> None: + """Record the table a browser rendered, keyed by the view that rendered it.""" + _put(_TABLE_ROWS, (user, browser, view_key(view)), rows, seq) + + +def get_table_rows(browser: str, user: str = "", view: str = "") -> list | None: + """Return the table a browser rendered for one view.""" + entry = _TABLE_ROWS.get((user, browser, view_key(view))) + if entry is None and user: + entry = _TABLE_ROWS.get(("", browser, view_key(view))) + return entry[0] if entry is not None else None + + +def set_widget_state( + browser: str, state: dict, seq: float = 0.0, user: str = "" +) -> None: + """Record the latest widget interaction state for one browser and user.""" + _put(_WIDGET_STATE, (user, browser), state, seq) + + +def get_widget_state(browser: str, user: str = "") -> dict | None: + """Return the latest widget interaction state for one browser and user.""" + entry = _WIDGET_STATE.get((user, browser)) + if entry is None and user: + entry = _WIDGET_STATE.get(("", browser)) + if entry is None: + entry = _freshest_any_user(_WIDGET_STATE, browser) + return entry[0] if entry is not None else None + + +_MAPS_TAB_RE = re.compile(r'
  • ', re.S) +_MAPS_BLOCK_RE = re.compile(r'
    ', re.S) +_MAPS_SECTION_RE = re.compile(r"]*>(.*?)", re.S) +_MAPS_ANCHOR_RE = re.compile( + r']*?title="(?P[^"]+)"', + re.I, +) +_MAPS_TITLE_RE = re.compile( + r"^(?P<name>.+?)\s*\((?P<date>[^()]*)\)\s*\((?:pdf|jpe?g|png)\)\s*$", re.I +) +_MAPS_FORMAT_SUFFIX_RE = re.compile(r"\s*\((?:pdf|jpe?g|png)\)\s*$", re.I) + + +def _text(fragment: str) -> str: + """Strip tags, unescape entities, and collapse whitespace in an HTML fragment.""" + from html import unescape + + return " ".join(unescape(re.sub(r"<[^>]+>", " ", fragment)).split()) + + +def parse_maps_page(html: str) -> list[dict]: + """Parse the oil & natural gas maps page into grouped map documents.""" + tabs = [_text(t) for t in _MAPS_TAB_RE.findall(html)] + tab_starts = [m.start() for m in _MAPS_BLOCK_RE.finditer(html)] + sections = [(m.start(), _text(m.group(1))) for m in _MAPS_SECTION_RE.finditer(html)] + + def tab_at(pos: int) -> str: + index = sum(1 for start in tab_starts if start <= pos) - 1 + if index < 0: + return "" + return tabs[index] if index < len(tabs) else f"Maps {index + 1}" + + def section_at(pos: int) -> str: + current = "" + for start, title in sections: + if start > pos: + break + current = title + return current + + entries: dict[tuple, dict] = {} + for match in _MAPS_ANCHOR_RE.finditer(html): + pos = match.start() + tab = tab_at(pos) + if not tab: + continue + href = match.group("href") + section = section_at(pos) + parsed = _MAPS_TITLE_RE.match(_text(match.group("title"))) + if parsed: + title, date = parsed.group("name"), parsed.group("date") + else: + title = _MAPS_FORMAT_SUFFIX_RE.sub("", _text(match.group("title"))) + date = "" + if section and title.lower().startswith(f"{section.lower()}:"): + title = title[len(section) + 1 :].strip() + key = (tab, section, title, date) + entry = entries.setdefault( + key, + {"tab": tab, "section": section, "title": title, "date": date}, + ) + entry["pdf" if href.lower().endswith(".pdf") else "image"] = href + return [e for e in entries.values() if e.get("pdf") or e.get("image")] + + +_MAPS_CATALOG: list[dict] | None = None + + +async def fetch_maps_catalog() -> list[dict]: + """Fetch and cache the parsed maps catalog for the process lifetime.""" + global _MAPS_CATALOG # noqa: PLW0603 + if _MAPS_CATALOG is None: + body, _content_type = await _fetch_upstream(f"{_EIA_ORIGIN}/{MAPS_PAGE}") + _MAPS_CATALOG = parse_maps_page(body.decode("utf-8", "replace")) + return _MAPS_CATALOG + + +def rewrite_html( + html: str, + proxy_prefix: str, + article: bool = False, + dark: bool = False, + browser: str = "", + user: str = "", +) -> str: + """Repoint root-absolute paths at the proxy, drop dead scripts, hide chrome.""" + html = _DEAD_SCRIPTS.sub("", html) + html = _AKAMAI_INLINE.sub("", html) + html = _AKAMAI_NOSCRIPT.sub("", html) + html = _SEARCH_INLINE.sub("", html) + if article: + html = _ARTICLE_DEAD_SCRIPTS.sub("", html) + escaped = proxy_prefix.replace("/", "\\/") + html = _ROOT_PATH_RE.sub(lambda m: f"{m.group(1)}{proxy_prefix}/", html) + html = _ESCAPED_ROOT_RE.sub(lambda m: f"{m.group(1)}{escaped}\\/", html) + html = _ABS_EIA_RE.sub(proxy_prefix, html) + html = _ESCAPED_EIA_RE.sub(escaped, html) + injected = ( + _CHROME_CSS + + _MAP_CONTRAST_CSS + + (_DARK_CSS if dark else "") + + _NAV_GUARD_JS + + _ASSET_FIX_JS + ) + if browser.startswith(("electricity", "coal")): + injected += _MAP_LAYOUT_CSS + if browser.startswith("naturalgas/ngqs"): + injected += _NGQS_GRID_CSS + if browser.startswith("states"): + injected += _STATES_CSS + if browser.startswith("international"): + injected += _INTERNATIONAL_CSS + if browser: + injected += ( + _xhr_tag_js(browser, user) + + _table_bridge_js(browser, user) + + _VIEW_SELECT_SYNC_JS + ) + if article: + injected += _ARTICLE_CSS + else: + injected += _view_bridge_js() + _DIALOG_CLAMP_JS + if "</head>" in html: + return html.replace("</head>", injected + "</head>", 1) + return injected + html + + +def _split_widget_params(query: str) -> tuple[str, bool, str, str, float, str]: + """Split the widget theme, browser, view, sequence and user out of a query.""" + from urllib.parse import parse_qsl, urlencode + + dark = False + browser = "" + view = "" + seq = 0.0 + user = "" + rest: list[tuple[str, str]] = [] + for key, value in parse_qsl(query, keep_blank_values=True): + if key == "obb_theme": + dark = value != "light" + elif key == "obb_browser": + browser = value if value in _BROWSER_PATHS else "" + elif key == "obb_view": + view = value + elif key == "obb_user": + user = value + elif key == "obb_seq": + try: + seq = float(value) + except ValueError: + seq = 0.0 + else: + rest.append((key, value)) + return urlencode(rest, safe=",~;"), dark, browser, view, seq, user + + +def _proxy_prefix(path: str) -> str: + """Derive the root-absolute proxy mount from a request path.""" + return path.split("/eia_proxy", 1)[0] + "/eia_proxy" + + +def _redirect_target(prefix: str, landed: str, dark: bool) -> str: + """Map an upstream redirect back onto the proxy, keeping the widget params.""" + from urllib.parse import parse_qsl, urlencode + + rest = landed[len(_EIA_ORIGIN) + 1 :] + path, _, query = rest.partition("?") + params = [(key, value) for key, value in parse_qsl(query, keep_blank_values=True)] + params.append(("obb_theme", "dark" if dark else "light")) + return f"{prefix}/{path}?{urlencode(params, safe=';,')}" + + +_PROXY_CACHE: dict[str, tuple[float, bytes, str]] = {} +_REDIRECTS: dict[str, str] = {} +_PROXY_CACHE_TTL = 3600.0 +_PROXY_CACHE_MAX = 512 +_REWRITE_CACHE: dict[tuple[str, str], str] = {} +_REWRITE_CACHE_MAX = 256 +_REWRITTEN_TTL = 60.0 + +_CURL_LOCAL = threading.local() + + +def _curl_session(): + """Return a per-thread curl_cffi session impersonating Chrome.""" + session = getattr(_CURL_LOCAL, "session", None) + if session is None: + from curl_cffi import requests as curl_requests + + session = curl_requests.Session( + impersonate="chrome", timeout=30, headers={"Referer": _EIA_ORIGIN} + ) + _CURL_LOCAL.session = session + return session + + +def _fetch_sync(target: str) -> tuple[bytes, str, int, str]: + """Fetch a URL on a worker thread, retrying on transient upstream failures.""" + import time + + last: Exception | None = None + for attempt in range(3): + try: + response = _curl_session().get(target, allow_redirects=True) + content_type = response.headers.get( + "Content-Type", "application/octet-stream" + ) + landed = str(response.url) if response.history else "" + return response.content, content_type, response.status_code, landed + except Exception as exc: # noqa: BLE001 + last = exc + _CURL_LOCAL.session = None + time.sleep(0.3 * (attempt + 1)) + raise last # type: ignore[misc] + + +def _post_sync(target: str, body: bytes, content_type: str) -> tuple[bytes, str, int]: + """POST a body to an eia.gov endpoint on a worker thread, with retries.""" + import time + + headers = {"Content-Type": content_type} if content_type else {} + last: Exception | None = None + for attempt in range(3): + try: + response = _curl_session().post( + target, data=body, headers=headers, allow_redirects=True + ) + content_type_out = response.headers.get( + "Content-Type", "application/octet-stream" + ) + return response.content, content_type_out, response.status_code + except Exception as exc: # noqa: BLE001 + last = exc + _CURL_LOCAL.session = None + time.sleep(0.3 * (attempt + 1)) + raise last # type: ignore[misc] + + +async def post_upstream( + target: str, body: bytes, content_type: str +) -> tuple[bytes, str]: + """POST to an eia.gov data endpoint (never cached; the query is dynamic).""" + import asyncio + + content, ct, _status = await asyncio.to_thread( + _post_sync, target, body, content_type + ) + return content, ct + + +def _cache_dir() -> Path: + """Return the on-disk proxy cache directory under the user cache root.""" + from openbb_core.app.utils import get_user_cache_directory + + return Path(get_user_cache_directory()) / "eia_proxy" + + +_STATIC_EXT = ( + ".js", + ".css", + ".map", + ".png", + ".jpg", + ".jpeg", + ".gif", + ".svg", + ".ico", + ".woff", + ".woff2", + ".ttf", + ".eot", + ".otf", + ".pdf", +) + + +def _is_static(target: str) -> bool: + """Return whether a target is an immutable asset safe to cache on disk.""" + return target.split("?", 1)[0].lower().endswith(_STATIC_EXT) + + +def _cache_paths(target: str) -> tuple[Path, Path]: + """Return the ``(body, content-type)`` disk-cache paths for a target URL.""" + from hashlib import sha256 + + digest = sha256(target.encode("utf-8")).hexdigest()[:32] + cache_dir = _cache_dir() + return cache_dir / digest, cache_dir / f"{digest}.type" + + +def _remember(target: str, body: bytes, content_type: str) -> None: + """Store a fetched resource in the in-memory cache, evicting the oldest.""" + from time import monotonic + + if len(_PROXY_CACHE) >= _PROXY_CACHE_MAX: + oldest = min(_PROXY_CACHE, key=lambda key: _PROXY_CACHE[key][0]) + del _PROXY_CACHE[oldest] + _PROXY_CACHE[target] = (monotonic(), body, content_type) + + +async def _fetch_upstream(target: str) -> tuple[bytes, str]: + """Fetch one eia.gov resource, served from memory then disk before network.""" + from time import monotonic + + cached = _PROXY_CACHE.get(target) + if cached and monotonic() - cached[0] < _PROXY_CACHE_TTL: + return cached[1], cached[2] + + static = _is_static(target) + body_path, type_path = _cache_paths(target) + if static and body_path.exists() and type_path.exists(): + body = body_path.read_bytes() + content_type = type_path.read_text(encoding="utf-8") + _remember(target, body, content_type) + return body, content_type + + import asyncio + + body, content_type, status, landed = await asyncio.to_thread(_fetch_sync, target) + + if landed and landed != target: + _REDIRECTS[target] = landed + _remember(landed, body, content_type) + + if status == 200: + _remember(target, body, content_type) + if static: + try: + _cache_dir().mkdir(parents=True, exist_ok=True) + body_path.write_bytes(body) + type_path.write_text(content_type, encoding="utf-8") + except OSError: + pass + return body, content_type + + +_WARM_ASSETS = ( + "global/styles/screen.css", + "global/styles/eia-styles.min.css?v=11.2", + "global/styles/EIA_global.css?v=11.1", + "global/scripts/vendor/jquery/jquery.min.js", + "global/scripts/vendor/jquery-migrate/jquery.migrate.min.js", + "global/scripts/global.min.js?v=11.3", + "global/scripts/eia-scripts.min.js?v=11.3", + "global/scripts/jquery/jquery-1.11.1.min.js", + "global/scripts/jquery/highcharts/3.0.10/js/highcharts.js", +) +_WARM_TASKS: set = set() +_ASSET_RE = re.compile( + r"""(?:href|src)=["']([^"']+\.(?:js|css)(?:\?[^"']*)?)["']""", re.I +) +_MODULE_RE = re.compile(r'"([^"]*node_modules[^"]*)"') +_URLARGS_RE = re.compile(r"""urlArgs['"]\]\s*=\s*['"]([^'"]+)['"]""") + + +async def _page_assets(page_path: str) -> set[str]: + """Collect the asset URLs a data-browser page declares, including modules.""" + body, _ = await _fetch_upstream(f"{_EIA_ORIGIN}/{page_path}") + html = body.decode("utf-8", "replace").replace("\\/", "/") + args = _URLARGS_RE.search(html) + suffix = f"?{args.group(1)}" if args else "" + + targets: set[str] = set() + for match in _ASSET_RE.finditer(html): + url = match.group(1) + if url.startswith("http"): + continue + targets.add( + f"{_EIA_ORIGIN}{url}" + if url.startswith("/") + else f"{_EIA_ORIGIN}/{page_path}{url}" + ) + for match in _MODULE_RE.finditer(html): + module = match.group(1) + if module.startswith("/"): + targets.add(f"{_EIA_ORIGIN}{module}.js{suffix}") + return targets + + +async def _warm_proxy_cache() -> None: + """Pre-fetch the shared and data-browser assets so the first load is warm.""" + import asyncio + from contextlib import suppress + + targets: set[str] = {f"{_EIA_ORIGIN}/{asset}" for asset in _WARM_ASSETS} + with suppress(Exception): + targets |= await _page_assets(EIA_DATA_BROWSERS["electricity"]["path"]) + + semaphore = asyncio.Semaphore(6) + + async def fetch(target: str) -> None: + async with semaphore: + with suppress(Exception): + await _fetch_upstream(target) + + await asyncio.gather(*(fetch(target) for target in targets)) + + +def _schedule_warm() -> None: + """Kick off the proxy cache warmup in the background at API startup.""" + import asyncio + + try: + loop = asyncio.get_running_loop() + except RuntimeError: + return + task = loop.create_task(_warm_proxy_cache()) + _WARM_TASKS.add(task) + task.add_done_callback(_WARM_TASKS.discard) + + +async def eia_table( + info: Annotated[dict, Depends(request_info)], +) -> Response: + """Record the table a browser has rendered, so ``raw`` serves that table.""" + import json + + _, _, browser, view, seq, user = _split_widget_params(info["query"]) + if not browser: + return Response(status_code=204) + try: + rows = json.loads(info["body"] or b"[]") + except ValueError: + return Response(status_code=204) + if isinstance(rows, list) and rows and all(isinstance(r, dict) for r in rows): + set_table_rows(browser, rows, seq, user, view) + return Response(status_code=204) + + +async def eia_state( + info: Annotated[dict, Depends(request_info)], +) -> Response: + """Record explicit iframe interaction state independently of table rows.""" + import json + + _, _, browser, view, seq, user = _split_widget_params(info["query"]) + if not browser: + return Response(status_code=204) + set_current_view(browser, view, seq, user) + try: + state = json.loads(info["body"] or b"{}") + except ValueError: + state = {} + if isinstance(state, dict): + set_widget_state(browser, state, seq, user) + return Response(status_code=204) + + +async def eia_mcp_state(browser: str, user: str = "") -> Response: + """Return the live table for one browser, read from this process's tracked state. + + The EIA MCP tool runs in its own subprocess (see ``eia_mcp.py``) with no + visibility into this process's in-memory browser state, so it calls back + here to read exactly what ``raw_table`` would return in this process. + """ + import json + + spec = EIA_DATA_BROWSERS.get(browser) + rows = await raw_table(browser, spec, user) if spec is not None else [] + return Response( + content=json.dumps(rows).encode("utf-8"), + media_type="application/json", + headers={"Cache-Control": "no-store"}, + ) + + +async def eia_view( + info: Annotated[dict, Depends(request_info)], +) -> Response: + """Record the view a browser navigated to, so ``raw`` follows the current view.""" + _, _, browser, view, seq, user = _split_widget_params(info["query"]) + if browser: + set_current_view(browser, view, seq, user) + return Response(status_code=204) + + +async def eia_proxy( + path: str, + info: Annotated[dict, Depends(request_info)], +) -> Response: + """Reverse-proxy an eia.gov data-browser resource, same-origin.""" + query, dark, tagged, view, seq, user = _split_widget_params(info["query"]) + target = f"{_EIA_ORIGIN}/{path}" + (f"?{query}" if query else "") + is_post = info["method"] == "POST" + try: + if is_post: + body, content_type = await post_upstream( + target, info["body"], info["content_type"] + ) + else: + body, content_type = await _fetch_upstream(target) + except Exception: # noqa: BLE001 + return Response(content=b"Upstream request failed.", status_code=502) + + is_data = is_data_response(target, content_type) + if is_data and not _PAGE_CONTINUATION_RE.search(target): + browser = tagged or _derive_browser(path) + if browser: + request = {"url": target, "method": info["method"]} + if is_post: + request["body"] = info["body"] + request["content_type"] = info["content_type"] + if view: + set_current_view(browser, view, seq, user) + set_data_target(browser, view, request, seq, user) + + prefix = _proxy_prefix(info["path"]) + landed = _REDIRECTS.get(target) + if landed and "text/html" in content_type and landed.startswith(f"{_EIA_ORIGIN}/"): + location = _redirect_target(prefix, landed, dark) + if location.split("?", 1)[0] != info["path"]: + return RedirectResponse(location, status_code=307) + static = {"Cache-Control": f"public, max-age={int(_PROXY_CACHE_TTL)}"} + if "text/html" in content_type: + return HTMLResponse( + content=rewrite_html( + body.decode("utf-8", "replace"), + prefix, + article=path.startswith(_ARTICLE_PATHS), + dark=dark, + browser=(path if path in _BROWSER_PATHS else _derive_browser(path)), + user=user, + ), + headers={"Cache-Control": "no-store"}, + ) + return _static_response(path, content_type, body, prefix, is_data, static) + + +def _rewritten(key: tuple[str, str], build) -> str: + """Return the rewritten text for ``key``, building and caching it on a miss.""" + cached = _REWRITE_CACHE.get(key) + if cached is not None: + return cached + text = build() + if len(_REWRITE_CACHE) >= _REWRITE_CACHE_MAX: + _REWRITE_CACHE.pop(next(iter(_REWRITE_CACHE))) + _REWRITE_CACHE[key] = text + return text + + +def _static_response( + path: str, + content_type: str, + body: bytes, + prefix: str, + is_data: bool, + static: dict, +) -> Response: + """Rewrite and return a proxied CSS/JS/binary resource.""" + rewritten = {"Cache-Control": f"public, max-age={int(_REWRITTEN_TTL)}"} + if "text/css" in content_type: + + def build_css() -> str: + css = body.decode("utf-8", "replace") + css = re.sub(r"""url\(\s*(['"]?)/(?!/)""", rf"url(\1{prefix}/", css) + return _ABS_EIA_RE.sub(prefix, css) + + css = _rewritten(("css", f"{prefix}|{path}"), build_css) + return Response(content=css, media_type="text/css", headers=rewritten) + if "javascript" in content_type: + + def build_js() -> str: + script = body.decode("utf-8", "replace") + if path.startswith(_SPA_PATHS): + script = _SPA_ROOT_RE.sub(rf"\1{prefix}/\2", script) + else: + script = _JS_ROOT_RE.sub(rf"\1{prefix}/\2", script) + script = _ABS_EIA_RE.sub(prefix, script) + return _ESCAPED_EIA_RE.sub(prefix.replace("/", "\\/"), script) + + script = _rewritten(("js", f"{prefix}|{path}"), build_js) + return Response(content=script, media_type=content_type, headers=rewritten) + headers = {"Cache-Control": "no-store"} if is_data else static + return Response(content=body, media_type=content_type, headers=headers) + + +_TABLE_METHOD = "getAggregateData" +_TABLE_ENDPOINT = "data/index.php" +_NON_AGG_HASH_KEYS = frozenset( + { + "agg", + "freq", + "rtype", + "ctype", + "ltype", + "maptype", + "rse", + "pin", + "start", + "end", + "linechart", + "columnchart", + "areachart", + "barchart", + "map", + "chartindexed", + } +) + + +def table_params_from_hash(fragment: str) -> dict | None: + """Build the browser's ``getAggregateData`` params from its URL fragment.""" + from urllib.parse import parse_qs + + if not fragment.startswith("#"): + return None + path, _, query = fragment[1:].partition("?") + topic = re.search(r"/topic/(\d+)", path) + if not topic or not query: + return None + + values = {key: value[0] for key, value in parse_qs(query).items() if value} + params: dict[str, str] = {"method": _TABLE_METHOD, "topic": topic.group(1)} + if "agg" in values: + params["agg"] = values["agg"] + for key, value in values.items(): + if key not in _NON_AGG_HASH_KEYS: + params[key] = value + params["ids"] = values.get("pin") or values.get(values.get("ctype", ""), "") or "" + params["freq"] = values.get("freq", "M") + params["rtype"] = values.get("rtype", "s") + return params + + +def _format_period(period: str) -> str: + """Render an EIA period code as an ISO-style date string.""" + if period.isdigit(): + if len(period) == 6: + return f"{period[:4]}-{period[4:]}" + if len(period) == 8: + return f"{period[:4]}-{period[4:6]}-{period[6:]}" + return period + + +def _flatten_cases(data: dict) -> dict: + """Collapse ``{caseId: {period: value}}`` down to ``{period: value}``.""" + if data and all(isinstance(value, dict) for value in data.values()): + merged: dict = {} + for series in data.values(): + merged.update(series) + return merged + return data + + +def _period_columns(all_periods: set) -> list[tuple[str, str]]: + """Return ``(display, raw)`` period pairs in ascending period order.""" + columns: list[tuple[str, str]] = [] + for period in sorted(all_periods, key=str): + display = _format_period(str(period)) + if display.isdigit(): + display = f"{display} " + columns.append((display, period)) + return columns + + +def _num(value): + """Coerce a measurement cell to ``float``, or to None. + + EIA marks withheld or negligible values with text in an otherwise numeric + column -- ``(s)`` for a value too small to display, ``--`` for not + available, ``W`` for withheld. These are missing data, not labels. + """ + try: + return float(value) + except (TypeError, ValueError): + return None + + +def _table_rows(table: dict) -> list[dict]: + """One row per series in the browser's table order, periods as columns.""" + units_default = table.get("UNITS") or table.get("units") or "" + entries = table.get("ROWS") or table.get("rows") or [] + if isinstance(entries, dict): + entries = list(entries.values()) + + parsed: list[tuple[str, str, str, dict]] = [] + all_periods: set = set() + for entry in entries: + if not isinstance(entry, dict): + continue + data = entry.get("DATA") if "DATA" in entry else entry.get("data") + data = _flatten_cases(data) if isinstance(data, dict) else {} + label = ( + entry.get("CHART_NAME") + or entry.get("chart_name") + or entry.get("DESCRIPTION") + or entry.get("description") + or entry.get("PINNED_NAME") + or "" + ) + source = entry.get("SERIES_ID") or entry.get("rowId") or entry.get("MSN") or "" + units = entry.get("UNITS") or entry.get("units") or units_default + all_periods.update(data.keys()) + parsed.append((str(label), str(source), str(units), data)) + + columns = _period_columns(all_periods) + rows: list[dict] = [] + for label, source, units, data in parsed: + row: dict = {"category": label, "units": units, "source_key": source} + for display, raw in columns: + row[display] = _num(data.get(raw)) + rows.append(row) + return rows + + +def _series_rows(series: list) -> list[dict]: + """One row per ``{series_id, data}`` series, periods as columns.""" + parsed: list[tuple[str, str, str, dict]] = [] + all_periods: set = set() + for entry in series: + if not isinstance(entry, dict): + continue + source = str( + entry.get("series_id") or entry.get("seriesID") or entry.get("id") or "" + ) + label = str(entry.get("name") or entry.get("description") or source) + units = str(entry.get("units") or entry.get("unit") or "") + data = entry.get("data") + if isinstance(data, dict): + points = data + elif isinstance(data, list): + points = { + point[0]: point[1] + for point in data + if isinstance(point, (list, tuple)) and len(point) > 1 + } + else: + continue + all_periods.update(points.keys()) + parsed.append((label, units, source, points)) + + columns = _period_columns(all_periods) + rows: list[dict] = [] + for label, units, source, points in parsed: + row: dict = {"category": label, "units": units, "source_key": source} + for display, raw in columns: + row[display] = _num(points.get(raw)) + rows.append(row) + return rows + + +def _is_states_table(series: list, payload: dict) -> bool: + """Return True for the State Profiles table payload. + + Its ``series`` entries carry only column metadata; the values live in the + top-level ``data`` records, keyed by each series' ``column_index``. + """ + return ( + isinstance(payload.get("data"), list) + and bool(series) + and isinstance(series[0], dict) + and "column_index" in series[0] + ) + + +def _states_table_rows(series: list, records: list) -> list[dict]: + """One row per State Profiles series, periods as columns.""" + columns = [ + meta for meta in series if isinstance(meta, dict) and meta.get("column_index") + ] + points: dict[str, dict] = {str(meta["column_index"]): {} for meta in columns} + all_periods: set = set() + for record in records: + if not isinstance(record, dict): + continue + period = str(record.get("time") or "") + if not period: + continue + all_periods.add(period) + for key, bucket in points.items(): + if key in record: + bucket[period] = record[key] + + period_columns = _period_columns(all_periods) + rows: list[dict] = [] + for meta in columns: + bucket = points[str(meta["column_index"])] + row: dict = { + "category": meta.get("name") or meta.get("series_id") or "", + "units": meta.get("units") or "", + "source_key": meta.get("series_id") or "", + } + for display, raw in period_columns: + row[display] = _num(bucket.get(raw)) + rows.append(row) + return rows + + +def _ranking_rows(series: list) -> list[dict]: + """One row per state in a State Energy Profiles ranking.""" + rows: list[dict] = [] + for entry in series: + if not isinstance(entry, dict): + continue + rows.append( + { + "category": entry.get("stateName") or entry.get("stateId") or "", + "units": entry.get("displayName") or "", + "source_key": entry.get("seriesId") or "", + "rank": _num(entry.get("rank")), + "period": entry.get("period") or "", + "value": _num(entry.get("value")), + } + ) + return rows + + +_SEDS_LABELS: dict = {} + + +def _seds_labels() -> tuple[dict, dict]: + """Return ``(state code -> name, MSN code -> series name)`` from the catalog.""" + if not _SEDS_LABELS: + from openbb_us_eia.utils import catalog + + choices = catalog.get_group("seds").get("choices") or {} + _SEDS_LABELS["state"] = { + choice["value"]: choice["label"] for choice in choices.get("state") or [] + } + _SEDS_LABELS["series"] = { + choice["value"]: choice["label"] for choice in choices.get("series") or [] + } + return _SEDS_LABELS["state"], _SEDS_LABELS["series"] + + +def _state_map_rows(series: dict) -> list[dict]: + """One row per state for a US map payload (``{msn: {state: value}}``).""" + state_names, series_names = _seds_labels() + codes = [code for code, values in series.items() if isinstance(values, dict)] + states: list[str] = [] + seen: set = set() + for code in codes: + for state in series[code]: + if state not in seen: + seen.add(state) + states.append(state) + rows: list[dict] = [] + for state in states: + row: dict = { + "category": state_names.get(state) or state, + "state": state, + } + for code in codes: + row[series_names.get(code) or code] = _num(series[code].get(state)) + rows.append(row) + return rows + + +def _intl_value(point): + """Return a point's full-precision value, or None for missing markers.""" + if not isinstance(point, list): + return point + value = point[-1] if point else None + return None if isinstance(value, str) else value + + +def _parse_intl_id(series_id: str) -> tuple[str, str, str, str]: + """Split an ``INTL.<product>-<activity>-<region>-<unit>.<freq>`` id. + + Returns ``(product, activity, region, unit)``; the product and activity are + empty when the id carries only a region and unit. + """ + core = series_id[5:] if series_id.startswith("INTL.") else series_id + segments = core.rsplit(".", 1)[0].split("-") + if len(segments) < 2: + return "", "", "", "" + if len(segments) < 4: + return "", "", segments[-2], segments[-1] + return segments[0], segments[1], segments[-2], segments[-1] + + +def _sentence(name: str) -> str: + """Capitalise an EIA label without touching the rest of its casing.""" + return name[:1].upper() + name[1:] if name else "" + + +def _intl_row_label(product: str, activity: str, labels: dict) -> str: + """Name a row the way the browser's table does. + + EIA labels a top-level product's row with the activity it totals + (``Production``), and each child product's row with the product itself + (``Fuel ethanol``). + """ + products = labels.get("product") or {} + activities = labels.get("activity") or {} + parents = labels.get("parent") or {} + if product and product in products and parents.get(product) is not None: + return _sentence(products[product]) + if activity and activity in activities: + return _sentence(activities[activity]) + return _sentence(products.get(product, "")) + + +def _epoch_period(stamp, frequency: str) -> str: + """Render an epoch-millisecond timestamp as the EIA period code for a frequency.""" + from datetime import datetime, timezone + + try: + moment = datetime.fromtimestamp(int(stamp) / 1000, tz=timezone.utc) + except (TypeError, ValueError, OSError, OverflowError): + return "" + if frequency == "M": + return f"{moment.year}{moment.month:02d}" + if frequency == "D": + return f"{moment.year}{moment.month:02d}{moment.day:02d}" + if frequency == "Q": + return f"{moment.year}-Q{(moment.month - 1) // 3 + 1}" + return str(moment.year) + + +def _is_intl_infographic(data) -> bool: + """Return True for the International overview's ``series_data/infographic`` rows.""" + return ( + isinstance(data, list) + and bool(data) + and isinstance(data[0], dict) + and "series_id" in data[0] + and isinstance(data[0].get("data"), list) + ) + + +def _is_intl_ranking(data) -> bool: + """Return True for the International overview's flat ``ranking`` records.""" + return ( + isinstance(data, list) + and bool(data) + and isinstance(data[0], dict) + and "ranking" in data[0] + and "iso" in data[0] + and "productid" in data[0] + ) + + +def _ranking_period(value) -> str: + """Return the four-digit year carried by a ranking's date field.""" + match = re.search(r"\d{4}", str(value if value is not None else "")) + return match.group(0) if match else "" + + +def _intl_ranking_rows(records: list, labels: dict | None = None) -> list[dict]: + """One row per International overview ranking, labelled from the config feeds.""" + labels = labels or {} + products = labels.get("product") or {} + activities = labels.get("activity") or {} + regions = labels.get("region") or {} + units = labels.get("unit") or {} + rows: list[dict] = [] + for entry in records: + if not isinstance(entry, dict): + continue + product = products.get(str(entry.get("productid"))) or "" + activity = activities.get(str(entry.get("activityid"))) or "" + iso = str(entry.get("iso") or "") + unit_code = entry.get("unitcode") + value = entry.get("unrounded_value") + if value is None: + value = entry.get("value") + rows.append( + { + "category": _sentence( + " ".join(part for part in (product, activity) if part) + ) + or iso, + "country": regions.get(iso) or iso, + "rank": _num(entry.get("ranking")), + "value": _num(value), + "units": units.get(unit_code) or (unit_code or ""), + "period": _ranking_period(entry.get("date")), + "source_key": iso, + } + ) + return rows + + +def _intl_row( + series_id: str, country: str, unit: str, labels: dict +) -> tuple[str, str, str, str]: + """Return ``(label, country, units, source_key)`` for one International series.""" + product, activity, region, coded_unit = _parse_intl_id(series_id) + regions = labels.get("region") or {} + units_map = labels.get("unit") or {} + unit = unit or coded_unit + return ( + _intl_row_label(product, activity, labels) or series_id, + country or regions.get(region) or region, + units_map.get(unit) or unit, + series_id, + ) + + +def _intl_infographic_rows(records: list, labels: dict | None = None) -> list[dict]: + """One row per International overview series, periods as columns.""" + labels = labels or {} + parsed: list[tuple[tuple[str, str, str, str], dict]] = [] + all_periods: set = set() + for entry in records: + if not isinstance(entry, dict): + continue + frequency = str(entry.get("frequency") or "A") + points: dict = {} + for point in entry.get("data") or []: + if not isinstance(point, dict): + continue + period = _epoch_period(point.get("date"), frequency) + if period: + points[period] = point.get("value") + all_periods.update(points) + iso = str(entry.get("iso") or "") + regions = labels.get("region") or {} + country = regions.get(iso) or iso or str(entry.get("name") or "") + parsed.append( + ( + _intl_row( + str(entry.get("series_id") or ""), + country, + str(entry.get("unit") or ""), + labels, + ), + points, + ) + ) + + columns = _period_columns(all_periods) + rows: list[dict] = [] + for (label, country, units, source), points in parsed: + row: dict = { + "category": label, + "country": country, + "units": units, + "source_key": source, + } + for display, raw in columns: + row[display] = _num(points.get(raw)) + rows.append(row) + return rows + + +def _intl_series_rows(data: dict, labels: dict | None = None) -> list[dict]: + """One row per International series, periods as columns, ordered as displayed. + + The grid groups by country -- World first, then the countries by name -- and + keeps the product order the payload arrives in. The payload itself is keyed + product-first, so it has to be regrouped to match the table on screen. + """ + labels = labels or {} + order_map: dict[str, int] = labels.get("product_order") or {} + parsed: list[tuple[tuple, tuple[str, str, str, str], dict]] = [] + all_periods: set = set() + for series_id, points in data.items(): + if not isinstance(points, dict): + continue + product = _parse_intl_id(series_id)[0] + order = (order_map.get(str(product), len(order_map)), str(product)) + flat = {period: _intl_value(point) for period, point in points.items()} + all_periods.update(flat.keys()) + parsed.append((order, _intl_row(series_id, "", "", labels), flat)) + + parsed.sort(key=lambda item: (item[1][1] != "World", item[1][1], item[0])) + + columns = _period_columns(all_periods) + rows: list[dict] = [] + for _order, (label, country, units, source), flat in parsed: + row: dict = { + "category": label, + "country": country, + "units": units, + "source_key": source, + } + for display, raw in columns: + row[display] = _num(flat.get(raw)) + rows.append(row) + return rows + + +def _plant_list_rows(payload: dict) -> list[dict] | None: + """Rows for the plant-level views, whose table is a record per plant. + + ``DATA_COLUMNS`` is the column set the grid shows; the record carries more + (coordinates, ids) that the table does not. + """ + records = payload.get("DATA") + columns = payload.get("DATA_COLUMNS") + if not isinstance(records, list) or not isinstance(columns, list): + return None + if not records or not isinstance(records[0], dict): + return None + names = [name for name in columns if isinstance(name, str)] + if not names: + return None + return [{name: record.get(name) for name in names} for record in records] + + +def _dict_payload_rows(payload: dict) -> list[dict]: + """Shape-dispatch a dict payload into tabular rows. + + The classic browsers return the table under ``TABLEDATA`` (electricity, + coal, imports), lowercase ``tabledata`` (AEO), or ``VIEWSDATA`` (STEO, + which has no ``TABLEDATA``). ``SERIESDATA`` holds the separately pinned + series and is only the table when no standard view is selected. + """ + plants = _plant_list_rows(payload) + if plants is not None: + return plants + return _keyed_payload_rows(payload) + + +def _keyed_payload_rows(payload: dict) -> list[dict]: + """Rows for a payload that names its table under a known key.""" + table = payload.get("TABLEDATA") or payload.get("tabledata") + if not isinstance(table, dict): + for key in ("VIEWSDATA", "SERIESDATA"): + candidate = payload.get(key) + if isinstance(candidate, dict) and candidate.get("ROWS"): + table = candidate + break + if isinstance(table, dict): + return _table_rows(table) + if isinstance(payload.get("TABLE_DATA"), list): + return _series_rows(payload["TABLE_DATA"]) + series = payload.get("series") + if isinstance(series, list) and series: + if _is_states_table(series, payload): + return _states_table_rows(series, payload["data"]) + return ( + _series_rows(series) + if isinstance(series[0], dict) and "data" in series[0] + else _ranking_rows(series) + ) + if isinstance(series, dict) and series: + return _state_map_rows(series) + return _data_payload_rows(payload.get("data")) + + +def _data_payload_rows(data) -> list[dict]: + """Rows for a ``data``-keyed payload (International series, overview, or plain).""" + if isinstance(data, dict): + return _intl_series_rows(data) + if _is_intl_infographic(data): + return _intl_infographic_rows(data) + return ( + [row for row in data if isinstance(row, dict)] if isinstance(data, list) else [] + ) + + +def rows_from_payload(payload) -> list[dict]: + """Shape-dispatch any EIA browser's data payload into tabular rows.""" + if isinstance(payload, dict): + return _dict_payload_rows(payload) + if not isinstance(payload, list): + return [] + nested = [rows_from_payload(item) for item in payload if isinstance(item, dict)] + if any(nested): + return [row for rows in nested for row in rows] + return [row for row in payload if isinstance(row, dict)] + + +def _inline_payload(html: str) -> dict: + """Return Total Energy's inline ``sampleData`` payload, or an empty dict.""" + import json + + start = html.find("sampleData") + brace = html.find("{", start) if start >= 0 else -1 + if brace < 0: + return {} + try: + payload, _ = json.JSONDecoder().raw_decode(html, brace) + except ValueError: + return {} + return payload if isinstance(payload, dict) else {} + + +def parse_inline_table(html: str) -> list[dict]: + """Pivot Total Energy's inline ``sampleData`` (ROWS/DATACOLUMNS) into rows.""" + payload = _inline_payload(html) + return _table_rows(payload) if payload else [] + + +def _ngqs_rows(payload: dict) -> list[dict]: + """Rows for the Natural Gas Query System, using the grid's own column headers. + + The report ships ``columns`` (``headerName``/``field``) alongside ``data``, + whose records are keyed by the short field ids the grid binds to. + """ + columns = payload.get("columns") + records = payload.get("data") + if not isinstance(columns, list) or not isinstance(records, list): + return [] + headers: list[tuple[str, str, bool]] = [] + for column in columns: + if not isinstance(column, dict) or not column.get("field"): + continue + header = _text(str(column.get("headerName") or column["field"])) + if header.isdigit(): + header = f"{header} " + headers.append((header, column["field"], bool(column.get("numeric")))) + + rows: list[dict] = [] + for record in records: + if not isinstance(record, dict): + continue + row: dict = {} + for header, field, numeric in headers: + value = record.get(field) + row[header] = _num(value) if numeric else value + rows.append(row) + return rows + + +_IMPORTS_LABELS: dict = {} +_IMPORTS_CONFIG = "petroleum/imports/browser/data/index.php?method=getConfig" +_IMPORTS_UNITS = "thousand barrels" + + +async def _imports_label_maps() -> dict: + """Return the origin, destination and grade names the imports table is built from. + + The imports endpoint returns only ``seriesID`` and ``data``; the browser + builds every row label client-side from its config. + """ + import json + + if _IMPORTS_LABELS: + return _IMPORTS_LABELS + try: + body, _ = await _fetch_upstream(f"{_EIA_ORIGIN}/{_IMPORTS_CONFIG}") + config = json.loads(body) + except (ValueError, OSError): + return {} + + def named(items) -> dict[str, str]: + return { + str(item["id"]): item["name"] + for item in items or [] + if item.get("id") and item.get("name") + } + + states, padds = named(config.get("states")), named(config.get("padds")) + labels = { + "origin": { + "CTY": named(config.get("countries")), + "REG": named(config.get("regions")), + "OPN": named(config.get("opecNonOpec")), + }, + "destination": { + "RF": named(config.get("refineries")), + "PT": named(config.get("ports")), + "RS": states, + "PS": states, + "RP": padds, + "PP": padds, + }, + "grade": named(config.get("grades")), + } + if labels["grade"]: + _IMPORTS_LABELS.update(labels) + return labels + + +def _imports_name(segment: str, maps: dict) -> str: + """Resolve a ``<TYPE>_<id>`` (or bare id) series segment to its name.""" + kind, _, ident = segment.partition("_") + if ident: + return (maps.get(kind) or {}).get(ident) or segment + for table in maps.values(): + if segment in table: + return table[segment] + return segment + + +def _imports_rows(records: list, labels: dict | None = None) -> list[dict]: + """One row per imports series, labelled the way the browser's table is.""" + labels = labels or {} + origins = labels.get("origin") or {} + destinations = labels.get("destination") or {} + grades = labels.get("grade") or {} + parsed: list[tuple[tuple[str, str, str, str, str], dict]] = [] + all_periods: set = set() + for entry in records: + if not isinstance(entry, dict): + continue + series_id = str(entry.get("seriesID") or "") + points = entry.get("data") + points = points if isinstance(points, dict) else {} + all_periods.update(points) + parts = series_id.split(".") + segments = parts[1].split("-") if len(parts) > 2 else [] + if len(segments) < 3: + parsed.append(((series_id, "", "", "", series_id), points)) + continue + origin = _imports_name(segments[0], origins) + destination = _imports_name(segments[1], destinations) + grade = ( + "all grades" + if segments[2] == "ALL" + else (grades.get(segments[2]) or segments[2]) + ) + cadence = "annual" if parts[2].upper() == "A" else "monthly" + label = f"Imports of {grade} from {origin} to {destination}, {cadence}" + parsed.append(((label, origin, destination, grade, series_id), points)) + + columns = _period_columns(all_periods) + rows: list[dict] = [] + for (label, origin, destination, grade, source), points in parsed: + row: dict = { + "category": label, + "origin": origin, + "destination": destination, + "grade": grade, + "units": _IMPORTS_UNITS, + "source_key": source, + } + for display, raw in columns: + row[display] = _num(points.get(raw)) + rows.append(row) + return rows + + +_INTL_LABELS: dict = {} +_INTL_LABEL_FEEDS = ("countries", "political_groups", "units", "products", "activities") + + +async def _intl_label_maps() -> dict: + """Return the region, unit, product and activity names International rows need.""" + import json + + if _INTL_LABELS: + return _INTL_LABELS + feeds: dict[str, list] = {} + try: + for feed in _INTL_LABEL_FEEDS: + body, _ = await _fetch_upstream( + f"{_EIA_ORIGIN}/international/api/{feed}/data" + ) + feeds[feed] = json.loads(body).get("data", []) + except (ValueError, OSError): + return {} + region_map = {c["iso"]: c["name"] for c in feeds["countries"] if c.get("iso")} + region_map.update( + { + g["iso"]: g["name"] + for g in feeds["political_groups"] + if g.get("iso") and g.get("name") + } + ) + labels = { + "region": region_map, + "unit": { + u["code"]: (u.get("short_name") or u.get("name")) + for u in feeds["units"] + if u.get("code") + }, + "product": { + str(p["id"]): p["name"] for p in feeds["products"] if p.get("name") + }, + "activity": { + str(a["id"]): a["name"] for a in feeds["activities"] if a.get("name") + }, + "parent": { + str(p["id"]): p.get("parent") for p in feeds["products"] if p.get("id") + }, + "product_order": { + str(p["id"]): index + for index, p in enumerate(feeds["products"]) + if p.get("id") is not None + }, + } + if region_map: + _INTL_LABELS.update(labels) + return labels + + +_PAYLOAD_FIRST = frozenset({"petroleum_imports"}) + + +def _view_query(view: str) -> str: + """Return a view's own query string, dropping the widget's ``obb_`` markers.""" + from urllib.parse import parse_qsl, urlencode + + query = view.partition("#")[0].partition("?")[2] + kept = [ + (key, value) + for key, value in parse_qsl(query, keep_blank_values=True) + if not key.startswith("obb_") + ] + return urlencode(kept, safe=",~;") + + +def _mer_hash_state(view: str) -> tuple[str, str, str]: + """Return the ``(frequency, start, end)`` the MER hash encodes for a view.""" + from urllib.parse import parse_qs + + fragment = view.partition("#")[2] + query = fragment.partition("?")[2] if "?" in fragment else "" + params = parse_qs(query) + return ( + (params.get("f") or [""])[0], + (params.get("start") or [""])[0], + (params.get("end") or [""])[0], + ) + + +def _filter_mer_payload(payload: dict, freq: str, start: str, end: str) -> None: + """Narrow the inline table to one frequency and the selected period range. + + The inline data carries every period at once -- annual codes are four digits, + monthly six -- so the frequency picks the column width and start/end clip it + to what the time slider shows. + """ + rows = payload.get("ROWS") or [] + if freq not in ("M", "A"): + freq = ( + "M" + if any( + len(str(period)) == 6 + for row in rows + if isinstance(row, dict) + for period in row.get("DATA") or {} + ) + else "A" + ) + width = 6 if freq == "M" else 4 + for row in rows: + if not isinstance(row, dict): + continue + row["DATA"] = { + period: value + for period, value in (row.get("DATA") or {}).items() + if len(str(period)) == width + and (not start or str(period) >= start) + and (not end or str(period) <= end) + } + + +async def _total_energy_table(path: str, user: str) -> list[dict]: + """Return the Monthly Energy Review table the user is viewing, from its inline data. + + The MER browser reloads to ``?tbl=<table>`` and keeps the frequency and time + range in its hash, so the tracked view names the full state. Fetching that + page and pivoting its inline data -- narrowed to that frequency and range -- + is deterministic, with no scrape or recorded request to go stale or wrong. + """ + view = get_current_view(path, user) + query = _view_query(view) + url = f"{_EIA_ORIGIN}/{path}" + (f"?{query}" if query else "") + body, _ = await _fetch_upstream(url) + payload = _inline_payload(body.decode("utf-8", "replace")) + if not payload: + return [] + _filter_mer_payload(payload, *_mer_hash_state(view)) + return _table_rows(payload) + + +async def raw_table(browser: str, spec: dict, user: str = "") -> list[dict]: + """Return the table the browser is showing, hierarchical where its payload allows.""" + import json + from urllib.parse import urlencode + + if browser == "maps": + return await fetch_maps_catalog() + + path = spec["path"] + if browser == "total_energy": + return await _total_energy_table(path, user) + + view = get_current_view(path, user) + payload_first = browser in _PAYLOAD_FIRST + if not payload_first: + rendered = get_table_rows(path, user, view) + if rendered: + return rendered + + request = get_data_target(path, user) + if request is None: + params = table_params_from_hash(spec["hash"]) + if params is None: + return (get_table_rows(path, user, view) or []) if payload_first else [] + query = urlencode(params, safe="~,") + endpoint = f"{_EIA_ORIGIN}/{path}{_TABLE_ENDPOINT}?{query}" + request = {"url": endpoint, "method": "GET"} + + if request.get("method") == "POST": + raw_body = request.get("body") + body, _ = await post_upstream( + request["url"], + raw_body if isinstance(raw_body, bytes) else b"", + str(request.get("content_type") or ""), + ) + else: + body, _ = await _fetch_upstream(request["url"]) + try: + payload = json.loads(body) + except (ValueError, AttributeError): + return (get_table_rows(path, user, view) or []) if payload_first else [] + payload = await _all_pages(request, payload) + labelled = await _labelled_rows(browser, payload, view) + result = rows_from_payload(payload) if labelled is None else labelled + return ( + result + if result or not payload_first + else (get_table_rows(path, user, view) or []) + ) + + +async def _all_pages(request: dict, payload): + """Follow a paged payload to its end, so ``raw`` is never a partial table. + + The page asks for ``limit`` series at a time and stitches the pages together + as they land. Replaying only the request that was recorded would answer with + the first page and silently drop the rest of the table. + """ + import json + from urllib.parse import parse_qsl, urlencode, urlparse, urlunparse + + if not isinstance(payload, dict) or not isinstance(payload.get("data"), dict): + return payload + total = payload.get("totalCount") + if not isinstance(total, int) or len(payload["data"]) >= total: + return payload + + parts = urlparse(request["url"]) + query = dict(parse_qsl(parts.query)) + try: + limit = int(query.get("limit", 0)) + except ValueError: + return payload + if limit <= 0: + return payload + + merged = dict(payload["data"]) + offset = limit + while len(merged) < total and offset < total: + query["offset"] = str(offset) + page_url = urlunparse(parts._replace(query=urlencode(query, safe="~,"))) + body, _ = await _fetch_upstream(page_url) + try: + page = json.loads(body) + except (ValueError, AttributeError): + break + chunk = page.get("data") if isinstance(page, dict) else None + if not isinstance(chunk, dict) or not chunk: + break + merged.update(chunk) + offset += limit + + return {**payload, "data": merged, "recordCount": len(merged)} + + +async def _labelled_rows(browser: str, payload, view: str = "") -> list[dict] | None: + """Rows for the browsers whose tables are labelled from a separate config.""" + if not isinstance(payload, dict): + return None + if browser == "international": + return await _intl_rows(payload) + if browser == "petroleum_imports": + records = payload.get("TABLE_DATA") + if isinstance(records, list) and records: + return _imports_rows(records, await _imports_label_maps()) + if browser == "natural_gas_query" and isinstance(payload.get("columns"), list): + return _ngqs_rows(payload) + return None + + +async def _intl_rows(payload: dict) -> list[dict] | None: + """Rows for an International payload, labelled the way its table is.""" + data = payload.get("data") + if isinstance(data, dict): + return _intl_series_rows(data, await _intl_label_maps()) + if isinstance(data, list) and _is_intl_infographic(data): + return _intl_infographic_rows(data, await _intl_label_maps()) + if isinstance(data, list) and _is_intl_ranking(data): + return _intl_ranking_rows(data, await _intl_label_maps()) + return None + + +def _widget_src( + proxy_base: str, path: str, default_hash: str, view: str, mode: str, user: str +) -> str: + """Build the iframe src, restoring the user's last view when one was stashed.""" + from urllib.parse import parse_qsl, urlencode + + if view: + head, marker, fragment = view.partition("#") + path, _, search = head.partition("?") + extra = [ + (key, value) + for key, value in parse_qsl(search, keep_blank_values=True) + if not key.startswith("obb_") + ] + tail = f"#{fragment}" if marker else "" + else: + extra = [] + tail = default_hash + params = [("obb_theme", mode)] + if user: + params.append(("obb_user", user)) + params.extend(extra) + return f"{proxy_base}/{path}?{urlencode(params, safe=',~;')}{tail}" + + +async def render_browser( + browser: str, + theme: str, + raw: bool, + info: dict | None, +) -> Response: + """Render one EIA data browser as an HTML widget, or its table as raw rows.""" + import json + import os + + from openbb_core.app.service.system_service import SystemService + + spec = EIA_DATA_BROWSERS.get(browser) or EIA_DATA_BROWSERS["electricity"] + info = info or {} + user = info.get("user", "") + if raw: + return JSONResponse( + content=await raw_table(browser, spec, user), + headers={"Cache-Control": "no-store"}, + ) + endpoint = info.get("url") + if endpoint: + proxy_base = endpoint.rsplit("/", 1)[0] + "/eia_proxy" + else: + host = os.environ.get("OPENBB_API_HOST", "127.0.0.1") + port = os.environ.get("OPENBB_API_PORT", "6900") + prefix = SystemService().system_settings.api_settings.prefix + root = f"http://{host}:{port}{prefix}/eia" + endpoint = f"{root}/{browser}_browser" + proxy_base = f"{root}/eia_proxy" + mode = "light" if theme == "light" else "dark" + view = "" if browser == "maps" else get_current_view(spec["path"], user) + payload: dict = { + "mode": "site", + "theme": mode, + "browser": browser, + "path": spec["path"], + "user": user, + "label": spec["label"], + "description": spec["description"], + "endpoint": endpoint, + "src": _widget_src(proxy_base, spec["path"], spec["hash"], view, mode, user), + "home": _widget_src(proxy_base, spec["path"], spec["hash"], "", mode, user), + "proxy": proxy_base, + "maps": [], + } + if browser == "maps": + payload["mode"] = "maps" + payload["maps"] = await fetch_maps_catalog() + blob = ( + json.dumps(payload) + .replace("<", "\\u003c") + .replace(">", "\\u003e") + .replace("&", "\\u0026") + ) + template = _TEMPLATE.read_text(encoding="utf-8") + return HTMLResponse( + content=template.replace("__EIA_BROWSER_DATA__", blob), + headers={"Cache-Control": "no-cache"}, + ) + + +@asynccontextmanager +async def lifespan(_app) -> AsyncIterator[None]: + """Warm the proxy cache for the lifetime of the API, cleaning up on shutdown.""" + _schedule_warm() + try: + yield + finally: + for task in list(_WARM_TASKS): + task.cancel() + + +router._api_router.lifespan_context = lifespan + +router._api_router.add_api_route( + path="/eia_proxy/{path:path}", + endpoint=eia_proxy, + methods=["GET", "POST"], + include_in_schema=False, +) + +router._api_router.add_api_route( + path="/eia_view", + endpoint=eia_view, + methods=["GET", "POST"], + include_in_schema=False, +) + +router._api_router.add_api_route( + path="/eia_table", + endpoint=eia_table, + methods=["POST"], + include_in_schema=False, +) + +router._api_router.add_api_route( + path="/eia_state", + endpoint=eia_state, + methods=["POST"], + include_in_schema=False, +) + +router._api_router.add_api_route( + path="/eia_mcp_state", + endpoint=eia_mcp_state, + methods=["GET"], + include_in_schema=False, +) + + +def _browser_endpoint(browser: str): + """Build the widget endpoint bound to one EIA data browser.""" + + async def endpoint( + info: Annotated[dict | None, Depends(request_info)] = None, + theme: str = "dark", + raw: bool = False, + ) -> Any: + import json + + response = await render_browser(browser, theme, raw, info) + if info is None: + body = bytes(response.body) + if isinstance(response, JSONResponse): + return json.loads(body) + return body.decode("utf-8", "replace") + return response + + endpoint.__name__ = f"{browser}_browser" + endpoint.__doc__ = EIA_DATA_BROWSERS[browser]["description"] + return endpoint + + +def widget_route(browser: str) -> str: + """Return the widget route path for one EIA data browser.""" + return f"/{browser}_browser" + + +def widget_id(browser: str) -> str: + """Return the Workspace widget id for one EIA data browser.""" + return f"eia_{browser}_browser_us_eia_obb" + + +for _browser, _spec in EIA_DATA_BROWSERS.items(): + router._api_router.add_api_route( + path=widget_route(_browser), + endpoint=_browser_endpoint(_browser), + methods=["GET"], + response_class=HTMLResponse, + openapi_extra={ + "widget_config": { + "name": f"EIA {_spec['label']} Browser", + "description": _spec["description"], + "category": "EIA", + "subCategory": "Data Browsers", + "source": ["EIA"], + "type": "iframe", + "widgetId": widget_id(_browser), + "gridData": {"w": 40, "h": 22}, + "params": [ + {"paramName": "theme", "show": False}, + {"paramName": "raw", "show": False}, + ], + "refetchInterval": False, + "staleTime": 1000, + "raw": True, + "storage": {"mcpUrl": _mcp_url()}, + } + }, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/eia_mcp.py b/openbb_platform/providers/eia/openbb_us_eia/eia_mcp.py new file mode 100644 index 00000000000..a8a56f774e7 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/eia_mcp.py @@ -0,0 +1,400 @@ +"""EIA MCP server: a streamable-http subprocess, reverse-proxied through the +OpenBB API so the Workspace connects on the API's own host/port. +""" + +import logging +from typing import Annotated, Any + +from fastapi import Depends +from starlette.requests import Request + +from openbb_us_eia.browsers import _user_key + +_logger = logging.getLogger(__name__) + +_MCP_HOST = "127.0.0.1" +_MCP_PATH = "/mcp" +_DEFAULT_MCP_PORT = 6923 + + +def mcp_port() -> int: + """Return the port the MCP subprocess listens on (``OPENBB_EIA_MCP_PORT``).""" + import os + + try: + return int(os.environ.get("OPENBB_EIA_MCP_PORT", str(_DEFAULT_MCP_PORT))) + except ValueError: + return _DEFAULT_MCP_PORT + + +def mcp_server_url() -> str: + """Return the streamable-http URL the Workspace connects to.""" + return f"http://{_MCP_HOST}:{mcp_port()}{_MCP_PATH}" + + +def _port_open(host: str, port: int) -> bool: + """Return True if something is already listening on host:port.""" + import socket + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + sock.settimeout(0.25) + return sock.connect_ex((host, port)) == 0 + + +def _api_state_url(browser: str, user: str) -> str: + """Return the main API process's URL for reading one browser's live state. + + The MCP tool runs in this module's own subprocess, which has no + visibility into the main API process's in-memory browser state (that + state lives only where ``eia_table``/``eia_view``/``eia_proxy`` run), so + the tool calls back into the main process to read it there. + """ + import os + from urllib.parse import urlencode + + from openbb_core.app.service.system_service import SystemService + + host = os.environ.get("OPENBB_API_HOST", "127.0.0.1") + port = os.environ.get("OPENBB_API_PORT", "6900") + prefix = SystemService().system_settings.api_settings.prefix + query = urlencode({"browser": browser, "user": user}) + return f"http://{host}:{port}{prefix}/eia/eia_mcp_state?{query}" + + +_mcp_process: Any = None + + +def ensure_mcp_subprocess() -> None: + """Launch the MCP server in its own process (idempotent). + + The streamable-http session manager must own its event loop and lifespan; + mounting it inside the OpenBB API — whose lifespan it cannot extend — + does not survive a real deployment, so it never finishes starting. + Running it as a subprocess gives it a clean uvicorn lifecycle. The + port-in-use guard keeps this safe when the API runs multiple workers. + """ + global _mcp_process # noqa: PLW0603 + import atexit + import os + import subprocess + import sys + + if _mcp_process is not None and _mcp_process.poll() is None: + return + port = mcp_port() + if _port_open(_MCP_HOST, port): + return + try: + env = dict(os.environ) + env["PYTHONPATH"] = os.pathsep.join(p for p in sys.path if p) + _mcp_process = subprocess.Popen( # noqa: S603 + [ + sys.executable, + "-m", + "openbb_us_eia.eia_mcp", + "--host", + _MCP_HOST, + "--port", + str(port), + ], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + env=env, + ) + atexit.register(stop_mcp_subprocess) + except Exception: # noqa: BLE001 + _mcp_process = None + + +def stop_mcp_subprocess() -> None: + """Terminate the MCP subprocess if this process started it.""" + global _mcp_process # noqa: PLW0603 + if _mcp_process is not None and _mcp_process.poll() is None: + _mcp_process.terminate() + _mcp_process = None + + +def _build_mcp_server() -> Any: + """Build the FastMCP server and register the EIA data-browser tool.""" + from fastmcp import FastMCP + + mcp: Any = FastMCP( + name="EIA Data Browsers", + instructions=( + "Tools for reading the exact table currently rendered on screen" + " in one of the EIA data-browser widgets." + ), + ) + + @mcp.tool + async def get_current_browser_data(browser: str) -> list[dict]: + """Return the exact table currently rendered on screen for one EIA data browser. + + Parameters + ---------- + browser : str + One of: electricity, coal, total_energy, steo, aeo, + international, petroleum_imports, natural_gas_query, states, maps. + + Returns + ------- + list[dict] + One record per row, matching exactly what the browser's iframe is + currently displaying. + """ + import json + + import aiohttp + from fastmcp.server.dependencies import get_http_headers + + headers = get_http_headers(include={"x-openbb-user"}) + user = _user_key(headers.get("x-openbb-user", "")) + url = _api_state_url(browser, user) + try: + async with ( + aiohttp.ClientSession( + timeout=aiohttp.ClientTimeout(total=30) + ) as session, + session.get(url) as response, + ): + if response.status != 200: + return [] + rows = json.loads(await response.read()) + except (aiohttp.ClientError, ValueError): + _logger.exception("Failed to read live browser state from the API") + return [] + return rows if isinstance(rows, list) else [] + + @mcp.tool + async def get_feed_articles(feed: str = "today_in_energy") -> list[dict]: + """Return the articles currently listed in one EIA RSS feed. + + Parameters + ---------- + feed : str + One of: today_in_energy, whats_new, press_releases, + congressional_testimony, presentations, gasoline_diesel, + heating_oil_propane. Unknown values fall back to today_in_energy. + + Returns + ------- + list[dict] + One record per article, with ``title``, ``date``, ``author``, + ``url`` and ``excerpt``. Pass a record's ``url`` to + ``get_article_content`` to read the full article. + """ + import aiohttp + + from openbb_us_eia.utils.rss import EIA_RSS_FEEDS, build_feed, fetch_feed + + if feed not in EIA_RSS_FEEDS: + feed = "today_in_energy" + try: + async with aiohttp.ClientSession( + timeout=aiohttp.ClientTimeout(total=30) + ) as session: + parsed = await fetch_feed(session, EIA_RSS_FEEDS[feed]["url"]) + except aiohttp.ClientError: + _logger.exception("Failed to fetch the EIA RSS feed") + return [] + return [ + {key: item[key] for key in ("title", "date", "author", "url", "excerpt")} + for item in build_feed(feed, parsed, 50)["items"] + ] + + @mcp.tool + async def get_article_content(url: str) -> str: + """Return the readable text of one EIA article. + + Parameters + ---------- + url : str + The article's ``url`` from ``get_feed_articles``. Only eia.gov + URLs are fetched. + + Returns + ------- + str + The article's prose, or an empty string if it could not be read. + """ + from urllib.parse import urlsplit + + import aiohttp + + from openbb_us_eia.utils.rss import article_text + + host = (urlsplit(url).hostname or "").lower() + if host != "eia.gov" and not host.endswith(".eia.gov"): + return "Only eia.gov article URLs can be fetched." + try: + async with ( + aiohttp.ClientSession( + timeout=aiohttp.ClientTimeout(total=30) + ) as session, + session.get(url) as response, + ): + if response.status != 200: + return "" + html = await response.text() + except (aiohttp.ClientError, UnicodeDecodeError): + _logger.exception("Failed to fetch the EIA article") + return "" + return article_text(html) + + return mcp + + +def _serve(host: str, port: int) -> None: + """Run the FastMCP streamable-http server — the subprocess entry point.""" + import uvicorn + from starlette.middleware.cors import CORSMiddleware + + mcp = _build_mcp_server() + app = mcp.http_app(path=_MCP_PATH, json_response=True, transport="streamable-http") + app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_methods=["*"], + allow_headers=["*"], + expose_headers=["mcp-session-id", "Mcp-Session-Id"], + ) + _exit_when_orphaned() + uvicorn.run(app, host=host, port=port, log_level="warning") + + +def _exit_when_orphaned() -> None: + """Exit if the parent API process goes away. + + The launcher cannot fire ``atexit`` when uvicorn SIGKILLs its workers on + a reload, which would otherwise leave this server running forever. + Polling the parent pid lets the subprocess clean itself up so reloads + never accumulate abandoned MCP servers. + """ + import os + import threading + import time + + parent = os.getppid() + + def _watch() -> None: + while True: + time.sleep(2) + if os.getppid() != parent: + os._exit(0) + + threading.Thread(target=_watch, daemon=True).start() + + +_FORWARD_REQ_HEADERS = { + "accept", + "content-type", + "mcp-session-id", + "mcp-protocol-version", + "x-openbb-user", +} +_DROP_RESP_HEADERS = { + "content-length", + "transfer-encoding", + "connection", + "content-encoding", +} + + +async def _await_ready(timeout: float = 10.0) -> bool: + """Poll until the MCP subprocess is accepting connections.""" + import asyncio + + for _ in range(max(1, int(timeout / 0.2))): + if _port_open(_MCP_HOST, mcp_port()): + return True + await asyncio.sleep(0.2) + return False + + +async def _extract_mcp_request(request: Request) -> dict: + """Pull plain values out of the request. + + The OpenBB router wraps endpoints as commands and deep-copies their + kwargs; a starlette ``Request`` cannot be deep-copied (it recurses), so + the proxy takes this plain dict via a dependency instead of the + ``Request`` itself. + """ + return { + "method": request.method, + "body": await request.body(), + "headers": { + k: v + for k, v in request.headers.items() + if k.lower() in _FORWARD_REQ_HEADERS + }, + "query": dict(request.query_params), + } + + +async def mcp_reverse_proxy( + data: Annotated[dict, Depends(_extract_mcp_request)], +) -> Any: + """Proxy an MCP request to the local subprocess, streaming the response. + + Lets the Workspace connect at the OpenBB API's own host/port — the + subprocess is an internal detail — while the subprocess still owns the + streamable-http lifecycle that an in-process mount could not start. + + The request arrives as a plain dict from ``_extract_mcp_request``: taking + the ``Request`` directly would put it in the command wrapper's kwargs, + which ``CommandRunner`` deep-copies, and deep-copying a ``Request`` + recurses until it raises ``RecursionError``. + """ + import asyncio + + import aiohttp + from starlette.responses import JSONResponse, StreamingResponse + + ensure_mcp_subprocess() + if not await _await_ready(): + return JSONResponse({"error": "MCP server failed to start"}, status_code=503) + + session = aiohttp.ClientSession( + timeout=aiohttp.ClientTimeout(total=None, sock_connect=10, sock_read=None) + ) + try: + upstream = await session.request( + data["method"], + mcp_server_url(), + headers=data["headers"], + data=data["body"] or None, + params=data["query"], + ) + except aiohttp.ClientError: + _logger.exception("MCP proxy request failed") + await session.close() + return JSONResponse({"error": "MCP proxy error."}, status_code=502) + + out_headers = { + k: v for k, v in upstream.headers.items() if k.lower() not in _DROP_RESP_HEADERS + } + out_headers["access-control-expose-headers"] = "mcp-session-id, Mcp-Session-Id" + + async def _stream() -> Any: + try: + async for chunk in upstream.content.iter_any(): + yield chunk + except (asyncio.CancelledError, asyncio.TimeoutError, aiohttp.ClientError): + return + finally: + upstream.release() + await session.close() + + return StreamingResponse( + _stream(), status_code=upstream.status, headers=out_headers + ) + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument("--host", default=_MCP_HOST) + parser.add_argument("--port", type=int, default=mcp_port()) + args = parser.parse_args() + _serve(args.host, args.port) diff --git a/openbb_platform/providers/eia/openbb_us_eia/eia_router.py b/openbb_platform/providers/eia/openbb_us_eia/eia_router.py new file mode 100644 index 00000000000..151b5ca2801 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/eia_router.py @@ -0,0 +1,580 @@ +"""EIA provider router.""" + +from collections import Counter +from typing import Literal + +from openbb_core.app.model.abstract.error import OpenBBError +from openbb_core.app.model.command_context import CommandContext +from openbb_core.app.model.example import APIEx +from openbb_core.app.model.obbject import OBBject +from openbb_core.app.provider_interface import ( + ExtraParams, + ProviderChoices, + StandardParams, +) +from openbb_core.app.query import Query as OBBQuery +from openbb_core.app.router import Router + +from openbb_us_eia import COMMODITY_INSTALLED +from openbb_us_eia.browsers import router as _browsers_router +from openbb_us_eia.eia_mcp import mcp_reverse_proxy +from openbb_us_eia.rss import router as _rss_router +from openbb_us_eia.utils import catalog +from openbb_us_eia.utils.catalog import dataset_summary, model_name + +router = Router( + prefix="", + description="US Energy Information Administration (EIA) provider router.", +) +router.include_router(_rss_router) +router.include_router(_browsers_router) +router._api_router.add_api_route( + path="/eia_mcp", + endpoint=mcp_reverse_proxy, + methods=["GET", "POST", "DELETE"], + include_in_schema=False, +) + + +async def get_eia_apps_json() -> list[dict]: + """Serve the EIA app definition for OpenBB Workspace.""" + import json + from pathlib import Path + + apps_file = Path(__file__).parent / "assets" / "apps.json" + try: + with apps_file.open("r", encoding="utf-8") as file: + return json.load(file) + except Exception: # noqa: BLE001 + return [] + + +router._api_router.add_api_route( + path="/apps.json", + endpoint=get_eia_apps_json, + methods=["GET"], + include_in_schema=False, +) + +EiaGroup = Literal[ + "aeo", + "coal", + "crude_oil_imports", + "densified_biomass", + "electricity", + "electricity_grid", + "ieo", + "international", + "natural_gas", + "nuclear_outages", + "petroleum", + "seds", + "state_electricity_profiles", + "total_energy", +] + +WIDGET_CATEGORY = "EIA" +WIDGET_SOURCE = "EIA" + +GROUP_TITLES: dict[str, str] = { + "aeo": "Annual Energy Outlook", + "coal": "Coal", + "crude_oil_imports": "Petroleum", + "densified_biomass": "Densified Biomass", + "electricity": "Electricity", + "electricity_grid": "Electric Grid Monitor", + "ieo": "International Energy Outlook", + "international": "International", + "natural_gas": "Natural Gas", + "nuclear_outages": "Nuclear Outages", + "petroleum": "Petroleum", + "seds": "State Energy Data System", + "state_electricity_profiles": "State Electricity Profiles", + "total_energy": "Total Energy", +} + + +def _widget_config(name: str, sub_category: str) -> dict[str, str | list[str]]: + """Build proper-cased Workspace widget metadata.""" + return { + "name": name, + "category": WIDGET_CATEGORY, + "subCategory": sub_category, + "source": [WIDGET_SOURCE], + } + + +@router.command( + methods=["GET"], + widget_config=_widget_config("EIA Dataset Catalog", "Reference"), + examples=[ + APIEx( + description="List every EIA dataset served by this extension.", + parameters={}, + ), + APIEx( + description="List the coal datasets with their filters and data columns.", + parameters={"group": "coal"}, + ), + ], +) +async def datasets(group: EiaGroup | None = None) -> OBBject: + """Catalog of EIA APIv2 datasets served by this extension.""" + rows: list[dict] = [] + for group_name, group_spec in catalog.load_catalog().items(): + if group is not None and group_name != group: + continue + for slug, spec in group_spec["datasets"].items(): + rows.append( + { + "group": group_name, + "dataset": slug, + "name": spec["name"], + "category": spec["category"], + "route": spec["path"], + "frequencies": ",".join(spec["frequencies"]), + "default_frequency": spec["default_frequency"], + "data_columns": ",".join(spec["data_columns"]), + "filters": ",".join( + facet + for facet, detail in spec["facets"].items() + if detail.get("filterable", True) + ), + "start_period": spec["start_period"], + "end_period": spec["end_period"], + "description": spec["description"] or None, + } + ) + return OBBject(results=rows) + + +@router.command( + methods=["GET"], + widget_config=_widget_config("EIA Filter Values", "Reference"), + examples=[ + APIEx( + description="List the spot price series available from the petroleum group.", + parameters={ + "group": "petroleum", + "dataset": "spot_prices", + "facet": "series", + }, + ), + APIEx( + description="List the balancing authorities of the hourly grid monitor.", + parameters={ + "group": "electricity_grid", + "dataset": "demand", + "facet": "respondent", + }, + ), + ], +) +async def facet_options( + group: EiaGroup, + facet: str, + dataset: str | None = None, +) -> OBBject: + """List the valid values for one filter (facet) of an EIA dataset.""" + from openbb_core.app.service.user_service import UserService + from openbb_core.provider.utils.helpers import amake_request + + from openbb_us_eia.utils.helpers import API_BASE, response_callback + + dataset = dataset or catalog.dataset_choices(group)[0] + spec = catalog.get_dataset(group, dataset) + facets = spec["facets"] + if facet not in facets: + raise OpenBBError( + ValueError( + f"'{facet}' is not a filter of dataset '{dataset}'." + f" Choices: {', '.join(facets)}" + ) + ) + embedded = facets[facet].get("choices") + if embedded: + grouped: dict[str, dict] = {} + for choice in embedded: + slug = choice.get("param") or choice["value"] + record = grouped.setdefault( + slug, {"value": slug, "label": choice["label"], "code": []} + ) + record["code"].append(choice["value"]) + results = [ + {**record, "code": ",".join(record["code"])} for record in grouped.values() + ] + return OBBject(results=sorted(results, key=lambda item: item["label"])) + credentials = UserService().default_user_settings.credentials.model_dump( + mode="json" + ) + api_key = credentials.get("eia_api_key") or "" + facet_id = facets[facet]["id"] + response = await amake_request( + f"{API_BASE}/{spec['path']}/facet/{facet_id}?api_key={api_key}", + response_callback=response_callback, + ) + values = response.get("response", {}).get("facets", []) # ty: ignore[unresolved-attribute] + results = [ + { + "value": str(item.get("id")), + "label": str(item.get("name") or item.get("id")), + "code": str(item.get("id")), + } + for item in values + ] + return OBBject(results=sorted(results, key=lambda item: item["label"])) + + +def _group_operation_id(func, group: str, dataset: str) -> str: + """Build a group-qualified OpenAPI operation id for a dataset command.""" + parts = [ + part.replace("_router", "").replace("openbb_", "") + for part in func.__module__.split(".") + ] + return "_".join(dict.fromkeys([*parts, group, dataset])) + + +def _register_dataset_command(target: Router, group: str, dataset: str) -> None: + """Register one dataset as a model command on a sub-router.""" + spec = catalog.get_dataset(group, dataset) + + async def _route( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, + ) -> OBBject: + return await OBBject.from_query(OBBQuery(**locals())) + + _route.__name__ = dataset + _route.__qualname__ = dataset + _route.__doc__ = dataset_summary(spec) + command_kwargs: dict = { + "model": model_name(group, dataset), + "examples": [APIEx(parameters={"provider": "eia", "limit": 100})], + "widget_config": _widget_config( + spec["name"], + spec.get("category") or GROUP_TITLES.get(group, group), + ), + } + if dataset in _MULTI_GROUP_DATASETS: + command_kwargs["operation_id"] = _group_operation_id(_route, group, dataset) + target.command(**command_kwargs)(_route) + + +def _build_group_router(group: str, description: str, categorized: bool) -> Router: + """Build one sub-router with a command per dataset of a catalog group. + + Parameters + ---------- + group : str + Catalog group name. + description : str + The sub-router (menu) description. + categorized : bool + Nest datasets under their EIA category as sub-sub-routers. + + Returns + ------- + Router + The assembled sub-router. + """ + group_router = Router(prefix="", description=description) + categories: dict[str, Router] = {} + for dataset, spec in catalog.get_group(group)["datasets"].items(): + target = group_router + if categorized and spec.get("category_slug"): + slug = spec["category_slug"] + if slug not in categories: + categories[slug] = Router( + prefix="", + description=f"{spec['category']} datasets.", + ) + target = categories[slug] + _register_dataset_command(target, group, dataset) + for slug, category_router in sorted(categories.items()): + group_router.include_router(category_router, prefix=f"/{slug}") + return group_router + + +_DATASET_GROUP_COUNTS = Counter( + slug + for group_spec in catalog.load_catalog().values() + for slug in group_spec["datasets"] +) +_MULTI_GROUP_DATASETS = frozenset( + slug for slug, count in _DATASET_GROUP_COUNTS.items() if count > 1 +) + + +_coal_router = _build_group_router( + "coal", + "US coal production, consumption, quality, reserves, shipments, prices, and trade.", + categorized=False, +) +_petroleum_router = _build_group_router( + "petroleum", + "US petroleum supply, disposition, prices, refining, movements, and stocks.", + categorized=True, +) +_natural_gas_router = _build_group_router( + "natural_gas", + "US natural gas production, consumption, storage, trade, reserves, and prices.", + categorized=True, +) +_electricity_router = _build_group_router( + "electricity", + "US electric power operations, generator inventory, plant fuel data, and retail sales.", + categorized=False, +) +_electricity_grid_router = _build_group_router( + "electricity_grid", + "Hourly and daily electric grid monitor: demand, generation by fuel, and interchange.", + categorized=False, +) +_state_profiles_router = _build_group_router( + "state_electricity_profiles", + "Annual state electricity profiles: rankings, capability, emissions, and net metering.", + categorized=False, +) +_biomass_router = _build_group_router( + "densified_biomass", + "Densified biomass (wood pellet) capacity, production, feedstocks, sales, and inventories.", + categorized=False, +) +_nuclear_router = _build_group_router( + "nuclear_outages", + "Daily US nuclear generator capacity and outages, nationally and by facility.", + categorized=False, +) + +router.include_router(_coal_router, prefix="/coal") +router.include_router(_petroleum_router, prefix="/petroleum") +router.include_router(_natural_gas_router, prefix="/natural_gas") +router.include_router(_electricity_router, prefix="/electricity") +router.include_router(_electricity_grid_router, prefix="/electricity_grid") +router.include_router(_state_profiles_router, prefix="/state_electricity_profiles") +router.include_router(_biomass_router, prefix="/densified_biomass") +router.include_router(_nuclear_router, prefix="/nuclear_outages") + + +@router.command( + model="EiaCrudeOilImports", + widget_config=_widget_config("Crude Oil Imports", "Petroleum"), + examples=[ + APIEx( + description="Monthly crude oil imports from Canada, by grade.", + parameters={"provider": "eia", "origin": "canada", "limit": 100}, + ), + ], +) +async def crude_oil_imports( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject: + """US crude oil imports by origin, destination, and grade.""" + return await OBBject.from_query(OBBQuery(**locals())) + + +@router.command( + model="EiaInternational", + widget_config=_widget_config("International Energy Data", "International"), + examples=[ + APIEx( + description="Annual petroleum production for OPEC members.", + parameters={ + "provider": "eia", + "product": "total_petroleum_and_other_liquids", + "activity": "production", + "country": "opec", + "limit": 100, + }, + ), + ], +) +async def international( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject: + """International energy production, consumption, and trade statistics by country and region.""" + return await OBBject.from_query(OBBQuery(**locals())) + + +@router.command( + model="EiaSeds", + widget_config=_widget_config( + "State Energy Data System (SEDS)", "State Energy Data System" + ), + examples=[ + APIEx( + description="Total energy consumption per capita for Texas.", + parameters={ + "provider": "eia", + "series": "total_energy_consumption_per_capita", + "state": "texas", + }, + ), + ], +) +async def seds( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject: + """State Energy Data System (SEDS): annual state-level energy estimates back to 1960.""" + return await OBBject.from_query(OBBQuery(**locals())) + + +@router.command( + model="EiaTotalEnergy", + widget_config=_widget_config( + "Total Energy (Monthly Energy Review)", "Total Energy" + ), + examples=[ + APIEx( + description="Monthly total US electricity net generation.", + parameters={"provider": "eia", "msn": "ELETPUS"}, + ), + ], +) +async def total_energy( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject: + """Monthly Energy Review series covering all energy sources, by MSN mnemonic.""" + return await OBBject.from_query(OBBQuery(**locals())) + + +@router.command( + model="EiaAeo", + widget_config=_widget_config("Annual Energy Outlook", "Annual Energy Outlook"), + examples=[ + APIEx( + description="Reference-case projections from the 2025 Annual Energy Outlook.", + parameters={ + "provider": "eia", + "release": "2025", + "scenario": "reference_case", + "table": "total_energy_supply_disposition_and_price_summary", + "region": "united_states", + }, + ), + ], +) +async def aeo( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject: + """Annual Energy Outlook: long-term US energy projections by release and scenario.""" + return await OBBject.from_query(OBBQuery(**locals())) + + +@router.command( + model="EiaIeo", + widget_config=_widget_config( + "International Energy Outlook", "International Energy Outlook" + ), + examples=[ + APIEx( + description="Reference-case projections from the 2023 International Energy Outlook.", + parameters={ + "provider": "eia", + "release": "2023", + "table": "3", + "limit": 500, + }, + ), + ], +) +async def ieo( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject: + """International Energy Outlook: long-term world energy projections by release and scenario.""" + return await OBBject.from_query(OBBQuery(**locals())) + + +@router.command( + model="EiaDataBrowser", + widget_config=_widget_config("EIA API Data Browser", "Reference"), + examples=[ + APIEx( + description="Query any APIv2 route directly - Brent spot price, monthly.", + parameters={ + "provider": "eia", + "route": "petroleum/pri/spt", + "frequency": "monthly", + "facets": "product:EPCBRENT", + "limit": 12, + }, + ), + ], +) +async def data_browser( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject: + """Query any EIA APIv2 data route directly by path, with facet filters and pagination.""" + return await OBBject.from_query(OBBQuery(**locals())) + + +if not COMMODITY_INSTALLED: + + @router.command( + model="PetroleumStatusReport", + widget_config=_widget_config("Weekly Petroleum Status Report", "Petroleum"), + examples=[ + APIEx(parameters={"provider": "eia"}), + APIEx( + description="Get the weekly estimates of the imports and exports of crude oil.", + parameters={ + "provider": "eia", + "category": "weekly_estimates", + "table": "imports", + }, + ), + ], + ) + async def petroleum_status_report( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, + ) -> OBBject: + """EIA Weekly Petroleum Status Report.""" + return await OBBject.from_query(OBBQuery(**locals())) + + @router.command( + model="ShortTermEnergyOutlook", + widget_config=_widget_config( + "Short-Term Energy Outlook", "Short-Term Energy Outlook" + ), + examples=[ + APIEx(parameters={"provider": "eia"}), + APIEx( + description="Get the US Energy Markets Summary table.", + parameters={"provider": "eia", "table": "01"}, + ), + ], + ) + async def short_term_energy_outlook( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, + ) -> OBBject: + """Monthly short term (18 month) projections using EIA's STEO model.""" + return await OBBject.from_query(OBBQuery(**locals())) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/aeo.py b/openbb_platform/providers/eia/openbb_us_eia/models/aeo.py new file mode 100644 index 00000000000..d93aa7e4460 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/aeo.py @@ -0,0 +1,290 @@ +"""Annual Energy Outlook model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaAeoQueryParams(EiaApiQueryParams): + """Annual Energy Outlook. Long-term energy projections by release year and scenario. Select the report vintage with the `release` parameter. + + Source: https://www.eia.gov/opendata/browser/aeo + """ + + __group__ = "aeo" + __json_schema_extra__ = { + "history": { + "multiple_items_allowed": True, + "choices": ["historic", "projection"], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "east_north_central", + "east_south_central", + "florida_reliability_coordinating_council", + "midcontinent_central", + "midcontinent_east", + "midcontinent_south", + "midcontinent_west", + "middle_atlantic", + "midwest_reliability_council_east", + "midwest_reliability_council_west", + "mountain", + "new_england", + "no_regional_tables", + "northeast_power_coordinating_council_long_island", + "northeast_power_coordinating_council_nyc_westchester", + "northeast_power_coordinating_council_new_england", + "northeast_power_coordinating_council_new_york_city_and_long", + "northeast_power_coordinating_council_northeast", + "northeast_power_coordinating_council_upstate_new_york", + "pjm_commonwealth_edison", + "pjm_dominion", + "pjm_east", + "pjm_west", + "pacific", + "reliability_first_corporation_east", + "reliability_first_corporation_michigan", + "reliability_first_corporation_west", + "serc_reliability_corporation_central", + "serc_reliability_corporation_delta", + "serc_reliability_corporation_east", + "serc_reliability_corporation_gateway", + "serc_reliability_corporation_southeastern", + "serc_reliability_corporation_virginia_carolina", + "south_atlantic", + "southwest_power_pool_central", + "southwest_power_pool_north", + "southwest_power_pool_south", + "texas_regional_entity", + "texas_reliability_entity", + "united_states", + "west_north_central", + "west_south_central", + "western_electricity_coordinating_council_basin", + "western_electricity_coordinating_council_california", + "western_electricity_coordinating_council_california_north", + "western_electricity_coordinating_council_california_south", + "western_electricity_coordinating_council_northwest_power", + "western_electricity_coordinating_council_rockies", + "western_electricity_coordinating_council_southwest", + ], + }, + "scenario": {"multiple_items_allowed": True}, + "series": {"multiple_items_allowed": True}, + "table": { + "multiple_items_allowed": True, + "choices": [ + "air_travel_energy_use", + "aircraft_stock", + "aluminum_industry_energy_consumption", + "bulk_chemical_industry_energy_consumption", + "cement_and_lime_industry_energy_consumption", + "coal_minemouth_prices_by_region_and_type", + "coal_production_and_minemouth_prices_by_region", + "coal_production_by_region_and_type", + "coal_supply_disposition_and_prices", + "commercial_sector_energy_consumption_floorspace_and", + "commercial_sector_key_indicators_and_consumption", + "components_of_selected_petroleum_product_prices", + "conversion_factors", + "electric_power_projections_by_electricity_market_module", + "electricity_generating_capacity", + "electricity_generation_capacity_by_electricity_market", + "electricity_generation_by_electricity_market_module_region", + "electricity_supply_disposition_prices_and_emissions", + "electricity_trade", + "employment_and_shipments_by_industry_and_income_and", + "energy_consumption_by_sector_and_source", + "energy_prices_by_sector_and_source", + "energy_related_carbon_dioxide_emissions_by_end_use", + "energy_related_carbon_dioxide_emissions_by_sector_and_source", + "food_industry_energy_consumption", + "freight_transportation_energy_use", + "glass_industry_energy_consumption", + "imported_liquids_by_source", + "industrial_sector_key_indicators_and_consumption", + "industrial_sector_macroeconomic_indicators", + "international_petroleum_and_other_liquids_supply", + "iron_and_steel_industry_energy_consumption", + "light_duty_vehicle_energy_consumption_by_technology_type", + "light_duty_vehicle_miles_traveled_by_technology_type", + "light_duty_vehicle_miles_per_gallon_by_technology_type", + "light_duty_vehicle_sales_by_technology_type", + "light_duty_vehicle_stock_by_technology_type", + "lower_48_crude_oil_production_and_wellhead_prices_by_supply", + "lower_48_natural_gas_production_and_supply_prices_by_supply", + "macroeconomic_indicators", + "metal_based_durables_industry_energy_consumption", + "natural_gas_consumption_by_end_use_sector_and_census", + "natural_gas_delivered_prices_by_end_use_sector_and_census", + "natural_gas_imports_and_exports", + "natural_gas_supply_disposition_and_prices", + "new_light_duty_vehicle_fuel_economy", + "new_light_duty_vehicle_prices", + "new_light_duty_vehicle_range", + "nonmanufacturing_sector_energy_consumption", + "oil_and_gas_end_of_year_reserves_and_annual_reserve", + "oil_and_gas_supply", + "other_manufacturing_industry_energy_consumption", + "paper_industry_energy_consumption", + "petroleum_and_other_liquids_prices", + "petroleum_and_other_liquids_supply_and_disposition", + "primary_natural_gas_flows_entering_ngtdm_region_from", + "refining_industry_energy_consumption", + "renewable_energy_consumption_by_sector_and_source", + "renewable_energy_generating_capacity_and_generation", + "renewable_energy_generation_by_fuel", + "residential_sector_equipment_stock_and_efficiency", + "residential_sector_key_indicators_and_consumption", + "summary_of_new_light_duty_vehicle_size_class_attributes", + "hydrogen_supply_disposition_and_prices", + "overnight_capital_costs_for_new_electricity_generating", + "shale_gas_and_tight_oil_production_by_play_1", + "carbon_dioxide_emissions_by_category_and_sector", + "capacity_with_carbon_capture_and_carbon_flows", + "technology_market_penetration_in_light_duty_vehicles", + "total_energy_supply_disposition_and_price_summary", + "transportation_fleet_car_and_truck_fuel_consumption_by_type", + "transportation_fleet_car_and_truck_sales_by_type_and", + "transportation_fleet_car_and_truck_stock_by_type_and", + "transportation_fleet_car_and_truck_vehicle_miles_traveled", + "transportation_sector_energy_use_by_fuel_type_within_a_mode", + "transportation_sector_energy_use_by_mode_and_type", + "transportation_sector_key_indicators_and_delivered_energy", + "world_metallurgical_coal_flows_by_importing_regions_and", + "world_steam_coal_flows_by_importing_regions_and_exporting", + "world_total_coal_flows_by_importing_regions_and_exporting", + ], + }, + } + + release: Literal[ + "2014", + "2014-er", + "2015", + "2016", + "2017", + "2018", + "2019", + "2020", + "2021", + "2022", + "2023", + "2025", + "2026", + ] = Field( + default="2026", + description="The Annual Energy Outlook release." + " Facet values vary by release; use the `facet_options` endpoint to list them.", + ) + history: Literal["historic", "projection"] | None = Field( + default=None, + description="History filter.", + ) + region: str | None = Field( + default=None, + description="Region filter. Accepts a comma-separated list of values.", + ) + scenario: str | None = Field( + default=None, + description="Scenario filter. Accepts a comma-separated list of values. There are 149 valid values - use the `facet_options` endpoint to list them.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + table: str | None = Field( + default=None, + description="Table filter. Accepts a comma-separated list of values.", + ) + + +class EiaAeoData(EiaApiData): + """Annual Energy Outlook. Long-term energy projections by release year and scenario. Select the report vintage with the `release` parameter.""" + + history: str | None = Field( + default=None, + description="History code.", + ) + history_name: str | None = Field( + default=None, + description="History name.", + ) + region: str | None = Field( + default=None, + description="Region code.", + ) + region_name: str | None = Field( + default=None, + description="Region name.", + ) + scenario: str | None = Field( + default=None, + description="Scenario code.", + ) + scenario_name: str | None = Field( + default=None, + description="Scenario name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + table: str | None = Field( + default=None, + description="Table code.", + ) + table_name: str | None = Field( + default=None, + description="Table name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + unit: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaAeoFetcher(Fetcher[EiaAeoQueryParams, list[EiaAeoData]]): + """Annual Energy Outlook fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaAeoQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaAeoQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaAeoQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaAeoQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaAeoData]: + """Transform the data.""" + return transform_dataset_data(EiaAeoData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/coal/__init__.py b/openbb_platform/providers/eia/openbb_us_eia/models/coal/__init__.py new file mode 100644 index 00000000000..5be31ab46c5 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/coal/__init__.py @@ -0,0 +1 @@ +"""EIA Coal models.""" diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/coal/aggregate_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/coal/aggregate_production.py new file mode 100644 index 00000000000..b69ffdfc56d --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/coal/aggregate_production.py @@ -0,0 +1,205 @@ +"""Aggregate Production model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaCoalAggregateProductionQueryParams(EiaApiQueryParams): + """Aggregate Production. Coal state aggregated data by mine type, includes production, productivity, labor hours, employees, and coal rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/ + + Source: https://www.eia.gov/opendata/browser/coal/aggregate-production + """ + + __group__ = "coal" + __dataset__ = "aggregate_production" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "average_employees", + "labor_hours", + "number_of_mines", + "production", + "productivity", + ], + }, + "coal_rank": { + "multiple_items_allowed": True, + "choices": ["all", "anthracite", "bituminous", "lignite", "subbituminous"], + }, + "mine_type": { + "multiple_items_allowed": True, + "choices": ["all", "refuse", "surface", "underground"], + }, + "state_region": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "appalachia_central", + "appalachia_northern", + "appalachia_southern", + "appalachia_total", + "arizona", + "arkansas", + "colorado", + "east_north_central", + "east_south_central", + "east_total", + "east_of_mississippi_river", + "illinois", + "illinois_basin", + "indiana", + "interior_region_total", + "kansas", + "kentucky", + "kentucky_east", + "kentucky_west", + "louisiana", + "maryland", + "middle_atlantic", + "midwest_total", + "mississippi", + "missouri", + "montana", + "mountain", + "new_mexico", + "north_dakota", + "ohio", + "oklahoma", + "other_interior", + "other_western", + "pacific_contiguous", + "pacific_noncontiguous", + "pennsylvania", + "pennsylvania_anthracite", + "pennsylvania_bituminous", + "powder_river_basin", + "south_atlantic", + "south_total", + "tennessee", + "texas", + "us_total", + "uinta_basin", + "utah", + "virginia", + "washington", + "west_north_central", + "west_south_central", + "west_total", + "west_virginia", + "west_virginia_northern", + "west_virginia_southern", + "west_of_mississippi_river", + "western_region_total", + "wyoming", + ], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: average_employees (number of employees); labor_hours (hours); number_of_mines (number of mines); production (short tons); productivity (short tons per labor hour).", + ) + coal_rank: str | None = Field( + default=None, + description="Coal Rank filter. Accepts a comma-separated list of values.", + ) + mine_type: Literal["all", "refuse", "surface", "underground"] | None = Field( + default=None, + description="Mine Type filter.", + ) + state_region: str | None = Field( + default=None, + description="State\\Region filter. Accepts a comma-separated list of values.", + ) + + +class EiaCoalAggregateProductionData(EiaApiData): + """Aggregate Production. Coal state aggregated data by mine type, includes production, productivity, labor hours, employees, and coal rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/""" + + coal_rank: str | None = Field( + default=None, + description="Coal Rank code.", + ) + coal_rank_name: str | None = Field( + default=None, + description="Coal Rank name.", + ) + mine_type: str | None = Field( + default=None, + description="Mine Type code.", + ) + mine_type_name: str | None = Field( + default=None, + description="Mine Type name.", + ) + state_region: str | None = Field( + default=None, + description="State\\Region code.", + ) + state_region_name: str | None = Field( + default=None, + description="State\\Region name.", + ) + average_employees: float | None = Field( + default=None, + description="Average employees (number of employees). Withheld or unavailable values return as null.", + ) + labor_hours: float | None = Field( + default=None, + description="Labor hours (hours). Withheld or unavailable values return as null.", + ) + number_of_mines: float | None = Field( + default=None, + description="Number of mines (number of mines). Withheld or unavailable values return as null.", + ) + production: float | None = Field( + default=None, + description="Production (short tons). Withheld or unavailable values return as null.", + ) + productivity: float | None = Field( + default=None, + description="Productivity (short tons per labor hour). Withheld or unavailable values return as null.", + ) + + +class EiaCoalAggregateProductionFetcher( + Fetcher[EiaCoalAggregateProductionQueryParams, list[EiaCoalAggregateProductionData]] +): + """Aggregate Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaCoalAggregateProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaCoalAggregateProductionQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaCoalAggregateProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaCoalAggregateProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaCoalAggregateProductionData]: + """Transform the data.""" + return transform_dataset_data(EiaCoalAggregateProductionData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/coal/by_mine_by_plant.py b/openbb_platform/providers/eia/openbb_us_eia/models/coal/by_mine_by_plant.py new file mode 100644 index 00000000000..ebf09242e28 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/coal/by_mine_by_plant.py @@ -0,0 +1,271 @@ +"""By Mine, By Plant model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaCoalByMineByPlantQueryParams(EiaApiQueryParams): + """By Mine, By Plant. Coal shipments from mine- to plant-level data, including price, quantity, quality, and rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/ + + Source: https://www.eia.gov/opendata/browser/coal/shipments/by-mine-by-plant + """ + + __group__ = "coal" + __dataset__ = "by_mine_by_plant" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "ash_content", + "heat_content", + "price", + "quantity", + "sulfur_content", + ], + }, + "coal_rank": { + "multiple_items_allowed": True, + "choices": [ + "all", + "anthracite", + "bituminous", + "lignite", + "subbituminous", + "synfuel_coal", + "waste_coal", + ], + }, + "coal_supplier": {"multiple_items_allowed": True}, + "mine": {"multiple_items_allowed": True}, + "mine_state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "colorado", + "illinois", + "indiana", + "kansas", + "kentucky_east", + "kentucky_west", + "louisiana", + "maryland", + "mississippi", + "missouri", + "montana", + "new_mexico", + "north_dakota", + "ohio", + "oklahoma", + "pennsylvania_anthracite", + "pennsylvania_bituminous", + "tennessee", + "texas", + "utah", + "virginia", + "west_virginia_northern", + "west_virginia_southern", + "wyoming", + ], + }, + "plant": {"multiple_items_allowed": True}, + "plant_state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "florida", + "georgia", + "hawaii", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "minnesota", + "mississippi", + "missouri", + "montana", + "nebraska", + "nevada", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pennsylvania", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "utah", + "virginia", + "washington", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + } + + frequency: Literal["annual", "quarterly"] | None = Field( + default=None, + description="The data frequency. The default is 'annual'.", + ) + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: ash_content (percent by weight); heat_content (Btu per pound); price (average dollars per ton); quantity (tons); sulfur_content (percent by weight).", + ) + coal_rank: str | None = Field( + default=None, + description="Coal Type filter. Accepts a comma-separated list of values.", + ) + coal_supplier: str | None = Field( + default=None, + description="Coal Supplier filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + mine: str | None = Field( + default=None, + description="Mine filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + mine_state: str | None = Field( + default=None, + description="Mine State\\Region filter. Accepts a comma-separated list of values.", + ) + plant: str | None = Field( + default=None, + description="Plant filter. Accepts a comma-separated list of values. There are 475 valid values - use the `facet_options` endpoint to list them.", + ) + plant_state: str | None = Field( + default=None, + description="Plant State\\Region filter. Accepts a comma-separated list of values.", + ) + + +class EiaCoalByMineByPlantData(EiaApiData): + """By Mine, By Plant. Coal shipments from mine- to plant-level data, including price, quantity, quality, and rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/""" + + coal_rank: str | None = Field( + default=None, + description="Coal Type code.", + ) + coal_rank_name: str | None = Field( + default=None, + description="Coal Type name.", + ) + coal_supplier: str | None = Field( + default=None, + description="Coal Supplier code.", + ) + coal_supplier_name: str | None = Field( + default=None, + description="Coal Supplier name.", + ) + mine: str | None = Field( + default=None, + description="Mine code.", + ) + mine_name: str | None = Field( + default=None, + description="Mine name.", + ) + mine_state: str | None = Field( + default=None, + description="Mine State\\Region code.", + ) + mine_state_name: str | None = Field( + default=None, + description="Mine State\\Region name.", + ) + plant: str | None = Field( + default=None, + description="Plant code.", + ) + plant_name: str | None = Field( + default=None, + description="Plant name.", + ) + plant_state: str | None = Field( + default=None, + description="Plant State\\Region code.", + ) + plant_state_name: str | None = Field( + default=None, + description="Plant State\\Region name.", + ) + ash_content: float | None = Field( + default=None, + description="Ash content (percent by weight). Withheld or unavailable values return as null.", + ) + heat_content: float | None = Field( + default=None, + description="Heat content (Btu per pound). Withheld or unavailable values return as null.", + ) + price: float | None = Field( + default=None, + description="Price (average dollars per ton). Withheld or unavailable values return as null.", + ) + quantity: float | None = Field( + default=None, + description="Quantity (tons). Withheld or unavailable values return as null.", + ) + sulfur_content: float | None = Field( + default=None, + description="Sulfur content (percent by weight). Withheld or unavailable values return as null.", + ) + + +class EiaCoalByMineByPlantFetcher( + Fetcher[EiaCoalByMineByPlantQueryParams, list[EiaCoalByMineByPlantData]] +): + """By Mine, By Plant fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaCoalByMineByPlantQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaCoalByMineByPlantQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaCoalByMineByPlantQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaCoalByMineByPlantQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaCoalByMineByPlantData]: + """Transform the data.""" + return transform_dataset_data(EiaCoalByMineByPlantData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/coal/consumption_and_quality.py b/openbb_platform/providers/eia/openbb_us_eia/models/coal/consumption_and_quality.py new file mode 100644 index 00000000000..b7ef8d4d596 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/coal/consumption_and_quality.py @@ -0,0 +1,219 @@ +"""Consumption and Quality model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaCoalConsumptionAndQualityQueryParams(EiaApiQueryParams): + """Consumption and Quality. Coal consumption and quality data by state and sector, including price, reciepts, heat content, sulfur content, ash content, and stocks. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/ + + Source: https://www.eia.gov/opendata/browser/coal/consumption-and-quality + """ + + __group__ = "coal" + __dataset__ = "consumption_and_quality" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "ash_content", + "consumption", + "heat_content", + "price", + "receipts", + "stocks", + "sulfur_content", + ], + }, + "sector": { + "multiple_items_allowed": True, + "choices": [ + "coke_plants", + "commercial_and_institutional", + "electric_power", + "electric_utility", + "ipp_chp", + "ipp_non_chp", + "independent_power_producers", + "other_industrial", + ], + }, + "state_region": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "district_of_columbia", + "east_north_central", + "east_south_central", + "florida", + "georgia", + "hawaii", + "idaho", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "middle_atlantic", + "minnesota", + "mississippi", + "missouri", + "montana", + "mountain", + "nebraska", + "nevada", + "new_england", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pacific", + "pacific_contiguous", + "pacific_noncontiguous", + "pennsylvania", + "puerto_rico", + "rhode_island", + "south_atlantic", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "us_total", + "utah", + "vermont", + "virginia", + "washington", + "west_north_central", + "west_south_central", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + } + + frequency: Literal["annual", "quarterly"] | None = Field( + default=None, + description="The data frequency. The default is 'annual'.", + ) + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: ash_content (average ash percent by weight); consumption (short tons); heat_content (average sulfur percent by weight); price (dollars per short ton); receipts (short tons); stocks (short tons); sulfur_content (average sulfur percent by weight).", + ) + sector: str | None = Field( + default=None, + description="Sector filter. Accepts a comma-separated list of values.", + ) + state_region: str | None = Field( + default=None, + description="U.S. Total, States, and Census Regions. filter. Accepts a comma-separated list of values.", + ) + + +class EiaCoalConsumptionAndQualityData(EiaApiData): + """Consumption and Quality. Coal consumption and quality data by state and sector, including price, reciepts, heat content, sulfur content, ash content, and stocks. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/""" + + sector: str | None = Field( + default=None, + description="Sector code.", + ) + sector_name: str | None = Field( + default=None, + description="Sector name.", + ) + state_region: str | None = Field( + default=None, + description="U.S. Total, States, and Census Regions. code.", + ) + state_region_name: str | None = Field( + default=None, + description="U.S. Total, States, and Census Regions. name.", + ) + ash_content: float | None = Field( + default=None, + description="Ash content (average ash percent by weight). Withheld or unavailable values return as null.", + ) + consumption: float | None = Field( + default=None, + description="Consumption (short tons). Withheld or unavailable values return as null.", + ) + heat_content: float | None = Field( + default=None, + description="Heat content (average sulfur percent by weight). Withheld or unavailable values return as null.", + ) + price: float | None = Field( + default=None, + description="Price (dollars per short ton). Withheld or unavailable values return as null.", + ) + receipts: float | None = Field( + default=None, + description="Receipts (short tons). Withheld or unavailable values return as null.", + ) + stocks: float | None = Field( + default=None, + description="Stocks (short tons). Withheld or unavailable values return as null.", + ) + sulfur_content: float | None = Field( + default=None, + description="Sulfur content (average sulfur percent by weight). Withheld or unavailable values return as null.", + ) + + +class EiaCoalConsumptionAndQualityFetcher( + Fetcher[ + EiaCoalConsumptionAndQualityQueryParams, list[EiaCoalConsumptionAndQualityData] + ] +): + """Consumption and Quality fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaCoalConsumptionAndQualityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaCoalConsumptionAndQualityQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaCoalConsumptionAndQualityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaCoalConsumptionAndQualityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaCoalConsumptionAndQualityData]: + """Transform the data.""" + return transform_dataset_data(EiaCoalConsumptionAndQualityData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/coal/exports_imports_quantity_price.py b/openbb_platform/providers/eia/openbb_us_eia/models/coal/exports_imports_quantity_price.py new file mode 100644 index 00000000000..f7e3f860a41 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/coal/exports_imports_quantity_price.py @@ -0,0 +1,193 @@ +"""Exports/Imports Quantity/Price model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaCoalExportsImportsQuantityPriceQueryParams(EiaApiQueryParams): + """Exports/Imports Quantity/Price. Coal import/export data, including price, quantity, country, rank, and customs district. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/ + + Source: https://www.eia.gov/opendata/browser/coal/exports-imports-quantity-price + """ + + __group__ = "coal" + __dataset__ = "exports_imports_quantity_price" + __json_schema_extra__ = { + "data_type": {"multiple_items_allowed": True, "choices": ["price", "quantity"]}, + "coal_rank": { + "multiple_items_allowed": True, + "choices": ["all", "coke", "metallurgical", "steam_coal"], + }, + "country": {"multiple_items_allowed": True}, + "customs_district": { + "multiple_items_allowed": True, + "choices": [ + "anchorage_ak", + "baltimore_md", + "boston_ma", + "buffalo_ny", + "charleston_sc", + "charlotte_nc", + "chicago_il", + "cleveland_oh", + "columbia_snake_or", + "dallas_fort_worth_tx", + "detroit_mi", + "duluth_mn", + "el_paso_tx", + "great_falls_mt", + "honolulu_hi", + "houston_galveston_tx", + "laredo_tx", + "los_angeles_ca", + "miami_fl", + "milwaukee_wi", + "minneapolis_mn", + "mobile_al", + "new_orleans_la", + "new_york_city_ny", + "nogales_az", + "norfolk_va", + "ogdensburg_ny", + "other_ports", + "pembina_nd", + "philadelphia_pa", + "port_arthur_tx", + "portland_me", + "portland_or", + "providence_ri", + "san_diego_ca", + "san_francisco_ca", + "san_juan_pr", + "savannah_ga", + "seattle_wa", + "st_albans_vt", + "tampa_fl", + "total", + "virgin_islands_of_the_united_states", + "wilmington_nc", + ], + }, + "export_import_type": { + "multiple_items_allowed": True, + "choices": ["exports", "imports"], + }, + } + + frequency: Literal["annual", "quarterly"] | None = Field( + default=None, + description="The data frequency. The default is 'annual'.", + ) + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: price (dollars per short ton); quantity (short tons).", + ) + coal_rank: str | None = Field( + default=None, + description="Coal Rank filter. Accepts a comma-separated list of values.", + ) + country: str | None = Field( + default=None, + description="Country filter. Accepts a comma-separated list of values. There are 141 valid values - use the `facet_options` endpoint to list them.", + ) + customs_district: str | None = Field( + default=None, + description="Customs District filter. Accepts a comma-separated list of values.", + ) + export_import_type: Literal["exports", "imports"] | None = Field( + default=None, + description="Export\\Import Type filter.", + ) + + +class EiaCoalExportsImportsQuantityPriceData(EiaApiData): + """Exports/Imports Quantity/Price. Coal import/export data, including price, quantity, country, rank, and customs district. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/""" + + coal_rank: str | None = Field( + default=None, + description="Coal Rank code.", + ) + coal_rank_name: str | None = Field( + default=None, + description="Coal Rank name.", + ) + country: str | None = Field( + default=None, + description="Country code.", + ) + country_name: str | None = Field( + default=None, + description="Country name.", + ) + customs_district: str | None = Field( + default=None, + description="Customs District code.", + ) + customs_district_name: str | None = Field( + default=None, + description="Customs District name.", + ) + export_import_type: str | None = Field( + default=None, + description="Export\\Import Type code.", + ) + export_import_type_name: str | None = Field( + default=None, + description="Export\\Import Type name.", + ) + price: float | None = Field( + default=None, + description="Price (dollars per short ton). Withheld or unavailable values return as null.", + ) + quantity: float | None = Field( + default=None, + description="Quantity (short tons). Withheld or unavailable values return as null.", + ) + + +class EiaCoalExportsImportsQuantityPriceFetcher( + Fetcher[ + EiaCoalExportsImportsQuantityPriceQueryParams, + list[EiaCoalExportsImportsQuantityPriceData], + ] +): + """Exports/Imports Quantity/Price fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaCoalExportsImportsQuantityPriceQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaCoalExportsImportsQuantityPriceQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaCoalExportsImportsQuantityPriceQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaCoalExportsImportsQuantityPriceQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaCoalExportsImportsQuantityPriceData]: + """Transform the data.""" + return transform_dataset_data( + EiaCoalExportsImportsQuantityPriceData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/coal/market_sales_price.py b/openbb_platform/providers/eia/openbb_us_eia/models/coal/market_sales_price.py new file mode 100644 index 00000000000..294f9ba437d --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/coal/market_sales_price.py @@ -0,0 +1,166 @@ +"""Market Sales Price model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaCoalMarketSalesPriceQueryParams(EiaApiQueryParams): + """Market Sales Price. Coal market sales prices and amounts by mine types for regions and states (unless withheld for pricing protections). Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/ + + Source: https://www.eia.gov/opendata/browser/coal/market-sales-price + """ + + __group__ = "coal" + __dataset__ = "market_sales_price" + __json_schema_extra__ = { + "data_type": {"multiple_items_allowed": True, "choices": ["price", "sales"]}, + "market_type": { + "multiple_items_allowed": True, + "choices": ["captive", "open_market", "total"], + }, + "state_region": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "appalachia_central", + "appalachia_northern", + "appalachia_southern", + "appalachia_total", + "arizona", + "arkansas", + "colorado", + "east_north_central", + "east_south_central", + "east_total", + "east_of_mississippi_river", + "illinois", + "illinois_basin", + "indiana", + "interior_region_total", + "kansas", + "kentucky", + "kentucky_east", + "kentucky_west", + "louisiana", + "maryland", + "middle_atlantic", + "midwest_total", + "mississippi", + "missouri", + "montana", + "mountain", + "new_mexico", + "north_dakota", + "ohio", + "oklahoma", + "other_interior", + "other_western", + "pacific_contiguous", + "pacific_noncontiguous", + "pennsylvania", + "pennsylvania_anthracite", + "pennsylvania_bituminous", + "powder_river_basin", + "south_atlantic", + "south_total", + "tennessee", + "texas", + "us_total", + "uinta_basin", + "utah", + "virginia", + "washington", + "west_north_central", + "west_south_central", + "west_total", + "west_virginia", + "west_virginia_northern", + "west_virginia_southern", + "west_of_mississippi_river", + "western_region_total", + "wyoming", + ], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: price (dollars per short ton); sales (short tons).", + ) + market_type: Literal["captive", "open_market", "total"] | None = Field( + default=None, + description="Market Type filter.", + ) + state_region: str | None = Field( + default=None, + description="State\\Region filter. Accepts a comma-separated list of values.", + ) + + +class EiaCoalMarketSalesPriceData(EiaApiData): + """Market Sales Price. Coal market sales prices and amounts by mine types for regions and states (unless withheld for pricing protections). Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/""" + + market_type: str | None = Field( + default=None, + description="Market Type code.", + ) + market_type_name: str | None = Field( + default=None, + description="Market Type name.", + ) + state_region: str | None = Field( + default=None, + description="State\\Region code.", + ) + state_region_name: str | None = Field( + default=None, + description="State\\Region name.", + ) + price: float | None = Field( + default=None, + description="Price (dollars per short ton). Withheld or unavailable values return as null.", + ) + sales: float | None = Field( + default=None, + description="Sales (short tons). Withheld or unavailable values return as null.", + ) + + +class EiaCoalMarketSalesPriceFetcher( + Fetcher[EiaCoalMarketSalesPriceQueryParams, list[EiaCoalMarketSalesPriceData]] +): + """Market Sales Price fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaCoalMarketSalesPriceQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaCoalMarketSalesPriceQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaCoalMarketSalesPriceQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaCoalMarketSalesPriceQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaCoalMarketSalesPriceData]: + """Transform the data.""" + return transform_dataset_data(EiaCoalMarketSalesPriceData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/coal/mine_aggregates.py b/openbb_platform/providers/eia/openbb_us_eia/models/coal/mine_aggregates.py new file mode 100644 index 00000000000..a848d949f7f --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/coal/mine_aggregates.py @@ -0,0 +1,173 @@ +"""Mine Aggregates model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaCoalMineAggregatesQueryParams(EiaApiQueryParams): + """Mine Aggregates. Coal shipments aggregated at mine-level data, including price, quantity, quality, and rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/ + + Source: https://www.eia.gov/opendata/browser/coal/shipments/mine-aggregates + """ + + __group__ = "coal" + __dataset__ = "mine_aggregates" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "ash_content", + "heat_content", + "price", + "quantity", + "sulfur_content", + ], + }, + "coal_rank": { + "multiple_items_allowed": True, + "choices": ["all", "anthracite", "bituminous", "lignite", "subbituminous"], + }, + "mine": {"multiple_items_allowed": True}, + "mine_state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "colorado", + "illinois", + "indiana", + "kansas", + "kentucky_east", + "kentucky_west", + "louisiana", + "maryland", + "mississippi", + "missouri", + "montana", + "new_mexico", + "north_dakota", + "ohio", + "oklahoma", + "pennsylvania_anthracite", + "pennsylvania_bituminous", + "tennessee", + "texas", + "utah", + "virginia", + "west_virginia_northern", + "west_virginia_southern", + "wyoming", + ], + }, + } + + frequency: Literal["annual", "quarterly"] | None = Field( + default=None, + description="The data frequency. The default is 'annual'.", + ) + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: ash_content (percent by weight); heat_content (Btu per pound); price (average dollars per ton); quantity (tons); sulfur_content (percent by weight).", + ) + coal_rank: str | None = Field( + default=None, + description="Coal Rank filter. Accepts a comma-separated list of values.", + ) + mine: str | None = Field( + default=None, + description="Mine filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + mine_state: str | None = Field( + default=None, + description="Mine State\\Region filter. Accepts a comma-separated list of values.", + ) + + +class EiaCoalMineAggregatesData(EiaApiData): + """Mine Aggregates. Coal shipments aggregated at mine-level data, including price, quantity, quality, and rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/""" + + coal_rank: str | None = Field( + default=None, + description="Coal Rank code.", + ) + coal_rank_name: str | None = Field( + default=None, + description="Coal Rank name.", + ) + mine: str | None = Field( + default=None, + description="Mine code.", + ) + mine_name: str | None = Field( + default=None, + description="Mine name.", + ) + mine_state: str | None = Field( + default=None, + description="Mine State\\Region code.", + ) + mine_state_name: str | None = Field( + default=None, + description="Mine State\\Region name.", + ) + ash_content: float | None = Field( + default=None, + description="Ash content (percent by weight). Withheld or unavailable values return as null.", + ) + heat_content: float | None = Field( + default=None, + description="Heat content (Btu per pound). Withheld or unavailable values return as null.", + ) + price: float | None = Field( + default=None, + description="Price (average dollars per ton). Withheld or unavailable values return as null.", + ) + quantity: float | None = Field( + default=None, + description="Quantity (tons). Withheld or unavailable values return as null.", + ) + sulfur_content: float | None = Field( + default=None, + description="Sulfur content (percent by weight). Withheld or unavailable values return as null.", + ) + + +class EiaCoalMineAggregatesFetcher( + Fetcher[EiaCoalMineAggregatesQueryParams, list[EiaCoalMineAggregatesData]] +): + """Mine Aggregates fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaCoalMineAggregatesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaCoalMineAggregatesQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaCoalMineAggregatesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaCoalMineAggregatesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaCoalMineAggregatesData]: + """Transform the data.""" + return transform_dataset_data(EiaCoalMineAggregatesData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/coal/mine_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/coal/mine_production.py new file mode 100644 index 00000000000..84e28cf38a1 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/coal/mine_production.py @@ -0,0 +1,365 @@ +"""Mine Production model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaCoalMineProductionQueryParams(EiaApiQueryParams): + """Mine Production. Coal mine-level data, including production, region, state, county, rank, status, type, name and description. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/ + + Source: https://www.eia.gov/opendata/browser/coal/mine-production + """ + + __group__ = "coal" + __dataset__ = "mine_production" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "average_employees", + "labor_hours", + "latitude", + "longitude", + "operating_company", + "operating_company_address", + "production", + "refuse_flag", + ], + }, + "census_region": { + "multiple_items_allowed": True, + "choices": [ + "east_north_central", + "east_south_central", + "middle_atlantic", + "mountain", + "pacific_contiguous", + "pacific_noncontiguous", + "south_atlantic", + "west_north_central", + "west_south_central", + ], + }, + "coal_rank": { + "multiple_items_allowed": True, + "choices": [ + "anthracite", + "bituminous", + "lignite", + "preparation_plant", + "subbituminous", + ], + }, + "mine": {"multiple_items_allowed": True}, + "mine_county": {"multiple_items_allowed": True}, + "mine_region": { + "multiple_items_allowed": True, + "choices": ["east", "midwest", "south", "west"], + }, + "mine_status": { + "multiple_items_allowed": True, + "choices": [ + "active", + "active_men_not_working_not_producing", + "active_men_working_not_producing", + "mine_closed_by_msha", + "new_under_construction", + "permanently_abandoned", + "temporarily_closed", + ], + }, + "mine_type": { + "multiple_items_allowed": True, + "choices": ["refuse", "surface", "underground"], + }, + "mississippi_region": { + "multiple_items_allowed": True, + "choices": ["east_of_mississippi_river", "west_of_mississippi_river"], + }, + "state_region": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "colorado", + "illinois", + "indiana", + "kansas", + "kentucky_east", + "kentucky_west", + "louisiana", + "maryland", + "mississippi", + "missouri", + "montana", + "new_mexico", + "north_dakota", + "ohio", + "oklahoma", + "pennsylvania_anthracite", + "pennsylvania_bituminous", + "tennessee", + "texas", + "utah", + "virginia", + "washington", + "west_virginia_northern", + "west_virginia_southern", + "wyoming", + ], + }, + "supply_region": { + "multiple_items_allowed": True, + "choices": [ + "appalachia_central", + "appalachia_northern", + "appalachia_southern", + "illinois_basin", + "other_interior", + "other_western", + "powder_river_basin", + "uinta_basin", + ], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: average_employees (number of employees); labor_hours (hours); latitude; longitude; operating_company; operating_company_address; production (short tons); refuse_flag.", + ) + census_region: ( + Literal[ + "east_north_central", + "east_south_central", + "middle_atlantic", + "mountain", + "pacific_contiguous", + "pacific_noncontiguous", + "south_atlantic", + "west_north_central", + "west_south_central", + ] + | None + ) = Field( + default=None, + description="Census Region filter.", + ) + coal_rank: str | None = Field( + default=None, + description="Coal Rank filter. Accepts a comma-separated list of values.", + ) + mine: str | None = Field( + default=None, + description="Mine filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + mine_county: str | None = Field( + default=None, + description="Mine County filter. Accepts a comma-separated list of values. There are 107 valid values - use the `facet_options` endpoint to list them.", + ) + mine_region: Literal["east", "midwest", "south", "west"] | None = Field( + default=None, + description="Region filter.", + ) + mine_status: ( + Literal[ + "active", + "active_men_not_working_not_producing", + "active_men_working_not_producing", + "mine_closed_by_msha", + "new_under_construction", + "permanently_abandoned", + "temporarily_closed", + ] + | None + ) = Field( + default=None, + description="Mine Status filter.", + ) + mine_type: Literal["refuse", "surface", "underground"] | None = Field( + default=None, + description="Mine Type filter.", + ) + mississippi_region: ( + Literal["east_of_mississippi_river", "west_of_mississippi_river"] | None + ) = Field( + default=None, + description="Mississippi Region filter.", + ) + state_region: str | None = Field( + default=None, + description="State filter. Accepts a comma-separated list of values.", + ) + supply_region: ( + Literal[ + "appalachia_central", + "appalachia_northern", + "appalachia_southern", + "illinois_basin", + "other_interior", + "other_western", + "powder_river_basin", + "uinta_basin", + ] + | None + ) = Field( + default=None, + description="Supply Region filter.", + ) + + +class EiaCoalMineProductionData(EiaApiData): + """Mine Production. Coal mine-level data, including production, region, state, county, rank, status, type, name and description. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/""" + + census_region: str | None = Field( + default=None, + description="Census Region code.", + ) + census_region_name: str | None = Field( + default=None, + description="Census Region name.", + ) + coal_rank: str | None = Field( + default=None, + description="Coal Rank code.", + ) + coal_rank_name: str | None = Field( + default=None, + description="Coal Rank name.", + ) + mine: str | None = Field( + default=None, + description="Mine code.", + ) + mine_name: str | None = Field( + default=None, + description="Mine name.", + ) + mine_county: str | None = Field( + default=None, + description="Mine County code.", + ) + mine_county_name: str | None = Field( + default=None, + description="Mine County name.", + ) + mine_region: str | None = Field( + default=None, + description="Region code.", + ) + mine_region_name: str | None = Field( + default=None, + description="Region name.", + ) + mine_status: str | None = Field( + default=None, + description="Mine Status code.", + ) + mine_status_name: str | None = Field( + default=None, + description="Mine Status name.", + ) + mine_type: str | None = Field( + default=None, + description="Mine Type code.", + ) + mine_type_name: str | None = Field( + default=None, + description="Mine Type name.", + ) + mississippi_region: str | None = Field( + default=None, + description="Mississippi Region code.", + ) + mississippi_region_name: str | None = Field( + default=None, + description="Mississippi Region name.", + ) + state_region: str | None = Field( + default=None, + description="State code.", + ) + state_region_name: str | None = Field( + default=None, + description="State name.", + ) + supply_region: str | None = Field( + default=None, + description="Supply Region code.", + ) + supply_region_name: str | None = Field( + default=None, + description="Supply Region name.", + ) + average_employees: float | None = Field( + default=None, + description="Average employees (number of employees). Withheld or unavailable values return as null.", + ) + labor_hours: float | None = Field( + default=None, + description="Labor hours (hours). Withheld or unavailable values return as null.", + ) + latitude: float | None = Field( + default=None, + description="Latitude. Withheld or unavailable values return as null.", + ) + longitude: float | None = Field( + default=None, + description="Longitude. Withheld or unavailable values return as null.", + ) + operating_company: str | None = Field( + default=None, + description="Operating company", + ) + operating_company_address: str | None = Field( + default=None, + description="Operating company address", + ) + production: float | None = Field( + default=None, + description="Production (short tons). Withheld or unavailable values return as null.", + ) + refuse_flag: str | None = Field( + default=None, + description="Refuse flag", + ) + + +class EiaCoalMineProductionFetcher( + Fetcher[EiaCoalMineProductionQueryParams, list[EiaCoalMineProductionData]] +): + """Mine Production fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaCoalMineProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaCoalMineProductionQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaCoalMineProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaCoalMineProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaCoalMineProductionData]: + """Transform the data.""" + return transform_dataset_data(EiaCoalMineProductionData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/coal/mine_state_aggregates.py b/openbb_platform/providers/eia/openbb_us_eia/models/coal/mine_state_aggregates.py new file mode 100644 index 00000000000..c5395395ebd --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/coal/mine_state_aggregates.py @@ -0,0 +1,188 @@ +"""Mine State Aggregates model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaCoalMineStateAggregatesQueryParams(EiaApiQueryParams): + """Mine State Aggregates. Coal shipments aggregated at state-level data, including price, quantity, quality, and rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/ + + Source: https://www.eia.gov/opendata/browser/coal/shipments/mine-state-aggregates + """ + + __group__ = "coal" + __dataset__ = "mine_state_aggregates" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "ash_content", + "heat_content", + "price", + "quantity", + "sulfur_content", + ], + }, + "coal_rank": { + "multiple_items_allowed": True, + "choices": ["all", "anthracite", "bituminous", "lignite", "subbituminous"], + }, + "mine_state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "appalachia_central", + "appalachia_northern", + "appalachia_southern", + "appalachia_total", + "arizona", + "arkansas", + "colorado", + "east_north_central", + "east_south_central", + "illinois", + "illinois_basin", + "indiana", + "interior_region_total", + "kansas", + "kentucky", + "kentucky_east", + "kentucky_west", + "louisiana", + "maryland", + "middle_atlantic", + "mississippi", + "missouri", + "montana", + "mountain", + "new_mexico", + "north_dakota", + "ohio", + "oklahoma", + "other_interior", + "other_western", + "overseas", + "pacific_contiguous", + "pacific_noncontiguous", + "pennsylvania", + "pennsylvania_anthracite", + "pennsylvania_bituminous", + "powder_river_basin", + "south_atlantic", + "tennessee", + "texas", + "us_total", + "uinta_basin", + "utah", + "virginia", + "washington", + "west_north_central", + "west_south_central", + "west_virginia", + "west_virginia_northern", + "west_virginia_southern", + "western_region_total", + "wyoming", + ], + }, + } + + frequency: Literal["annual", "quarterly"] | None = Field( + default=None, + description="The data frequency. The default is 'annual'.", + ) + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: ash_content (percent by weight); heat_content (Btu per pound); price (average dollars per ton); quantity (tons); sulfur_content (percent by weight).", + ) + coal_rank: str | None = Field( + default=None, + description="Coal Rank filter. Accepts a comma-separated list of values.", + ) + mine_state: str | None = Field( + default=None, + description="Mine State\\Region filter. Accepts a comma-separated list of values.", + ) + + +class EiaCoalMineStateAggregatesData(EiaApiData): + """Mine State Aggregates. Coal shipments aggregated at state-level data, including price, quantity, quality, and rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/""" + + coal_rank: str | None = Field( + default=None, + description="Coal Rank code.", + ) + coal_rank_name: str | None = Field( + default=None, + description="Coal Rank name.", + ) + mine_state: str | None = Field( + default=None, + description="Mine State\\Region code.", + ) + mine_state_name: str | None = Field( + default=None, + description="Mine State\\Region name.", + ) + ash_content: float | None = Field( + default=None, + description="Ash content (percent by weight). Withheld or unavailable values return as null.", + ) + heat_content: float | None = Field( + default=None, + description="Heat content (Btu per pound). Withheld or unavailable values return as null.", + ) + price: float | None = Field( + default=None, + description="Price (average dollars per ton). Withheld or unavailable values return as null.", + ) + quantity: float | None = Field( + default=None, + description="Quantity (tons). Withheld or unavailable values return as null.", + ) + sulfur_content: float | None = Field( + default=None, + description="Sulfur content (percent by weight). Withheld or unavailable values return as null.", + ) + + +class EiaCoalMineStateAggregatesFetcher( + Fetcher[EiaCoalMineStateAggregatesQueryParams, list[EiaCoalMineStateAggregatesData]] +): + """Mine State Aggregates fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaCoalMineStateAggregatesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaCoalMineStateAggregatesQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaCoalMineStateAggregatesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaCoalMineStateAggregatesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaCoalMineStateAggregatesData]: + """Transform the data.""" + return transform_dataset_data(EiaCoalMineStateAggregatesData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/coal/plant_aggregates.py b/openbb_platform/providers/eia/openbb_us_eia/models/coal/plant_aggregates.py new file mode 100644 index 00000000000..263fe11e655 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/coal/plant_aggregates.py @@ -0,0 +1,175 @@ +"""Plant Aggregates model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaCoalPlantAggregatesQueryParams(EiaApiQueryParams): + """Plant Aggregates. Coal reciepts aggregated to plant-level data, including price, quantity, quality, and rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/ + + Source: https://www.eia.gov/opendata/browser/coal/shipments/plant-aggregates + """ + + __group__ = "coal" + __dataset__ = "plant_aggregates" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "ash_content", + "heat_content", + "price", + "quantity", + "sulfur_content", + ], + }, + "coal_rank": { + "multiple_items_allowed": True, + "choices": ["all", "anthracite", "bituminous", "lignite", "subbituminous"], + }, + "plant": {"multiple_items_allowed": True}, + "state_region": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "colorado", + "illinois", + "indiana", + "kansas", + "kentucky_east", + "kentucky_west", + "louisiana", + "maryland", + "mississippi", + "missouri", + "montana", + "new_mexico", + "north_dakota", + "ohio", + "oklahoma", + "overseas", + "pennsylvania_anthracite", + "pennsylvania_bituminous", + "tennessee", + "texas", + "utah", + "virginia", + "washington", + "west_virginia_northern", + "west_virginia_southern", + "wyoming", + ], + }, + } + + frequency: Literal["annual", "quarterly"] | None = Field( + default=None, + description="The data frequency. The default is 'annual'.", + ) + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: ash_content (percent by weight); heat_content (Btu per pound); price (average dollars per ton); quantity (tons); sulfur_content (percent by weight).", + ) + coal_rank: str | None = Field( + default=None, + description="Coal Rank filter. Accepts a comma-separated list of values.", + ) + plant: str | None = Field( + default=None, + description="Plant filter. Accepts a comma-separated list of values. There are 530 valid values - use the `facet_options` endpoint to list them.", + ) + state_region: str | None = Field( + default=None, + description="Plant State\\Region. filter. Accepts a comma-separated list of values.", + ) + + +class EiaCoalPlantAggregatesData(EiaApiData): + """Plant Aggregates. Coal reciepts aggregated to plant-level data, including price, quantity, quality, and rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/""" + + coal_rank: str | None = Field( + default=None, + description="Coal Rank code.", + ) + coal_rank_name: str | None = Field( + default=None, + description="Coal Rank name.", + ) + plant: str | None = Field( + default=None, + description="Plant code.", + ) + plant_name: str | None = Field( + default=None, + description="Plant name.", + ) + state_region: str | None = Field( + default=None, + description="Plant State\\Region. code.", + ) + state_region_name: str | None = Field( + default=None, + description="Plant State\\Region. name.", + ) + ash_content: float | None = Field( + default=None, + description="Ash content (percent by weight). Withheld or unavailable values return as null.", + ) + heat_content: float | None = Field( + default=None, + description="Heat content (Btu per pound). Withheld or unavailable values return as null.", + ) + price: float | None = Field( + default=None, + description="Price (average dollars per ton). Withheld or unavailable values return as null.", + ) + quantity: float | None = Field( + default=None, + description="Quantity (tons). Withheld or unavailable values return as null.", + ) + sulfur_content: float | None = Field( + default=None, + description="Sulfur content (percent by weight). Withheld or unavailable values return as null.", + ) + + +class EiaCoalPlantAggregatesFetcher( + Fetcher[EiaCoalPlantAggregatesQueryParams, list[EiaCoalPlantAggregatesData]] +): + """Plant Aggregates fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaCoalPlantAggregatesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaCoalPlantAggregatesQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaCoalPlantAggregatesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaCoalPlantAggregatesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaCoalPlantAggregatesData]: + """Transform the data.""" + return transform_dataset_data(EiaCoalPlantAggregatesData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/coal/plant_state_aggregates.py b/openbb_platform/providers/eia/openbb_us_eia/models/coal/plant_state_aggregates.py new file mode 100644 index 00000000000..65ba564cb8f --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/coal/plant_state_aggregates.py @@ -0,0 +1,195 @@ +"""Plant State Aggregates model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaCoalPlantStateAggregatesQueryParams(EiaApiQueryParams): + """Plant State Aggregates. Coal reciepts aggregated at state-level data, including price, quantity, quality, and rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/ + + Source: https://www.eia.gov/opendata/browser/coal/shipments/plant-state-aggregates + """ + + __group__ = "coal" + __dataset__ = "plant_state_aggregates" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "ash_content", + "heat_content", + "price", + "quantity", + "sulfur_content", + ], + }, + "coal_rank": { + "multiple_items_allowed": True, + "choices": ["all", "anthracite", "bituminous", "lignite", "subbituminous"], + }, + "plant_state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "east_north_central", + "east_south_central", + "florida", + "georgia", + "hawaii", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "middle_atlantic", + "minnesota", + "mississippi", + "missouri", + "montana", + "mountain", + "nebraska", + "nevada", + "new_england", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pacific_contiguous", + "pacific_noncontiguous", + "pennsylvania", + "rhode_island", + "south_atlantic", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "us_total", + "utah", + "virginia", + "washington", + "west_north_central", + "west_south_central", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + } + + frequency: Literal["annual", "quarterly"] | None = Field( + default=None, + description="The data frequency. The default is 'annual'.", + ) + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: ash_content (percent by weight); heat_content (Btu per pound); price (average dollars per ton); quantity (tons); sulfur_content (percent by weight).", + ) + coal_rank: str | None = Field( + default=None, + description="Coal Rank filter. Accepts a comma-separated list of values.", + ) + plant_state: str | None = Field( + default=None, + description="Plant State\\Region filter. Accepts a comma-separated list of values.", + ) + + +class EiaCoalPlantStateAggregatesData(EiaApiData): + """Plant State Aggregates. Coal reciepts aggregated at state-level data, including price, quantity, quality, and rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/""" + + coal_rank: str | None = Field( + default=None, + description="Coal Rank code.", + ) + coal_rank_name: str | None = Field( + default=None, + description="Coal Rank name.", + ) + plant_state: str | None = Field( + default=None, + description="Plant State\\Region code.", + ) + plant_state_name: str | None = Field( + default=None, + description="Plant State\\Region name.", + ) + ash_content: float | None = Field( + default=None, + description="Ash content (percent by weight). Withheld or unavailable values return as null.", + ) + heat_content: float | None = Field( + default=None, + description="Heat content (Btu per pound). Withheld or unavailable values return as null.", + ) + price: float | None = Field( + default=None, + description="Price (average dollars per ton). Withheld or unavailable values return as null.", + ) + quantity: float | None = Field( + default=None, + description="Quantity (tons). Withheld or unavailable values return as null.", + ) + sulfur_content: float | None = Field( + default=None, + description="Sulfur content (percent by weight). Withheld or unavailable values return as null.", + ) + + +class EiaCoalPlantStateAggregatesFetcher( + Fetcher[ + EiaCoalPlantStateAggregatesQueryParams, list[EiaCoalPlantStateAggregatesData] + ] +): + """Plant State Aggregates fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaCoalPlantStateAggregatesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaCoalPlantStateAggregatesQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaCoalPlantStateAggregatesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaCoalPlantStateAggregatesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaCoalPlantStateAggregatesData]: + """Transform the data.""" + return transform_dataset_data(EiaCoalPlantStateAggregatesData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/coal/price_by_rank.py b/openbb_platform/providers/eia/openbb_us_eia/models/coal/price_by_rank.py new file mode 100644 index 00000000000..ebd58e93e6e --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/coal/price_by_rank.py @@ -0,0 +1,157 @@ +"""Price by Rank model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaCoalPriceByRankQueryParams(EiaApiQueryParams): + """Price by Rank. Coal prices by rank data for region and state. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/ + + Source: https://www.eia.gov/opendata/browser/coal/price-by-rank + """ + + __group__ = "coal" + __dataset__ = "price_by_rank" + __json_schema_extra__ = { + "coal_rank": { + "multiple_items_allowed": True, + "choices": ["all", "anthracite", "bituminous", "lignite", "subbituminous"], + }, + "state_region": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "appalachia_central", + "appalachia_northern", + "appalachia_southern", + "appalachia_total", + "arizona", + "arkansas", + "colorado", + "east_north_central", + "east_south_central", + "east_total", + "east_of_mississippi_river", + "illinois", + "illinois_basin", + "indiana", + "interior_region_total", + "kansas", + "kentucky", + "kentucky_east", + "kentucky_west", + "louisiana", + "maryland", + "middle_atlantic", + "midwest_total", + "mississippi", + "missouri", + "montana", + "mountain", + "new_mexico", + "north_dakota", + "ohio", + "oklahoma", + "other_interior", + "other_western", + "pacific_contiguous", + "pacific_noncontiguous", + "pennsylvania", + "pennsylvania_anthracite", + "pennsylvania_bituminous", + "powder_river_basin", + "south_atlantic", + "south_total", + "tennessee", + "texas", + "us_total", + "uinta_basin", + "utah", + "virginia", + "washington", + "west_north_central", + "west_south_central", + "west_total", + "west_virginia", + "west_virginia_northern", + "west_virginia_southern", + "west_of_mississippi_river", + "western_region_total", + "wyoming", + ], + }, + } + + coal_rank: str | None = Field( + default=None, + description="Coal Rank filter. Accepts a comma-separated list of values.", + ) + state_region: str | None = Field( + default=None, + description="State\\Region filter. Accepts a comma-separated list of values.", + ) + + +class EiaCoalPriceByRankData(EiaApiData): + """Price by Rank. Coal prices by rank data for region and state. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/""" + + coal_rank: str | None = Field( + default=None, + description="Coal Rank code.", + ) + coal_rank_name: str | None = Field( + default=None, + description="Coal Rank name.", + ) + state_region: str | None = Field( + default=None, + description="State\\Region code.", + ) + state_region_name: str | None = Field( + default=None, + description="State\\Region name.", + ) + price: float | None = Field( + default=None, + description="Price (dollars per short ton). Withheld or unavailable values return as null.", + ) + + +class EiaCoalPriceByRankFetcher( + Fetcher[EiaCoalPriceByRankQueryParams, list[EiaCoalPriceByRankData]] +): + """Price by Rank fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaCoalPriceByRankQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaCoalPriceByRankQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaCoalPriceByRankQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaCoalPriceByRankQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaCoalPriceByRankData]: + """Transform the data.""" + return transform_dataset_data(EiaCoalPriceByRankData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/coal/receipts.py b/openbb_platform/providers/eia/openbb_us_eia/models/coal/receipts.py new file mode 100644 index 00000000000..1c258b14c82 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/coal/receipts.py @@ -0,0 +1,494 @@ +"""Receipts model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaCoalReceiptsQueryParams(EiaApiQueryParams): + """Receipts. Coal shipment detailed by reciepient data, including transportation type, supplier, mine, coal basin, county, state, rank, contract type, price, quantity, and quality. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/ + + Source: https://www.eia.gov/opendata/browser/coal/shipments/receipts + """ + + __group__ = "coal" + __dataset__ = "receipts" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "ash_content", + "heat_content", + "price", + "quantity", + "sulfur_content", + ], + }, + "coal_rank": { + "multiple_items_allowed": True, + "choices": ["all", "anthracite", "bituminous", "lignite", "subbituminous"], + }, + "coal_supplier": {"multiple_items_allowed": True}, + "contract_type": { + "multiple_items_allowed": True, + "choices": [ + "contract_purchase", + "new_contract", + "none", + "spot_market_purchase", + ], + }, + "mine": {"multiple_items_allowed": True}, + "mine_basin": { + "multiple_items_allowed": True, + "choices": [ + "appalachia_central", + "appalachia_northern", + "appalachia_southern", + "illinois_basin", + "other_interior", + "other_western", + "powder_river_basin", + "uinta_basin", + ], + }, + "mine_county": { + "multiple_items_allowed": True, + "choices": [ + "10", + "101", + "107", + "109", + "115", + "119", + "127", + "129", + "133", + "147", + "149", + "159", + "175", + "177", + "189", + "203", + "225", + "233", + "235", + "237", + "25", + "3", + "33", + "39", + "47", + "49", + "53", + "61", + "63", + "67", + "7", + "71", + "77", + "79", + "81", + "85", + "9", + "91", + "95", + "97", + "99", + "anderson", + "atascosa", + "bourbon", + "campbell", + "choctaw", + "clay", + "columbiana", + "coshocton", + "craig", + "crawford", + "cullman", + "daviess", + "dickenson", + "douglas", + "emery", + "fayette", + "freestone", + "gallatin", + "jefferson", + "lawrence", + "lee", + "leon", + "limestone", + "lincoln", + "marion", + "mclean", + "meigs", + "montgomery", + "natchitoches", + "navajo", + "noble", + "none", + "okmulgee", + "oliver", + "perry", + "richland", + "rio_blanco", + "robertson", + "rogers", + "rusk", + "saline", + "san_juan", + "shelby", + "stark", + "sullivan", + "tazewell", + "titus", + "tuscaloosa", + "tuscarawas", + "vermilion", + "vigo", + "vinton", + "warrick", + "white", + "williamson", + "wise", + "yukon_koyukuk", + ], + }, + "mine_state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "colorado", + "illinois", + "indiana", + "kansas", + "kentucky_east", + "kentucky_west", + "louisiana", + "maryland", + "mississippi", + "missouri", + "montana", + "new_mexico", + "north_dakota", + "ohio", + "oklahoma", + "pennsylvania_anthracite", + "pennsylvania_bituminous", + "tennessee", + "texas", + "utah", + "virginia", + "west_virginia_northern", + "west_virginia_southern", + "wyoming", + ], + }, + "mine_type": { + "multiple_items_allowed": True, + "choices": ["surface", "underground"], + }, + "plant": {"multiple_items_allowed": True}, + "plant_state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "florida", + "georgia", + "hawaii", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "minnesota", + "mississippi", + "missouri", + "montana", + "nebraska", + "nevada", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pennsylvania", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "utah", + "virginia", + "washington", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + "transportation_mode": { + "multiple_items_allowed": True, + "choices": [ + "great_lakes", + "none", + "pipeline", + "rail", + "river", + "tidewater_piers", + "tramway_conveyor", + "truck", + "water", + ], + }, + } + + frequency: Literal["annual", "quarterly"] | None = Field( + default=None, + description="The data frequency. The default is 'annual'.", + ) + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: ash_content (percent by weight); heat_content (Btu per pound); price (average dollars per ton); quantity (tons); sulfur_content (percent by weight).", + ) + coal_rank: str | None = Field( + default=None, + description="Coal Rank filter. Accepts a comma-separated list of values.", + ) + coal_supplier: str | None = Field( + default=None, + description="Coal Supplier filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + contract_type: ( + Literal["contract_purchase", "new_contract", "none", "spot_market_purchase"] + | None + ) = Field( + default=None, + description="Contract Type filter.", + ) + mine: str | None = Field( + default=None, + description="Mine filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + mine_basin: ( + Literal[ + "appalachia_central", + "appalachia_northern", + "appalachia_southern", + "illinois_basin", + "other_interior", + "other_western", + "powder_river_basin", + "uinta_basin", + ] + | None + ) = Field( + default=None, + description="Mine Basin filter.", + ) + mine_county: str | None = Field( + default=None, + description="Mine County filter. Accepts a comma-separated list of values.", + ) + mine_state: str | None = Field( + default=None, + description="Mine State\\Region filter. Accepts a comma-separated list of values.", + ) + mine_type: Literal["surface", "underground"] | None = Field( + default=None, + description="Mine Type filter.", + ) + plant: str | None = Field( + default=None, + description="Plant filter. Accepts a comma-separated list of values. There are 471 valid values - use the `facet_options` endpoint to list them.", + ) + plant_state: str | None = Field( + default=None, + description="Plant State\\Region filter. Accepts a comma-separated list of values.", + ) + transportation_mode: ( + Literal[ + "great_lakes", + "none", + "pipeline", + "rail", + "river", + "tidewater_piers", + "tramway_conveyor", + "truck", + "water", + ] + | None + ) = Field( + default=None, + description="Transportation Mode filter.", + ) + + +class EiaCoalReceiptsData(EiaApiData): + """Receipts. Coal shipment detailed by reciepient data, including transportation type, supplier, mine, coal basin, county, state, rank, contract type, price, quantity, and quality. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/""" + + coal_rank: str | None = Field( + default=None, + description="Coal Rank code.", + ) + coal_rank_name: str | None = Field( + default=None, + description="Coal Rank name.", + ) + coal_supplier: str | None = Field( + default=None, + description="Coal Supplier code.", + ) + coal_supplier_name: str | None = Field( + default=None, + description="Coal Supplier name.", + ) + contract_type: str | None = Field( + default=None, + description="Contract Type code.", + ) + contract_type_name: str | None = Field( + default=None, + description="Contract Type name.", + ) + mine: str | None = Field( + default=None, + description="Mine code.", + ) + mine_name: str | None = Field( + default=None, + description="Mine name.", + ) + mine_basin: str | None = Field( + default=None, + description="Mine Basin code.", + ) + mine_basin_name: str | None = Field( + default=None, + description="Mine Basin name.", + ) + mine_county: str | None = Field( + default=None, + description="Mine County code.", + ) + mine_county_name: str | None = Field( + default=None, + description="Mine County name.", + ) + mine_state: str | None = Field( + default=None, + description="Mine State\\Region code.", + ) + mine_state_name: str | None = Field( + default=None, + description="Mine State\\Region name.", + ) + mine_type: str | None = Field( + default=None, + description="Mine Type code.", + ) + mine_type_name: str | None = Field( + default=None, + description="Mine Type name.", + ) + plant: str | None = Field( + default=None, + description="Plant code.", + ) + plant_name: str | None = Field( + default=None, + description="Plant name.", + ) + plant_state: str | None = Field( + default=None, + description="Plant State\\Region code.", + ) + plant_state_name: str | None = Field( + default=None, + description="Plant State\\Region name.", + ) + transportation_mode: str | None = Field( + default=None, + description="Transportation Mode code.", + ) + transportation_mode_name: str | None = Field( + default=None, + description="Transportation Mode name.", + ) + ash_content: float | None = Field( + default=None, + description="Ash content (percent by weight). Withheld or unavailable values return as null.", + ) + heat_content: float | None = Field( + default=None, + description="Heat content (Btu per pound). Withheld or unavailable values return as null.", + ) + price: float | None = Field( + default=None, + description="Price (average dollars per ton). Withheld or unavailable values return as null.", + ) + quantity: float | None = Field( + default=None, + description="Quantity (tons). Withheld or unavailable values return as null.", + ) + sulfur_content: float | None = Field( + default=None, + description="Sulfur content (percent by weight). Withheld or unavailable values return as null.", + ) + + +class EiaCoalReceiptsFetcher( + Fetcher[EiaCoalReceiptsQueryParams, list[EiaCoalReceiptsData]] +): + """Receipts fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaCoalReceiptsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaCoalReceiptsQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaCoalReceiptsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaCoalReceiptsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaCoalReceiptsData]: + """Transform the data.""" + return transform_dataset_data(EiaCoalReceiptsData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/coal/reserves_capacity.py b/openbb_platform/providers/eia/openbb_us_eia/models/coal/reserves_capacity.py new file mode 100644 index 00000000000..754158ec74c --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/coal/reserves_capacity.py @@ -0,0 +1,177 @@ +"""Reserves Capacity model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaCoalReservesCapacityQueryParams(EiaApiQueryParams): + """Reserves Capacity. Coal capacity data, including productive capacity, stocks, and recoverable reserves by state, region and mine type. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/ + + Source: https://www.eia.gov/opendata/browser/coal/reserves-capacity + """ + + __group__ = "coal" + __dataset__ = "reserves_capacity" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "producer_distributor_stocks", + "productive_capacity", + "recoverable_reserves", + ], + }, + "mine_type": { + "multiple_items_allowed": True, + "choices": ["surface", "total", "underground"], + }, + "state_region": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "appalachia_central", + "appalachia_northern", + "appalachia_southern", + "appalachia_total", + "arizona", + "arkansas", + "colorado", + "east_north_central", + "east_south_central", + "east_total", + "east_of_mississippi_river", + "illinois", + "illinois_basin", + "indiana", + "interior_region_total", + "kansas", + "kentucky", + "kentucky_east", + "kentucky_west", + "louisiana", + "maryland", + "middle_atlantic", + "midwest_total", + "mississippi", + "missouri", + "montana", + "mountain", + "new_mexico", + "north_dakota", + "ohio", + "oklahoma", + "other_interior", + "other_western", + "pacific_contiguous", + "pacific_noncontiguous", + "pennsylvania", + "pennsylvania_anthracite", + "pennsylvania_bituminous", + "powder_river_basin", + "south_atlantic", + "south_total", + "tennessee", + "texas", + "us_total", + "uinta_basin", + "utah", + "virginia", + "washington", + "west_north_central", + "west_south_central", + "west_total", + "west_virginia", + "west_virginia_northern", + "west_virginia_southern", + "west_of_mississippi_river", + "western_region_total", + "wyoming", + ], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: producer_distributor_stocks (short tons); productive_capacity (short tons); recoverable_reserves (short tons).", + ) + mine_type: Literal["surface", "total", "underground"] | None = Field( + default=None, + description="Mine Type filter.", + ) + state_region: str | None = Field( + default=None, + description="State\\Region filter. Accepts a comma-separated list of values.", + ) + + +class EiaCoalReservesCapacityData(EiaApiData): + """Reserves Capacity. Coal capacity data, including productive capacity, stocks, and recoverable reserves by state, region and mine type. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https://www.eia.gov/coal/data/browser/""" + + mine_type: str | None = Field( + default=None, + description="Mine Type code.", + ) + mine_type_name: str | None = Field( + default=None, + description="Mine Type name.", + ) + state_region: str | None = Field( + default=None, + description="State\\Region code.", + ) + state_region_name: str | None = Field( + default=None, + description="State\\Region name.", + ) + producer_distributor_stocks: float | None = Field( + default=None, + description="Producer distributor stocks (short tons). Withheld or unavailable values return as null.", + ) + productive_capacity: float | None = Field( + default=None, + description="Productive capacity (short tons). Withheld or unavailable values return as null.", + ) + recoverable_reserves: float | None = Field( + default=None, + description="Recoverable reserves (short tons). Withheld or unavailable values return as null.", + ) + + +class EiaCoalReservesCapacityFetcher( + Fetcher[EiaCoalReservesCapacityQueryParams, list[EiaCoalReservesCapacityData]] +): + """Reserves Capacity fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaCoalReservesCapacityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaCoalReservesCapacityQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaCoalReservesCapacityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaCoalReservesCapacityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaCoalReservesCapacityData]: + """Transform the data.""" + return transform_dataset_data(EiaCoalReservesCapacityData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/crude_oil_imports.py b/openbb_platform/providers/eia/openbb_us_eia/models/crude_oil_imports.py new file mode 100644 index 00000000000..20f66576438 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/crude_oil_imports.py @@ -0,0 +1,246 @@ +"""Crude Oil Imports model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaCrudeOilImportsQueryParams(EiaApiQueryParams): + """Crude Oil Imports. Crude oil imports by country to destination, includes type, grade, quantity. Source: EIA-814 Interactive data product: www.eia.gov/petroleum/imports/companylevel/ + + Source: https://www.eia.gov/opendata/browser/crude-oil-imports + """ + + __group__ = "crude_oil_imports" + __dataset__ = "crude_oil_imports" + __json_schema_extra__ = { + "destination": {"multiple_items_allowed": True}, + "destination_type": { + "multiple_items_allowed": True, + "choices": [ + "port", + "port_padd", + "port_state", + "refinery", + "refinery_padd", + "refinery_state", + "united_states", + ], + }, + "grade": { + "multiple_items_allowed": True, + "choices": [ + "heavy_sour", + "heavy_sweet", + "light_sour", + "light_sweet", + "medium", + ], + }, + "origin": { + "multiple_items_allowed": True, + "choices": [ + "africa", + "albania", + "algeria", + "angola", + "argentina", + "asia_pacific", + "australia", + "azerbaijan", + "barbados", + "belize", + "bolivia", + "brazil", + "brunei", + "cameroon", + "canada", + "canada_region", + "chad", + "china", + "colombia", + "congo_brazzaville", + "congo_kinshasa", + "cote_d_ivoire", + "denmark", + "ecuador", + "egypt", + "equatorial_guinea", + "eurasia", + "europe", + "gabon", + "ghana", + "guatemala", + "guyana", + "indonesia", + "iran", + "iraq", + "italy", + "kazakhstan", + "kuwait", + "libya", + "malaysia", + "mauritania", + "mexico", + "middle_east", + "netherlands", + "nigeria", + "non_opec", + "norway", + "opec", + "oman", + "other_americas", + "panama", + "papua_new_guinea", + "peru", + "qatar", + "russia", + "saudi_arabia", + "senegal", + "south_africa", + "south_sudan", + "spain", + "syria", + "thailand", + "the_bahamas", + "trinidad_and_tobago", + "tunisia", + "united_arab_emirates", + "united_kingdom", + "venezuela", + "vietnam", + "world", + "yemen", + ], + }, + "origin_type": { + "multiple_items_allowed": True, + "choices": ["country", "opec_non_opec", "region", "world"], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + destination: str | None = Field( + default=None, + description="Destination Id filter. Accepts a comma-separated list of values. There are 513 valid values - use the `facet_options` endpoint to list them.", + ) + destination_type: ( + Literal[ + "port", + "port_padd", + "port_state", + "refinery", + "refinery_padd", + "refinery_state", + "united_states", + ] + | None + ) = Field( + default=None, + description="Destination Type filter.", + ) + grade: ( + Literal["heavy_sour", "heavy_sweet", "light_sour", "light_sweet", "medium"] + | None + ) = Field( + default=None, + description="Grade Id filter.", + ) + origin: str | None = Field( + default=None, + description="Origin Id filter. Accepts a comma-separated list of values.", + ) + origin_type: Literal["country", "opec_non_opec", "region", "world"] | None = Field( + default=None, + description="Origin Type filter.", + ) + + +class EiaCrudeOilImportsData(EiaApiData): + """Crude Oil Imports. Crude oil imports by country to destination, includes type, grade, quantity. Source: EIA-814 Interactive data product: www.eia.gov/petroleum/imports/companylevel/""" + + destination: str | None = Field( + default=None, + description="Destination Id code.", + ) + destination_name: str | None = Field( + default=None, + description="Destination Id name.", + ) + destination_type: str | None = Field( + default=None, + description="Destination Type code.", + ) + destination_type_name: str | None = Field( + default=None, + description="Destination Type name.", + ) + grade: str | None = Field( + default=None, + description="Grade Id code.", + ) + grade_name: str | None = Field( + default=None, + description="Grade Id name.", + ) + origin: str | None = Field( + default=None, + description="Origin Id code.", + ) + origin_name: str | None = Field( + default=None, + description="Origin Id name.", + ) + origin_type: str | None = Field( + default=None, + description="Origin Type code.", + ) + origin_type_name: str | None = Field( + default=None, + description="Origin Type name.", + ) + quantity: float | None = Field( + default=None, + description="Quantity (thousand barrels). Withheld or unavailable values return as null.", + ) + + +class EiaCrudeOilImportsFetcher( + Fetcher[EiaCrudeOilImportsQueryParams, list[EiaCrudeOilImportsData]] +): + """Crude Oil Imports fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaCrudeOilImportsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaCrudeOilImportsQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaCrudeOilImportsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaCrudeOilImportsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaCrudeOilImportsData]: + """Transform the data.""" + return transform_dataset_data(EiaCrudeOilImportsData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/data_browser.py b/openbb_platform/providers/eia/openbb_us_eia/models/data_browser.py new file mode 100644 index 00000000000..7e944cb2288 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/data_browser.py @@ -0,0 +1,218 @@ +"""EIA Data Browser model.""" + +from datetime import date as dateType +from typing import Any, Literal + +from openbb_core.app.model.abstract.error import OpenBBError +from openbb_core.provider.abstract.fetcher import Fetcher +from openbb_core.provider.abstract.query_params import QueryParams +from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS +from pydantic import Field, field_validator + +from openbb_us_eia.utils.api_query import EiaApiData, _snake, maybe_float, paginate + + +class EiaDataBrowserQueryParams(QueryParams): + """EIA Data Browser query parameters.""" + + route: str = Field( + description="The API route to query, e.g. 'petroleum/pri/spt' or" + " 'electricity/rto/region-data'.", + ) + frequency: str | None = Field( + default=None, + description="The data frequency id, e.g. 'monthly'." + " The default is the route's native frequency.", + ) + data_type: str | None = Field( + default=None, + description="Data column id(s) to return, comma-separated," + " e.g. 'value' or 'quantity,price'." + " The default returns every column available for the route.", + ) + facets: str | None = Field( + default=None, + description="Facet filters as 'facetId:value' pairs separated by" + " semicolons, with multiple values comma-separated," + " e.g. 'duoarea:NUS;product:EPD2D,EPD2DXL0'.", + ) + start_date: dateType | None = Field( + default=None, + description=QUERY_DESCRIPTIONS.get("start_date", ""), + ) + end_date: dateType | None = Field( + default=None, + description=QUERY_DESCRIPTIONS.get("end_date", ""), + ) + sort: Literal["asc", "desc"] = Field( + default="asc", + description="Sort the results by date.", + ) + limit: int | None = Field( + default=None, + gt=0, + description="Maximum number of rows to return." + " The default returns all rows, paginating requests as needed.", + ) + + @field_validator("route", mode="after") + @classmethod + def _clean_route(cls, value: str) -> str: + """Strip separators and any trailing '/data' segment from the route.""" + route = value.strip().strip("/") + return route.removesuffix("/data") + + @property + def facet_query(self) -> dict[str, list[str]]: + """Parse the facets string into a facet id to values mapping.""" + query: dict[str, list[str]] = {} + for raw_pair in (self.facets or "").split(";"): + pair = raw_pair.strip() + if not pair: + continue + if ":" not in pair: + raise OpenBBError( + ValueError( + f"Invalid facet filter '{pair}'." + " Use 'facetId:value1,value2' pairs separated by semicolons." + ) + ) + facet_id, values = pair.split(":", 1) + query[facet_id.strip()] = [ + item.strip() for item in values.split(",") if item.strip() + ] + return query + + +class EiaDataBrowserData(EiaApiData): + """EIA Data Browser data.""" + + +class EiaDataBrowserFetcher( + Fetcher[EiaDataBrowserQueryParams, list[EiaDataBrowserData]] +): + """EIA Data Browser fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaDataBrowserQueryParams: + """Transform the query parameters.""" + query = EiaDataBrowserQueryParams(**params) + _ = query.facet_query + return query + + @staticmethod + async def aextract_data( + query: EiaDataBrowserQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Resolve the route's metadata and request all pages of data.""" + from openbb_core.provider.utils.helpers import amake_request, amake_requests + + from openbb_us_eia.utils.catalog import format_period + from openbb_us_eia.utils.helpers import ( + API_BASE, + build_data_url, + response_callback, + ) + + api_key = credentials.get("eia_api_key", "") if credentials else "" + metadata = await amake_request( + f"{API_BASE}/{query.route}?api_key={api_key}", + response_callback=response_callback, + ) + node = metadata.get("response", {}) # ty: ignore[unresolved-attribute] + if node.get("routes"): + children = ", ".join(child["id"] for child in node["routes"]) + raise OpenBBError( + f"'{query.route}' is not a data route. Child routes: {children}" + ) + frequencies = {freq["id"]: freq for freq in node.get("frequency", []) or []} + if not frequencies: + raise OpenBBError(f"'{query.route}' is not a valid EIA data route.") + frequency = query.frequency or node.get("defaultFrequency") + if frequency not in frequencies: + raise OpenBBError( + f"Frequency '{query.frequency}' is not available for" + f" '{query.route}'. Choices: {', '.join(frequencies)}" + ) + period_format = frequencies[frequency].get("format", "YYYY-MM-DD") + + data_columns = list(node.get("data") or {}) + if query.data_type: + requested = [ + item.strip() for item in query.data_type.split(",") if item.strip() + ] + invalid = [item for item in requested if item not in data_columns] + if invalid: + raise OpenBBError( + f"Invalid data_type value(s) {', '.join(invalid)} for" + f" '{query.route}'. Choices: {', '.join(data_columns)}" + ) + data_columns = requested + + facet_ids = {facet["id"] for facet in node.get("facets", []) or []} + facets = query.facet_query + unknown = sorted(set(facets) - facet_ids) + if unknown: + raise OpenBBError( + f"Invalid facet id(s) {', '.join(unknown)} for '{query.route}'." + f" Choices: {', '.join(sorted(facet_ids))}" + ) + + request = { + "path": query.route, + "api_key": api_key, + "frequency": frequency, + "data_columns": data_columns, + "facets": facets, + "facet_params": {facet_id: facet_id for facet_id in facet_ids}, + "coverage": (node.get("startPeriod"), node.get("endPeriod")), + "start": ( + format_period(query.start_date, period_format) + if query.start_date + else None + ), + "end": ( + format_period(query.end_date, period_format) if query.end_date else None + ), + "sort": query.sort, + } + result = await paginate( + build_data_url, + request, + limit=query.limit, + amake_request=amake_request, + amake_requests=amake_requests, + response_callback=response_callback, + ) + result["period_format"] = period_format + result["data_columns"] = data_columns + return result + + @staticmethod + def transform_data( + query: EiaDataBrowserQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaDataBrowserData]: + """Normalize column names, parse periods, and sort the rows.""" + from openbb_us_eia.utils.catalog import parse_period + + date_format = data.get("date_format") or data["period_format"] + numeric = {_snake(column) for column in data["data_columns"]} + rows: list[dict] = [] + for row in data["rows"]: + record: dict[str, Any] = { + "date": parse_period(str(row["period"]), date_format) + } + for key, value in row.items(): + if key == "period": + continue + name = _snake(key) + record[name] = maybe_float(value) if name in numeric else value + rows.append(record) + rows.sort(key=lambda row: row["date"], reverse=query.sort == "desc") + if query.limit is not None: + rows = rows[: query.limit] + return [EiaDataBrowserData(**row) for row in rows] diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/__init__.py b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/__init__.py new file mode 100644 index 00000000000..51db865ed39 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/__init__.py @@ -0,0 +1 @@ +"""EIA Densified Biomass models.""" diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/capacity_by_region.py b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/capacity_by_region.py new file mode 100644 index 00000000000..57693cfb958 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/capacity_by_region.py @@ -0,0 +1,106 @@ +"""Capacity by Region model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaDensifiedBiomassCapacityByRegionQueryParams(EiaApiQueryParams): + """Capacity by Region. Densified biomass capacity includes number of facilities and number of employees. Source: EIA-63C Report: www.eia.gov/biomass/ + + Source: https://www.eia.gov/opendata/browser/densified-biomass/capacity-by-region + """ + + __group__ = "densified_biomass" + __dataset__ = "capacity_by_region" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": ["capacity", "number_of_facilities", "number_of_fte_employees"], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["east", "south", "us_total", "west"], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: capacity (tons); number_of_facilities (number of facilities); number_of_fte_employees (number of fte employees).", + ) + region: Literal["east", "south", "us_total", "west"] | None = Field( + default=None, + description="Region filter.", + ) + + +class EiaDensifiedBiomassCapacityByRegionData(EiaApiData): + """Capacity by Region. Densified biomass capacity includes number of facilities and number of employees. Source: EIA-63C Report: www.eia.gov/biomass/""" + + region: str | None = Field( + default=None, + description="Region code.", + ) + region_name: str | None = Field( + default=None, + description="Region name.", + ) + capacity: float | None = Field( + default=None, + description="Capacity (tons). Withheld or unavailable values return as null.", + ) + number_of_facilities: float | None = Field( + default=None, + description="Number of facilities (number of facilities). Withheld or unavailable values return as null.", + ) + number_of_fte_employees: float | None = Field( + default=None, + description="Number of fte employees (number of fte employees). Withheld or unavailable values return as null.", + ) + + +class EiaDensifiedBiomassCapacityByRegionFetcher( + Fetcher[ + EiaDensifiedBiomassCapacityByRegionQueryParams, + list[EiaDensifiedBiomassCapacityByRegionData], + ] +): + """Capacity by Region fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaDensifiedBiomassCapacityByRegionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaDensifiedBiomassCapacityByRegionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaDensifiedBiomassCapacityByRegionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaDensifiedBiomassCapacityByRegionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaDensifiedBiomassCapacityByRegionData]: + """Transform the data.""" + return transform_dataset_data( + EiaDensifiedBiomassCapacityByRegionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/characteristics_by_region.py b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/characteristics_by_region.py new file mode 100644 index 00000000000..22030781630 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/characteristics_by_region.py @@ -0,0 +1,133 @@ +"""Characteristics by Region model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaDensifiedBiomassCharacteristicsByRegionQueryParams(EiaApiQueryParams): + """Characteristics by Region. Densified biomass characteristics includes fuel type, average ash, heat, and moisture content by region. Source: EIA-63C Report: www.eia.gov/biomass/ + + Source: https://www.eia.gov/opendata/browser/densified-biomass/characteristics-by-region + """ + + __group__ = "densified_biomass" + __dataset__ = "characteristics_by_region" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": ["average_ash", "average_heat", "average_moisture"], + }, + "fuel_type": { + "multiple_items_allowed": True, + "choices": [ + "compressed_bricks_log", + "wood_pellets_premium_standard", + "wood_pellets_utility", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["east", "south", "west"], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: average_ash (percent by weight); average_heat (btu/lb); average_moisture (percent by weight).", + ) + fuel_type: ( + Literal[ + "compressed_bricks_log", + "wood_pellets_premium_standard", + "wood_pellets_utility", + ] + | None + ) = Field( + default=None, + description="Fuel Type filter.", + ) + region: Literal["east", "south", "west"] | None = Field( + default=None, + description="Region filter.", + ) + + +class EiaDensifiedBiomassCharacteristicsByRegionData(EiaApiData): + """Characteristics by Region. Densified biomass characteristics includes fuel type, average ash, heat, and moisture content by region. Source: EIA-63C Report: www.eia.gov/biomass/""" + + fuel_type: str | None = Field( + default=None, + description="Fuel Type code.", + ) + fuel_type_name: str | None = Field( + default=None, + description="Fuel Type name.", + ) + region: str | None = Field( + default=None, + description="Region code.", + ) + region_name: str | None = Field( + default=None, + description="Region name.", + ) + average_ash: float | None = Field( + default=None, + description="Average ash (percent by weight). Withheld or unavailable values return as null.", + ) + average_heat: float | None = Field( + default=None, + description="Average heat (btu/lb). Withheld or unavailable values return as null.", + ) + average_moisture: float | None = Field( + default=None, + description="Average moisture (percent by weight). Withheld or unavailable values return as null.", + ) + + +class EiaDensifiedBiomassCharacteristicsByRegionFetcher( + Fetcher[ + EiaDensifiedBiomassCharacteristicsByRegionQueryParams, + list[EiaDensifiedBiomassCharacteristicsByRegionData], + ] +): + """Characteristics by Region fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaDensifiedBiomassCharacteristicsByRegionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaDensifiedBiomassCharacteristicsByRegionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaDensifiedBiomassCharacteristicsByRegionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaDensifiedBiomassCharacteristicsByRegionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaDensifiedBiomassCharacteristicsByRegionData]: + """Transform the data.""" + return transform_dataset_data( + EiaDensifiedBiomassCharacteristicsByRegionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/export_sales_and_price.py b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/export_sales_and_price.py new file mode 100644 index 00000000000..a5b71742a30 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/export_sales_and_price.py @@ -0,0 +1,86 @@ +"""Export Sales and Price model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaDensifiedBiomassExportSalesAndPriceQueryParams(EiaApiQueryParams): + """Export Sales and Price. Densified biomass export prices and quantity. Source: EIA-63C Report: www.eia.gov/biomass/ + + Source: https://www.eia.gov/opendata/browser/densified-biomass/export-sales-and-price + """ + + __group__ = "densified_biomass" + __dataset__ = "export_sales_and_price" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": ["average_price", "quantity"], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: average_price (USD per ton); quantity (tons).", + ) + + +class EiaDensifiedBiomassExportSalesAndPriceData(EiaApiData): + """Export Sales and Price. Densified biomass export prices and quantity. Source: EIA-63C Report: www.eia.gov/biomass/""" + + average_price: float | None = Field( + default=None, + description="Average price (USD per ton). Withheld or unavailable values return as null.", + ) + quantity: float | None = Field( + default=None, + description="Quantity (tons). Withheld or unavailable values return as null.", + ) + + +class EiaDensifiedBiomassExportSalesAndPriceFetcher( + Fetcher[ + EiaDensifiedBiomassExportSalesAndPriceQueryParams, + list[EiaDensifiedBiomassExportSalesAndPriceData], + ] +): + """Export Sales and Price fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaDensifiedBiomassExportSalesAndPriceQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaDensifiedBiomassExportSalesAndPriceQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaDensifiedBiomassExportSalesAndPriceQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaDensifiedBiomassExportSalesAndPriceQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaDensifiedBiomassExportSalesAndPriceData]: + """Transform the data.""" + return transform_dataset_data( + EiaDensifiedBiomassExportSalesAndPriceData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/feedstocks_and_costs.py b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/feedstocks_and_costs.py new file mode 100644 index 00000000000..14704d0724c --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/feedstocks_and_costs.py @@ -0,0 +1,112 @@ +"""Feedstocks and Costs model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaDensifiedBiomassFeedstocksAndCostsQueryParams(EiaApiQueryParams): + """Feedstocks and Costs. Densified biomass feedstocks and cost by type. Source: EIA-63C Report: www.eia.gov/biomass/ + + Source: https://www.eia.gov/opendata/browser/densified-biomass/feedstocks-and-cost + """ + + __group__ = "densified_biomass" + __dataset__ = "feedstocks_and_costs" + __json_schema_extra__ = { + "data_type": {"multiple_items_allowed": True, "choices": ["cost", "quantity"]}, + "fuel_type": { + "multiple_items_allowed": True, + "choices": [ + "other_residuals", + "roundwood_pulpwood", + "sawmill_residuals", + "wood_product_manufacturing_residuals", + ], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: cost (USD per ton); quantity (tons).", + ) + fuel_type: ( + Literal[ + "other_residuals", + "roundwood_pulpwood", + "sawmill_residuals", + "wood_product_manufacturing_residuals", + ] + | None + ) = Field( + default=None, + description="Fuel Type filter.", + ) + + +class EiaDensifiedBiomassFeedstocksAndCostsData(EiaApiData): + """Feedstocks and Costs. Densified biomass feedstocks and cost by type. Source: EIA-63C Report: www.eia.gov/biomass/""" + + fuel_type: str | None = Field( + default=None, + description="Fuel Type code.", + ) + fuel_type_name: str | None = Field( + default=None, + description="Fuel Type name.", + ) + cost: float | None = Field( + default=None, + description="Cost (USD per ton). Withheld or unavailable values return as null.", + ) + quantity: float | None = Field( + default=None, + description="Quantity (tons). Withheld or unavailable values return as null.", + ) + + +class EiaDensifiedBiomassFeedstocksAndCostsFetcher( + Fetcher[ + EiaDensifiedBiomassFeedstocksAndCostsQueryParams, + list[EiaDensifiedBiomassFeedstocksAndCostsData], + ] +): + """Feedstocks and Costs fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaDensifiedBiomassFeedstocksAndCostsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaDensifiedBiomassFeedstocksAndCostsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaDensifiedBiomassFeedstocksAndCostsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaDensifiedBiomassFeedstocksAndCostsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaDensifiedBiomassFeedstocksAndCostsData]: + """Transform the data.""" + return transform_dataset_data( + EiaDensifiedBiomassFeedstocksAndCostsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/inventories_by_region.py b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/inventories_by_region.py new file mode 100644 index 00000000000..8df0cab026a --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/inventories_by_region.py @@ -0,0 +1,117 @@ +"""Inventories by Region model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaDensifiedBiomassInventoriesByRegionQueryParams(EiaApiQueryParams): + """Inventories by Region. Densified biomass inventories by region and fuel type. Source: EIA-63C Report: www.eia.gov/biomass/ + + Source: https://www.eia.gov/opendata/browser/densified-biomass/inventories-by-region + """ + + __group__ = "densified_biomass" + __dataset__ = "inventories_by_region" + __json_schema_extra__ = { + "fuel_type": { + "multiple_items_allowed": True, + "choices": [ + "compressed_bricks_log", + "wood_pellets_premium_standard", + "wood_pellets_utility", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["east", "south", "us_total", "west"], + }, + } + + fuel_type: ( + Literal[ + "compressed_bricks_log", + "wood_pellets_premium_standard", + "wood_pellets_utility", + ] + | None + ) = Field( + default=None, + description="Fuel Type filter.", + ) + region: Literal["east", "south", "us_total", "west"] | None = Field( + default=None, + description="Region filter.", + ) + + +class EiaDensifiedBiomassInventoriesByRegionData(EiaApiData): + """Inventories by Region. Densified biomass inventories by region and fuel type. Source: EIA-63C Report: www.eia.gov/biomass/""" + + fuel_type: str | None = Field( + default=None, + description="Fuel Type code.", + ) + fuel_type_name: str | None = Field( + default=None, + description="Fuel Type name.", + ) + region: str | None = Field( + default=None, + description="Region code.", + ) + region_name: str | None = Field( + default=None, + description="Region name.", + ) + inventory: float | None = Field( + default=None, + description="Inventory. Withheld or unavailable values return as null.", + ) + + +class EiaDensifiedBiomassInventoriesByRegionFetcher( + Fetcher[ + EiaDensifiedBiomassInventoriesByRegionQueryParams, + list[EiaDensifiedBiomassInventoriesByRegionData], + ] +): + """Inventories by Region fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaDensifiedBiomassInventoriesByRegionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaDensifiedBiomassInventoriesByRegionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaDensifiedBiomassInventoriesByRegionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaDensifiedBiomassInventoriesByRegionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaDensifiedBiomassInventoriesByRegionData]: + """Transform the data.""" + return transform_dataset_data( + EiaDensifiedBiomassInventoriesByRegionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/production_by_region.py b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/production_by_region.py new file mode 100644 index 00000000000..52761553be1 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/production_by_region.py @@ -0,0 +1,117 @@ +"""Production by Region model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaDensifiedBiomassProductionByRegionQueryParams(EiaApiQueryParams): + """Production by Region. Densified biomass production by region and fuel type. Source: EIA-63C Report: www.eia.gov/biomass/ + + Source: https://www.eia.gov/opendata/browser/densified-biomass/production-by-region + """ + + __group__ = "densified_biomass" + __dataset__ = "production_by_region" + __json_schema_extra__ = { + "fuel_type": { + "multiple_items_allowed": True, + "choices": [ + "compressed_bricks_log", + "wood_pellets_premium_standard", + "wood_pellets_utility", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["east", "south", "us_total", "west"], + }, + } + + fuel_type: ( + Literal[ + "compressed_bricks_log", + "wood_pellets_premium_standard", + "wood_pellets_utility", + ] + | None + ) = Field( + default=None, + description="Fuel Type filter.", + ) + region: Literal["east", "south", "us_total", "west"] | None = Field( + default=None, + description="Region filter.", + ) + + +class EiaDensifiedBiomassProductionByRegionData(EiaApiData): + """Production by Region. Densified biomass production by region and fuel type. Source: EIA-63C Report: www.eia.gov/biomass/""" + + fuel_type: str | None = Field( + default=None, + description="Fuel Type code.", + ) + fuel_type_name: str | None = Field( + default=None, + description="Fuel Type name.", + ) + region: str | None = Field( + default=None, + description="Region code.", + ) + region_name: str | None = Field( + default=None, + description="Region name.", + ) + production: float | None = Field( + default=None, + description="Production (tons). Withheld or unavailable values return as null.", + ) + + +class EiaDensifiedBiomassProductionByRegionFetcher( + Fetcher[ + EiaDensifiedBiomassProductionByRegionQueryParams, + list[EiaDensifiedBiomassProductionByRegionData], + ] +): + """Production by Region fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaDensifiedBiomassProductionByRegionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaDensifiedBiomassProductionByRegionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaDensifiedBiomassProductionByRegionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaDensifiedBiomassProductionByRegionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaDensifiedBiomassProductionByRegionData]: + """Transform the data.""" + return transform_dataset_data( + EiaDensifiedBiomassProductionByRegionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/sales_and_price_by_region.py b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/sales_and_price_by_region.py new file mode 100644 index 00000000000..d507e073a81 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/sales_and_price_by_region.py @@ -0,0 +1,102 @@ +"""Sales and Price by Region model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaDensifiedBiomassSalesAndPriceByRegionQueryParams(EiaApiQueryParams): + """Sales and Price by Region. Densified biomass sales and average price by region. Source: EIA-63C Report: www.eia.gov/biomass/ + + Source: https://www.eia.gov/opendata/browser/densified-biomass/sales-and-price-by-region + """ + + __group__ = "densified_biomass" + __dataset__ = "sales_and_price_by_region" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": ["average_price", "quantity"], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["east", "south", "us_total", "west"], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: average_price (USD per ton); quantity (tons).", + ) + region: Literal["east", "south", "us_total", "west"] | None = Field( + default=None, + description="Region filter.", + ) + + +class EiaDensifiedBiomassSalesAndPriceByRegionData(EiaApiData): + """Sales and Price by Region. Densified biomass sales and average price by region. Source: EIA-63C Report: www.eia.gov/biomass/""" + + region: str | None = Field( + default=None, + description="Region code.", + ) + region_name: str | None = Field( + default=None, + description="Region name.", + ) + average_price: float | None = Field( + default=None, + description="Average price (USD per ton). Withheld or unavailable values return as null.", + ) + quantity: float | None = Field( + default=None, + description="Quantity (tons). Withheld or unavailable values return as null.", + ) + + +class EiaDensifiedBiomassSalesAndPriceByRegionFetcher( + Fetcher[ + EiaDensifiedBiomassSalesAndPriceByRegionQueryParams, + list[EiaDensifiedBiomassSalesAndPriceByRegionData], + ] +): + """Sales and Price by Region fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaDensifiedBiomassSalesAndPriceByRegionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaDensifiedBiomassSalesAndPriceByRegionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaDensifiedBiomassSalesAndPriceByRegionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaDensifiedBiomassSalesAndPriceByRegionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaDensifiedBiomassSalesAndPriceByRegionData]: + """Transform the data.""" + return transform_dataset_data( + EiaDensifiedBiomassSalesAndPriceByRegionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/wood_pellet_plant_capacity.py b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/wood_pellet_plant_capacity.py new file mode 100644 index 00000000000..f78332b1b03 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/densified_biomass/wood_pellet_plant_capacity.py @@ -0,0 +1,187 @@ +"""Wood Pellet Plant Capacity model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaDensifiedBiomassWoodPelletPlantCapacityQueryParams(EiaApiQueryParams): + """Wood Pellet Plant Capacity. Details on wood pellet plants includes region, respondent, capacity, and status. Source: EIA-63C Report: www.eia.gov/biomass/ + + Source: https://www.eia.gov/opendata/browser/densified-biomass/wood-pellet-plants + """ + + __group__ = "densified_biomass" + __dataset__ = "wood_pellet_plant_capacity" + __json_schema_extra__ = { + "region": { + "multiple_items_allowed": True, + "choices": ["east", "south", "west"], + }, + "respondent": {"multiple_items_allowed": True}, + "state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "florida", + "georgia", + "idaho", + "illinois", + "indiana", + "iowa", + "kentucky", + "louisiana", + "maine", + "michigan", + "mississippi", + "missouri", + "new_hampshire", + "new_mexico", + "new_york", + "north_carolina", + "ohio", + "oregon", + "pennsylvania", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "utah", + "vermont", + "virginia", + "washington", + "west_virginia", + "wisconsin", + ], + }, + "status": { + "multiple_items_allowed": True, + "choices": [ + "currently_operating", + "none", + "temporarily_not_in_operation", + "under_construction_planned", + "currently_operating_currently_operating", + ], + }, + } + + region: Literal["east", "south", "west"] | None = Field( + default=None, + description="Region filter.", + ) + respondent: str | None = Field( + default=None, + description="Respondent filter. Accepts a comma-separated list of values. There are 161 valid values - use the `facet_options` endpoint to list them.", + ) + state: str | None = Field( + default=None, + description="State filter. Accepts a comma-separated list of values.", + ) + status: ( + Literal[ + "currently_operating", + "none", + "temporarily_not_in_operation", + "under_construction_planned", + "currently_operating_currently_operating", + ] + | None + ) = Field( + default=None, + description="Operational Status filter.", + ) + + +class EiaDensifiedBiomassWoodPelletPlantCapacityData(EiaApiData): + """Wood Pellet Plant Capacity. Details on wood pellet plants includes region, respondent, capacity, and status. Source: EIA-63C Report: www.eia.gov/biomass/""" + + region: str | None = Field( + default=None, + description="Region code.", + ) + region_name: str | None = Field( + default=None, + description="Region name.", + ) + respondent: str | None = Field( + default=None, + description="Respondent code.", + ) + respondent_name: str | None = Field( + default=None, + description="Respondent name.", + ) + state: str | None = Field( + default=None, + description="State code.", + ) + state_name: str | None = Field( + default=None, + description="State name.", + ) + status: str | None = Field( + default=None, + description="Operational Status code.", + ) + status_name: str | None = Field( + default=None, + description="Operational Status name.", + ) + capacity: float | None = Field( + default=None, + description="Capacity (tons per year). Withheld or unavailable values return as null.", + ) + + +class EiaDensifiedBiomassWoodPelletPlantCapacityFetcher( + Fetcher[ + EiaDensifiedBiomassWoodPelletPlantCapacityQueryParams, + list[EiaDensifiedBiomassWoodPelletPlantCapacityData], + ] +): + """Wood Pellet Plant Capacity fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaDensifiedBiomassWoodPelletPlantCapacityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaDensifiedBiomassWoodPelletPlantCapacityQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaDensifiedBiomassWoodPelletPlantCapacityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaDensifiedBiomassWoodPelletPlantCapacityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaDensifiedBiomassWoodPelletPlantCapacityData]: + """Transform the data.""" + return transform_dataset_data( + EiaDensifiedBiomassWoodPelletPlantCapacityData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/electricity/__init__.py b/openbb_platform/providers/eia/openbb_us_eia/models/electricity/__init__.py new file mode 100644 index 00000000000..f438ffbd90b --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/electricity/__init__.py @@ -0,0 +1 @@ +"""EIA Electricity models.""" diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/electricity/electric_power_operations.py b/openbb_platform/providers/eia/openbb_us_eia/models/electricity/electric_power_operations.py new file mode 100644 index 00000000000..2f3be9c9e08 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/electricity/electric_power_operations.py @@ -0,0 +1,331 @@ +"""Electric Power Operations (Annual and Monthly) model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaElectricityElectricPowerOperationsQueryParams(EiaApiQueryParams): + """Electric Power Operations (Annual and Monthly). Monthly and annual electric power operations by state, sector, and energy source. Source: Form EIA-923 + + Source: https://www.eia.gov/opendata/browser/electricity/electric-power-operational-data + """ + + __group__ = "electricity" + __dataset__ = "electric_power_operations" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "ash_content", + "consumption_for_eg", + "consumption_for_eg_btu", + "consumption_uto", + "consumption_uto_btu", + "cost", + "cost_per_btu", + "generation", + "heat_content", + "receipts", + "receipts_btu", + "stocks", + "sulfur_content", + "total_consumption", + "total_consumption_btu", + ], + }, + "fuel": { + "multiple_items_allowed": True, + "choices": [ + "all_coal_products", + "all_fuels", + "all_renewables", + "anthracite_coal", + "biogenic_municipal_solid_waste", + "biomass", + "bituminous_coal", + "bituminous_coal_and_synthetic_coal", + "coal_excluding_waste_coal", + "conventional_hydroelectric", + "distillate_fuel_oil", + "estimated_small_scale_solar_photovoltaic", + "estimated_total_solar", + "estimated_total_solar_photovoltaic", + "fossil_fuels", + "geothermal", + "hydro_electric_pumped_storage", + "landfill_gas", + "lignite_coal", + "municiapl_landfill_gas", + "natural_gas", + "natural_gas_and_other_gases", + "nuclear", + "offshore_wind_turbine", + "onshore_wind_turbine", + "other", + "other_gases", + "other_renewables", + "petroleum", + "petroleum_coke", + "petroleum_liquids", + "refined_coal", + "renewable", + "renewable_waste_products", + "residual_fuel_oil", + "solar", + "solar_photovoltaic", + "solar_thermal", + "subbituminous_coal", + "waste_coal", + "waste_oil_and_other_oils", + "wind", + "wood_and_wood_wastes", + ], + }, + "sector": { + "multiple_items_allowed": True, + "choices": [ + "all_commercial", + "all_industrial", + "all_sectors", + "coal_consumption", + "commercial_chp", + "commercial_non_chp", + "electric_power", + "electric_power_sector_non_chp", + "electric_utility", + "ipp_chp", + "ipp_non_chp", + "independent_power_producers", + "industrial_chp", + "industrial_non_chp", + "residential", + ], + }, + "state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "district_of_columbia", + "east_north_central", + "east_south_central", + "florida", + "georgia", + "hawaii", + "idaho", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "middle_atlantic", + "minnesota", + "mississippi", + "missouri", + "montana", + "mountain", + "nebraska", + "nevada", + "new_england", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pacific", + "pacific_contiguous", + "pacific_noncontiguous", + "pennsylvania", + "puerto_rico", + "rhode_island", + "south_atlantic", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "us_total", + "utah", + "vermont", + "virginia", + "washington", + "west_north_central", + "west_south_central", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + } + + frequency: Literal["annual", "monthly", "quarterly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: ash_content = Average Ash Content of Consumed Fuel; consumption_for_eg = Consumption of Fuels for Electricity Generation (Physical Units); consumption_for_eg_btu = Consumption of Fuels for Electricity Generation (BTUs); consumption_uto = Consumption of Fuels for Useful Thermal Output (Physical Units); consumption_uto_btu = Consumption of Fuels for Useful Thermal Output (BTUs); cost = Average Cost of Fuels (per Physical Unit); cost_per_btu = Average Cost of Fuels (per BTU); generation = Utility Scale Electricity Net Generation; heat_content = Average Heat Content of Consumed Fuels; receipts = Receipts of Fuel (Physical Units); receipts_btu = Receipts of Fuel (BTUs); stocks = Stocks of Fuel (Physical Units); sulfur_content = Average Sulfur Content of Consumed Fuel; total_consumption = Consumption of Fuels for Electricity Generation and Useful Thermal Output (Physical Units); total_consumption_btu = Consumption of Fuels for Electricity Generation and Useful Thermal Output (BTUs).", + ) + fuel: str | None = Field( + default=None, + description="Energy Source filter. Accepts a comma-separated list of values.", + ) + sector: str | None = Field( + default=None, + description="Sector filter. Accepts a comma-separated list of values.", + ) + state: str | None = Field( + default=None, + description="State / Census Region filter. Accepts a comma-separated list of values.", + ) + + +class EiaElectricityElectricPowerOperationsData(EiaApiData): + """Electric Power Operations (Annual and Monthly). Monthly and annual electric power operations by state, sector, and energy source. Source: Form EIA-923""" + + fuel: str | None = Field( + default=None, + description="Energy Source code.", + ) + fuel_name: str | None = Field( + default=None, + description="Energy Source name.", + ) + sector: str | None = Field( + default=None, + description="Sector code.", + ) + sector_name: str | None = Field( + default=None, + description="Sector name.", + ) + state: str | None = Field( + default=None, + description="State / Census Region code.", + ) + state_name: str | None = Field( + default=None, + description="State / Census Region name.", + ) + ash_content: float | None = Field( + default=None, + description="Average Ash Content of Consumed Fuel. Withheld or unavailable values return as null.", + ) + consumption_for_eg: float | None = Field( + default=None, + description="Consumption of Fuels for Electricity Generation (Physical Units). Withheld or unavailable values return as null.", + ) + consumption_for_eg_btu: float | None = Field( + default=None, + description="Consumption of Fuels for Electricity Generation (BTUs). Withheld or unavailable values return as null.", + ) + consumption_uto: float | None = Field( + default=None, + description="Consumption of Fuels for Useful Thermal Output (Physical Units). Withheld or unavailable values return as null.", + ) + consumption_uto_btu: float | None = Field( + default=None, + description="Consumption of Fuels for Useful Thermal Output (BTUs). Withheld or unavailable values return as null.", + ) + cost: float | None = Field( + default=None, + description="Average Cost of Fuels (per Physical Unit). Withheld or unavailable values return as null.", + ) + cost_per_btu: float | None = Field( + default=None, + description="Average Cost of Fuels (per BTU). Withheld or unavailable values return as null.", + ) + generation: float | None = Field( + default=None, + description="Utility Scale Electricity Net Generation. Withheld or unavailable values return as null.", + ) + heat_content: float | None = Field( + default=None, + description="Average Heat Content of Consumed Fuels. Withheld or unavailable values return as null.", + ) + receipts: float | None = Field( + default=None, + description="Receipts of Fuel (Physical Units). Withheld or unavailable values return as null.", + ) + receipts_btu: float | None = Field( + default=None, + description="Receipts of Fuel (BTUs). Withheld or unavailable values return as null.", + ) + stocks: float | None = Field( + default=None, + description="Stocks of Fuel (Physical Units). Withheld or unavailable values return as null.", + ) + sulfur_content: float | None = Field( + default=None, + description="Average Sulfur Content of Consumed Fuel. Withheld or unavailable values return as null.", + ) + total_consumption: float | None = Field( + default=None, + description="Consumption of Fuels for Electricity Generation and Useful Thermal Output (Physical Units). Withheld or unavailable values return as null.", + ) + total_consumption_btu: float | None = Field( + default=None, + description="Consumption of Fuels for Electricity Generation and Useful Thermal Output (BTUs). Withheld or unavailable values return as null.", + ) + + +class EiaElectricityElectricPowerOperationsFetcher( + Fetcher[ + EiaElectricityElectricPowerOperationsQueryParams, + list[EiaElectricityElectricPowerOperationsData], + ] +): + """Electric Power Operations (Annual and Monthly) fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaElectricityElectricPowerOperationsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaElectricityElectricPowerOperationsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaElectricityElectricPowerOperationsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaElectricityElectricPowerOperationsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaElectricityElectricPowerOperationsData]: + """Transform the data.""" + return transform_dataset_data( + EiaElectricityElectricPowerOperationsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/electricity/electric_power_operations_for_individual_power_plants.py b/openbb_platform/providers/eia/openbb_us_eia/models/electricity/electric_power_operations_for_individual_power_plants.py new file mode 100644 index 00000000000..25ff6043d7b --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/electricity/electric_power_operations_for_individual_power_plants.py @@ -0,0 +1,341 @@ +"""Electric Power Operations for Individual Power Plants (Annual and Monthly) model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaElectricityElectricPowerOperationsForIndividualPowerPlantsQueryParams( + EiaApiQueryParams +): + """Electric Power Operations for Individual Power Plants (Annual and Monthly). Annual and monthly electric power operations for individual power plants, by energy source and prime mover Source: Form EIA-923 + + Source: https://www.eia.gov/opendata/browser/electricity/facility-fuel + """ + + __group__ = "electricity" + __dataset__ = "electric_power_operations_for_individual_power_plants" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "average_heat_content", + "consumption_for_eg", + "consumption_for_eg_btu", + "generation", + "gross_generation", + "total_consumption", + "total_consumption_btu", + ], + }, + "fuel": { + "multiple_items_allowed": True, + "choices": [ + "agricultural_by_products", + "anthracite_coal", + "bituminous_coal", + "black_liquor", + "blast_furnace_gas", + "coal_synfuel", + "coal_derived_synthesis_gas", + "distillate_fuel_oil", + "electricity_used_for_energy_storage", + "gaseous_propane", + "geothermal", + "hydrogen", + "jet_fuel", + "kerosene", + "landfill_gas", + "lignite_coal", + "municipal_solid_waste", + "municipal_solid_waste_biogenic", + "municipal_solid_waste_non_biogenic", + "natural_gas", + "nuclear", + "other", + "other_biomass_gas", + "other_biomass_liquids", + "other_biomass_solids", + "other_gas", + "other_gases", + "petroleum_coke", + "purchased_steam", + "refined_coal", + "residual_fuel_oil", + "sludge_waste", + "solar", + "subbituminous_coal", + "synthesis_gas_from_petroleum_coke", + "tire_derived_fuels", + "total", + "waste_coal", + "waste_heat", + "waste_oil", + "water", + "wind", + "wood_waste_liquids", + "wood_wood_waste", + ], + }, + "fuel_type": { + "multiple_items_allowed": True, + "choices": [ + "coal", + "distillate_fuel_oil", + "geothermal", + "hydroelectric_conventional", + "hydroelectric_pumped_storage", + "municiapl_landfill_gas", + "natural_gas", + "nuclear", + "other", + "other_gases", + "petroleum_coke", + "residual_fuel_oil", + "solar", + "total", + "waste_coal", + "waste_oil_and_other_oils", + "wind", + "wood_waste_solids", + "other_renewables", + ], + }, + "plant": {"multiple_items_allowed": True}, + "prime_mover": { + "multiple_items_allowed": True, + "choices": [ + "value", + "all", + "ba", + "bt", + "ca", + "cc", + "ce", + "cp", + "cs", + "ct", + "fc", + "fw", + "gt", + "hy", + "ic", + "ot", + "ps", + "pv", + "st", + "ws", + "wt", + ], + }, + "state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "district_of_columbia", + "florida", + "georgia", + "hawaii", + "idaho", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "minnesota", + "mississippi", + "missouri", + "montana", + "nebraska", + "nevada", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "none", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pennsylvania", + "puerto_rico", + "rhode_island", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "utah", + "vermont", + "virginia", + "washington", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + } + + frequency: Literal["annual", "monthly", "quarterly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: average_heat_content = Average Heat Content of Consumed Fuels; consumption_for_eg = Consumption of Fuels for Electricity Generation (Physical Units); consumption_for_eg_btu = Consumption of Fuels for Electricity Generation (BTUs) (MMBtu); generation = Net Generation (megawatthours); gross_generation (megawatthours); total_consumption = Consumption of Fuels for Electricity Generation and Useful Thermal Output (Physical Units); total_consumption_btu = Consumption of Fuels for Electricity Generation and Useful Thermal Output (BTUs) (MMBtu).", + ) + fuel: str | None = Field( + default=None, + description="2002 Fuel Source filter. Accepts a comma-separated list of values.", + ) + fuel_type: str | None = Field( + default=None, + description="Fuel Source filter. Accepts a comma-separated list of values.", + ) + plant: str | None = Field( + default=None, + description="Plant ID and Name filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + prime_mover: str | None = Field( + default=None, + description="Prime Mover filter. Accepts a comma-separated list of values.", + ) + state: str | None = Field( + default=None, + description="State filter. Accepts a comma-separated list of values.", + ) + + +class EiaElectricityElectricPowerOperationsForIndividualPowerPlantsData(EiaApiData): + """Electric Power Operations for Individual Power Plants (Annual and Monthly). Annual and monthly electric power operations for individual power plants, by energy source and prime mover Source: Form EIA-923""" + + fuel: str | None = Field( + default=None, + description="2002 Fuel Source code.", + ) + fuel_name: str | None = Field( + default=None, + description="2002 Fuel Source name.", + ) + fuel_type: str | None = Field( + default=None, + description="Fuel Source code.", + ) + fuel_type_name: str | None = Field( + default=None, + description="Fuel Source name.", + ) + plant: str | None = Field( + default=None, + description="Plant ID and Name code.", + ) + plant_name: str | None = Field( + default=None, + description="Plant ID and Name name.", + ) + prime_mover: str | None = Field( + default=None, + description="Prime Mover code.", + ) + prime_mover_name: str | None = Field( + default=None, + description="Prime Mover name.", + ) + state: str | None = Field( + default=None, + description="State code.", + ) + state_name: str | None = Field( + default=None, + description="State name.", + ) + average_heat_content: float | None = Field( + default=None, + description="Average Heat Content of Consumed Fuels. Withheld or unavailable values return as null.", + ) + consumption_for_eg: float | None = Field( + default=None, + description="Consumption of Fuels for Electricity Generation (Physical Units). Withheld or unavailable values return as null.", + ) + consumption_for_eg_btu: float | None = Field( + default=None, + description="Consumption of Fuels for Electricity Generation (BTUs) (MMBtu). Withheld or unavailable values return as null.", + ) + generation: float | None = Field( + default=None, + description="Net Generation (megawatthours). Withheld or unavailable values return as null.", + ) + gross_generation: float | None = Field( + default=None, + description="Gross Generation (megawatthours). Withheld or unavailable values return as null.", + ) + total_consumption: float | None = Field( + default=None, + description="Consumption of Fuels for Electricity Generation and Useful Thermal Output (Physical Units). Withheld or unavailable values return as null.", + ) + total_consumption_btu: float | None = Field( + default=None, + description="Consumption of Fuels for Electricity Generation and Useful Thermal Output (BTUs) (MMBtu). Withheld or unavailable values return as null.", + ) + + +class EiaElectricityElectricPowerOperationsForIndividualPowerPlantsFetcher( + Fetcher[ + EiaElectricityElectricPowerOperationsForIndividualPowerPlantsQueryParams, + list[EiaElectricityElectricPowerOperationsForIndividualPowerPlantsData], + ] +): + """Electric Power Operations for Individual Power Plants (Annual and Monthly) fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaElectricityElectricPowerOperationsForIndividualPowerPlantsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaElectricityElectricPowerOperationsForIndividualPowerPlantsQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaElectricityElectricPowerOperationsForIndividualPowerPlantsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaElectricityElectricPowerOperationsForIndividualPowerPlantsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaElectricityElectricPowerOperationsForIndividualPowerPlantsData]: + """Transform the data.""" + return transform_dataset_data( + EiaElectricityElectricPowerOperationsForIndividualPowerPlantsData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/electricity/electricity_sales_to_ultimate_customers.py b/openbb_platform/providers/eia/openbb_us_eia/models/electricity/electricity_sales_to_ultimate_customers.py new file mode 100644 index 00000000000..22393741af5 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/electricity/electricity_sales_to_ultimate_customers.py @@ -0,0 +1,200 @@ +"""Electricity Sales to Ultimate Customers model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaElectricityElectricitySalesToUltimateCustomersQueryParams(EiaApiQueryParams): + """Electricity Sales to Ultimate Customers. Electricity sales to ultimate customer by state and sector (number of customers, average price, revenue, and megawatthours of sales). Sources: Forms EIA-826, EIA-861, EIA-861M + + Source: https://www.eia.gov/opendata/browser/electricity/retail-sales + """ + + __group__ = "electricity" + __dataset__ = "electricity_sales_to_ultimate_customers" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": ["customers", "price", "revenue", "sales"], + }, + "sector": { + "multiple_items_allowed": True, + "choices": [ + "all_sectors", + "commercial", + "industrial", + "other", + "residential", + "transportation", + ], + }, + "state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "district_of_columbia", + "east_north_central", + "east_south_central", + "florida", + "georgia", + "hawaii", + "idaho", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "middle_atlantic", + "minnesota", + "mississippi", + "missouri", + "montana", + "mountain", + "nebraska", + "nevada", + "new_england", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pacific_contiguous", + "pacific_noncontiguous", + "pennsylvania", + "rhode_island", + "south_atlantic", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "us_total", + "utah", + "vermont", + "virginia", + "washington", + "west_north_central", + "west_south_central", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + } + + frequency: Literal["annual", "monthly", "quarterly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: customers = Number of Ultimate Customers (number of customers); price = Average Price of Electricity to Ultimate Customers (cents per kilowatt-hour); revenue = Revenue from Sales to Ultimate Customers (million dollars); sales = Megawatt-hours Sold to Ultimate Customers (million kilowatt hours).", + ) + sector: str | None = Field( + default=None, + description="Sector filter. Accepts a comma-separated list of values.", + ) + state: str | None = Field( + default=None, + description="State / Census Region filter. Accepts a comma-separated list of values.", + ) + + +class EiaElectricityElectricitySalesToUltimateCustomersData(EiaApiData): + """Electricity Sales to Ultimate Customers. Electricity sales to ultimate customer by state and sector (number of customers, average price, revenue, and megawatthours of sales). Sources: Forms EIA-826, EIA-861, EIA-861M""" + + sector: str | None = Field( + default=None, + description="Sector code.", + ) + sector_name: str | None = Field( + default=None, + description="Sector name.", + ) + state: str | None = Field( + default=None, + description="State / Census Region code.", + ) + state_name: str | None = Field( + default=None, + description="State / Census Region name.", + ) + customers: float | None = Field( + default=None, + description="Number of Ultimate Customers (number of customers). Withheld or unavailable values return as null.", + ) + price: float | None = Field( + default=None, + description="Average Price of Electricity to Ultimate Customers (cents per kilowatt-hour). Withheld or unavailable values return as null.", + ) + revenue: float | None = Field( + default=None, + description="Revenue from Sales to Ultimate Customers (million dollars). Withheld or unavailable values return as null.", + ) + sales: float | None = Field( + default=None, + description="Megawatt-hours Sold to Ultimate Customers (million kilowatt hours). Withheld or unavailable values return as null.", + ) + + +class EiaElectricityElectricitySalesToUltimateCustomersFetcher( + Fetcher[ + EiaElectricityElectricitySalesToUltimateCustomersQueryParams, + list[EiaElectricityElectricitySalesToUltimateCustomersData], + ] +): + """Electricity Sales to Ultimate Customers fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaElectricityElectricitySalesToUltimateCustomersQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaElectricityElectricitySalesToUltimateCustomersQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaElectricityElectricitySalesToUltimateCustomersQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaElectricityElectricitySalesToUltimateCustomersQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaElectricityElectricitySalesToUltimateCustomersData]: + """Transform the data.""" + return transform_dataset_data( + EiaElectricityElectricitySalesToUltimateCustomersData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/electricity/inventory_of_operable_generators.py b/openbb_platform/providers/eia/openbb_us_eia/models/electricity/inventory_of_operable_generators.py new file mode 100644 index 00000000000..099327b7463 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/electricity/inventory_of_operable_generators.py @@ -0,0 +1,554 @@ +"""Inventory of Operable Generators model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaElectricityInventoryOfOperableGeneratorsQueryParams(EiaApiQueryParams): + """Inventory of Operable Generators. Inventory of operable generators in the U.S. Source: Forms EIA-860, EIA-860M + + Source: https://www.eia.gov/opendata/browser/electricity/operating-generator-capacity + """ + + __group__ = "electricity" + __dataset__ = "inventory_of_operable_generators" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "county", + "latitude", + "longitude", + "nameplate_capacity_mw", + "net_summer_capacity_mw", + "net_winter_capacity_mw", + "operating_year_month", + "planned_derate_summer_cap_mw", + "planned_derate_year_month", + "planned_retirement_year_month", + "planned_uprate_summer_cap_mw", + "planned_uprate_year_month", + ], + }, + "balancing_authority": { + "multiple_items_allowed": True, + "choices": [ + "alcoa_power_generating_yadkin_division", + "american_electric_power_service_corp_as_agent_for_public", + "arizona_public_service_company", + "arlington_valley_avba", + "associated_electric_cooperative", + "avangrid_renewables", + "avista_corporation", + "balancing_authority_of_northern_california", + "board_of_public_utilities", + "bonneville_power_administration", + "california_independent_system_operator", + "chugach_electric_assn", + "city_utilities_of_springfield_mo", + "city_of_homestead", + "city_of_tacoma_department_of_public_utilities_light_division", + "city_of_tallahassee", + "constellation_energy_control_and_dispatch", + "dominion_energy_south_carolina", + "duke_energy_carolinas", + "duke_energy_progress_west", + "el_paso_electric_company", + "electric_energy", + "electric_reliability_council_of_texas", + "florida_municipal_power_pool", + "florida_power_and_light_company", + "gainesville_regional_utilities", + "gila_river_power", + "grand_river_dam_authority", + "gridliance", + "gridforce_energy_management", + "gridforce_south", + "griffith_energy", + "hawaiian_electric_co", + "iso_new_england", + "idaho_power_company", + "imperial_irrigation_district", + "independence_power_and_light", + "jea", + "kcpl_greater_missouri_operations", + "kansas_city_power_and_light_company", + "lg_and_e_and_ku_services_company_as_agent_for_louisville", + "lincoln_electric_system", + "los_angeles_department_of_water_and_power", + "midcontinent_independent_transmission_system_operator", + "naturener_power_watch", + "naturener_wind_watch", + "nebraska_public_power_district", + "nevada_power_company", + "new_brunswick_system_operator", + "new_harquahala_generating_company_hgba", + "new_smyrna_beach_utilities_commission_of", + "new_york_independent_system_operator", + "no_ba", + "northwestern_energy", + "ohio_valley_electric_corporation", + "oklahoma_gas_and_electric_co", + "omaha_public_power_district", + "pjm_interconnection", + "pud_no_1_of_douglas_county", + "pacificorp_east", + "pacificorp_west", + "portland_general_electric_company", + "powersouth_energy_cooperative", + "progress_energy_carolinas_east", + "progress_energy_florida", + "public_service_company_of_colorado", + "public_service_company_of_new_mexico", + "public_utility_district_no_1_of_chelan_county", + "public_utility_district_no_2_of_grant_county_washington", + "puget_sound_energy", + "salt_river_project", + "seattle_city_light", + "seminole_electric_cooperative", + "south_carolina_electric_and_amp_gas_company", + "southeastern_power_administration", + "southern_company_services_trans", + "southwest_power_pool", + "southwestern_power_administration", + "southwestern_public_service_co", + "sunflower_electric_power_corporation", + "tampa_electric_company", + "tennessee_valley_authority", + "the_empire_district_electric_company", + "tucson_electric_power_company", + "turlock_irrigation_district", + "westar_energy", + "western_area_power_administration_desert_southwest_region", + "western_area_power_administration_rocky_mountain_region", + "western_area_power_administration_upper_great_plains_east", + "western_area_power_administration_ugp_west", + "western_farmers_electric_cooperative", + ], + }, + "energy_source": { + "multiple_items_allowed": True, + "choices": [ + "value", + "agriculture_byproducts", + "bituminous_coal", + "black_liquor", + "blast_furnace_gas", + "coal_derived_synthesis_gas", + "disillate_fuel_oil", + "electricity_used_for_energy_storage", + "gaseous_propane", + "geothermal", + "jet_fuel", + "kerosene", + "landfill_gas", + "lignite", + "municipal_solid_waste", + "natural_gas", + "nuclear", + "other", + "other_biomass_gases", + "other_biomass_liquids", + "other_biomass_solids", + "other_gas", + "petroleum_coke", + "purchased_steam", + "refined_coal", + "residual_fuel_oil", + "sludge_waste", + "solar", + "subbituminous_coal", + "synthesis_gas_from_petroleum_coke", + "tire_derived_fuel", + "waste_coal", + "waste_heat", + "waste_oil", + "water", + "wind", + "wood_waste_liquids", + "wood_waste_solids", + ], + }, + "entity": {"multiple_items_allowed": True}, + "generator": {"multiple_items_allowed": True}, + "plant": {"multiple_items_allowed": True}, + "prime_mover": { + "multiple_items_allowed": True, + "choices": [ + "ba", + "bt", + "ca", + "ce", + "cp", + "cs", + "ct", + "fc", + "fw", + "gt", + "hy", + "ic", + "ot", + "ps", + "pv", + "st", + "ws", + "wt", + ], + }, + "sector": { + "multiple_items_allowed": True, + "choices": [ + "commercial_chp", + "commercial_non_chp", + "electric_utility", + "ipp_chp", + "ipp_non_chp", + "industrial_chp", + "industrial_non_chp", + ], + }, + "state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "district_of_columbia", + "florida", + "georgia", + "hawaii", + "idaho", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "minnesota", + "mississippi", + "missouri", + "montana", + "nebraska", + "nevada", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pennsylvania", + "rhode_island", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "utah", + "vermont", + "virginia", + "washington", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + "status": { + "multiple_items_allowed": True, + "choices": [ + "operating", + "out_of_service_and_not_expected_to_return_to_service_in", + "out_of_service_but_expected_to_return_to_service_in_next", + "standby_backup_available_for_service_but_not_normally_used", + ], + }, + "technology": { + "multiple_items_allowed": True, + "choices": [ + "all_other", + "batteries", + "coal_integrated_gasification_combined_cycle", + "conventional_hydroelectric", + "conventional_steam_coal", + "flywheels", + "geothermal", + "hydroelectric_pumped_storage", + "landfill_gas", + "municipal_solid_waste", + "natural_gas_fired_combined_cycle", + "natural_gas_fired_combustion_turbine", + "natural_gas_internal_combustion_engine", + "natural_gas_steam_turbine", + "natural_gas_with_compressed_air_storage", + "nuclear", + "offshore_wind_turbine", + "onshore_wind_turbine", + "other_gases", + "other_natural_gas", + "other_waste_biomass", + "petroleum_coke", + "petroleum_liquids", + "solar_photovoltaic", + "solar_thermal_with_energy_storage", + "solar_thermal_without_energy_storage", + "wood_wood_waste_biomass", + ], + }, + "unit": {"multiple_items_allowed": True}, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: county; latitude; longitude; nameplate_capacity_mw = Nameplate Capacity (MW); net_summer_capacity_mw = Net Summer Capacity (MW); net_winter_capacity_mw = Net Winter Capacity (MW); operating_year_month = Operating Date (Year and Month); planned_derate_summer_cap_mw = Magnitude of Planned Derate (Summer Capacity) (MW); planned_derate_year_month = Planned Derate Date (Year and Month); planned_retirement_year_month = Planned Retirement Date (Year and Month); planned_uprate_summer_cap_mw = Magnitude of Planned Uprate (Summer Capacity) (MW); planned_uprate_year_month = Planned Uprate Date (Year and Month).", + ) + balancing_authority: str | None = Field( + default=None, + description="Balancing Authority filter. Accepts a comma-separated list of values.", + ) + energy_source: str | None = Field( + default=None, + description="Primary Energy Source filter. Accepts a comma-separated list of values.", + ) + entity: str | None = Field( + default=None, + description="Entity ID and Name filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + generator: str | None = Field( + default=None, + description="Generator ID filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + plant: str | None = Field( + default=None, + description="Plant ID and Name filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + prime_mover: str | None = Field( + default=None, + description="Prime Mover Code filter. Accepts a comma-separated list of values.", + ) + sector: str | None = Field( + default=None, + description="Sector filter. Accepts a comma-separated list of values.", + ) + state: str | None = Field( + default=None, + description="State filter. Accepts a comma-separated list of values.", + ) + status: ( + Literal[ + "operating", + "out_of_service_and_not_expected_to_return_to_service_in", + "out_of_service_but_expected_to_return_to_service_in_next", + "standby_backup_available_for_service_but_not_normally_used", + ] + | None + ) = Field( + default=None, + description="Operating Status Code filter.", + ) + technology: str | None = Field( + default=None, + description="Technology filter. Accepts a comma-separated list of values.", + ) + unit: str | None = Field( + default=None, + description="Unit Code filter. Accepts a comma-separated list of values. There are 385 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaElectricityInventoryOfOperableGeneratorsData(EiaApiData): + """Inventory of Operable Generators. Inventory of operable generators in the U.S. Source: Forms EIA-860, EIA-860M""" + + balancing_authority: str | None = Field( + default=None, + description="Balancing Authority code.", + ) + balancing_authority_name: str | None = Field( + default=None, + description="Balancing Authority name.", + ) + energy_source: str | None = Field( + default=None, + description="Primary Energy Source code.", + ) + energy_source_name: str | None = Field( + default=None, + description="Primary Energy Source name.", + ) + entity: str | None = Field( + default=None, + description="Entity ID and Name code.", + ) + entity_name: str | None = Field( + default=None, + description="Entity ID and Name name.", + ) + generator: str | None = Field( + default=None, + description="Generator ID code.", + ) + generator_name: str | None = Field( + default=None, + description="Generator ID name.", + ) + plant: str | None = Field( + default=None, + description="Plant ID and Name code.", + ) + plant_name: str | None = Field( + default=None, + description="Plant ID and Name name.", + ) + prime_mover: str | None = Field( + default=None, + description="Prime Mover Code code.", + ) + prime_mover_name: str | None = Field( + default=None, + description="Prime Mover Code name.", + ) + sector: str | None = Field( + default=None, + description="Sector code.", + ) + sector_name: str | None = Field( + default=None, + description="Sector name.", + ) + state: str | None = Field( + default=None, + description="State code.", + ) + state_name: str | None = Field( + default=None, + description="State name.", + ) + status: str | None = Field( + default=None, + description="Operating Status Code code.", + ) + status_name: str | None = Field( + default=None, + description="Operating Status Code name.", + ) + technology: str | None = Field( + default=None, + description="Technology code.", + ) + technology_name: str | None = Field( + default=None, + description="Technology name.", + ) + unit: str | None = Field( + default=None, + description="Unit Code code.", + ) + unit_name: str | None = Field( + default=None, + description="Unit Code name.", + ) + county: str | None = Field( + default=None, + description="County", + ) + latitude: float | None = Field( + default=None, + description="Latitude. Withheld or unavailable values return as null.", + ) + longitude: float | None = Field( + default=None, + description="Longitude. Withheld or unavailable values return as null.", + ) + nameplate_capacity_mw: float | None = Field( + default=None, + description="Nameplate Capacity (MW). Withheld or unavailable values return as null.", + ) + net_summer_capacity_mw: float | None = Field( + default=None, + description="Net Summer Capacity (MW). Withheld or unavailable values return as null.", + ) + net_winter_capacity_mw: float | None = Field( + default=None, + description="Net Winter Capacity (MW). Withheld or unavailable values return as null.", + ) + operating_year_month: str | None = Field( + default=None, + description="Operating Date (Year and Month)", + ) + planned_derate_summer_cap_mw: float | None = Field( + default=None, + description="Magnitude of Planned Derate (Summer Capacity) (MW). Withheld or unavailable values return as null.", + ) + planned_derate_year_month: str | None = Field( + default=None, + description="Planned Derate Date (Year and Month)", + ) + planned_retirement_year_month: str | None = Field( + default=None, + description="Planned Retirement Date (Year and Month)", + ) + planned_uprate_summer_cap_mw: float | None = Field( + default=None, + description="Magnitude of Planned Uprate (Summer Capacity) (MW). Withheld or unavailable values return as null.", + ) + planned_uprate_year_month: str | None = Field( + default=None, + description="Planned Uprate Date (Year and Month)", + ) + + +class EiaElectricityInventoryOfOperableGeneratorsFetcher( + Fetcher[ + EiaElectricityInventoryOfOperableGeneratorsQueryParams, + list[EiaElectricityInventoryOfOperableGeneratorsData], + ] +): + """Inventory of Operable Generators fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaElectricityInventoryOfOperableGeneratorsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaElectricityInventoryOfOperableGeneratorsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaElectricityInventoryOfOperableGeneratorsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaElectricityInventoryOfOperableGeneratorsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaElectricityInventoryOfOperableGeneratorsData]: + """Transform the data.""" + return transform_dataset_data( + EiaElectricityInventoryOfOperableGeneratorsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/__init__.py b/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/__init__.py new file mode 100644 index 00000000000..c3813f5c9f6 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/__init__.py @@ -0,0 +1 @@ +"""EIA Electricity Grid models.""" diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/demand.py b/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/demand.py new file mode 100644 index 00000000000..5199a5ecea8 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/demand.py @@ -0,0 +1,211 @@ +"""Hourly Demand, Demand Forecast, Generation, and Interchange model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaElectricityGridDemandQueryParams(EiaApiQueryParams): + """Hourly Demand, Demand Forecast, Generation, and Interchange. Hourly demand, day-ahead demand forecast, net generation, and interchange by balancing authority. Source: Form EIA-930 Product: Hourly Electric Grid Monitor + + Source: https://www.eia.gov/opendata/browser/electricity/rto/region-data + """ + + __group__ = "electricity_grid" + __dataset__ = "demand" + __json_schema_extra__ = { + "respondent": { + "multiple_items_allowed": True, + "choices": [ + "alcoa_power_generating_yadkin_division", + "arizona_public_service_company", + "arlington_valley", + "associated_electric_cooperative", + "avangrid_renewables", + "avista_corporation", + "balancing_authority_of_northern_california", + "bonneville_power_administration", + "california", + "california_independent_system_operator", + "carolinas", + "central", + "city_of_homestead", + "city_of_tacoma_department_of_public_utilities_light_division", + "city_of_tallahassee", + "dominion_energy_south_carolina", + "duke_energy_carolinas", + "duke_energy_florida", + "duke_energy_progress_east", + "duke_energy_progress_west", + "el_paso_electric_company", + "electric_energy", + "electric_reliability_council_of_texas", + "florida", + "florida_municipal_power_pool", + "florida_power_and_light_co", + "gainesville_regional_utilities", + "gridliance", + "gridforce_energy_management", + "griffith_energy", + "iso_new_england", + "idaho_power_company", + "imperial_irrigation_district", + "jea", + "lg_and_e_and_ku_services_company_as_agent_for_louisville", + "los_angeles_department_of_water_and_power", + "mid_atlantic", + "midcontinent_independent_system_operator", + "midwest", + "naturener_power_watch", + "naturener_wind_watch", + "nevada_power_company", + "new_england", + "new_harquahala_generating_company", + "new_york", + "new_york_independent_system_operator", + "northwestern_corporation", + "northwest", + "pjm_interconnection", + "pud_no_1_of_douglas_county", + "pacificorp_east", + "pacificorp_west", + "portland_general_electric_company", + "powersouth_energy_cooperative", + "public_service_company_of_colorado", + "public_service_company_of_new_mexico", + "public_utility_district_no_1_of_chelan_county", + "public_utility_district_no_2_of_grant_county_washington", + "puget_sound_energy", + "salt_river_project_agricultural_improvement_and_power", + "seattle_city_light", + "seminole_electric_cooperative", + "sikeston_board_of_municipal_utilities", + "south_carolina_public_service_authority", + "southeast", + "southeastern_power_administration", + "southern_company_services_trans", + "southwest", + "southwest_power_pool", + "southwestern_power_administration", + "tampa_electric_company", + "tennessee", + "tennessee_valley_authority", + "texas", + "tucson_electric_power", + "turlock_irrigation_district", + "united_states_lower_48", + "utilities_commission_of_new_smyrna_beach", + "western_area_power_administration_desert_southwest_region", + "western_area_power_administration_rocky_mountain_region", + "western_area_power_administration_upper_great_plains_west", + ], + }, + "series_type": { + "multiple_items_allowed": True, + "choices": [ + "day_ahead_demand_forecast", + "demand", + "net_generation", + "total_interchange", + ], + }, + "timezone": { + "multiple_items_allowed": True, + "choices": ["arizona", "central", "eastern", "mountain", "pacific"], + }, + } + + frequency: Literal["daily", "hourly", "local-hourly"] | None = Field( + default=None, + description="The data frequency. The default is 'hourly'.", + ) + respondent: str | None = Field( + default=None, + description="Balancing Authority / Region filter. Accepts a comma-separated list of values.", + ) + series_type: ( + Literal[ + "day_ahead_demand_forecast", "demand", "net_generation", "total_interchange" + ] + | None + ) = Field( + default=None, + description="Metric filter.", + ) + timezone: Literal["arizona", "central", "eastern", "mountain", "pacific"] | None = ( + Field( + default=None, + description="Time Zone for Determining Date filter. Only applies to frequency: daily.", + ) + ) + + +class EiaElectricityGridDemandData(EiaApiData): + """Hourly Demand, Demand Forecast, Generation, and Interchange. Hourly demand, day-ahead demand forecast, net generation, and interchange by balancing authority. Source: Form EIA-930 Product: Hourly Electric Grid Monitor""" + + respondent: str | None = Field( + default=None, + description="Balancing Authority / Region code.", + ) + respondent_name: str | None = Field( + default=None, + description="Balancing Authority / Region name.", + ) + series_type: str | None = Field( + default=None, + description="Metric code.", + ) + series_type_name: str | None = Field( + default=None, + description="Metric name.", + ) + timezone: str | None = Field( + default=None, + description="Time Zone for Determining Date code.", + ) + timezone_name: str | None = Field( + default=None, + description="Time Zone for Determining Date name.", + ) + value: float | None = Field( + default=None, + description="Demand, Demand Forecast, Net Generation, or Interchange (megawatthours). Withheld or unavailable values return as null.", + ) + + +class EiaElectricityGridDemandFetcher( + Fetcher[EiaElectricityGridDemandQueryParams, list[EiaElectricityGridDemandData]] +): + """Hourly Demand, Demand Forecast, Generation, and Interchange fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaElectricityGridDemandQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaElectricityGridDemandQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaElectricityGridDemandQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaElectricityGridDemandQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaElectricityGridDemandData]: + """Transform the data.""" + return transform_dataset_data(EiaElectricityGridDemandData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/demand_by_subregion.py b/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/demand_by_subregion.py new file mode 100644 index 00000000000..4ac04820bb1 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/demand_by_subregion.py @@ -0,0 +1,222 @@ +"""Hourly Demand by Subregion model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaElectricityGridDemandBySubregionQueryParams(EiaApiQueryParams): + """Hourly Demand by Subregion. Hourly demand by balancing authority subregion. Source: Form EIA-930 Product: Hourly Electric Grid Monitor + + Source: https://www.eia.gov/opendata/browser/electricity/rto/region-sub-ba-data + """ + + __group__ = "electricity_grid" + __dataset__ = "demand_by_subregion" + __json_schema_extra__ = { + "parent": { + "multiple_items_allowed": True, + "choices": [ + "california_independent_system_operator", + "electric_reliability_council_of_texas", + "iso_new_england", + "midcontinent_independent_system_operator", + "new_york_independent_system_operator", + "pjm_interconnection", + "public_service_company_of_new_mexico", + "southwest_power_pool", + ], + }, + "subregion": { + "multiple_items_allowed": True, + "choices": [ + "aepw_american_electric_power_west", + "allegheny_power_zone_pjm", + "american_electric_power_zone", + "american_transmission_systems_zone_pjm", + "atlantic_electric_zone", + "baltimore_gas_null_zone_pjm", + "capital_nyis", + "central_nyis", + "city_of_acoma_pueblo_pnm", + "city_of_gallup", + "city_of_springfield", + "commonwealth_edison_zone", + "connecticut", + "dayton_power_null_zone_pjm", + "delmarva_power_null_zone_pjm", + "dominion_virginia_power_zone", + "duke_energy_ohio_kentucky_zone_pjm", + "dunwoodie_nyis", + "duquesne_lighting_company_zone", + "erco_coast", + "erco_far_west", + "erco_north_central", + "erco_south_central", + "east", + "east_kentucky_power_cooperative_zone_pjm", + "empire_district_electric_company", + "freeport", + "genesee_nyis", + "grand_river_dam_authority_swpp", + "hudson_valley", + "isne_northeast_mass", + "isne_vermont", + "independence_power_null_swpp", + "jersey_central_power_null_zone_pjm", + "jicarilla_apache_nation", + "kafb_pnm", + "kcec_pnm", + "kcp_and_l_greater_missouri_operations_swpp", + "kansas_city_board_of_public_utilities_swpp", + "kansas_city_power_and_light", + "lincoln_electric_system", + "long_island_nyis", + "los_alamos_county", + "maine", + "metropolitan_edison_zone_pjm", + "millwood_nyis", + "mohawk_valley_nyis", + "navajo_tribal_utility_authority_pnm", + "nebraska_public_power_district", + "new_hampshire", + "new_york_city_nyis", + "north", + "north_nyis", + "oklahoma_gas_and_electric_co_swpp", + "omaha_public_power_district_swpp", + "peco_energy_zone_pjm", + "pnm_system_firm_load", + "pacific_gas_and_electric", + "pennsylvania_electric_zone_pjm", + "pennsylvania_power_and_light_zone", + "potomac_electric_power_zone", + "public_service_electric_and_gas_of_new_jersey_zone_pjm", + "rhode_island", + "rockland_electric_zone_pjm", + "san_diego_gas_and_electric", + "south", + "southeast_mass", + "southern_california_edison", + "southwestern_public_service_company_swpp", + "sunflower_electric", + "tri_state_generation_and_transmission", + "valley_electric_association_ciso", + "west", + "west_nyis", + "westar_energy", + "western_area_power_upper_great_plains_east", + "western_farmers_electric_cooperative", + "western_central_mass", + "zone_1", + "zone_4_miso", + "zone_6_miso", + "zones_2_and_7", + "zones_3_and_5", + "zones_8_9_and_10_miso", + ], + }, + "timezone": { + "multiple_items_allowed": True, + "choices": ["arizona", "central", "eastern", "mountain", "pacific"], + }, + } + + frequency: Literal["daily", "hourly", "local-hourly"] | None = Field( + default=None, + description="The data frequency. The default is 'hourly'.", + ) + parent: str | None = Field( + default=None, + description="Balancing Authority filter. Accepts a comma-separated list of values.", + ) + subregion: str | None = Field( + default=None, + description="Subregion filter. Accepts a comma-separated list of values.", + ) + timezone: Literal["arizona", "central", "eastern", "mountain", "pacific"] | None = ( + Field( + default=None, + description="Time Zone for Determining Date filter. Only applies to frequency: daily.", + ) + ) + + +class EiaElectricityGridDemandBySubregionData(EiaApiData): + """Hourly Demand by Subregion. Hourly demand by balancing authority subregion. Source: Form EIA-930 Product: Hourly Electric Grid Monitor""" + + parent: str | None = Field( + default=None, + description="Balancing Authority code.", + ) + parent_name: str | None = Field( + default=None, + description="Balancing Authority name.", + ) + subregion: str | None = Field( + default=None, + description="Subregion code.", + ) + subregion_name: str | None = Field( + default=None, + description="Subregion name.", + ) + timezone: str | None = Field( + default=None, + description="Time Zone for Determining Date code.", + ) + timezone_name: str | None = Field( + default=None, + description="Time Zone for Determining Date name.", + ) + value: float | None = Field( + default=None, + description="Demand (megawatthours). Withheld or unavailable values return as null.", + ) + + +class EiaElectricityGridDemandBySubregionFetcher( + Fetcher[ + EiaElectricityGridDemandBySubregionQueryParams, + list[EiaElectricityGridDemandBySubregionData], + ] +): + """Hourly Demand by Subregion fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaElectricityGridDemandBySubregionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaElectricityGridDemandBySubregionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaElectricityGridDemandBySubregionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaElectricityGridDemandBySubregionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaElectricityGridDemandBySubregionData]: + """Transform the data.""" + return transform_dataset_data( + EiaElectricityGridDemandBySubregionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/generation_by_fuel.py b/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/generation_by_fuel.py new file mode 100644 index 00000000000..5bddf6749c8 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/generation_by_fuel.py @@ -0,0 +1,227 @@ +"""Hourly Generation by Energy Source model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaElectricityGridGenerationByFuelQueryParams(EiaApiQueryParams): + """Hourly Generation by Energy Source. Hourly net generation by balancing authority and energy source. Source: Form EIA-930 Product: Hourly Electric Grid Monitor + + Source: https://www.eia.gov/opendata/browser/electricity/rto/fuel-type-data + """ + + __group__ = "electricity_grid" + __dataset__ = "generation_by_fuel" + __json_schema_extra__ = { + "fuel_type": { + "multiple_items_allowed": True, + "choices": [ + "battery_storage", + "coal", + "geothermal", + "hydro", + "natural_gas", + "nuclear", + "other", + "other_energy_storage", + "petroleum", + "pumped_storage", + "solar", + "solar_with_integrated_battery_storage", + "unknown", + "unknown_energy", + "wind", + "wind_with_integrated_battery_storage", + ], + }, + "respondent": { + "multiple_items_allowed": True, + "choices": [ + "alcoa_power_generating_yadkin_division", + "arizona_public_service_company", + "arlington_valley", + "associated_electric_cooperative", + "avangrid_renewables", + "avista_corporation", + "balancing_authority_of_northern_california", + "bonneville_power_administration", + "california", + "california_independent_system_operator", + "carolinas", + "central", + "city_of_homestead", + "city_of_tacoma_department_of_public_utilities_light_division", + "city_of_tallahassee", + "dominion_energy_south_carolina", + "duke_energy_carolinas", + "duke_energy_florida", + "duke_energy_progress_east", + "duke_energy_progress_west", + "el_paso_electric_company", + "electric_energy", + "electric_reliability_council_of_texas", + "florida", + "florida_municipal_power_pool", + "florida_power_and_light_co", + "gainesville_regional_utilities", + "gridliance", + "gridforce_energy_management", + "griffith_energy", + "iso_new_england", + "idaho_power_company", + "imperial_irrigation_district", + "jea", + "lg_and_e_and_ku_services_company_as_agent_for_louisville", + "los_angeles_department_of_water_and_power", + "mid_atlantic", + "midcontinent_independent_system_operator", + "midwest", + "naturener_power_watch", + "naturener_wind_watch", + "nevada_power_company", + "new_england", + "new_harquahala_generating_company", + "new_york", + "new_york_independent_system_operator", + "northwestern_corporation", + "northwest", + "pjm_interconnection", + "pud_no_1_of_douglas_county", + "pacificorp_east", + "pacificorp_west", + "portland_general_electric_company", + "powersouth_energy_cooperative", + "public_service_company_of_colorado", + "public_service_company_of_new_mexico", + "public_utility_district_no_1_of_chelan_county", + "public_utility_district_no_2_of_grant_county_washington", + "puget_sound_energy", + "salt_river_project_agricultural_improvement_and_power", + "seattle_city_light", + "seminole_electric_cooperative", + "sikeston_board_of_municipal_utilities", + "south_carolina_public_service_authority", + "southeast", + "southeastern_power_administration", + "southern_company_services_trans", + "southwest", + "southwest_power_pool", + "southwestern_power_administration", + "tampa_electric_company", + "tennessee", + "tennessee_valley_authority", + "texas", + "tucson_electric_power", + "turlock_irrigation_district", + "united_states_lower_48", + "utilities_commission_of_new_smyrna_beach", + "western_area_power_administration_desert_southwest_region", + "western_area_power_administration_rocky_mountain_region", + "western_area_power_administration_upper_great_plains_west", + ], + }, + "timezone": { + "multiple_items_allowed": True, + "choices": ["arizona", "central", "eastern", "mountain", "pacific"], + }, + } + + frequency: Literal["daily", "hourly", "local-hourly"] | None = Field( + default=None, + description="The data frequency. The default is 'hourly'.", + ) + fuel_type: str | None = Field( + default=None, + description="Energy Source filter. Accepts a comma-separated list of values.", + ) + respondent: str | None = Field( + default=None, + description="Balancing Authority / Region filter. Accepts a comma-separated list of values.", + ) + timezone: Literal["arizona", "central", "eastern", "mountain", "pacific"] | None = ( + Field( + default=None, + description="Time Zone for Determining Date filter. Only applies to frequency: daily.", + ) + ) + + +class EiaElectricityGridGenerationByFuelData(EiaApiData): + """Hourly Generation by Energy Source. Hourly net generation by balancing authority and energy source. Source: Form EIA-930 Product: Hourly Electric Grid Monitor""" + + fuel_type: str | None = Field( + default=None, + description="Energy Source code.", + ) + fuel_type_name: str | None = Field( + default=None, + description="Energy Source name.", + ) + respondent: str | None = Field( + default=None, + description="Balancing Authority / Region code.", + ) + respondent_name: str | None = Field( + default=None, + description="Balancing Authority / Region name.", + ) + timezone: str | None = Field( + default=None, + description="Time Zone for Determining Date code.", + ) + timezone_name: str | None = Field( + default=None, + description="Time Zone for Determining Date name.", + ) + value: float | None = Field( + default=None, + description="Net Generation (megawatthours). Withheld or unavailable values return as null.", + ) + + +class EiaElectricityGridGenerationByFuelFetcher( + Fetcher[ + EiaElectricityGridGenerationByFuelQueryParams, + list[EiaElectricityGridGenerationByFuelData], + ] +): + """Hourly Generation by Energy Source fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaElectricityGridGenerationByFuelQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaElectricityGridGenerationByFuelQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaElectricityGridGenerationByFuelQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaElectricityGridGenerationByFuelQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaElectricityGridGenerationByFuelData]: + """Transform the data.""" + return transform_dataset_data( + EiaElectricityGridGenerationByFuelData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/interchange.py b/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/interchange.py new file mode 100644 index 00000000000..614832d90ee --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/electricity_grid/interchange.py @@ -0,0 +1,297 @@ +"""Hourly Interchange by Neighboring Balancing Authority model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaElectricityGridInterchangeQueryParams(EiaApiQueryParams): + """Hourly Interchange by Neighboring Balancing Authority. Daily interchange between neighboring balancing authorities. Source: Form EIA-930 Product: Hourly Electric Grid Monitor + + Source: https://www.eia.gov/opendata/browser/electricity/rto/interchange-data + """ + + __group__ = "electricity_grid" + __dataset__ = "interchange" + __json_schema_extra__ = { + "from_ba": { + "multiple_items_allowed": True, + "choices": [ + "alcoa_power_generating_yadkin_division", + "arizona_public_service_company", + "arlington_valley", + "associated_electric_cooperative", + "avangrid_renewables", + "avista_corporation", + "balancing_authority_of_northern_california", + "bonneville_power_administration", + "california", + "california_independent_system_operator", + "carolinas", + "central", + "city_of_homestead", + "city_of_tacoma_department_of_public_utilities_light_division", + "city_of_tallahassee", + "dominion_energy_south_carolina", + "duke_energy_carolinas", + "duke_energy_florida", + "duke_energy_progress_east", + "duke_energy_progress_west", + "el_paso_electric_company", + "electric_energy", + "electric_reliability_council_of_texas", + "florida", + "florida_municipal_power_pool", + "florida_power_and_light_co", + "gainesville_regional_utilities", + "gridliance", + "gridforce_energy_management", + "griffith_energy", + "iso_new_england", + "idaho_power_company", + "imperial_irrigation_district", + "jea", + "lg_and_e_and_ku_services_company_as_agent_for_louisville", + "los_angeles_department_of_water_and_power", + "mid_atlantic", + "midcontinent_independent_system_operator", + "midwest", + "naturener_power_watch", + "naturener_wind_watch", + "nevada_power_company", + "new_england", + "new_harquahala_generating_company", + "new_york", + "new_york_independent_system_operator", + "northwestern_corporation", + "northwest", + "pjm_interconnection", + "pud_no_1_of_douglas_county", + "pacificorp_east", + "pacificorp_west", + "portland_general_electric_company", + "powersouth_energy_cooperative", + "public_service_company_of_colorado", + "public_service_company_of_new_mexico", + "public_utility_district_no_1_of_chelan_county", + "public_utility_district_no_2_of_grant_county_washington", + "puget_sound_energy", + "salt_river_project_agricultural_improvement_and_power", + "seattle_city_light", + "seminole_electric_cooperative", + "sikeston_board_of_municipal_utilities", + "south_carolina_public_service_authority", + "southeast", + "southeastern_power_administration", + "southern_company_services_trans", + "southwest", + "southwest_power_pool", + "southwestern_power_administration", + "tampa_electric_company", + "tennessee", + "tennessee_valley_authority", + "texas", + "tucson_electric_power", + "turlock_irrigation_district", + "united_states_lower_48", + "utilities_commission_of_new_smyrna_beach", + "western_area_power_administration_desert_southwest_region", + "western_area_power_administration_rocky_mountain_region", + "western_area_power_administration_upper_great_plains_west", + ], + }, + "timezone": { + "multiple_items_allowed": True, + "choices": ["arizona", "central", "eastern", "mountain", "pacific"], + }, + "to_ba": { + "multiple_items_allowed": True, + "choices": [ + "alberta_electric_system_operator", + "alcoa_power_generating_yadkin_division", + "arizona_public_service_company", + "arlington_valley", + "associated_electric_cooperative", + "avangrid_renewables", + "avista_corporation", + "balancing_authority_of_northern_california", + "bonneville_power_administration", + "british_columbia_hydro_and_power_authority", + "california", + "california_independent_system_operator", + "canada", + "carolinas", + "central", + "centro_nacional_de_control_de_energia", + "city_of_homestead", + "city_of_tacoma_department_of_public_utilities_light_division", + "city_of_tallahassee", + "dominion_energy_south_carolina", + "duke_energy_carolinas", + "duke_energy_florida", + "duke_energy_progress_east", + "duke_energy_progress_west", + "el_paso_electric_company", + "electric_energy", + "electric_reliability_council_of_texas", + "florida", + "florida_municipal_power_pool", + "florida_power_and_light_co", + "gainesville_regional_utilities", + "gridliance", + "gridforce_energy_management", + "griffith_energy", + "hydro_quebec_transenergie", + "iso_new_england", + "idaho_power_company", + "imperial_irrigation_district", + "jea", + "lg_and_e_and_ku_services_company_as_agent_for_louisville", + "los_angeles_department_of_water_and_power", + "manitoba_hydro", + "mexico", + "mid_atlantic", + "midcontinent_independent_system_operator", + "midwest", + "naturener_power_watch", + "naturener_wind_watch", + "nevada_power_company", + "new_brunswick_system_operator", + "new_england", + "new_harquahala_generating_company", + "new_york", + "new_york_independent_system_operator", + "northwestern_corporation", + "northwest", + "ontario_ieso", + "pjm_interconnection", + "pud_no_1_of_douglas_county", + "pacificorp_east", + "pacificorp_west", + "portland_general_electric_company", + "powersouth_energy_cooperative", + "public_service_company_of_colorado", + "public_service_company_of_new_mexico", + "public_utility_district_no_1_of_chelan_county", + "public_utility_district_no_2_of_grant_county_washington", + "puget_sound_energy", + "salt_river_project_agricultural_improvement_and_power", + "saskatchewan_power_corporation", + "seattle_city_light", + "seminole_electric_cooperative", + "sikeston_board_of_municipal_utilities", + "south_carolina_public_service_authority", + "southeast", + "southeastern_power_administration", + "southern_company_services_trans", + "southwest", + "southwest_power_pool", + "southwestern_power_administration", + "tampa_electric_company", + "tennessee", + "tennessee_valley_authority", + "texas", + "tucson_electric_power", + "turlock_irrigation_district", + "utilities_commission_of_new_smyrna_beach", + "western_area_power_administration_desert_southwest_region", + "western_area_power_administration_rocky_mountain_region", + "western_area_power_administration_upper_great_plains_west", + ], + }, + } + + frequency: Literal["daily", "hourly", "local-hourly"] | None = Field( + default=None, + description="The data frequency. The default is 'hourly'.", + ) + from_ba: str | None = Field( + default=None, + description="Balancing Authority / Region filter. Accepts a comma-separated list of values.", + ) + timezone: Literal["arizona", "central", "eastern", "mountain", "pacific"] | None = ( + Field( + default=None, + description="Time Zone for Determining Date filter. Only applies to frequency: daily.", + ) + ) + to_ba: str | None = Field( + default=None, + description="Neighboring Balancing Authority / Region filter. Accepts a comma-separated list of values.", + ) + + +class EiaElectricityGridInterchangeData(EiaApiData): + """Hourly Interchange by Neighboring Balancing Authority. Daily interchange between neighboring balancing authorities. Source: Form EIA-930 Product: Hourly Electric Grid Monitor""" + + from_ba: str | None = Field( + default=None, + description="Balancing Authority / Region code.", + ) + from_ba_name: str | None = Field( + default=None, + description="Balancing Authority / Region name.", + ) + timezone: str | None = Field( + default=None, + description="Time Zone for Determining Date code.", + ) + timezone_name: str | None = Field( + default=None, + description="Time Zone for Determining Date name.", + ) + to_ba: str | None = Field( + default=None, + description="Neighboring Balancing Authority / Region code.", + ) + to_ba_name: str | None = Field( + default=None, + description="Neighboring Balancing Authority / Region name.", + ) + value: float | None = Field( + default=None, + description="Interchange (megawatthours). Withheld or unavailable values return as null.", + ) + + +class EiaElectricityGridInterchangeFetcher( + Fetcher[ + EiaElectricityGridInterchangeQueryParams, + list[EiaElectricityGridInterchangeData], + ] +): + """Hourly Interchange by Neighboring Balancing Authority fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaElectricityGridInterchangeQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaElectricityGridInterchangeQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaElectricityGridInterchangeQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaElectricityGridInterchangeQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaElectricityGridInterchangeData]: + """Transform the data.""" + return transform_dataset_data(EiaElectricityGridInterchangeData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/ieo.py b/openbb_platform/providers/eia/openbb_us_eia/models/ieo.py new file mode 100644 index 00000000000..7e9473fa7c3 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/ieo.py @@ -0,0 +1,268 @@ +"""International Energy Outlook model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaIeoQueryParams(EiaApiQueryParams): + """International Energy Outlook. Long-term energy projections by release year and scenario. Select the report vintage with the `release` parameter. + + Source: https://www.eia.gov/opendata/browser/ieo + """ + + __group__ = "ieo" + __json_schema_extra__ = { + "history": { + "multiple_items_allowed": True, + "choices": ["historic", "projection"], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "africa", + "africa_and_middle_east", + "americas", + "asia_pacific", + "australia_and_new_zealand", + "australia_new_zealand", + "brazil", + "canada", + "china", + "eastern_europe_and_eurasia", + "europe_and_eurasia", + "india", + "japan", + "mexico", + "mexico_and_other_oecd_americas", + "middle_east", + "no_regional_tables", + "oecd_europe", + "other_americas", + "other_asia_pacific", + "other_non_oecd_americas", + "other_non_oecd_asia", + "other_non_oecd_europe_and_eurasia", + "russia", + "south_korea", + "total_non_oecd", + "total_oecd", + "total_world", + "united_states", + "western_europe", + ], + }, + "scenario": { + "multiple_items_allowed": True, + "choices": [ + "high_economic_growth", + "high_oil_price", + "high_zero_carbon_technology_cost", + "low_economic_growth", + "low_oil_price", + "low_zero_carbon_technology_cost", + "reference", + ], + }, + "series": {"multiple_items_allowed": True}, + "table": { + "multiple_items_allowed": True, + "choices": [ + "aircraft_efficiency", + "buildings_delivered_energy_consumption_by_end_use_sector", + "delivered_energy_consumption_by_end_use_sector_and_fuel", + "freight_air_transport", + "industrial_energy_consumption_by_sector_for_selected_regions", + "international_other_liquid_fuels_a_production_by_region_and", + "light_duty_vehicle_stocks_by_technology", + "new_light_duty_vehicle_sales_by_technology", + "passenger_air_travel", + "passenger_aircraft_capacity", + "revenue_freight_air_transport", + "revenue_passenger_air_travel", + "total_commercial_jet_fuel_use_by_region", + "transportation_sector_energy_consumption_by_region_and_fuel", + "transportation_sector_freight_transport_energy_consumption", + "transportation_sector_passenger_transport_energy", + "world_carbon_dioxide_emissions_by_region", + "world_carbon_dioxide_emissions_from_coal_use_by_region", + "world_carbon_dioxide_emissions_from_liquids_use_by_region", + "world_carbon_dioxide_emissions_from_natural_gas_use_by", + "world_carbon_dioxide_intensity_of_energy_use_by_region", + "world_coal_consumption_by_region", + "world_coal_exports_by_region", + "world_coal_imports_by_region", + "world_coal_supply_by_region", + "world_consumption_of_hydroelectricity_and_other_renewable", + "world_crude_oil_a_production_by_region_and_country", + "world_energy_intensity_by_region", + "world_gross_domestic_product_by_region_expressed_in_market", + "world_gross_domestic_product_by_region_expressed_in", + "world_gross_domestic_product_per_capita_by_region_expressed", + "world_installed_coal_fired_generating_capacity_by_region", + "world_installed_geothermal_generating_capacity_by_region", + "world_installed_hydroelectric_and_other_renewable", + "world_installed_hydroelectric_generating_capacity_by_region", + "world_installed_liquids_fired_generating_capacity_by_region", + "world_installed_natural_gas_fired_generating_capacity_by", + "world_installed_nuclear_generating_capacity_by_region_and", + "world_installed_other_renewable_generating_capacity_by", + "world_installed_solar_generating_capacity_by_region_and", + "world_installed_wind_powered_generating_capacity_by_region", + "world_liquids_consumption_by_region", + "world_metallurgical_coal_consumptiom_by_region", + "world_metallurgical_coal_consumption_by_region", + "world_metallurgical_coal_exports_by_region", + "world_metallurgical_coal_imports_by_region", + "world_metallurgical_coal_net_trade_by_region", + "world_metallurgical_coal_supply_by_region", + "world_natural_gas_consumption_by_region", + "world_net_coal_fired_electricity_generation_by_region_and", + "world_net_geothermal_electricity_generation_by_region_and", + "world_net_hydroelectric_and_other_renewable_electricity", + "world_net_hydroelectric_electricity_generation_by_region", + "world_net_liquids_fired_electricity_generation_by_region", + "world_net_natural_gas_fired_electricity_generation_by", + "world_net_nuclear_electricity_generation_by_region_and", + "world_net_other_renewable_electricity_generation_by_region", + "world_net_solar_electricity_generation_by_region_and_country", + "world_net_trade_in_natural_gas_by_region", + "world_net_wind_powered_electricity_generation_by_region_and", + "world_nuclear_energy_consumption_by_region", + "world_other_natural_gas_production_by_region", + "world_petroleum_and_other_liquids_production_by_region_and", + "world_population_by_region", + "world_thermal_coal_consumptiom_by_region", + "world_thermal_coal_exports_by_region", + "world_thermal_coal_imports_by_region", + "world_thermal_coal_net_trade_by_region", + "world_thermal_coal_supply_by_region", + "world_tight_gas_shale_gas_and_coalbed_methane_production_by", + "world_total_coal_consumptiom_by_region", + "world_total_coal_exports_by_region", + "world_total_coal_imports_by_region", + "world_total_coal_net_trade_by_region", + "world_total_coal_supply_by_region", + "world_total_energy_consumption_by_region_and_fuel", + "world_total_installed_generating_capacity_by_region_and", + "world_total_natural_gas_production_by_region", + "world_total_net_electricity_generation_by_region_and_country", + "world_total_primary_energy_consumption_by_region", + ], + }, + } + + release: Literal["2017", "2019", "2021", "2023"] = Field( + default="2023", + description="The International Energy Outlook release." + " Facet values vary by release; use the `facet_options` endpoint to list them.", + ) + history: Literal["historic", "projection"] | None = Field( + default=None, + description="History filter.", + ) + region: str | None = Field( + default=None, + description="Region filter. Accepts a comma-separated list of values.", + ) + scenario: str | None = Field( + default=None, + description="Scenario filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + table: str | None = Field( + default=None, + description="Table filter. Accepts a comma-separated list of values.", + ) + + +class EiaIeoData(EiaApiData): + """International Energy Outlook. Long-term energy projections by release year and scenario. Select the report vintage with the `release` parameter.""" + + history: str | None = Field( + default=None, + description="History code.", + ) + history_name: str | None = Field( + default=None, + description="History name.", + ) + region: str | None = Field( + default=None, + description="Region code.", + ) + region_name: str | None = Field( + default=None, + description="Region name.", + ) + scenario: str | None = Field( + default=None, + description="Scenario code.", + ) + scenario_name: str | None = Field( + default=None, + description="Scenario name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + table: str | None = Field( + default=None, + description="Table code.", + ) + table_name: str | None = Field( + default=None, + description="Table name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + unit: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaIeoFetcher(Fetcher[EiaIeoQueryParams, list[EiaIeoData]]): + """International Energy Outlook fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaIeoQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaIeoQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaIeoQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaIeoQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaIeoData]: + """Transform the data.""" + return transform_dataset_data(EiaIeoData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/international.py b/openbb_platform/providers/eia/openbb_us_eia/models/international.py new file mode 100644 index 00000000000..b085c01454c --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/international.py @@ -0,0 +1,182 @@ +"""International model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaInternationalQueryParams(EiaApiQueryParams): + """International. Country level production, consumption, imports, exports by energy source (petroleum, natural gas, electricity, renewable, etc.) Interactive product: https://www.eia.gov/international/data/world + + Source: https://www.eia.gov/opendata/browser/international + """ + + __group__ = "international" + __dataset__ = "international" + __json_schema_extra__ = { + "activity": { + "multiple_items_allowed": True, + "choices": ["consumption", "imports", "production", "stocks_oecd"], + }, + "country": {"multiple_items_allowed": True}, + "country_type": { + "multiple_items_allowed": True, + "choices": ["country", "region"], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "canada_imports_by_source", + "crude_oil_including_lease_condensate", + "crude_oil_ngpl_and_other_liquids", + "france_imports_by_source", + "germany_imports_by_source", + "italy_imports_by_source", + "japan_imports_by_source", + "ngpl", + "oecd_europe_imports_by_source", + "oecd_imports", + "other_liquids", + "petroleum_and_other_liquids", + "refined_petroleum_products", + "refinery_processing_gain", + "south_korea_imports_by_source", + "total_petroleum_and_other_liquids", + "us_imports_by_source", + "united_kingdom_imports_by_source", + ], + }, + "unit": { + "multiple_items_allowed": True, + "choices": [ + "1000_metric_tons", + "millions_barrels", + "thousand_barrels_per_day", + ], + }, + } + + frequency: Literal["annual", "monthly", "quarterly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + activity: Literal["consumption", "imports", "production", "stocks_oecd"] | None = ( + Field( + default=None, + description="Activity filter.", + ) + ) + country: str | None = Field( + default=None, + description="Country/Region filter. Accepts a comma-separated list of values. There are 268 valid values - use the `facet_options` endpoint to list them.", + ) + country_type: Literal["country", "region"] | None = Field( + default=None, + description="Country/Region Type filter.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + unit: ( + Literal["1000_metric_tons", "millions_barrels", "thousand_barrels_per_day"] + | None + ) = Field( + default=None, + description="Unit filter.", + ) + + +class EiaInternationalData(EiaApiData): + """International. Country level production, consumption, imports, exports by energy source (petroleum, natural gas, electricity, renewable, etc.) Interactive product: https://www.eia.gov/international/data/world""" + + activity: str | None = Field( + default=None, + description="Activity code.", + ) + activity_name: str | None = Field( + default=None, + description="Activity name.", + ) + country: str | None = Field( + default=None, + description="Country/Region code.", + ) + country_name: str | None = Field( + default=None, + description="Country/Region name.", + ) + country_type: str | None = Field( + default=None, + description="Country/Region Type code.", + ) + country_type_name: str | None = Field( + default=None, + description="Country/Region Type name.", + ) + data_flag: str | None = Field( + default=None, + description="Data flag ID code.", + ) + data_flag_name: str | None = Field( + default=None, + description="Data flag ID name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + unit: str | None = Field( + default=None, + description="Unit code.", + ) + unit_name: str | None = Field( + default=None, + description="Unit name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + + +class EiaInternationalFetcher( + Fetcher[EiaInternationalQueryParams, list[EiaInternationalData]] +): + """International fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaInternationalQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaInternationalQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaInternationalQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaInternationalQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaInternationalData]: + """Transform the data.""" + return transform_dataset_data(EiaInternationalData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/__init__.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/__init__.py new file mode 100644 index 00000000000..5cb164fbd98 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/__init__.py @@ -0,0 +1 @@ +"""EIA Natural Gas models.""" diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/associated_dissolved_proved_reserves.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/associated_dissolved_proved_reserves.py new file mode 100644 index 00000000000..37a821eb121 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/associated_dissolved_proved_reserves.py @@ -0,0 +1,170 @@ +"""Associated-Dissolved Natural Gas Proved Reserves, Wet After Lease Separation model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasAssociatedDissolvedProvedReservesQueryParams(EiaApiQueryParams): + """Associated-Dissolved Natural Gas Proved Reserves, Wet After Lease Separation. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/adng + """ + + __group__ = "natural_gas" + __dataset__ = "associated_dissolved_proved_reserves" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "associated_dissolved_production_from_reserves", + "associated_dissolved_proved_reserves", + "associated_dissolved_reserves_acquisitions", + "associated_dissolved_reserves_adjustments", + "associated_dissolved_reserves_extensions", + "associated_dissolved_reserves_extensions_and_discoveries", + "associated_dissolved_reserves_new_field_discoveries", + "associated_dissolved_reserves_new_reservoir_discoveries_in", + "associated_dissolved_reserves_revision_decreases", + "associated_dissolved_reserves_revision_increases", + "associated_dissolved_reserves_sales", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 572 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasAssociatedDissolvedProvedReservesData(EiaApiData): + """Associated-Dissolved Natural Gas Proved Reserves, Wet After Lease Separation. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasAssociatedDissolvedProvedReservesFetcher( + Fetcher[ + EiaNaturalGasAssociatedDissolvedProvedReservesQueryParams, + list[EiaNaturalGasAssociatedDissolvedProvedReservesData], + ] +): + """Associated-Dissolved Natural Gas Proved Reserves, Wet After Lease Separation fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasAssociatedDissolvedProvedReservesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasAssociatedDissolvedProvedReservesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasAssociatedDissolvedProvedReservesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasAssociatedDissolvedProvedReservesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasAssociatedDissolvedProvedReservesData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasAssociatedDissolvedProvedReservesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/average_depth_of_crude_oil_and_natural_gas_wells.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/average_depth_of_crude_oil_and_natural_gas_wells.py new file mode 100644 index 00000000000..eb7921eb9ad --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/average_depth_of_crude_oil_and_natural_gas_wells.py @@ -0,0 +1,153 @@ +"""Average Depth of Crude Oil and Natural Gas Wells model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWellsQueryParams( + EiaApiQueryParams +): + """Average Depth of Crude Oil and Natural Gas Wells. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/welldep + """ + + __group__ = "natural_gas" + __dataset__ = "average_depth_of_crude_oil_and_natural_gas_wells" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "average_depth_of_developmental_wells_drilled", + "average_depth_of_exploratory_wells_drilled", + "average_depth_of_exploratory_and_developmental_wells_drilled", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": ["wells_dry", "wells_gas", "wells_oil", "wells_total"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_average_depth_of_crude_oil_developmental_wells_drilled", + "us_average_depth_of_crude_oil_exploratory_wells_drilled", + "us_average_depth_of_crude_oil_exploratory_and_developmental", + "us_average_depth_of_crude_oil_natural_gas_and_dry_developmental_wells_drilled_feet_per_well", + "us_average_depth_of_crude_oil_natural_gas_and_dry_exploratory_wells_drilled_feet_per_well", + "us_average_depth_of_crude_oil_natural_gas_and_dry_exploratory_and_developmental_wells_drilled_feet_per_well", + "us_average_depth_of_dry_exploratory_and_developmental_wells", + "us_average_depth_of_dry_holes_developmental_wells_drilled", + "us_average_depth_of_dry_holes_exploratory_wells_drilled", + "us_average_depth_of_natural_gas_developmental_wells_drilled", + "us_average_depth_of_natural_gas_exploratory_wells_drilled", + "us_average_depth_of_natural_gas_exploratory_and", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWellsData(EiaApiData): + """Average Depth of Crude Oil and Natural Gas Wells. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWellsFetcher( + Fetcher[ + EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWellsQueryParams, + list[EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWellsData], + ] +): + """Average Depth of Crude Oil and Natural Gas Wells fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWellsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWellsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWellsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWellsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWellsData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWellsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/coalbed_methane.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/coalbed_methane.py new file mode 100644 index 00000000000..3463c9d857f --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/coalbed_methane.py @@ -0,0 +1,164 @@ +"""Coalbed Methane model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasCoalbedMethaneQueryParams(EiaApiQueryParams): + """Coalbed Methane. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/coalbed + """ + + __group__ = "natural_gas" + __dataset__ = "coalbed_methane" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "coalbed_methane_proved_reserves", + "coalbed_methane_reserves_acquisitions", + "coalbed_methane_reserves_adjustments", + "coalbed_methane_reserves_based_production", + "coalbed_methane_reserves_extensions", + "coalbed_methane_reserves_extensions_and_discoveries", + "coalbed_methane_reserves_new_field_discoveries", + "coalbed_methane_reserves_new_reservoir_discoveries_in_old", + "coalbed_methane_reserves_revision_decreases", + "coalbed_methane_reserves_revision_increases", + "coalbed_methane_reserves_sales", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 560 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasCoalbedMethaneData(EiaApiData): + """Coalbed Methane. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasCoalbedMethaneFetcher( + Fetcher[ + EiaNaturalGasCoalbedMethaneQueryParams, list[EiaNaturalGasCoalbedMethaneData] + ] +): + """Coalbed Methane fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasCoalbedMethaneQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaNaturalGasCoalbedMethaneQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasCoalbedMethaneQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasCoalbedMethaneQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasCoalbedMethaneData]: + """Transform the data.""" + return transform_dataset_data(EiaNaturalGasCoalbedMethaneData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/coalbed_methane_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/coalbed_methane_production.py new file mode 100644 index 00000000000..f629aeb10ba --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/coalbed_methane_production.py @@ -0,0 +1,200 @@ +"""Coalbed Methane Production model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasCoalbedMethaneProductionQueryParams(EiaApiQueryParams): + """Coalbed Methane Production. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/prod/coalbed + """ + + __group__ = "natural_gas" + __dataset__ = "coalbed_methane_production" + __json_schema_extra__ = { + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alabama_coalbed_methane_production", + "alaska_coalbed_methane_production", + "arkansas_coalbed_methane_production", + "california_coalbed_methane_production", + "colorado_coalbed_methane_production", + "eastern_states_coalbed_methane_production", + "florida_coalbed_methane_production", + "kansas_coalbed_methane_production", + "kentucky_coalbed_methane_production", + "louisiana_coalbed_methane_production", + "louisiana_north_coalbed_methane_production", + "louisiana_south_onshore_coalbed_methane_production", + "louisiana_state_offshore_coalbed_methane_production", + "lower_48_federal_offshore_coalbed_methane_production", + "lower_48_states_coalbed_methane_production", + "michigan_coalbed_methane_production", + "mississippi_coalbed_methane_production", + "montana_coalbed_methane_production", + "new_mexico_coalbed_methane_production", + "new_mexico_east_coalbed_methane_production", + "new_mexico_west_coalbed_methane_production", + "new_york_coalbed_methane_production", + "north_dakota_coalbed_methane_production", + "ohio_coalbed_methane_production", + "oklahoma_coalbed_methane_production", + "other_states_natural_gas_coalbed_methane_reserves_based", + "pennsylvania_coalbed_methane_production", + "texas_coalbed_methane_production", + "texas_rrc_district_1_coalbed_methane_production", + "texas_rrc_district_10_coalbed_methane_production", + "texas_rrc_district_2_onshore_coalbed_methane_production", + "texas_rrc_district_3_onshore_coalbed_methane_production", + "texas_rrc_district_4_onshore_coalbed_methane_production", + "texas_rrc_district_5_coalbed_methane_production", + "texas_rrc_district_6_coalbed_methane_production", + "texas_rrc_district_7b_coalbed_methane_production", + "texas_rrc_district_7c_coalbed_methane_production", + "texas_rrc_district_8_coalbed_methane_production", + "texas_rrc_district_8a_coalbed_methane_production", + "texas_rrc_district_9_coalbed_methane_production", + "texas_state_offshore_coalbed_methane_production", + "us_coalbed_methane_production", + "utah_coalbed_methane_production", + "virginia_coalbed_methane_production", + "west_virginia_coalbed_methane_production", + "western_states_coalbed_methane_production", + "wyoming_coalbed_methane_production", + ], + }, + } + + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasCoalbedMethaneProductionData(EiaApiData): + """Coalbed Methane Production. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasCoalbedMethaneProductionFetcher( + Fetcher[ + EiaNaturalGasCoalbedMethaneProductionQueryParams, + list[EiaNaturalGasCoalbedMethaneProductionData], + ] +): + """Coalbed Methane Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasCoalbedMethaneProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasCoalbedMethaneProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasCoalbedMethaneProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasCoalbedMethaneProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasCoalbedMethaneProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasCoalbedMethaneProductionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/costs_of_crude_oil_and_natural_gas_wells_drilled.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/costs_of_crude_oil_and_natural_gas_wells_drilled.py new file mode 100644 index 00000000000..47c112a098e --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/costs_of_crude_oil_and_natural_gas_wells_drilled.py @@ -0,0 +1,152 @@ +"""Costs of Crude Oil and Natural Gas Wells Drilled model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilledQueryParams( + EiaApiQueryParams +): + """Costs of Crude Oil and Natural Gas Wells Drilled. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/wellcost + """ + + __group__ = "natural_gas" + __dataset__ = "costs_of_crude_oil_and_natural_gas_wells_drilled" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "nominal_cost_per_foot_of_dry_wells_drilled", + "nominal_cost_per_well_drilled", + "real_cost", + "real_cost_per_foot", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": ["wells_dry", "wells_gas", "wells_oil", "wells_total"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_nominal_cost_per_crude_oil_well_drilled", + "us_nominal_cost_per_crude_oil_natural_gas_and_dry_well", + "us_nominal_cost_per_dry_well_drilled", + "us_nominal_cost_per_foot_of_crude_oil_wells_drilled", + "us_nominal_cost_per_foot_of_crude_oil_natural_gas_and_dry", + "us_nominal_cost_per_foot_of_dry_wells_drilled", + "us_nominal_cost_per_foot_of_natural_gas_wells_drilled", + "us_nominal_cost_per_natural_gas_well_drilled", + "us_real_cost_per_crude_oil_natural_gas_and_dry_well_drilled", + "us_real_cost_per_foot_of_crude_oil_natural_gas_and_dry", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilledData(EiaApiData): + """Costs of Crude Oil and Natural Gas Wells Drilled. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilledFetcher( + Fetcher[ + EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilledQueryParams, + list[EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilledData], + ] +): + """Costs of Crude Oil and Natural Gas Wells Drilled fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilledQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilledQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilledQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilledQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilledData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilledData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/crude_oil_and_natural_gas_drilling_activity.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/crude_oil_and_natural_gas_drilling_activity.py new file mode 100644 index 00000000000..4bf5b2c8ddd --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/crude_oil_and_natural_gas_drilling_activity.py @@ -0,0 +1,158 @@ +"""Crude Oil and Natural Gas Drilling Activity model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasCrudeOilAndNaturalGasDrillingActivityQueryParams(EiaApiQueryParams): + """Crude Oil and Natural Gas Drilling Activity. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/drill + """ + + __group__ = "natural_gas" + __dataset__ = "crude_oil_and_natural_gas_drilling_activity" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "active_well_service_rigs_in_operation", + "rotary_rigs_in_operation", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "crude_oil_and_natural_gas", + "rotary_rigs_in_operation", + "rotary_rigs_in_operation_gas", + "rotary_rigs_in_operation_oil", + ], + }, + "region": {"multiple_items_allowed": True, "choices": ["na", "us"]}, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_crude_oil_rotary_rigs_in_operation", + "us_crude_oil_and_natural_gas_active_well_service_rigs_in", + "us_crude_oil_and_natural_gas_rotary_rigs_in_operation", + "us_natural_gas_rotary_rigs_in_operation", + "us_offshore_crude_oil_and_natural_gas_rotary_rigs_in", + "us_onshore_crude_oil_and_natural_gas_rotary_rigs_in", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasCrudeOilAndNaturalGasDrillingActivityData(EiaApiData): + """Crude Oil and Natural Gas Drilling Activity. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasCrudeOilAndNaturalGasDrillingActivityFetcher( + Fetcher[ + EiaNaturalGasCrudeOilAndNaturalGasDrillingActivityQueryParams, + list[EiaNaturalGasCrudeOilAndNaturalGasDrillingActivityData], + ] +): + """Crude Oil and Natural Gas Drilling Activity fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasCrudeOilAndNaturalGasDrillingActivityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasCrudeOilAndNaturalGasDrillingActivityQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasCrudeOilAndNaturalGasDrillingActivityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasCrudeOilAndNaturalGasDrillingActivityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasCrudeOilAndNaturalGasDrillingActivityData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasCrudeOilAndNaturalGasDrillingActivityData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/crude_oil_and_natural_gas_exploratory_and_development_wells.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/crude_oil_and_natural_gas_exploratory_and_development_wells.py new file mode 100644 index 00000000000..5177eb53914 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/crude_oil_and_natural_gas_exploratory_and_development_wells.py @@ -0,0 +1,162 @@ +"""Crude Oil and Natural Gas Exploratory and Development Wells model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsQueryParams( + EiaApiQueryParams +): + """Crude Oil and Natural Gas Exploratory and Development Wells. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/wellend + """ + + __group__ = "natural_gas" + __dataset__ = "crude_oil_and_natural_gas_exploratory_and_development_wells" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "developmental_wells_drilled", + "exploratory_wells_drilled", + "exploratory_and_developmental_wells_drilled", + "footage_drilled_for_exploratory_and_developmental_wells", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": ["wells_dry", "wells_gas", "wells_oil", "wells_total"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_crude_oil_developmental_wells_drilled", + "us_crude_oil_exploratory_wells_drilled", + "us_crude_oil_exploratory_and_developmental_wells_drilled", + "us_crude_oil_natural_gas_and_dry_developmental_wells_drilled", + "us_crude_oil_natural_gas_and_dry_exploratory_wells_drilled", + "us_crude_oil_natural_gas_and_dry_exploratory_and", + "us_dry_developmental_wells_drilled", + "us_dry_exploratory_wells_drilled", + "us_dry_exploratory_and_developmental_wells_drilled", + "us_footage_drilled_for_crude_oil_natural_gas_and_dry", + "us_natural_gas_developmental_wells_drilled", + "us_natural_gas_exploratory_wells_drilled", + "us_natural_gas_exploratory_and_developmental_wells_drilled", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsData(EiaApiData): + """Crude Oil and Natural Gas Exploratory and Development Wells. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsFetcher( + Fetcher[ + EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsQueryParams, + list[EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsData], + ] +): + """Crude Oil and Natural Gas Exploratory and Development Wells fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/crude_oil_plus_lease_condensate.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/crude_oil_plus_lease_condensate.py new file mode 100644 index 00000000000..de0f466d94a --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/crude_oil_plus_lease_condensate.py @@ -0,0 +1,170 @@ +"""Crude Oil plus Lease Condensate model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasCrudeOilPlusLeaseCondensateQueryParams(EiaApiQueryParams): + """Crude Oil plus Lease Condensate. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/cplc + """ + + __group__ = "natural_gas" + __dataset__ = "crude_oil_plus_lease_condensate" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "production_from_reserves", + "proved_reserves", + "reserves_acquisitions", + "reserves_adjustments", + "reserves_extensions", + "reserves_extensions_and_discoveries", + "reserves_new_field_discoveries", + "reserves_new_reservoir_discoveries_in_old_fields", + "reserves_revision_decreases", + "reserves_revision_increases", + "reserves_sales", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 572 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasCrudeOilPlusLeaseCondensateData(EiaApiData): + """Crude Oil plus Lease Condensate. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasCrudeOilPlusLeaseCondensateFetcher( + Fetcher[ + EiaNaturalGasCrudeOilPlusLeaseCondensateQueryParams, + list[EiaNaturalGasCrudeOilPlusLeaseCondensateData], + ] +): + """Crude Oil plus Lease Condensate fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasCrudeOilPlusLeaseCondensateQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasCrudeOilPlusLeaseCondensateQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasCrudeOilPlusLeaseCondensateQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasCrudeOilPlusLeaseCondensateQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasCrudeOilPlusLeaseCondensateData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasCrudeOilPlusLeaseCondensateData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/dry_natural_gas_proved_reserves.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/dry_natural_gas_proved_reserves.py new file mode 100644 index 00000000000..152444dcf6b --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/dry_natural_gas_proved_reserves.py @@ -0,0 +1,169 @@ +"""Dry Natural Gas Proved Reserves model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasDryNaturalGasProvedReservesQueryParams(EiaApiQueryParams): + """Dry Natural Gas Proved Reserves. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/dry + """ + + __group__ = "natural_gas" + __dataset__ = "dry_natural_gas_proved_reserves" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "dry_expected_future_production", + "dry_production_from_reserves", + "dry_reserves_acquisitions", + "dry_reserves_adjustments", + "dry_reserves_extensions", + "dry_reserves_extensions_and_discoveries", + "dry_reserves_new_field_discoveries", + "dry_reserves_new_reservoir_discoveries_in_old_fields", + "dry_reserves_revision_decreases", + "dry_reserves_revision_increases", + "dry_reserves_sales", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 561 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasDryNaturalGasProvedReservesData(EiaApiData): + """Dry Natural Gas Proved Reserves. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasDryNaturalGasProvedReservesFetcher( + Fetcher[ + EiaNaturalGasDryNaturalGasProvedReservesQueryParams, + list[EiaNaturalGasDryNaturalGasProvedReservesData], + ] +): + """Dry Natural Gas Proved Reserves fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasDryNaturalGasProvedReservesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasDryNaturalGasProvedReservesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasDryNaturalGasProvedReservesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasDryNaturalGasProvedReservesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasDryNaturalGasProvedReservesData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasDryNaturalGasProvedReservesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/federal_offshore_gulf_of_america_proved_reserves.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/federal_offshore_gulf_of_america_proved_reserves.py new file mode 100644 index 00000000000..38250e55e14 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/federal_offshore_gulf_of_america_proved_reserves.py @@ -0,0 +1,178 @@ +"""Federal Offshore Gulf of America Proved Reserves model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReservesQueryParams( + EiaApiQueryParams +): + """Federal Offshore Gulf of America Proved Reserves. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/deep + """ + + __group__ = "natural_gas" + __dataset__ = "federal_offshore_gulf_of_america_proved_reserves" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "dry_expected_future_production", + "dry_reserves_deepwater_percentage", + "dry_reserves_from_greater_than_200_meters", + "dry_reserves_from_less_than_200_meters", + "lease_condensate_proved_reserves", + "lease_condensate_reserves_deepwater_percentage", + "lease_condensate_reserves_from_greater_than_200_meters", + "lease_condensate_reserves_from_less_than_200_meters", + "proved_reserves", + "reserves_deepwater_percentage", + "reserves_greater_than_200_meters", + "reserves_less_than_200_meters", + "wet_after_lease_separation_proved_reserves", + "wet_after_lease_separation_reserves_deepwater_percentage", + "wet_after_lease_separation_reserves_from_greater_than_200", + "wet_after_lease_separation_reserves_from_less_than_200", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "crude_oil", + "natural_gas", + "natural_gas_liquids_and_liquid_refinery_gases", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "gulf_of_america_federal_offshore_crude_oil_proved_reserves_million_barrels", + "gulf_of_america_federal_offshore_crude_oil_proved_reserves_from_greater_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_crude_oil_proved_reserves_from_less_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_dry_natural_gas_expected", + "gulf_of_america_federal_offshore_dry_natural_gas_proved_reserves_from_greater_than_200_meters_deep_billion_cubic_feet", + "gulf_of_america_federal_offshore_dry_natural_gas_proved_reserves_from_less_than_200_meters_deep_billion_cubic_feet", + "gulf_of_america_federal_offshore_natural_gas_liquids_lease_condensate_proved_reserves_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_lease_condensate_proved_reserves_from_greater_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_lease_condensate_proved_reserves_from_less_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_proved_reserves_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_proved_reserves_from_greater_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_proved_reserves_from_less_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_wet_after_lease_separation_proved_reserves_billion_cubic_feet", + "gulf_of_america_federal_offshore_natural_gas_wet_after_lease_separation_proved_reserves_from_greater_than_200_meters_deep_billion_cubic_feet", + "gulf_of_america_federal_offshore_natural_gas_wet_after_lease_separation_proved_reserves_from_less_than_200_meters_deep_billion_cubic_feet", + "gulf_of_america_federal_offshore_percentage_of_crude_oil", + "gulf_of_america_federal_offshore_percentage_of_dry_natural", + "gulf_of_america_federal_offshore_percentage_of_natural_gas_liquids_lease_condensate_proved_reserves_from_greater_than_200_meters_deep", + "gulf_of_america_federal_offshore_percentage_of_natural_gas_liquids_proved_reserves_from_greater_than_200_meters_deep", + "gulf_of_america_federal_offshore_percentage_of_natural_gas_wet_after_lease_separation_proved_reserves_from_greater_than_200_meters_deep", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReservesData(EiaApiData): + """Federal Offshore Gulf of America Proved Reserves. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReservesFetcher( + Fetcher[ + EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReservesQueryParams, + list[EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReservesData], + ] +): + """Federal Offshore Gulf of America Proved Reserves fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReservesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReservesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReservesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReservesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReservesData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReservesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/footage_drilled_for_crude_oil_and_natural_gas_wells.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/footage_drilled_for_crude_oil_and_natural_gas_wells.py new file mode 100644 index 00000000000..186c617f25c --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/footage_drilled_for_crude_oil_and_natural_gas_wells.py @@ -0,0 +1,153 @@ +"""Footage Drilled for Crude Oil and Natural Gas Wells model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWellsQueryParams( + EiaApiQueryParams +): + """Footage Drilled for Crude Oil and Natural Gas Wells. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/wellfoot + """ + + __group__ = "natural_gas" + __dataset__ = "footage_drilled_for_crude_oil_and_natural_gas_wells" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "footage_drilled_for_developmental_wells", + "footage_drilled_for_exploratory_wells", + "footage_drilled_for_exploratory_and_developmental_wells", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": ["wells_dry", "wells_gas", "wells_oil", "wells_total"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_footage_drilled_for_crude_oil_developmental_wells", + "us_footage_drilled_for_crude_oil_exploratory_wells", + "us_footage_drilled_for_crude_oil_exploratory_and", + "us_footage_drilled_for_crude_oil_natural_gas_and_dry_developmental_wells_thousand_feet", + "us_footage_drilled_for_crude_oil_natural_gas_and_dry_exploratory_wells_thousand_feet", + "us_footage_drilled_for_crude_oil_natural_gas_and_dry_exploratory_and_developmental_wells_thousand_feet", + "us_footage_drilled_for_dry_developmental_wells", + "us_footage_drilled_for_dry_exploratory_wells", + "us_footage_drilled_for_dry_exploratory_and_developmental", + "us_footage_drilled_for_natural_gas_developmental_wells", + "us_footage_drilled_for_natural_gas_exploratory_wells", + "us_footage_drilled_for_natural_gas_exploratory_and", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWellsData(EiaApiData): + """Footage Drilled for Crude Oil and Natural Gas Wells. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWellsFetcher( + Fetcher[ + EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWellsQueryParams, + list[EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWellsData], + ] +): + """Footage Drilled for Crude Oil and Natural Gas Wells fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWellsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWellsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWellsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWellsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWellsData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWellsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/gulf_of_america_federal_offshore_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/gulf_of_america_federal_offshore_production.py new file mode 100644 index 00000000000..ca02246e60e --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/gulf_of_america_federal_offshore_production.py @@ -0,0 +1,176 @@ +"""Gulf of America Federal Offshore Production model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasGulfOfAmericaFederalOffshoreProductionQueryParams(EiaApiQueryParams): + """Gulf of America Federal Offshore Production. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/prod/deep + """ + + __group__ = "natural_gas" + __dataset__ = "gulf_of_america_federal_offshore_production" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "dry_production_from_reserves", + "dry_reserves_based_production_deepwater_percentage", + "dry_reserves_based_production_from_greater_than_200_meters", + "dry_reserves_based_production_from_less_than_200_meters", + "lease_condensate_reserves_based_production", + "lease_condensate_reserves_based_production_deepwater", + "lease_condensate_reserves_based_production_from_greater", + "lease_condensate_reserves_based_production_from_less_than", + "production_from_reserves", + "reserves_based_production_deepwater_percentage", + "reserves_based_production_from_greater_than_200_meters", + "reserves_based_production_from_less_than_200_meters", + "wet_after_lease_separation_reserves_based_production", + "wet_after_lease_separation_reserves_based_production_from_greater_than_200_meters", + "wet_after_lease_separation_reserves_based_production_from_less_than_200_meters", + "wet_after_lease_separation_reserves_based_production_from_reserves", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "crude_oil", + "natural_gas", + "natural_gas_liquids_and_liquid_refinery_gases", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "gulf_of_america_federal_offshore_crude_oil_production", + "gulf_of_america_federal_offshore_crude_oil_production_from_greater_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_crude_oil_production_from_less_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_dry_natural_gas_production_billion_cubic_feet", + "gulf_of_america_federal_offshore_dry_natural_gas_production_from_greater_than_200_meters_deep_billion_cubic_feet", + "gulf_of_america_federal_offshore_dry_natural_gas_production_from_less_than_200_meters_deep_billion_cubic_feet", + "gulf_of_america_federal_offshore_natural_gas_liquids_lease_condensate_production_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_lease_condensate_production_from_greater_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_lease_condensate_production_from_less_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_production_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_production_from_greater_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_production_from_less_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_wet_after_lease_separation_production_billion_cubic_feet", + "gulf_of_america_federal_offshore_natural_gas_wet_after_lease_separation_production_from_greater_than_200_meters_deep_billion_cubic_feet", + "gulf_of_america_federal_offshore_natural_gas_wet_after_lease_separation_production_from_less_than_200_meters_deep_billion_cubic_feet", + "gulf_of_america_federal_offshore_percentage_of_crude_oil", + "gulf_of_america_federal_offshore_percentage_of_dry_natural", + "gulf_of_america_federal_offshore_percentage_of_natural_gas_liquids_lease_condensate_production_from_greater_than_200_meters_deep", + "gulf_of_america_federal_offshore_percentage_of_natural_gas_liquids_production_from_greater_than_200_meters_deep", + "gulf_of_america_federal_offshore_percentage_of_natural_gas_wet_after_lease_separation_production_from_greater_than_200_meters_deep", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasGulfOfAmericaFederalOffshoreProductionData(EiaApiData): + """Gulf of America Federal Offshore Production. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasGulfOfAmericaFederalOffshoreProductionFetcher( + Fetcher[ + EiaNaturalGasGulfOfAmericaFederalOffshoreProductionQueryParams, + list[EiaNaturalGasGulfOfAmericaFederalOffshoreProductionData], + ] +): + """Gulf of America Federal Offshore Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasGulfOfAmericaFederalOffshoreProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasGulfOfAmericaFederalOffshoreProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasGulfOfAmericaFederalOffshoreProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasGulfOfAmericaFederalOffshoreProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasGulfOfAmericaFederalOffshoreProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasGulfOfAmericaFederalOffshoreProductionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/heat_content_of_natural_gas_consumed.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/heat_content_of_natural_gas_consumed.py new file mode 100644 index 00000000000..162ea1f665c --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/heat_content_of_natural_gas_consumed.py @@ -0,0 +1,236 @@ +"""Heat Content of Natural Gas Consumed model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasHeatContentOfNaturalGasConsumedQueryParams(EiaApiQueryParams): + """Heat Content of Natural Gas Consumed. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/cons/heat + """ + + __group__ = "natural_gas" + __dataset__ = "heat_content_of_natural_gas_consumed" + __json_schema_extra__ = { + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alabama_heat_content_of_natural_gas_deliveries_to_consumers", + "alaska_heat_content_of_natural_gas_deliveries_to_consumers", + "arizona_heat_content_of_natural_gas_deliveries_to_consumers", + "arkansas_heat_content_of_natural_gas_deliveries_to_consumers", + "california_heat_content_of_natural_gas_deliveries_to", + "colorado_heat_content_of_natural_gas_deliveries_to_consumers", + "connecticut_heat_content_of_natural_gas_deliveries_to", + "delaware_heat_content_of_natural_gas_deliveries_to_consumers", + "district_of_columbia_heat_content_of_natural_gas_deliveries", + "florida_heat_content_of_natural_gas_deliveries_to_consumers", + "georgia_heat_content_of_natural_gas_deliveries_to_consumers", + "hawaii_heat_content_of_natural_gas_deliveries_to_consumers", + "idaho_heat_content_of_natural_gas_deliveries_to_consumers", + "illinois_heat_content_of_natural_gas_deliveries_to_consumers", + "indiana_heat_content_of_natural_gas_deliveries_to_consumers", + "iowa_heat_content_of_natural_gas_deliveries_to_consumers", + "kansas_heat_content_of_natural_gas_deliveries_to_consumers", + "kentucky_heat_content_of_natural_gas_deliveries_to_consumers", + "louisiana_heat_content_of_natural_gas_deliveries_to", + "maine_heat_content_of_natural_gas_deliveries_to_consumers", + "maryland_heat_content_of_natural_gas_deliveries_to_consumers", + "massachusetts_heat_content_of_natural_gas_deliveries_to", + "michigan_heat_content_of_natural_gas_deliveries_to_consumers", + "minnesota_heat_content_of_natural_gas_deliveries_to", + "mississippi_heat_content_of_natural_gas_deliveries_to", + "missouri_heat_content_of_natural_gas_deliveries_to_consumers", + "montana_heat_content_of_natural_gas_deliveries_to_consumers", + "nebraska_heat_content_of_natural_gas_deliveries_to_consumers", + "nevada_heat_content_of_natural_gas_deliveries_to_consumers", + "new_hampshire_heat_content_of_natural_gas_deliveries_to", + "new_jersey_heat_content_of_natural_gas_deliveries_to", + "new_mexico_heat_content_of_natural_gas_deliveries_to", + "new_york_heat_content_of_natural_gas_deliveries_to_consumers", + "north_carolina_heat_content_of_natural_gas_deliveries_to", + "north_dakota_heat_content_of_natural_gas_deliveries_to", + "ohio_heat_content_of_natural_gas_deliveries_to_consumers", + "oklahoma_heat_content_of_natural_gas_deliveries_to_consumers", + "oregon_heat_content_of_natural_gas_deliveries_to_consumers", + "pennsylvania_heat_content_of_natural_gas_deliveries_to", + "rhode_island_heat_content_of_natural_gas_deliveries_to", + "south_carolina_heat_content_of_natural_gas_deliveries_to", + "south_dakota_heat_content_of_natural_gas_deliveries_to", + "tennessee_heat_content_of_natural_gas_deliveries_to", + "texas_heat_content_of_natural_gas_deliveries_to_consumers", + "us_heat_content_of_natural_gas_deliveries_to_consumers", + "utah_heat_content_of_natural_gas_deliveries_to_consumers", + "vermont_heat_content_of_natural_gas_deliveries_to_consumers", + "virginia_heat_content_of_natural_gas_deliveries_to_consumers", + "washington_heat_content_of_natural_gas_deliveries_to", + "west_virginia_heat_content_of_natural_gas_deliveries_to", + "wisconsin_heat_content_of_natural_gas_deliveries_to", + "wyoming_heat_content_of_natural_gas_deliveries_to_consumers", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasHeatContentOfNaturalGasConsumedData(EiaApiData): + """Heat Content of Natural Gas Consumed. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasHeatContentOfNaturalGasConsumedFetcher( + Fetcher[ + EiaNaturalGasHeatContentOfNaturalGasConsumedQueryParams, + list[EiaNaturalGasHeatContentOfNaturalGasConsumedData], + ] +): + """Heat Content of Natural Gas Consumed fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasHeatContentOfNaturalGasConsumedQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasHeatContentOfNaturalGasConsumedQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasHeatContentOfNaturalGasConsumedQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasHeatContentOfNaturalGasConsumedQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasHeatContentOfNaturalGasConsumedData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasHeatContentOfNaturalGasConsumedData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/international_interstate_movements_of_natural_gas_by_state.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/international_interstate_movements_of_natural_gas_by_state.py new file mode 100644 index 00000000000..14b7dfae93f --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/international_interstate_movements_of_natural_gas_by_state.py @@ -0,0 +1,143 @@ +"""International & Interstate Movements of Natural Gas by State model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByStateQueryParams( + EiaApiQueryParams +): + """International & Interstate Movements of Natural Gas by State. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/move/ist + """ + + __group__ = "natural_gas" + __dataset__ = "international_interstate_movements_of_natural_gas_by_state" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "exports_intransit", + "imports_intransit", + "interstate_and_across_us_borders_delivered_exports_to", + "interstate_and_across_us_borders_net_interstate_receipts", + "interstate_and_across_us_borders_receipts_imports", + "interstate_movements_deliveries", + "interstate_movements_net_receipts", + "interstate_movements_receipts", + "net_movements_across_us_borders", + ], + }, + "region": {"multiple_items_allowed": True}, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values. There are 738 valid values - use the `facet_options` endpoint to list them.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByStateData(EiaApiData): + """International & Interstate Movements of Natural Gas by State. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByStateFetcher( + Fetcher[ + EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByStateQueryParams, + list[EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByStateData], + ] +): + """International & Interstate Movements of Natural Gas by State fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByStateQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByStateQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByStateQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByStateQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByStateData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByStateData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/lease_condensate.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/lease_condensate.py new file mode 100644 index 00000000000..901bfbad738 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/lease_condensate.py @@ -0,0 +1,164 @@ +"""Lease Condensate model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasLeaseCondensateQueryParams(EiaApiQueryParams): + """Lease Condensate. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/lc + """ + + __group__ = "natural_gas" + __dataset__ = "lease_condensate" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "lease_condensate_proved_reserves", + "lease_condensate_reserves_acquisitions", + "lease_condensate_reserves_adjustments", + "lease_condensate_reserves_based_production", + "lease_condensate_reserves_extensions", + "lease_condensate_reserves_extensions_and_discoveries", + "lease_condensate_reserves_new_field_discoveries", + "lease_condensate_reserves_new_reservoir_discoveries_in_old", + "lease_condensate_reserves_revision_decreases", + "lease_condensate_reserves_revision_increases", + "lease_condensate_reserves_sales", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 552 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasLeaseCondensateData(EiaApiData): + """Lease Condensate. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasLeaseCondensateFetcher( + Fetcher[ + EiaNaturalGasLeaseCondensateQueryParams, list[EiaNaturalGasLeaseCondensateData] + ] +): + """Lease Condensate fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasLeaseCondensateQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaNaturalGasLeaseCondensateQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasLeaseCondensateQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasLeaseCondensateQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasLeaseCondensateData]: + """Transform the data.""" + return transform_dataset_data(EiaNaturalGasLeaseCondensateData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/lease_condensate_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/lease_condensate_production.py new file mode 100644 index 00000000000..a519ca8d560 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/lease_condensate_production.py @@ -0,0 +1,197 @@ +"""Lease Condensate Production model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasLeaseCondensateProductionQueryParams(EiaApiQueryParams): + """Lease Condensate Production. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/prod/lc + """ + + __group__ = "natural_gas" + __dataset__ = "lease_condensate_production" + __json_schema_extra__ = { + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_nm", + "usa_ok", + "usa_ut", + "usa_wv", + "usa_wy", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alabama_natural_gas_liquids_lease_condensate_reserves_based", + "alaska_natural_gas_liquids_lease_condensate_reserves_based", + "arkansas_natural_gas_liquids_lease_condensate_reserves", + "calif_coastal_region_onshore_natural_gas_liquids_lease", + "calif_los_angeles_basin_onshore_natural_gas_liquids_lease", + "calif_san_joaquin_basin_onshore_natural_gas_liquids_lease", + "california_natural_gas_liquids_lease_condensate_reserves", + "california_state_offshore_natural_gas_liquids_lease", + "colorado_natural_gas_liquids_lease_condensate_reserves", + "federal_offshore_california_natural_gas_liquids_lease", + "florida_natural_gas_liquids_lease_condensate_reserves_based", + "gulf_of_america_federal_offshore_central_and_eastern_natural_gas_liquids_lease_condensate_reserves_based_production_million_barrels", + "gulf_of_america_federal_offshore_western_natural_gas_liquids_lease_condensate_reserves_based_production_million_barrels", + "kansas_natural_gas_liquids_lease_condensate_reserves_based", + "kentucky_natural_gas_liquids_lease_condensate_reserves", + "louisiana_natural_gas_liquids_lease_condensate_reserves", + "louisiana_north_natural_gas_liquids_lease_condensate", + "louisiana_south_onshore_natural_gas_liquids_lease", + "louisiana_state_offshore_natural_gas_liquids_lease", + "lower_48_federal_offshore_natural_gas_liquids_lease", + "lower_48_states_natural_gas_liquids_lease_condensate", + "michigan_natural_gas_liquids_lease_condensate_reserves", + "mississippi_natural_gas_liquids_lease_condensate_reserves", + "montana_natural_gas_liquids_lease_condensate_reserves_based", + "new_mexico_natural_gas_liquids_lease_condensate_reserves", + "new_mexico_east_natural_gas_liquids_lease_condensate", + "new_mexico_west_natural_gas_liquids_lease_condensate", + "north_dakota_natural_gas_liquids_lease_condensate_reserves", + "oklahoma_natural_gas_liquids_lease_condensate_reserves", + "texas_natural_gas_liquids_lease_condensate_reserves_based", + "texas_rrc_district_1_natural_gas_liquids_lease_condensate", + "texas_rrc_district_10_natural_gas_liquids_lease_condensate", + "texas_rrc_district_2_onshore_natural_gas_liquids_lease", + "texas_rrc_district_3_onshore_natural_gas_liquids_lease", + "texas_rrc_district_4_onshore_natural_gas_liquids_lease", + "texas_rrc_district_5_natural_gas_liquids_lease_condensate", + "texas_rrc_district_6_natural_gas_liquids_lease_condensate", + "texas_rrc_district_7b_natural_gas_liquids_lease_condensate", + "texas_rrc_district_7c_natural_gas_liquids_lease_condensate", + "texas_rrc_district_8_natural_gas_liquids_lease_condensate", + "texas_rrc_district_8a_natural_gas_liquids_lease_condensate", + "texas_rrc_district_9_natural_gas_liquids_lease_condensate", + "texas_state_offshore_natural_gas_liquids_lease_condensate", + "us_natural_gas_liquids_lease_condensate_reserves_based", + "utah_natural_gas_liquids_lease_condensate_reserves_based", + "utah_and_wyoming_natural_gas_liquids_lease_condensate", + "west_virginia_natural_gas_liquids_lease_condensate_reserves", + "wyoming_natural_gas_liquids_lease_condensate_reserves_based", + ], + }, + } + + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasLeaseCondensateProductionData(EiaApiData): + """Lease Condensate Production. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasLeaseCondensateProductionFetcher( + Fetcher[ + EiaNaturalGasLeaseCondensateProductionQueryParams, + list[EiaNaturalGasLeaseCondensateProductionData], + ] +): + """Lease Condensate Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasLeaseCondensateProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasLeaseCondensateProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasLeaseCondensateProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasLeaseCondensateProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasLeaseCondensateProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasLeaseCondensateProductionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/lng_storage_additions_and_withdrawals.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/lng_storage_additions_and_withdrawals.py new file mode 100644 index 00000000000..6b27f4f631e --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/lng_storage_additions_and_withdrawals.py @@ -0,0 +1,178 @@ +"""Liquefied Natural Gas Additions to and Withdrawals from Storage model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasLngStorageAdditionsAndWithdrawalsQueryParams(EiaApiQueryParams): + """Liquefied Natural Gas Additions to and Withdrawals from Storage. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/stor/lng + """ + + __group__ = "natural_gas" + __dataset__ = "lng_storage_additions_and_withdrawals" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "lng_storage_additions", + "lng_storage_net_withdrawals", + "lng_storage_withdrawals", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_de", + "usa_ga", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_la", + "usa_md", + "usa_me", + "usa_mo", + "usa_mt", + "usa_nc", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_wi", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 123 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasLngStorageAdditionsAndWithdrawalsData(EiaApiData): + """Liquefied Natural Gas Additions to and Withdrawals from Storage. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasLngStorageAdditionsAndWithdrawalsFetcher( + Fetcher[ + EiaNaturalGasLngStorageAdditionsAndWithdrawalsQueryParams, + list[EiaNaturalGasLngStorageAdditionsAndWithdrawalsData], + ] +): + """Liquefied Natural Gas Additions to and Withdrawals from Storage fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasLngStorageAdditionsAndWithdrawalsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasLngStorageAdditionsAndWithdrawalsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasLngStorageAdditionsAndWithdrawalsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasLngStorageAdditionsAndWithdrawalsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasLngStorageAdditionsAndWithdrawalsData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasLngStorageAdditionsAndWithdrawalsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/maximum_us_active_seismic_crew_counts.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/maximum_us_active_seismic_crew_counts.py new file mode 100644 index 00000000000..d0848db9c6d --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/maximum_us_active_seismic_crew_counts.py @@ -0,0 +1,150 @@ +"""Maximum US Active Seismic Crew Counts model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasMaximumUsActiveSeismicCrewCountsQueryParams(EiaApiQueryParams): + """Maximum US Active Seismic Crew Counts. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/seis + """ + + __group__ = "natural_gas" + __dataset__ = "maximum_us_active_seismic_crew_counts" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "maximum_number_of_active_crews_engaged_in_four_dimensional", + "maximum_number_of_active_crews_engaged_in_sismic_surveying", + "maximum_number_of_active_crews_engaged_in_three_dimensional", + "maximum_number_of_active_crews_engaged_in_two_dimensional", + ], + }, + "region": {"multiple_items_allowed": True, "choices": ["na", "us", "usa_ak"]}, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alaska_maximum_number_of_active_crews_engaged_in_four", + "alaska_maximum_number_of_active_crews_engaged_in_seismic", + "alaska_maximum_number_of_active_crews_engaged_in_three", + "alaska_maximum_number_of_active_crews_engaged_in_two", + "us_lower_48_states_offshore_maximum_number_of_active_crews_engaged_in_seismic_surveying_count", + "us_lower_48_states_onshore_maximum_number_of_active_crews_engaged_in_seismic_surveying_count", + "us_maximum_number_of_active_crews_engaged_in_seismic", + "us_lower_48_states_offshore_maximum_number_of_active_crews_engaged_in_four_dimensional_seismic_surveying_count", + "us_lower_48_states_offshore_maximum_number_of_active_crews_engaged_in_three_dimensional_seismic_surveying_count", + "us_lower_48_states_offshore_maximum_number_of_active_crews_engaged_in_two_dimensional_seismic_surveying_count", + "us_lower_48_states_onshore_maximum_number_of_active_crews_engaged_in_four_dimensional_seismic_surveying_count", + "us_lower_48_states_onshore_maximum_number_of_active_crews_engaged_in_three_dimensional_seismic_surveying_count", + "us_lower_48_states_onshore_maximum_number_of_active_crews_engaged_in_two_dimensional_seismic_surveying_count", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasMaximumUsActiveSeismicCrewCountsData(EiaApiData): + """Maximum US Active Seismic Crew Counts. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasMaximumUsActiveSeismicCrewCountsFetcher( + Fetcher[ + EiaNaturalGasMaximumUsActiveSeismicCrewCountsQueryParams, + list[EiaNaturalGasMaximumUsActiveSeismicCrewCountsData], + ] +): + """Maximum US Active Seismic Crew Counts fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasMaximumUsActiveSeismicCrewCountsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasMaximumUsActiveSeismicCrewCountsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasMaximumUsActiveSeismicCrewCountsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasMaximumUsActiveSeismicCrewCountsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasMaximumUsActiveSeismicCrewCountsData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasMaximumUsActiveSeismicCrewCountsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_annual_supply_disposition_by_state.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_annual_supply_disposition_by_state.py new file mode 100644 index 00000000000..a4fc671f4dc --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_annual_supply_disposition_by_state.py @@ -0,0 +1,185 @@ +"""Natural Gas Annual Supply & Disposition by State model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNaturalGasAnnualSupplyDispositionByStateQueryParams( + EiaApiQueryParams +): + """Natural Gas Annual Supply & Disposition by State. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/sum/snd + """ + + __group__ = "natural_gas" + __dataset__ = "natural_gas_annual_supply_disposition_by_state" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "balancing_item", + "dry_production", + "input_supplemental_fuels", + "total_consumption", + "underground_storage_injections", + "underground_storage_withdrawals", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "minnesota", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 104 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasNaturalGasAnnualSupplyDispositionByStateData(EiaApiData): + """Natural Gas Annual Supply & Disposition by State. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNaturalGasAnnualSupplyDispositionByStateFetcher( + Fetcher[ + EiaNaturalGasNaturalGasAnnualSupplyDispositionByStateQueryParams, + list[EiaNaturalGasNaturalGasAnnualSupplyDispositionByStateData], + ] +): + """Natural Gas Annual Supply & Disposition by State fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNaturalGasAnnualSupplyDispositionByStateQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNaturalGasAnnualSupplyDispositionByStateQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNaturalGasAnnualSupplyDispositionByStateQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNaturalGasAnnualSupplyDispositionByStateQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNaturalGasAnnualSupplyDispositionByStateData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNaturalGasAnnualSupplyDispositionByStateData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_consumption_by_end_use.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_consumption_by_end_use.py new file mode 100644 index 00000000000..e9195e2496d --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_consumption_by_end_use.py @@ -0,0 +1,198 @@ +"""Natural Gas Consumption by End Use model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNaturalGasConsumptionByEndUseQueryParams(EiaApiQueryParams): + """Natural Gas Consumption by End Use. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/cons/sum + """ + + __group__ = "natural_gas" + __dataset__ = "natural_gas_consumption_by_end_use" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "commercial_consumption", + "delivered_to_consumers", + "electric_power_consumption", + "industrial_consumption", + "lease_and_plant_fuel_consumption", + "pipeline_fuel_consumption", + "residential_consumption", + "total_consumption", + "vehicle_fuel_consumption", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 315 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasNaturalGasConsumptionByEndUseData(EiaApiData): + """Natural Gas Consumption by End Use. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNaturalGasConsumptionByEndUseFetcher( + Fetcher[ + EiaNaturalGasNaturalGasConsumptionByEndUseQueryParams, + list[EiaNaturalGasNaturalGasConsumptionByEndUseData], + ] +): + """Natural Gas Consumption by End Use fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNaturalGasConsumptionByEndUseQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNaturalGasConsumptionByEndUseQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNaturalGasConsumptionByEndUseQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNaturalGasConsumptionByEndUseQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNaturalGasConsumptionByEndUseData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNaturalGasConsumptionByEndUseData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_delivered_for_the_account_of_others.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_delivered_for_the_account_of_others.py new file mode 100644 index 00000000000..cd3b33feb6b --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_delivered_for_the_account_of_others.py @@ -0,0 +1,192 @@ +"""Natural Gas Delivered for the Account of Others model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthersQueryParams( + EiaApiQueryParams +): + """Natural Gas Delivered for the Account of Others. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/cons/acct + """ + + __group__ = "natural_gas" + __dataset__ = "natural_gas_delivered_for_the_account_of_others" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "total_residential_consumers_deliveries", + "of_total_commercial_delivered_for_the_account_of_others", + "of_total_industrial_delivered_for_the_account_of_others", + "delivered_to_commercial_consumers_for_the_account_of_others", + "delivered_to_industrial_consumers_for_the_account_of_others", + "residential_transported", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 269 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthersData(EiaApiData): + """Natural Gas Delivered for the Account of Others. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthersFetcher( + Fetcher[ + EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthersQueryParams, + list[EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthersData], + ] +): + """Natural Gas Delivered for the Account of Others fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthersQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthersQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthersQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthersQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthersData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthersData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_gross_withdrawals_and_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_gross_withdrawals_and_production.py new file mode 100644 index 00000000000..eeb859efd7b --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_gross_withdrawals_and_production.py @@ -0,0 +1,186 @@ +"""Natural Gas Gross Withdrawals and Production model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNaturalGasGrossWithdrawalsAndProductionQueryParams( + EiaApiQueryParams +): + """Natural Gas Gross Withdrawals and Production. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/prod/sum + """ + + __group__ = "natural_gas" + __dataset__ = "natural_gas_gross_withdrawals_and_production" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "dry_production", + "extraction_loss", + "gross_withdrawals", + "marketed_production", + "removed_from_natural_gas", + "repressuring", + "vented_and_flared", + "withdrawals_from_coalbed_wells", + "withdrawals_from_gas_wells", + "withdrawals_from_oil_wells", + "withdrawals_from_shale_gas", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 434 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasNaturalGasGrossWithdrawalsAndProductionData(EiaApiData): + """Natural Gas Gross Withdrawals and Production. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNaturalGasGrossWithdrawalsAndProductionFetcher( + Fetcher[ + EiaNaturalGasNaturalGasGrossWithdrawalsAndProductionQueryParams, + list[EiaNaturalGasNaturalGasGrossWithdrawalsAndProductionData], + ] +): + """Natural Gas Gross Withdrawals and Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNaturalGasGrossWithdrawalsAndProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNaturalGasGrossWithdrawalsAndProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNaturalGasGrossWithdrawalsAndProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNaturalGasGrossWithdrawalsAndProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNaturalGasGrossWithdrawalsAndProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNaturalGasGrossWithdrawalsAndProductionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_liquids_proved_reserves.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_liquids_proved_reserves.py new file mode 100644 index 00000000000..968980adb72 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_liquids_proved_reserves.py @@ -0,0 +1,167 @@ +"""Natural Gas Liquids Proved Reserves model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNaturalGasLiquidsProvedReservesQueryParams(EiaApiQueryParams): + """Natural Gas Liquids Proved Reserves. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/ngl + """ + + __group__ = "natural_gas" + __dataset__ = "natural_gas_liquids_proved_reserves" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "production_from_reserves", + "proved_reserves", + "reserves_acquisitions", + "reserves_adjustments", + "reserves_extensions", + "reserves_new_field_discoveries", + "reserves_new_reservoir_discoveries_in_old_fields", + "reserves_revision_decreases", + "reserves_revision_increases", + "reserves_sales", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 494 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasNaturalGasLiquidsProvedReservesData(EiaApiData): + """Natural Gas Liquids Proved Reserves. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNaturalGasLiquidsProvedReservesFetcher( + Fetcher[ + EiaNaturalGasNaturalGasLiquidsProvedReservesQueryParams, + list[EiaNaturalGasNaturalGasLiquidsProvedReservesData], + ] +): + """Natural Gas Liquids Proved Reserves fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNaturalGasLiquidsProvedReservesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNaturalGasLiquidsProvedReservesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNaturalGasLiquidsProvedReservesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNaturalGasLiquidsProvedReservesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNaturalGasLiquidsProvedReservesData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNaturalGasLiquidsProvedReservesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_plant_liquids_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_plant_liquids_production.py new file mode 100644 index 00000000000..3e5219322fb --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_plant_liquids_production.py @@ -0,0 +1,199 @@ +"""Natural Gas Plant Liquids Production model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNaturalGasPlantLiquidsProductionQueryParams(EiaApiQueryParams): + """Natural Gas Plant Liquids Production. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/prod/ngpl + """ + + __group__ = "natural_gas" + __dataset__ = "natural_gas_plant_liquids_production" + __json_schema_extra__ = { + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_nm", + "usa_ok", + "usa_ut", + "usa_wv", + "usa_wy", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alabama_natural_gas_plant_liquids_reserves_based_production", + "alaska_natural_gas_plant_liquids_reserves_based_production", + "arkansas_natural_gas_plant_liquids_reserves_based_production", + "calif_coastal_region_onshore_natural_gas_plant_liquids", + "calif_los_angeles_basin_onshore_natural_gas_plant_liquids", + "calif_san_joaquin_basin_onshore_natural_gas_plant_liquids", + "california_natural_gas_plant_liquids_reserves_based", + "california_state_offshore_natural_gas_plant_liquids", + "colorado_natural_gas_plant_liquids_reserves_based_production", + "federal_offshore_california_natural_gas_plant_liquids", + "florida_natural_gas_plant_liquids_reserves_based_production", + "gulf_of_america_federal_offshore_central_and_eastern_natural_gas_plant_liquids_reserves_based_production_million_barrels", + "gulf_of_america_federal_offshore_western_natural_gas_plant_liquids_reserves_based_production_million_barrels", + "kansas_natural_gas_plant_liquids_reserves_based_production", + "kentucky_natural_gas_plant_liquids_reserves_based_production", + "louisiana_natural_gas_plant_liquids_reserves_based", + "louisiana_north_natural_gas_plant_liquids_reserves_based", + "louisiana_south_onshore_natural_gas_plant_liquids_reserves", + "louisiana_state_offshore_natural_gas_plant_liquids_reserves", + "lower_48_federal_offshore_natural_gas_plant_liquids", + "lower_48_states_natural_gas_plant_liquids_reserves_based", + "michigan_natural_gas_plant_liquids_reserves_based_production", + "mississippi_natural_gas_plant_liquids_reserves_based", + "montana_natural_gas_plant_liquids_reserves_based_production", + "new_mexico_natural_gas_plant_liquids_reserves_based", + "new_mexico_east_natural_gas_plant_liquids_reserves_based", + "new_mexico_west_natural_gas_plant_liquids_reserves_based", + "north_dakota_natural_gas_plant_liquids_reserves_based", + "ohio_natural_gas_plant_liquids_reserves_based_production", + "oklahoma_natural_gas_plant_liquids_reserves_based_production", + "texas_natural_gas_plant_liquids_reserves_based_production", + "texas_rrc_district_1_natural_gas_plant_liquids_reserves", + "texas_rrc_district_10_natural_gas_plant_liquids_reserves", + "texas_rrc_district_2_onshore_natural_gas_plant_liquids", + "texas_rrc_district_3_onshore_natural_gas_plant_liquids", + "texas_rrc_district_4_onshore_natural_gas_plant_liquids", + "texas_rrc_district_5_natural_gas_plant_liquids_reserves", + "texas_rrc_district_6_natural_gas_plant_liquids_reserves", + "texas_rrc_district_7b_natural_gas_plant_liquids_reserves", + "texas_rrc_district_7c_natural_gas_plant_liquids_reserves", + "texas_rrc_district_8_natural_gas_plant_liquids_reserves", + "texas_rrc_district_8a_natural_gas_plant_liquids_reserves", + "texas_rrc_district_9_natural_gas_plant_liquids_reserves", + "texas_state_offshore_natural_gas_plant_liquids_reserves", + "us_natural_gas_plant_liquids_reserves_based_production", + "utah_natural_gas_plant_liquids_reserves_based_production", + "utah_and_wyoming_natural_gas_plant_liquids_reserves_based", + "west_virginia_natural_gas_plant_liquids_reserves_based", + "wyoming_natural_gas_plant_liquids_reserves_based_production", + ], + }, + } + + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasNaturalGasPlantLiquidsProductionData(EiaApiData): + """Natural Gas Plant Liquids Production. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNaturalGasPlantLiquidsProductionFetcher( + Fetcher[ + EiaNaturalGasNaturalGasPlantLiquidsProductionQueryParams, + list[EiaNaturalGasNaturalGasPlantLiquidsProductionData], + ] +): + """Natural Gas Plant Liquids Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNaturalGasPlantLiquidsProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNaturalGasPlantLiquidsProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNaturalGasPlantLiquidsProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNaturalGasPlantLiquidsProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNaturalGasPlantLiquidsProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNaturalGasPlantLiquidsProductionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_plant_processing.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_plant_processing.py new file mode 100644 index 00000000000..7245976796f --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_plant_processing.py @@ -0,0 +1,186 @@ +"""Natural Gas Plant Processing model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNaturalGasPlantProcessingQueryParams(EiaApiQueryParams): + """Natural Gas Plant Processing. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/prod/pp + """ + + __group__ = "natural_gas" + __dataset__ = "natural_gas_plant_processing" + __json_schema_extra__ = { + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_id", + "usa_il", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_wv", + "usa_wy", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alabama_natural_gas_plant_liquids_production", + "alaska_natural_gas_plant_liquids_production", + "arkansas_natural_gas_plant_liquids_production", + "california_natural_gas_plant_liquids_production", + "colorado_natural_gas_plant_liquids_production", + "florida_natural_gas_plant_liquids_production", + "gulf_of_america_natural_gas_plant_liquids_production", + "idaho_natural_gas_plant_liquids_production", + "illinois_natural_gas_plant_liquids_production", + "kansas_natural_gas_plant_liquids_production", + "kentucky_natural_gas_plant_liquids_production", + "louisiana_natural_gas_plant_liquids_production", + "michigan_natural_gas_plant_liquids_production", + "mississippi_natural_gas_plant_liquids_production", + "montana_natural_gas_plant_liquids_production", + "new_mexico_natural_gas_plant_liquids_production", + "north_dakota_natural_gas_plant_liquids_production", + "ohio_natural_gas_plant_liquids_production", + "oklahoma_natural_gas_plant_liquids_production", + "pennsylvania_natural_gas_plant_liquids_production", + "south_dakota_natural_gas_plant_liquids_production", + "tennessee_natural_gas_plant_liquids_production", + "texas_natural_gas_plant_liquids_production", + "us_natural_gas_plant_liquids_production", + "utah_natural_gas_plant_liquids_production", + "west_virginia_natural_gas_plant_liquids_production", + "wyoming_natural_gas_plant_liquids_production", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasNaturalGasPlantProcessingData(EiaApiData): + """Natural Gas Plant Processing. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNaturalGasPlantProcessingFetcher( + Fetcher[ + EiaNaturalGasNaturalGasPlantProcessingQueryParams, + list[EiaNaturalGasNaturalGasPlantProcessingData], + ] +): + """Natural Gas Plant Processing fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNaturalGasPlantProcessingQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNaturalGasPlantProcessingQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNaturalGasPlantProcessingQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNaturalGasPlantProcessingQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNaturalGasPlantProcessingData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNaturalGasPlantProcessingData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_prices.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_prices.py new file mode 100644 index 00000000000..25a4a22b2c4 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_prices.py @@ -0,0 +1,200 @@ +"""Natural Gas Prices model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNaturalGasPricesQueryParams(EiaApiQueryParams): + """Natural Gas Prices. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/pri/sum + """ + + __group__ = "natural_gas" + __dataset__ = "natural_gas_prices" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "of_industrial_consumers_sales", + "city_gate_price", + "electric_power_price", + "exports", + "imports_price", + "industrial_price", + "lng_imports", + "liquefied_natural_gas_exports_price", + "percent_sold_to_the_commercial_sector", + "percent_sold_to_the_residential_consumers", + "pipeline_exports", + "pipeline_imports_price", + "price_delivered_to_commercial_sectors", + "price_delivered_to_residential_consumers", + "wellhead_acquisition_price", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 423 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasNaturalGasPricesData(EiaApiData): + """Natural Gas Prices. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNaturalGasPricesFetcher( + Fetcher[ + EiaNaturalGasNaturalGasPricesQueryParams, + list[EiaNaturalGasNaturalGasPricesData], + ] +): + """Natural Gas Prices fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNaturalGasPricesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaNaturalGasNaturalGasPricesQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNaturalGasPricesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNaturalGasPricesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNaturalGasPricesData]: + """Transform the data.""" + return transform_dataset_data(EiaNaturalGasNaturalGasPricesData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_proved_reserves_wet_after_lease_separation.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_proved_reserves_wet_after_lease_separation.py new file mode 100644 index 00000000000..0feb542df50 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_proved_reserves_wet_after_lease_separation.py @@ -0,0 +1,174 @@ +"""Natural Gas Proved Reserves, Wet After Lease Separation model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparationQueryParams( + EiaApiQueryParams +): + """Natural Gas Proved Reserves, Wet After Lease Separation. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/wals + """ + + __group__ = "natural_gas" + __dataset__ = "natural_gas_proved_reserves_wet_after_lease_separation" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "wet_after_lease_separation_proved_reserves", + "wet_after_lease_separation_reserves_acquisitions", + "wet_after_lease_separation_reserves_adjustments", + "wet_after_lease_separation_reserves_based_production_from", + "wet_after_lease_separation_reserves_extensions", + "wet_after_lease_separation_reserves_extensions_and", + "wet_after_lease_separation_reserves_new_field_discoveries", + "wet_after_lease_separation_reserves_new_reservoir", + "wet_after_lease_separation_reserves_revision_decreases", + "wet_after_lease_separation_reserves_revision_increases", + "wet_after_lease_separation_reserves_sales", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 561 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparationData(EiaApiData): + """Natural Gas Proved Reserves, Wet After Lease Separation. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparationFetcher( + Fetcher[ + EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparationQueryParams, + list[EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparationData], + ] +): + """Natural Gas Proved Reserves, Wet After Lease Separation fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparationQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparationQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparationQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparationQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparationData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparationData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_reserves_summary_as_of_dec_31.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_reserves_summary_as_of_dec_31.py new file mode 100644 index 00000000000..7b006025e75 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_reserves_summary_as_of_dec_31.py @@ -0,0 +1,172 @@ +"""Natural Gas Reserves Summary as of Dec model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNaturalGasReservesSummaryAsOfDec31QueryParams(EiaApiQueryParams): + """Natural Gas Reserves Summary as of Dec. 31. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/sum + """ + + __group__ = "natural_gas" + __dataset__ = "natural_gas_reserves_summary_as_of_dec_31" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "associated_dissolved_proved_reserves", + "dry_expected_future_production", + "nonassociated_proved_reserves", + "proved_reserves", + "wet_after_lease_separation_proved_reserves", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": ["natural_gas", "natural_gas_liquids_and_liquid_refinery_gases"], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 256 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasNaturalGasReservesSummaryAsOfDec31Data(EiaApiData): + """Natural Gas Reserves Summary as of Dec. 31. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNaturalGasReservesSummaryAsOfDec31Fetcher( + Fetcher[ + EiaNaturalGasNaturalGasReservesSummaryAsOfDec31QueryParams, + list[EiaNaturalGasNaturalGasReservesSummaryAsOfDec31Data], + ] +): + """Natural Gas Reserves Summary as of Dec fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNaturalGasReservesSummaryAsOfDec31QueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNaturalGasReservesSummaryAsOfDec31QueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNaturalGasReservesSummaryAsOfDec31QueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNaturalGasReservesSummaryAsOfDec31QueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNaturalGasReservesSummaryAsOfDec31Data]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNaturalGasReservesSummaryAsOfDec31Data, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_spot_and_futures_prices.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_spot_and_futures_prices.py new file mode 100644 index 00000000000..620333fbd74 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_spot_and_futures_prices.py @@ -0,0 +1,147 @@ +"""Natural Gas Spot and Futures Prices (NYMEX) (Futures prices after April 5, 2024, are not available) model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNaturalGasSpotAndFuturesPricesQueryParams(EiaApiQueryParams): + """Natural Gas Spot and Futures Prices (NYMEX) (Futures prices after April 5, 2024, are not available). EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/pri/fut + """ + + __group__ = "natural_gas" + __dataset__ = "natural_gas_spot_and_futures_prices" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "future_contract_1", + "future_contract_2", + "future_contract_3", + "future_contract_4", + "spot_price", + ], + }, + "region": {"multiple_items_allowed": True, "choices": ["na", "new_york_city"]}, + "series": { + "multiple_items_allowed": True, + "choices": [ + "henry_hub_natural_gas_spot_price", + "natural_gas_futures_contract_1", + "natural_gas_futures_contract_2", + "natural_gas_futures_contract_3", + "natural_gas_futures_contract_4", + ], + }, + } + + frequency: Literal["annual", "daily", "monthly", "weekly"] | None = Field( + default=None, + description="The data frequency. The default is 'weekly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasNaturalGasSpotAndFuturesPricesData(EiaApiData): + """Natural Gas Spot and Futures Prices (NYMEX) (Futures prices after April 5, 2024, are not available). EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNaturalGasSpotAndFuturesPricesFetcher( + Fetcher[ + EiaNaturalGasNaturalGasSpotAndFuturesPricesQueryParams, + list[EiaNaturalGasNaturalGasSpotAndFuturesPricesData], + ] +): + """Natural Gas Spot and Futures Prices (NYMEX) (Futures prices after April 5, 2024, are not available) fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNaturalGasSpotAndFuturesPricesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNaturalGasSpotAndFuturesPricesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNaturalGasSpotAndFuturesPricesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNaturalGasSpotAndFuturesPricesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNaturalGasSpotAndFuturesPricesData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNaturalGasSpotAndFuturesPricesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_summary.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_summary.py new file mode 100644 index 00000000000..705234235fc --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_summary.py @@ -0,0 +1,233 @@ +"""Natural Gas Summary model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNaturalGasSummaryQueryParams(EiaApiQueryParams): + """Natural Gas Summary. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/sum/lsum + """ + + __group__ = "natural_gas" + __dataset__ = "natural_gas_summary" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "city_gate_price", + "commercial_consumption", + "delivered_to_consumers", + "dry_production", + "electric_power_consumption", + "electric_power_price", + "exports", + "exports_price", + "extraction_loss", + "gross_withdrawals", + "imports", + "imports_price", + "industrial_consumption", + "industrial_price", + "lng_imports", + "lease_and_plant_fuel_consumption", + "liquefied_natural_gas_exports", + "liquefied_natural_gas_exports_price", + "liquefied_natural_gas_imports", + "marketed_production", + "pipeline_exports", + "pipeline_exports_price", + "pipeline_fuel_consumption", + "pipeline_imports", + "pipeline_imports_price", + "price_delivered_to_commercial_sectors", + "price_delivered_to_residential_consumers", + "removed_from_natural_gas", + "repressuring", + "residential_consumption", + "total_consumption", + "total_underground_storage", + "total_underground_storage_capacity", + "underground_storage_base_gas", + "underground_storage_injections", + "underground_storage_net_withdrawals", + "underground_storage_withdrawals", + "underground_storage_working_gas", + "vehicle_fuel_consumption", + "vented_and_flared", + "wellhead_acquisition_price", + "withdrawals_from_coalbed_wells", + "withdrawals_from_gas_wells", + "withdrawals_from_oil_wells", + "withdrawals_from_shale_gas", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaNaturalGasNaturalGasSummaryData(EiaApiData): + """Natural Gas Summary. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNaturalGasSummaryFetcher( + Fetcher[ + EiaNaturalGasNaturalGasSummaryQueryParams, + list[EiaNaturalGasNaturalGasSummaryData], + ] +): + """Natural Gas Summary fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNaturalGasSummaryQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNaturalGasSummaryQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNaturalGasSummaryQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNaturalGasSummaryQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNaturalGasSummaryData]: + """Transform the data.""" + return transform_dataset_data(EiaNaturalGasNaturalGasSummaryData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_wellhead_value_and_marketed_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_wellhead_value_and_marketed_production.py new file mode 100644 index 00000000000..c9c9100205c --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/natural_gas_wellhead_value_and_marketed_production.py @@ -0,0 +1,215 @@ +"""Natural Gas Wellhead Value and Marketed Production model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNaturalGasWellheadValueAndMarketedProductionQueryParams( + EiaApiQueryParams +): + """Natural Gas Wellhead Value and Marketed Production. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/prod/whv + """ + + __group__ = "natural_gas" + __dataset__ = "natural_gas_wellhead_value_and_marketed_production" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": ["marketed_production", "wellhead_acquisition_price"], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alabama_natural_gas_marketed_production", + "alaska_natural_gas_marketed_production", + "arizona_natural_gas_marketed_production", + "arkansas_natural_gas_marketed_production", + "california_natural_gas_marketed_production", + "colorado_natural_gas_marketed_production", + "federal_offshore_gulf_of_america_natural_gas_marketed", + "florida_natural_gas_marketed_production", + "idaho_marketed_production_of_natural_gas", + "illinois_natural_gas_marketed_production", + "indiana_natural_gas_marketed_production", + "kansas_natural_gas_marketed_production", + "kentucky_natural_gas_marketed_production", + "louisiana_natural_gas_marketed_production", + "maryland_natural_gas_marketed_production", + "michigan_natural_gas_marketed_production", + "mississippi_natural_gas_marketed_production", + "missouri_natural_gas_marketed_production", + "montana_natural_gas_marketed_production", + "nebraska_natural_gas_marketed_production", + "nevada_natural_gas_marketed_production", + "new_mexico_natural_gas_marketed_production", + "new_york_natural_gas_marketed_production", + "north_dakota_natural_gas_marketed_production", + "ohio_natural_gas_marketed_production", + "oklahoma_natural_gas_marketed_production", + "oregon_natural_gas_marketed_production", + "pennsylvania_natural_gas_marketed_production", + "south_dakota_natural_gas_marketed_production", + "tennessee_natural_gas_marketed_production", + "texas_natural_gas_marketed_production", + "us_natural_gas_marketed_production", + "us_natural_gas_wellhead_price", + "utah_natural_gas_marketed_production", + "virginia_natural_gas_marketed_production", + "west_virginia_natural_gas_marketed_production", + "wyoming_natural_gas_marketed_production", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasNaturalGasWellheadValueAndMarketedProductionData(EiaApiData): + """Natural Gas Wellhead Value and Marketed Production. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNaturalGasWellheadValueAndMarketedProductionFetcher( + Fetcher[ + EiaNaturalGasNaturalGasWellheadValueAndMarketedProductionQueryParams, + list[EiaNaturalGasNaturalGasWellheadValueAndMarketedProductionData], + ] +): + """Natural Gas Wellhead Value and Marketed Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNaturalGasWellheadValueAndMarketedProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNaturalGasWellheadValueAndMarketedProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNaturalGasWellheadValueAndMarketedProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNaturalGasWellheadValueAndMarketedProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNaturalGasWellheadValueAndMarketedProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNaturalGasWellheadValueAndMarketedProductionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/nonassociated_proved_reserves.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/nonassociated_proved_reserves.py new file mode 100644 index 00000000000..8ce98a2442f --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/nonassociated_proved_reserves.py @@ -0,0 +1,170 @@ +"""Nonassociated Natural Gas Proved Reserves, Wet After Lease Separation model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNonassociatedProvedReservesQueryParams(EiaApiQueryParams): + """Nonassociated Natural Gas Proved Reserves, Wet After Lease Separation. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/nang + """ + + __group__ = "natural_gas" + __dataset__ = "nonassociated_proved_reserves" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "nonassociated_production_from_reserves", + "nonassociated_proved_reserves", + "nonassociated_reserves_acquisitions", + "nonassociated_reserves_adjustments", + "nonassociated_reserves_extensions", + "nonassociated_reserves_extensions_and_discoveries", + "nonassociated_reserves_new_field_discoveries", + "nonassociated_reserves_new_reservoir_discoveries_in_old", + "nonassociated_reserves_revision_decreases", + "nonassociated_reserves_revision_increases", + "nonassociated_reserves_sales", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 572 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasNonassociatedProvedReservesData(EiaApiData): + """Nonassociated Natural Gas Proved Reserves, Wet After Lease Separation. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNonassociatedProvedReservesFetcher( + Fetcher[ + EiaNaturalGasNonassociatedProvedReservesQueryParams, + list[EiaNaturalGasNonassociatedProvedReservesData], + ] +): + """Nonassociated Natural Gas Proved Reserves, Wet After Lease Separation fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNonassociatedProvedReservesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNonassociatedProvedReservesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNonassociatedProvedReservesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNonassociatedProvedReservesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNonassociatedProvedReservesData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNonassociatedProvedReservesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/number_of_gas_producing_oil_wells.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/number_of_gas_producing_oil_wells.py new file mode 100644 index 00000000000..62fe7e90965 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/number_of_gas_producing_oil_wells.py @@ -0,0 +1,198 @@ +"""Number of Gas Producing Oil Wells model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNumberOfGasProducingOilWellsQueryParams(EiaApiQueryParams): + """Number of Gas Producing Oil Wells. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/prod/oilwells + """ + + __group__ = "natural_gas" + __dataset__ = "number_of_gas_producing_oil_wells" + __json_schema_extra__ = { + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alabama_natural_gas_number_of_oil_wells", + "alaska_natural_gas_number_of_oil_wells", + "arizona_natural_gas_number_of_oil_wells", + "arkansas_natural_gas_number_of_oil_wells", + "california_natural_gas_number_of_oil_wells", + "colorado_natural_gas_number_of_oil_wells", + "federal_offshore_gulf_of_america_natural_gas_number_of_oil", + "florida_natural_gas_number_of_oil_wells", + "illinois_natural_gas_number_of_oil_wells", + "indiana_natural_gas_number_of_oil_wells", + "kansas_natural_gas_number_of_oil_wells", + "kentucky_natural_gas_number_of_oil_wells", + "louisiana_natural_gas_number_of_oil_wells", + "maryland_natural_gas_number_of_oil_wells", + "michigan_natural_gas_number_of_oil_wells", + "mississippi_natural_gas_number_of_oil_wells", + "missouri_natural_gas_number_of_oil_wells", + "montana_natural_gas_number_of_oil_wells", + "nebraska_natural_gas_number_of_oil_wells", + "nevada_natural_gas_number_of_oil_wells", + "new_mexico_natural_gas_number_of_oil_wells", + "new_york_natural_gas_number_of_oil_wells", + "north_dakota_natural_gas_number_of_oil_wells", + "ohio_natural_gas_number_of_oil_wells", + "oklahoma_natural_gas_number_of_oil_wells", + "oregon_natural_gas_number_of_oil_wells", + "pennsylvania_natural_gas_number_of_oil_wells", + "south_dakota_natural_gas_number_of_oil_wells", + "tennessee_natural_gas_number_of_oil_wells", + "texas_natural_gas_number_of_oil_wells", + "us_natural_gas_number_of_oil_wells", + "utah_natural_gas_number_of_oil_wells", + "virginia_natural_gas_number_of_oil_wells", + "west_virginia_natural_gas_number_of_oil_wells", + "wyoming_natural_gas_number_of_oil_wells", + ], + }, + } + + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasNumberOfGasProducingOilWellsData(EiaApiData): + """Number of Gas Producing Oil Wells. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNumberOfGasProducingOilWellsFetcher( + Fetcher[ + EiaNaturalGasNumberOfGasProducingOilWellsQueryParams, + list[EiaNaturalGasNumberOfGasProducingOilWellsData], + ] +): + """Number of Gas Producing Oil Wells fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNumberOfGasProducingOilWellsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNumberOfGasProducingOilWellsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNumberOfGasProducingOilWellsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNumberOfGasProducingOilWellsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNumberOfGasProducingOilWellsData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNumberOfGasProducingOilWellsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/number_of_natural_gas_consumers.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/number_of_natural_gas_consumers.py new file mode 100644 index 00000000000..79703eabdbd --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/number_of_natural_gas_consumers.py @@ -0,0 +1,196 @@ +"""Number of Natural Gas Consumers model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNumberOfNaturalGasConsumersQueryParams(EiaApiQueryParams): + """Number of Natural Gas Consumers. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/cons/num + """ + + __group__ = "natural_gas" + __dataset__ = "number_of_natural_gas_consumers" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "average_annual_consumption_per_commercial_consumer", + "average_annual_consumption_per_industrial_consumer", + "number_of_commercial_consumers", + "number_of_commercial_consumers_sales", + "number_of_commercial_consumers_transported", + "number_of_industrial_consumers", + "number_of_industrial_consumers_sales", + "number_of_industrial_consumers_transported", + "number_of_residential_consumers", + "number_of_residential_consumers_sales", + "number_of_residential_consumers_transported", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 548 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasNumberOfNaturalGasConsumersData(EiaApiData): + """Number of Natural Gas Consumers. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNumberOfNaturalGasConsumersFetcher( + Fetcher[ + EiaNaturalGasNumberOfNaturalGasConsumersQueryParams, + list[EiaNaturalGasNumberOfNaturalGasConsumersData], + ] +): + """Number of Natural Gas Consumers fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNumberOfNaturalGasConsumersQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNumberOfNaturalGasConsumersQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNumberOfNaturalGasConsumersQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNumberOfNaturalGasConsumersQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNumberOfNaturalGasConsumersData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNumberOfNaturalGasConsumersData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/number_of_producing_gas_wells.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/number_of_producing_gas_wells.py new file mode 100644 index 00000000000..9a9e4aa95e5 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/number_of_producing_gas_wells.py @@ -0,0 +1,200 @@ +"""Number of Producing Gas Wells model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasNumberOfProducingGasWellsQueryParams(EiaApiQueryParams): + """Number of Producing Gas Wells. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/prod/wells + """ + + __group__ = "natural_gas" + __dataset__ = "number_of_producing_gas_wells" + __json_schema_extra__ = { + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alabama_natural_gas_number_of_gas_and_gas_condensate_wells", + "alaska_natural_gas_number_of_gas_and_gas_condensate_wells", + "arizona_natural_gas_number_of_gas_and_gas_condensate_wells", + "arkansas_natural_gas_number_of_gas_and_gas_condensate_wells", + "california_natural_gas_number_of_gas_and_gas_condensate", + "colorado_natural_gas_number_of_gas_and_gas_condensate_wells", + "federal_offshore_gulf_of_america_natural_gas_number_of_gas", + "florida_natural_gas_number_of_gas_and_gas_condensate_wells", + "idaho_number_of_gas_and_gas_condensate_wells_of_natural_gas", + "illinois_natural_gas_number_of_gas_and_gas_condensate_wells", + "indiana_natural_gas_number_of_gas_and_gas_condensate_wells", + "kansas_natural_gas_number_of_gas_and_gas_condensate_wells", + "kentucky_natural_gas_number_of_gas_and_gas_condensate_wells", + "louisiana_natural_gas_number_of_gas_and_gas_condensate_wells", + "maryland_natural_gas_number_of_gas_and_gas_condensate_wells", + "michigan_natural_gas_number_of_gas_and_gas_condensate_wells", + "mississippi_natural_gas_number_of_gas_and_gas_condensate", + "missouri_natural_gas_number_of_gas_and_gas_condensate_wells", + "montana_natural_gas_number_of_gas_and_gas_condensate_wells", + "nebraska_natural_gas_number_of_gas_and_gas_condensate_wells", + "nevada_natural_gas_number_of_gas_and_gas_condensate_wells", + "new_mexico_natural_gas_number_of_gas_and_gas_condensate", + "new_york_natural_gas_number_of_gas_and_gas_condensate_wells", + "north_dakota_natural_gas_number_of_gas_and_gas_condensate", + "ohio_natural_gas_number_of_gas_and_gas_condensate_wells", + "oklahoma_natural_gas_number_of_gas_and_gas_condensate_wells", + "oregon_natural_gas_number_of_gas_and_gas_condensate_wells", + "pennsylvania_natural_gas_number_of_gas_and_gas_condensate", + "south_dakota_natural_gas_number_of_gas_and_gas_condensate", + "tennessee_natural_gas_number_of_gas_and_gas_condensate_wells", + "texas_natural_gas_number_of_gas_and_gas_condensate_wells", + "us_natural_gas_number_of_gas_and_gas_condensate_wells", + "utah_natural_gas_number_of_gas_and_gas_condensate_wells", + "virginia_natural_gas_number_of_gas_and_gas_condensate_wells", + "west_virginia_natural_gas_number_of_gas_and_gas_condensate", + "wyoming_natural_gas_number_of_gas_and_gas_condensate_wells", + ], + }, + } + + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasNumberOfProducingGasWellsData(EiaApiData): + """Number of Producing Gas Wells. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasNumberOfProducingGasWellsFetcher( + Fetcher[ + EiaNaturalGasNumberOfProducingGasWellsQueryParams, + list[EiaNaturalGasNumberOfProducingGasWellsData], + ] +): + """Number of Producing Gas Wells fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasNumberOfProducingGasWellsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasNumberOfProducingGasWellsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasNumberOfProducingGasWellsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasNumberOfProducingGasWellsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasNumberOfProducingGasWellsData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasNumberOfProducingGasWellsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/offshore_gross_withdrawals_of_natural_gas.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/offshore_gross_withdrawals_of_natural_gas.py new file mode 100644 index 00000000000..19aee06fc20 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/offshore_gross_withdrawals_of_natural_gas.py @@ -0,0 +1,138 @@ +"""Offshore Gross Withdrawals of Natural Gas model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGasQueryParams(EiaApiQueryParams): + """Offshore Gross Withdrawals of Natural Gas. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/prod/off + """ + + __group__ = "natural_gas" + __dataset__ = "offshore_gross_withdrawals_of_natural_gas" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "gross_withdrawals", + "withdrawals_from_gas_wells", + "withdrawals_from_oil_wells", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "federal_offshore_gulf_of_america_natural_gas_gross_withdrawals_mmcf", + "federal_offshore_gulf_of_america_natural_gas_gross_withdrawals_from_gas_wells_mmcf", + "federal_offshore_gulf_of_america_natural_gas_gross_withdrawals_from_oil_wells_mmcf", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGasData(EiaApiData): + """Offshore Gross Withdrawals of Natural Gas. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGasFetcher( + Fetcher[ + EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGasQueryParams, + list[EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGasData], + ] +): + """Offshore Gross Withdrawals of Natural Gas fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGasQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGasQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGasQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGasQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGasData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGasData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/plant_liquids_in_proved_reserves.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/plant_liquids_in_proved_reserves.py new file mode 100644 index 00000000000..9075a51e3a4 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/plant_liquids_in_proved_reserves.py @@ -0,0 +1,201 @@ +"""Estimated Natural Gas Plant Liquids contained in Total Natural Gas Proved Reserves model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasPlantLiquidsInProvedReservesQueryParams(EiaApiQueryParams): + """Estimated Natural Gas Plant Liquids contained in Total Natural Gas Proved Reserves. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/ngpl + """ + + __group__ = "natural_gas" + __dataset__ = "plant_liquids_in_proved_reserves" + __json_schema_extra__ = { + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_wv", + "usa_wy", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alabama_natural_gas_plant_liquids_expected_future_production", + "alaska_natural_gas_plant_liquids_expected_future_production", + "arkansas_natural_gas_plant_liquids_expected_future", + "california_natural_gas_plant_liquids_expected_future", + "california_coastal_region_onshore_natural_gas_plant_liquids", + "california_los_angeles_basin_onshore_natural_gas_plant", + "california_san_joaquin_basin_onshore_natural_gas_plant", + "california_state_offshore_natural_gas_plant_liquids", + "colorado_natural_gas_plant_liquids_expected_future", + "federal_offshore_california_natural_gas_plant_liquids", + "florida_natural_gas_plant_liquids_expected_future_production", + "gulf_of_america_federal_offshore_central_and_eastern_natural_gas_plant_liquids_expected_future_production_million_barrels", + "gulf_of_america_federal_offshore_western_natural_gas_plant_liquids_expected_future_production_million_barrels", + "kansas_natural_gas_plant_liquids_expected_future_production", + "kentucky_natural_gas_plant_liquids_expected_future", + "louisiana_natural_gas_plant_liquids_expected_future", + "louisiana_north_natural_gas_plant_liquids_expected_future", + "louisiana_south_onshore_natural_gas_plant_liquids_expected", + "louisiana_state_offshore_natural_gas_plant_liquids_expected", + "lower_48_federal_offshore_natural_gas_plant_liquids", + "lower_48_states_natural_gas_plant_liquids_expected_future", + "michigan_natural_gas_plant_liquids_expected_future", + "mississippi_natural_gas_plant_liquids_expected_future", + "montana_natural_gas_plant_liquids_expected_future_production", + "new_mexico_natural_gas_plant_liquids_expected_future", + "new_mexico_east_natural_gas_plant_liquids_expected_future", + "new_mexico_west_natural_gas_plant_liquids_expected_future", + "north_dakota_natural_gas_plant_liquids_expected_future", + "ohio_natural_gas_plant_liquids_expected_future_production", + "oklahoma_natural_gas_plant_liquids_expected_future", + "pennsylvania_natural_gas_plant_liquids_expected_future", + "texas_natural_gas_plant_liquids_expected_future_production", + "texas_rrc_district_1_natural_gas_plant_liquids_expected", + "texas_rrc_district_10_natural_gas_plant_liquids_expected", + "texas_rrc_district_2_onshore_natural_gas_plant_liquids", + "texas_rrc_district_3_onshore_natural_gas_plant_liquids", + "texas_rrc_district_4_onshore_natural_gas_plant_liquids", + "texas_rrc_district_5_natural_gas_plant_liquids_expected", + "texas_rrc_district_6_natural_gas_plant_liquids_expected", + "texas_rrc_district_7b_natural_gas_plant_liquids_expected", + "texas_rrc_district_7c_natural_gas_plant_liquids_expected", + "texas_rrc_district_8_natural_gas_plant_liquids_expected", + "texas_rrc_district_8a_natural_gas_plant_liquids_expected", + "texas_rrc_district_9_natural_gas_plant_liquids_expected", + "texas_state_offshore_natural_gas_plant_liquids_expected", + "us_natural_gas_plant_liquids_expected_future_production", + "utah_natural_gas_plant_liquids_expected_future_production", + "utah_and_wyoming_natural_gas_plant_liquids_expected_future", + "west_virginia_natural_gas_plant_liquids_expected_future", + "wyoming_natural_gas_plant_liquids_expected_future_production", + ], + }, + } + + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasPlantLiquidsInProvedReservesData(EiaApiData): + """Estimated Natural Gas Plant Liquids contained in Total Natural Gas Proved Reserves. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasPlantLiquidsInProvedReservesFetcher( + Fetcher[ + EiaNaturalGasPlantLiquidsInProvedReservesQueryParams, + list[EiaNaturalGasPlantLiquidsInProvedReservesData], + ] +): + """Estimated Natural Gas Plant Liquids contained in Total Natural Gas Proved Reserves fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasPlantLiquidsInProvedReservesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasPlantLiquidsInProvedReservesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasPlantLiquidsInProvedReservesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasPlantLiquidsInProvedReservesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasPlantLiquidsInProvedReservesData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasPlantLiquidsInProvedReservesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/proved_nonproducing_reserves.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/proved_nonproducing_reserves.py new file mode 100644 index 00000000000..ce688c43dc7 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/proved_nonproducing_reserves.py @@ -0,0 +1,178 @@ +"""Proved Nonproducing Reserves model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasProvedNonproducingReservesQueryParams(EiaApiQueryParams): + """Proved Nonproducing Reserves. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/nprod + """ + + __group__ = "natural_gas" + __dataset__ = "proved_nonproducing_reserves" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "associated_dissolved_reserves_in_nonproducing_reservoirs", + "lease_condensate_reserves_in_nonproducing_reservoirs", + "nonassociated_reserves_in_nonproducing_reservoirs", + "reserves_in_nonproducing_reservoirs", + "wet_after_lease_separation_reserves_in_nonproducing", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "crude_oil", + "natural_gas", + "natural_gas_liquids_and_liquid_refinery_gases", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 270 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasProvedNonproducingReservesData(EiaApiData): + """Proved Nonproducing Reserves. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasProvedNonproducingReservesFetcher( + Fetcher[ + EiaNaturalGasProvedNonproducingReservesQueryParams, + list[EiaNaturalGasProvedNonproducingReservesData], + ] +): + """Proved Nonproducing Reserves fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasProvedNonproducingReservesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasProvedNonproducingReservesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasProvedNonproducingReservesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasProvedNonproducingReservesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasProvedNonproducingReservesData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasProvedNonproducingReservesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/residential_and_commercial_prices_selected_states.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/residential_and_commercial_prices_selected_states.py new file mode 100644 index 00000000000..6e14daf454f --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/residential_and_commercial_prices_selected_states.py @@ -0,0 +1,175 @@ +"""Average Price of Natural Gas Delivered to Residential and Commercial Consumers by Local Distribution and Marketers in Selected States model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasResidentialAndCommercialPricesSelectedStatesQueryParams( + EiaApiQueryParams +): + """Average Price of Natural Gas Delivered to Residential and Commercial Consumers by Local Distribution and Marketers in Selected States. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/pri/rescom + """ + + __group__ = "natural_gas" + __dataset__ = "residential_and_commercial_prices_selected_states" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "price_delivered_to_commercial_sectors", + "price_delivered_to_residential_consumers", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "florida", + "new_york", + "ohio", + "usa_dc", + "usa_ga", + "usa_md", + "usa_mi", + "usa_nj", + "usa_pa", + "usa_va", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "district_of_columbia_price_of_natural_gas_delivered_to", + "district_of_columbia_price_of_natural_gas_sold_to", + "florida_price_of_natural_gas_delivered_to_residential", + "florida_price_of_natural_gas_sold_to_commercial_consumers", + "georgia_price_of_natural_gas_delivered_to_residential", + "georgia_price_of_natural_gas_sold_to_commercial_consumers", + "maryland_price_of_natural_gas_delivered_to_residential", + "maryland_price_of_natural_gas_sold_to_commercial_consumers", + "michigan_price_of_natural_gas_delivered_to_residential", + "michigan_price_of_natural_gas_sold_to_commercial_consumers", + "new_jersey_price_of_natural_gas_delivered_to_residential", + "new_jersey_price_of_natural_gas_sold_to_commercial_consumers", + "new_york_price_of_natural_gas_delivered_to_residential", + "new_york_price_of_natural_gas_sold_to_commercial_consumers", + "ohio_price_of_natural_gas_delivered_to_residential_consumers", + "ohio_price_of_natural_gas_sold_to_commercial_consumers", + "pennsylvania_price_of_natural_gas_delivered_to_residential", + "pennsylvania_price_of_natural_gas_sold_to_commercial", + "virginia_price_of_natural_gas_delivered_to_residential", + "virginia_price_of_natural_gas_sold_to_commercial_consumers", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasResidentialAndCommercialPricesSelectedStatesData(EiaApiData): + """Average Price of Natural Gas Delivered to Residential and Commercial Consumers by Local Distribution and Marketers in Selected States. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasResidentialAndCommercialPricesSelectedStatesFetcher( + Fetcher[ + EiaNaturalGasResidentialAndCommercialPricesSelectedStatesQueryParams, + list[EiaNaturalGasResidentialAndCommercialPricesSelectedStatesData], + ] +): + """Average Price of Natural Gas Delivered to Residential and Commercial Consumers by Local Distribution and Marketers in Selected States fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasResidentialAndCommercialPricesSelectedStatesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasResidentialAndCommercialPricesSelectedStatesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasResidentialAndCommercialPricesSelectedStatesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasResidentialAndCommercialPricesSelectedStatesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasResidentialAndCommercialPricesSelectedStatesData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasResidentialAndCommercialPricesSelectedStatesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/shale_gas.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/shale_gas.py new file mode 100644 index 00000000000..d0e2365d35f --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/shale_gas.py @@ -0,0 +1,159 @@ +"""Shale Gas model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasShaleGasQueryParams(EiaApiQueryParams): + """Shale Gas. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/enr/shalegas + """ + + __group__ = "natural_gas" + __dataset__ = "shale_gas" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "shale_proved_reserves", + "shale_reserves_acquisitions", + "shale_reserves_adjustments", + "shale_reserves_based_production", + "shale_reserves_extensions", + "shale_reserves_extensions_and_discoveries", + "shale_reserves_new_field_discoveries", + "shale_reserves_new_reservoir_discoveries_in_old_fields", + "shale_reserves_revision_decreases", + "shale_reserves_revision_increases", + "shale_reserves_sales", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 485 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasShaleGasData(EiaApiData): + """Shale Gas. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasShaleGasFetcher( + Fetcher[EiaNaturalGasShaleGasQueryParams, list[EiaNaturalGasShaleGasData]] +): + """Shale Gas fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaNaturalGasShaleGasQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaNaturalGasShaleGasQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasShaleGasQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasShaleGasQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasShaleGasData]: + """Transform the data.""" + return transform_dataset_data(EiaNaturalGasShaleGasData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/shale_gas_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/shale_gas_production.py new file mode 100644 index 00000000000..f829a8f61c6 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/shale_gas_production.py @@ -0,0 +1,192 @@ +"""Shale Gas Production model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasShaleGasProductionQueryParams(EiaApiQueryParams): + """Shale Gas Production. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/prod/shalegas + """ + + __group__ = "natural_gas" + __dataset__ = "shale_gas_production" + __json_schema_extra__ = { + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alabama_shale_production", + "alaska_shale_production", + "arkansas_shale_production", + "california_shale_production", + "colorado_shale_production", + "eastern_states_shale_production", + "kansas_shale_production", + "kentucky_shale_production", + "louisiana_shale_production", + "louisiana_north_shale_production", + "louisiana_south_onshore_shale_production", + "lower_48_federal_offshore_shale_production", + "michigan_shale_production", + "mississippi_shale_production", + "montana_shale_production", + "new_mexico_shale_production", + "new_mexico_east_shale_production", + "new_mexico_west_shale_production", + "new_york_shale_production", + "north_dakota_shale_production", + "ohio_shale_production", + "oklahoma_shale_production", + "pennsylvania_shale_production", + "texas_shale_production", + "texas_rrc_district_1_shale_production", + "texas_rrc_district_10_shale_production", + "texas_rrc_district_2_onsh_shale_production", + "texas_rrc_district_3_onsh_shale_production", + "texas_rrc_district_4_onsh_shale_production", + "texas_rrc_district_5_shale_production", + "texas_rrc_district_6_shale_production", + "texas_rrc_district_7b_shale_production", + "texas_rrc_district_7c_shale_production", + "texas_rrc_district_8_shale_production", + "texas_rrc_district_8a_shale_production", + "texas_rrc_district_9_shale_production", + "us_shale_production", + "utah_shale_production", + "virginia_shale_production", + "west_virginia_shale_production", + "western_states_shale_production", + "wyoming_shale_production", + ], + }, + } + + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasShaleGasProductionData(EiaApiData): + """Shale Gas Production. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasShaleGasProductionFetcher( + Fetcher[ + EiaNaturalGasShaleGasProductionQueryParams, + list[EiaNaturalGasShaleGasProductionData], + ] +): + """Shale Gas Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasShaleGasProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasShaleGasProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasShaleGasProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasShaleGasProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasShaleGasProductionData]: + """Transform the data.""" + return transform_dataset_data(EiaNaturalGasShaleGasProductionData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/share_of_total_us_natural_gas_delivered_to_consumers.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/share_of_total_us_natural_gas_delivered_to_consumers.py new file mode 100644 index 00000000000..556f2ec4060 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/share_of_total_us_natural_gas_delivered_to_consumers.py @@ -0,0 +1,192 @@ +"""Share of Total US Natural Gas Delivered to Consumers model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumersQueryParams( + EiaApiQueryParams +): + """Share of Total US Natural Gas Delivered to Consumers. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/cons/pns + """ + + __group__ = "natural_gas" + __dataset__ = "share_of_total_us_natural_gas_delivered_to_consumers" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "total_commercial_deliveries", + "total_industrial_deliveries", + "of_total_electric_utility_deliveries", + "of_total_residential_deliveries", + "of_total_vehicle_fuel_deliveries", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 260 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumersData(EiaApiData): + """Share of Total US Natural Gas Delivered to Consumers. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumersFetcher( + Fetcher[ + EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumersQueryParams, + list[EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumersData], + ] +): + """Share of Total US Natural Gas Delivered to Consumers fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumersQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumersQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumersQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumersQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumersData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumersData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/supplemental_gas_supplies.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/supplemental_gas_supplies.py new file mode 100644 index 00000000000..ca43627275e --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/supplemental_gas_supplies.py @@ -0,0 +1,113 @@ +"""Supplemental Gas Supplies model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasSupplementalGasSuppliesQueryParams(EiaApiQueryParams): + """Supplemental Gas Supplies. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/prod/ss + """ + + __group__ = "natural_gas" + __dataset__ = "supplemental_gas_supplies" + __json_schema_extra__ = {} + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + + +class EiaNaturalGasSupplementalGasSuppliesData(EiaApiData): + """Supplemental Gas Supplies. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasSupplementalGasSuppliesFetcher( + Fetcher[ + EiaNaturalGasSupplementalGasSuppliesQueryParams, + list[EiaNaturalGasSupplementalGasSuppliesData], + ] +): + """Supplemental Gas Supplies fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasSupplementalGasSuppliesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasSupplementalGasSuppliesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasSupplementalGasSuppliesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasSupplementalGasSuppliesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasSupplementalGasSuppliesData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasSupplementalGasSuppliesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/underground_natural_gas_storage_by_all_operators.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/underground_natural_gas_storage_by_all_operators.py new file mode 100644 index 00000000000..0e6cc4524b3 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/underground_natural_gas_storage_by_all_operators.py @@ -0,0 +1,180 @@ +"""Underground Natural Gas Storage by All Operators model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasUndergroundNaturalGasStorageByAllOperatorsQueryParams( + EiaApiQueryParams +): + """Underground Natural Gas Storage by All Operators. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/stor/sum + """ + + __group__ = "natural_gas" + __dataset__ = "underground_natural_gas_storage_by_all_operators" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "total_underground_storage", + "underground_change_in_working_gas", + "underground_storage_base_gas", + "underground_storage_injections", + "underground_storage_net_withdrawals", + "underground_storage_withdrawals", + "underground_storage_working_gas", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "minnesota", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ia", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_ne", + "usa_nm", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_tn", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 329 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasUndergroundNaturalGasStorageByAllOperatorsData(EiaApiData): + """Underground Natural Gas Storage by All Operators. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasUndergroundNaturalGasStorageByAllOperatorsFetcher( + Fetcher[ + EiaNaturalGasUndergroundNaturalGasStorageByAllOperatorsQueryParams, + list[EiaNaturalGasUndergroundNaturalGasStorageByAllOperatorsData], + ] +): + """Underground Natural Gas Storage by All Operators fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasUndergroundNaturalGasStorageByAllOperatorsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasUndergroundNaturalGasStorageByAllOperatorsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasUndergroundNaturalGasStorageByAllOperatorsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasUndergroundNaturalGasStorageByAllOperatorsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasUndergroundNaturalGasStorageByAllOperatorsData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasUndergroundNaturalGasStorageByAllOperatorsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/underground_natural_gas_storage_capacity.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/underground_natural_gas_storage_capacity.py new file mode 100644 index 00000000000..94784ae6bd9 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/underground_natural_gas_storage_capacity.py @@ -0,0 +1,173 @@ +"""Underground Natural Gas Storage Capacity model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasUndergroundNaturalGasStorageCapacityQueryParams(EiaApiQueryParams): + """Underground Natural Gas Storage Capacity. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/stor/cap + """ + + __group__ = "natural_gas" + __dataset__ = "underground_natural_gas_storage_capacity" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "count_of_underground_storage_capacity", + "total_underground_storage_capacity", + "working_underground_storage_capacity", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "minnesota", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_ia", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_ne", + "usa_nm", + "usa_ok", + "usa_or", + "usa_pa", + "usa_tn", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 123 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasUndergroundNaturalGasStorageCapacityData(EiaApiData): + """Underground Natural Gas Storage Capacity. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasUndergroundNaturalGasStorageCapacityFetcher( + Fetcher[ + EiaNaturalGasUndergroundNaturalGasStorageCapacityQueryParams, + list[EiaNaturalGasUndergroundNaturalGasStorageCapacityData], + ] +): + """Underground Natural Gas Storage Capacity fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasUndergroundNaturalGasStorageCapacityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasUndergroundNaturalGasStorageCapacityQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasUndergroundNaturalGasStorageCapacityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasUndergroundNaturalGasStorageCapacityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasUndergroundNaturalGasStorageCapacityData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasUndergroundNaturalGasStorageCapacityData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_exports_and_re_exports_by_country.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_exports_and_re_exports_by_country.py new file mode 100644 index 00000000000..d13ce8edd5d --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_exports_and_re_exports_by_country.py @@ -0,0 +1,202 @@ +"""US Natural Gas Exports and Re-Exports by Country model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasUsNaturalGasExportsAndReExportsByCountryQueryParams( + EiaApiQueryParams +): + """US Natural Gas Exports and Re-Exports by Country. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/move/expc + """ + + __group__ = "natural_gas" + __dataset__ = "us_natural_gas_exports_and_re_exports_by_country" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "compressed_natural_gas_exports", + "compressed_natural_gas_exports_for_price", + "exports", + "exports_price", + "exports_by_truck", + "exports_by_vessel", + "exports_by_vessel_and_truck", + "liquefied_natural_gas_exports", + "liquefied_natural_gas_exports_price", + "pipeline_exports", + "pipeline_exports_price", + "re_exports", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "are", + "arg", + "atg", + "bel", + "bgd", + "bhr", + "bhs", + "bra", + "brb", + "can", + "chl", + "chn", + "col", + "deu", + "dom", + "egy", + "esp", + "fra", + "gbr", + "grc", + "hrv", + "hti", + "idn", + "ind", + "isr", + "ita", + "jam", + "jor", + "jpn", + "kor", + "kwt", + "ltu", + "mex", + "mrt", + "mys", + "na", + "nic", + "nld", + "pak", + "pan", + "phl", + "pol", + "prt", + "rus", + "sen", + "sgp", + "slv", + "tha", + "tur", + "twn", + "us", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 154 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasUsNaturalGasExportsAndReExportsByCountryData(EiaApiData): + """US Natural Gas Exports and Re-Exports by Country. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasUsNaturalGasExportsAndReExportsByCountryFetcher( + Fetcher[ + EiaNaturalGasUsNaturalGasExportsAndReExportsByCountryQueryParams, + list[EiaNaturalGasUsNaturalGasExportsAndReExportsByCountryData], + ] +): + """US Natural Gas Exports and Re-Exports by Country fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasUsNaturalGasExportsAndReExportsByCountryQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasUsNaturalGasExportsAndReExportsByCountryQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasUsNaturalGasExportsAndReExportsByCountryQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasUsNaturalGasExportsAndReExportsByCountryQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasUsNaturalGasExportsAndReExportsByCountryData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasUsNaturalGasExportsAndReExportsByCountryData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_exports_and_re_exports_by_point_of_exit.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_exports_and_re_exports_by_point_of_exit.py new file mode 100644 index 00000000000..1440e61441c --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_exports_and_re_exports_by_point_of_exit.py @@ -0,0 +1,141 @@ +"""US Natural Gas Exports and Re-Exports by Point of Exit model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExitQueryParams( + EiaApiQueryParams +): + """US Natural Gas Exports and Re-Exports by Point of Exit. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/move/poe2 + """ + + __group__ = "natural_gas" + __dataset__ = "us_natural_gas_exports_and_re_exports_by_point_of_exit" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "compressed_natural_gas_exports", + "compressed_natural_gas_exports_for_price", + "liquefied_natural_gas_exports", + "liquefied_natural_gas_exports_price", + "pipeline_exports", + "pipeline_exports_price", + ], + }, + "region": {"multiple_items_allowed": True}, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values. There are 446 valid values - use the `facet_options` endpoint to list them.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 934 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExitData(EiaApiData): + """US Natural Gas Exports and Re-Exports by Point of Exit. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExitFetcher( + Fetcher[ + EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExitQueryParams, + list[EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExitData], + ] +): + """US Natural Gas Exports and Re-Exports by Point of Exit fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExitQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExitQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExitQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExitQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExitData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExitData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_imports_by_country.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_imports_by_country.py new file mode 100644 index 00000000000..421173985be --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_imports_by_country.py @@ -0,0 +1,225 @@ +"""US Natural Gas Imports by Country model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasUsNaturalGasImportsByCountryQueryParams(EiaApiQueryParams): + """US Natural Gas Imports by Country. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/move/impc + """ + + __group__ = "natural_gas" + __dataset__ = "us_natural_gas_imports_by_country" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "compressed_natural_gas_imports", + "compressed_natural_gas_imports_for_price", + "imports", + "imports_price", + "lng_imports", + "liquefied_natural_gas_imports", + "pipeline_imports", + "pipeline_imports_price", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "are", + "aus", + "brn", + "can", + "dza", + "egy", + "fra", + "gbr", + "gnq", + "idn", + "jam", + "mex", + "mys", + "na", + "nga", + "nor", + "omn", + "per", + "qat", + "tto", + "us", + "yem", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "compressed_us_natural_gas_imports", + "compressed_us_natural_gas_imports_from_canada", + "price_of_compressed_us_natural_gas_imports", + "price_of_compressed_us_natural_gas_imports_from_canada", + "price_of_us_liquefied_natural_gas_imports_from_algeria", + "price_of_us_liquefied_natural_gas_imports_from_australia", + "price_of_us_liquefied_natural_gas_imports_from_brunei", + "price_of_us_liquefied_natural_gas_imports_from_canada", + "price_of_us_liquefied_natural_gas_imports_from_egypt", + "price_of_us_liquefied_natural_gas_imports_from_equatorial", + "price_of_us_liquefied_natural_gas_imports_from_france", + "price_of_us_liquefied_natural_gas_imports_from_indonesia", + "price_of_us_liquefied_natural_gas_imports_from_malaysia", + "price_of_us_liquefied_natural_gas_imports_from_nigeria", + "price_of_us_liquefied_natural_gas_imports_from_norway", + "price_of_us_liquefied_natural_gas_imports_from_oman", + "price_of_us_liquefied_natural_gas_imports_from_other", + "price_of_us_liquefied_natural_gas_imports_from_peru", + "price_of_us_liquefied_natural_gas_imports_from_qatar", + "price_of_us_liquefied_natural_gas_imports_from_the_united", + "price_of_us_liquefied_natural_gas_imports_from_trinidad_and", + "price_of_us_liquefied_natural_gas_imports_from_united", + "price_of_us_liquefied_natural_gas_imports_from_yemen", + "price_of_us_liquefied_natural_gas_imports_from_jamaica", + "price_of_us_natural_gas_imports", + "price_of_us_natural_gas_lng_imports", + "price_of_us_natural_gas_pipeline_imports_from_canada", + "price_of_us_natural_gas_pipeline_imports_from_mexico", + "us_liquefied_natural_gas_imports", + "us_liquefied_natural_gas_imports_from_algeria", + "us_liquefied_natural_gas_imports_from_australia", + "us_liquefied_natural_gas_imports_from_brunei", + "us_liquefied_natural_gas_imports_from_canada", + "us_liquefied_natural_gas_imports_from_egypt", + "us_liquefied_natural_gas_imports_from_equatorial_guinea", + "us_liquefied_natural_gas_imports_from_france", + "us_liquefied_natural_gas_imports_from_indonesia", + "us_liquefied_natural_gas_imports_from_malaysia", + "us_liquefied_natural_gas_imports_from_nigeria", + "us_liquefied_natural_gas_imports_from_norway", + "us_liquefied_natural_gas_imports_from_oman", + "us_liquefied_natural_gas_imports_from_other_countries", + "us_liquefied_natural_gas_imports_from_peru", + "us_liquefied_natural_gas_imports_from_qatar", + "us_liquefied_natural_gas_imports_from_the_united_arab", + "us_liquefied_natural_gas_imports_from_trinidad_and_tobago", + "us_liquefied_natural_gas_imports_from_united_kingdom", + "us_liquefied_natural_gas_imports_from_yemen", + "us_liquefied_natural_gas_imports_from_jamaica", + "us_natural_gas_imports", + "us_natural_gas_pipeline_imports", + "us_natural_gas_pipeline_imports_from_canada", + "us_natural_gas_pipeline_imports_from_mexico", + "us_natural_gas_pipeline_imports_price", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasUsNaturalGasImportsByCountryData(EiaApiData): + """US Natural Gas Imports by Country. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasUsNaturalGasImportsByCountryFetcher( + Fetcher[ + EiaNaturalGasUsNaturalGasImportsByCountryQueryParams, + list[EiaNaturalGasUsNaturalGasImportsByCountryData], + ] +): + """US Natural Gas Imports by Country fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasUsNaturalGasImportsByCountryQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasUsNaturalGasImportsByCountryQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasUsNaturalGasImportsByCountryQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasUsNaturalGasImportsByCountryQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasUsNaturalGasImportsByCountryData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasUsNaturalGasImportsByCountryData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_imports_by_point_of_entry.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_imports_by_point_of_entry.py new file mode 100644 index 00000000000..9f6073cabde --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_imports_by_point_of_entry.py @@ -0,0 +1,139 @@ +"""US Natural Gas Imports by Point of Entry model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasUsNaturalGasImportsByPointOfEntryQueryParams(EiaApiQueryParams): + """US Natural Gas Imports by Point of Entry. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/move/poe1 + """ + + __group__ = "natural_gas" + __dataset__ = "us_natural_gas_imports_by_point_of_entry" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "compressed_natural_gas_imports", + "compressed_natural_gas_imports_for_price", + "lng_imports", + "liquefied_natural_gas_imports", + "pipeline_imports", + "pipeline_imports_price", + ], + }, + "region": {"multiple_items_allowed": True}, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values. There are 110 valid values - use the `facet_options` endpoint to list them.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 252 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaNaturalGasUsNaturalGasImportsByPointOfEntryData(EiaApiData): + """US Natural Gas Imports by Point of Entry. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasUsNaturalGasImportsByPointOfEntryFetcher( + Fetcher[ + EiaNaturalGasUsNaturalGasImportsByPointOfEntryQueryParams, + list[EiaNaturalGasUsNaturalGasImportsByPointOfEntryData], + ] +): + """US Natural Gas Imports by Point of Entry fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasUsNaturalGasImportsByPointOfEntryQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasUsNaturalGasImportsByPointOfEntryQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasUsNaturalGasImportsByPointOfEntryQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasUsNaturalGasImportsByPointOfEntryQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasUsNaturalGasImportsByPointOfEntryData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasUsNaturalGasImportsByPointOfEntryData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_imports_exports_by_state.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_imports_exports_by_state.py new file mode 100644 index 00000000000..810714f5162 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_imports_exports_by_state.py @@ -0,0 +1,135 @@ +"""US Natural Gas Imports & Exports by State model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasUsNaturalGasImportsExportsByStateQueryParams(EiaApiQueryParams): + """US Natural Gas Imports & Exports by State. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/move/state + """ + + __group__ = "natural_gas" + __dataset__ = "us_natural_gas_imports_exports_by_state" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": ["exports", "exports_price", "imports", "imports_price"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "price_of_us_natural_gas_exports", + "price_of_us_natural_gas_imports", + "us_natural_gas_exports", + "us_natural_gas_imports", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasUsNaturalGasImportsExportsByStateData(EiaApiData): + """US Natural Gas Imports & Exports by State. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasUsNaturalGasImportsExportsByStateFetcher( + Fetcher[ + EiaNaturalGasUsNaturalGasImportsExportsByStateQueryParams, + list[EiaNaturalGasUsNaturalGasImportsExportsByStateData], + ] +): + """US Natural Gas Imports & Exports by State fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasUsNaturalGasImportsExportsByStateQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasUsNaturalGasImportsExportsByStateQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasUsNaturalGasImportsExportsByStateQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasUsNaturalGasImportsExportsByStateQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasUsNaturalGasImportsExportsByStateData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasUsNaturalGasImportsExportsByStateData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_monthly_supply_and_disposition_balance.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_monthly_supply_and_disposition_balance.py new file mode 100644 index 00000000000..b49dea549d5 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_natural_gas_monthly_supply_and_disposition_balance.py @@ -0,0 +1,154 @@ +"""US Natural Gas Monthly Supply and Disposition Balance model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalanceQueryParams( + EiaApiQueryParams +): + """US Natural Gas Monthly Supply and Disposition Balance. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/sum/sndm + """ + + __group__ = "natural_gas" + __dataset__ = "us_natural_gas_monthly_supply_and_disposition_balance" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "balancing_item", + "dry_production", + "extraction_loss", + "gross_withdrawals", + "input_supplemental_fuels", + "marketed_production", + "net_imports", + "net_withdrawals_from_storage", + "total_consumption", + ], + }, + "region": {"multiple_items_allowed": True, "choices": ["us"]}, + "series": { + "multiple_items_allowed": True, + "choices": [ + "balancing_item", + "us_dry_natural_gas_production", + "us_natural_gas_gross_withdrawals", + "us_natural_gas_marketed_production", + "us_natural_gas_net_imports", + "us_natural_gas_net_withdrawals_from_storage", + "us_natural_gas_plant_liquids_production_gaseous_equivalent", + "us_natural_gas_total_consumption", + "us_supplemental_gaseous_fuels", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalanceData(EiaApiData): + """US Natural Gas Monthly Supply and Disposition Balance. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalanceFetcher( + Fetcher[ + EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalanceQueryParams, + list[EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalanceData], + ] +): + """US Natural Gas Monthly Supply and Disposition Balance fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalanceQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalanceQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalanceQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalanceQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalanceData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalanceData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_underground_natural_gas_storage_by_storage_type.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_underground_natural_gas_storage_by_storage_type.py new file mode 100644 index 00000000000..5908892ed78 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/us_underground_natural_gas_storage_by_storage_type.py @@ -0,0 +1,170 @@ +"""US Underground Natural Gas Storage by Storage Type model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasUsUndergroundNaturalGasStorageByStorageTypeQueryParams( + EiaApiQueryParams +): + """US Underground Natural Gas Storage by Storage Type. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/stor/type + """ + + __group__ = "natural_gas" + __dataset__ = "us_underground_natural_gas_storage_by_storage_type" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "non_salt_underground_storage_base_gas", + "non_salt_underground_storage_total", + "non_salt_underground_storage_working_gas", + "non_salt_underground_storage_activity_net", + "non_salt_underground_storage_activity_withdraw", + "non_salt_underground_storage_injections", + "salt_underground_storage_base_gas", + "salt_underground_storage_total", + "salt_underground_storage_working_gas", + "salt_underground_storage_activity_injects", + "salt_underground_storage_activity_net", + "salt_underground_storage_activity_withdraw", + "total_underground_storage", + "underground_storage_base_gas", + "underground_storage_injections", + "underground_storage_net_withdrawals", + "underground_storage_withdrawals", + "underground_storage_working_gas", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_natural_gas_underground_storage_withdrawals", + "us_natural_gas_non_salt_underground_storage_base_gas", + "us_natural_gas_non_salt_underground_storage_total", + "us_natural_gas_non_salt_underground_storage_working_gas", + "us_natural_gas_non_salt_underground_storage_activity_net", + "us_natural_gas_non_salt_underground_storage_activity", + "us_natural_gas_non_salt_underground_storage_injections", + "us_natural_gas_salt_underground_storage_base_gas", + "us_natural_gas_salt_underground_storage_total", + "us_natural_gas_salt_underground_storage_working_gas", + "us_natural_gas_salt_underground_storage_activity_injects", + "us_natural_gas_salt_underground_storage_activity_net", + "us_natural_gas_salt_underground_storage_activity_withdraw", + "us_natural_gas_underground_storage_net_withdrawals", + "us_natural_gas_underground_storage_volume", + "us_total_natural_gas_injections_into_underground_storage", + "us_total_natural_gas_in_underground_storage_base_gas_mmcf", + "us_total_natural_gas_in_underground_storage_working_gas_mmcf", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasUsUndergroundNaturalGasStorageByStorageTypeData(EiaApiData): + """US Underground Natural Gas Storage by Storage Type. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasUsUndergroundNaturalGasStorageByStorageTypeFetcher( + Fetcher[ + EiaNaturalGasUsUndergroundNaturalGasStorageByStorageTypeQueryParams, + list[EiaNaturalGasUsUndergroundNaturalGasStorageByStorageTypeData], + ] +): + """US Underground Natural Gas Storage by Storage Type fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasUsUndergroundNaturalGasStorageByStorageTypeQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasUsUndergroundNaturalGasStorageByStorageTypeQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasUsUndergroundNaturalGasStorageByStorageTypeQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasUsUndergroundNaturalGasStorageByStorageTypeQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasUsUndergroundNaturalGasStorageByStorageTypeData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasUsUndergroundNaturalGasStorageByStorageTypeData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/weekly_working_gas_in_underground_storage.py b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/weekly_working_gas_in_underground_storage.py new file mode 100644 index 00000000000..dab98d75283 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/natural_gas/weekly_working_gas_in_underground_storage.py @@ -0,0 +1,144 @@ +"""Weekly Working Gas in Underground Storage model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNaturalGasWeeklyWorkingGasInUndergroundStorageQueryParams(EiaApiQueryParams): + """Weekly Working Gas in Underground Storage. EIA natural gas survey data + + Source: https://www.eia.gov/opendata/browser/natural-gas/stor/wkly + """ + + __group__ = "natural_gas" + __dataset__ = "weekly_working_gas_in_underground_storage" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "non_salt_underground_storage_working_gas", + "salt_underground_storage_working_gas", + "underground_storage_working_gas", + ], + }, + "region": {"multiple_items_allowed": True, "choices": ["na"]}, + "series": { + "multiple_items_allowed": True, + "choices": [ + "weekly_east_region_natural_gas_working_underground_storage", + "weekly_lower_48_states_natural_gas_working_underground", + "weekly_midwest_region_natural_gas_working_underground", + "weekly_mountain_region_natural_gas_working_underground", + "weekly_nonsalt_region_natural_gas_working_underground", + "weekly_pacific_region_natural_gas_working_underground", + "weekly_salt_region_natural_gas_working_underground_storage", + "weekly_south_central_region_natural_gas_working_underground", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaNaturalGasWeeklyWorkingGasInUndergroundStorageData(EiaApiData): + """Weekly Working Gas in Underground Storage. EIA natural gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaNaturalGasWeeklyWorkingGasInUndergroundStorageFetcher( + Fetcher[ + EiaNaturalGasWeeklyWorkingGasInUndergroundStorageQueryParams, + list[EiaNaturalGasWeeklyWorkingGasInUndergroundStorageData], + ] +): + """Weekly Working Gas in Underground Storage fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNaturalGasWeeklyWorkingGasInUndergroundStorageQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNaturalGasWeeklyWorkingGasInUndergroundStorageQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNaturalGasWeeklyWorkingGasInUndergroundStorageQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNaturalGasWeeklyWorkingGasInUndergroundStorageQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNaturalGasWeeklyWorkingGasInUndergroundStorageData]: + """Transform the data.""" + return transform_dataset_data( + EiaNaturalGasWeeklyWorkingGasInUndergroundStorageData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/__init__.py b/openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/__init__.py new file mode 100644 index 00000000000..f2098306a21 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/__init__.py @@ -0,0 +1 @@ +"""EIA Nuclear Outages models.""" diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/facility_level_nuclear_outages.py b/openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/facility_level_nuclear_outages.py new file mode 100644 index 00000000000..7142bdbbaaf --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/facility_level_nuclear_outages.py @@ -0,0 +1,173 @@ +"""Facility Level Nuclear Outages model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNuclearOutagesFacilityLevelNuclearOutagesQueryParams(EiaApiQueryParams): + """Facility Level Nuclear Outages. Facility level nuclear outages with capacity, outages, and percent outage. Source: Nuclear Regulatory Commission's Power Reactor Status Report. Interactive data report: Daily Status of Nuclear Reactors. + + Source: https://www.eia.gov/opendata/browser/nuclear-outages/facility-nuclear-outages + """ + + __group__ = "nuclear_outages" + __dataset__ = "facility_level_nuclear_outages" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": ["capacity", "outage", "percent_outage"], + }, + "facility": { + "multiple_items_allowed": True, + "choices": [ + "arkansas_nuclear_one", + "beaver_valley", + "braidwood_generation_station", + "browns_ferry", + "brunswick", + "byron_generating_station", + "callaway", + "calvert_cliffs_nuclear_power_plant", + "catawba", + "clinton_power_station", + "columbia_generating_station", + "comanche_peak", + "cooper", + "crystal_river", + "davis_besse", + "diablo_canyon", + "donald_c_cook", + "dresden_generating_station", + "duane_arnold", + "edwin_i_hatch", + "fermi", + "fort_calhoun", + "grand_gulf", + "h_b_robinson", + "harris", + "indian_point_2", + "indian_point_3", + "james_a_fitzpatrick", + "joseph_m_farley", + "kewaunee", + "lasalle_generating_station", + "limerick", + "mcguire", + "millstone", + "monticello", + "nine_mile_point_nuclear_station", + "north_anna", + "oconee", + "oyster_creek", + "ppl_susquehanna", + "pseg_hope_creek_generating_station", + "pseg_salem_generating_station", + "palisades", + "palo_verde", + "peach_bottom", + "perry", + "pilgrim_nuclear_power_station", + "point_beach", + "prairie_island", + "quad_cities_generating_station", + "r_e_ginna_nuclear_power_plant", + "river_bend_station", + "san_onofre", + "seabrook", + "sequoyah", + "south_texas_project", + "st_lucie", + "surry", + "three_mile_island", + "turkey_point", + "v_c_summer", + "vermont_yankee", + "vogtle", + "waterford_3", + "watts_bar_nuclear_plant", + "wolf_creek_generating_station", + ], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: capacity (megawatts); outage (megawatts); percent_outage (percent).", + ) + facility: str | None = Field( + default=None, + description="Plant code filter. Accepts a comma-separated list of values.", + ) + + +class EiaNuclearOutagesFacilityLevelNuclearOutagesData(EiaApiData): + """Facility Level Nuclear Outages. Facility level nuclear outages with capacity, outages, and percent outage. Source: Nuclear Regulatory Commission's Power Reactor Status Report. Interactive data report: Daily Status of Nuclear Reactors.""" + + facility: str | None = Field( + default=None, + description="Plant code code.", + ) + facility_name: str | None = Field( + default=None, + description="Plant code name.", + ) + capacity: float | None = Field( + default=None, + description="Capacity (megawatts). Withheld or unavailable values return as null.", + ) + outage: float | None = Field( + default=None, + description="Outage (megawatts). Withheld or unavailable values return as null.", + ) + percent_outage: float | None = Field( + default=None, + description="Percent outage (percent). Withheld or unavailable values return as null.", + ) + + +class EiaNuclearOutagesFacilityLevelNuclearOutagesFetcher( + Fetcher[ + EiaNuclearOutagesFacilityLevelNuclearOutagesQueryParams, + list[EiaNuclearOutagesFacilityLevelNuclearOutagesData], + ] +): + """Facility Level Nuclear Outages fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNuclearOutagesFacilityLevelNuclearOutagesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNuclearOutagesFacilityLevelNuclearOutagesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNuclearOutagesFacilityLevelNuclearOutagesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNuclearOutagesFacilityLevelNuclearOutagesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNuclearOutagesFacilityLevelNuclearOutagesData]: + """Transform the data.""" + return transform_dataset_data( + EiaNuclearOutagesFacilityLevelNuclearOutagesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/generator_level_nuclear_outages.py b/openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/generator_level_nuclear_outages.py new file mode 100644 index 00000000000..87b302c3cb3 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/generator_level_nuclear_outages.py @@ -0,0 +1,186 @@ +"""Generator Level Nuclear Outages model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNuclearOutagesGeneratorLevelNuclearOutagesQueryParams(EiaApiQueryParams): + """Generator Level Nuclear Outages. Generator level nuclear outages with capacity, outages, and percent outage. Source: Nuclear Regulatory Commission's Power Reactor Status Report. Interactive data report: Daily Status of Nuclear Reactors. + + Source: https://www.eia.gov/opendata/browser/nuclear-outages/generator-nuclear-outages + """ + + __group__ = "nuclear_outages" + __dataset__ = "generator_level_nuclear_outages" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": ["capacity", "outage", "percent_outage"], + }, + "facility": { + "multiple_items_allowed": True, + "choices": [ + "arkansas_nuclear_one", + "beaver_valley", + "braidwood_generation_station", + "browns_ferry", + "brunswick", + "byron_generating_station", + "callaway", + "calvert_cliffs_nuclear_power_plant", + "catawba", + "clinton_power_station", + "columbia_generating_station", + "comanche_peak", + "cooper", + "crystal_river", + "davis_besse", + "diablo_canyon", + "donald_c_cook", + "dresden_generating_station", + "duane_arnold", + "edwin_i_hatch", + "fermi", + "fort_calhoun", + "grand_gulf", + "h_b_robinson", + "harris", + "indian_point_2", + "indian_point_3", + "james_a_fitzpatrick", + "joseph_m_farley", + "kewaunee", + "lasalle_generating_station", + "limerick", + "mcguire", + "millstone", + "monticello", + "nine_mile_point_nuclear_station", + "north_anna", + "oconee", + "oyster_creek", + "ppl_susquehanna", + "pseg_hope_creek_generating_station", + "pseg_salem_generating_station", + "palisades", + "palo_verde", + "peach_bottom", + "perry", + "pilgrim_nuclear_power_station", + "point_beach", + "prairie_island", + "quad_cities_generating_station", + "r_e_ginna_nuclear_power_plant", + "river_bend_station", + "san_onofre", + "seabrook", + "sequoyah", + "south_texas_project", + "st_lucie", + "surry", + "three_mile_island", + "turkey_point", + "v_c_summer", + "vermont_yankee", + "vogtle", + "waterford_3", + "watts_bar_nuclear_plant", + "wolf_creek_generating_station", + ], + }, + "generator": {"multiple_items_allowed": True, "choices": ["1", "2", "3", "4"]}, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: capacity (megawatts); outage (megawatts); percent_outage (percent).", + ) + facility: str | None = Field( + default=None, + description="Plant code filter. Accepts a comma-separated list of values.", + ) + generator: Literal["1", "2", "3", "4"] | None = Field( + default=None, + description="Facility's generator ID number filter.", + ) + + +class EiaNuclearOutagesGeneratorLevelNuclearOutagesData(EiaApiData): + """Generator Level Nuclear Outages. Generator level nuclear outages with capacity, outages, and percent outage. Source: Nuclear Regulatory Commission's Power Reactor Status Report. Interactive data report: Daily Status of Nuclear Reactors.""" + + facility: str | None = Field( + default=None, + description="Plant code code.", + ) + facility_name: str | None = Field( + default=None, + description="Plant code name.", + ) + generator: str | None = Field( + default=None, + description="Facility's generator ID number code.", + ) + generator_name: str | None = Field( + default=None, + description="Facility's generator ID number name.", + ) + capacity: float | None = Field( + default=None, + description="Capacity (megawatts). Withheld or unavailable values return as null.", + ) + outage: float | None = Field( + default=None, + description="Outage (megawatts). Withheld or unavailable values return as null.", + ) + percent_outage: float | None = Field( + default=None, + description="Percent outage (percent). Withheld or unavailable values return as null.", + ) + + +class EiaNuclearOutagesGeneratorLevelNuclearOutagesFetcher( + Fetcher[ + EiaNuclearOutagesGeneratorLevelNuclearOutagesQueryParams, + list[EiaNuclearOutagesGeneratorLevelNuclearOutagesData], + ] +): + """Generator Level Nuclear Outages fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNuclearOutagesGeneratorLevelNuclearOutagesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNuclearOutagesGeneratorLevelNuclearOutagesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNuclearOutagesGeneratorLevelNuclearOutagesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNuclearOutagesGeneratorLevelNuclearOutagesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNuclearOutagesGeneratorLevelNuclearOutagesData]: + """Transform the data.""" + return transform_dataset_data( + EiaNuclearOutagesGeneratorLevelNuclearOutagesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/us_nuclear_outages.py b/openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/us_nuclear_outages.py new file mode 100644 index 00000000000..e76de3568bc --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/nuclear_outages/us_nuclear_outages.py @@ -0,0 +1,90 @@ +"""US Nuclear Outages model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaNuclearOutagesUsNuclearOutagesQueryParams(EiaApiQueryParams): + """US Nuclear Outages. Nuclear outages daily with capacity, outages, and percent outage. Source: Nuclear Regulatory Commission's Power Reactor Status Report. Interactive data report: Daily Status of Nuclear Reactors. + + Source: https://www.eia.gov/opendata/browser/nuclear-outages/us-nuclear-outages + """ + + __group__ = "nuclear_outages" + __dataset__ = "us_nuclear_outages" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": ["capacity", "outage", "percent_outage"], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: capacity (megawatts); outage (megawatts); percent_outage (percent).", + ) + + +class EiaNuclearOutagesUsNuclearOutagesData(EiaApiData): + """US Nuclear Outages. Nuclear outages daily with capacity, outages, and percent outage. Source: Nuclear Regulatory Commission's Power Reactor Status Report. Interactive data report: Daily Status of Nuclear Reactors.""" + + capacity: float | None = Field( + default=None, + description="Capacity (megawatts). Withheld or unavailable values return as null.", + ) + outage: float | None = Field( + default=None, + description="Outage (megawatts). Withheld or unavailable values return as null.", + ) + percent_outage: float | None = Field( + default=None, + description="Percent outage (percent). Withheld or unavailable values return as null.", + ) + + +class EiaNuclearOutagesUsNuclearOutagesFetcher( + Fetcher[ + EiaNuclearOutagesUsNuclearOutagesQueryParams, + list[EiaNuclearOutagesUsNuclearOutagesData], + ] +): + """US Nuclear Outages fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaNuclearOutagesUsNuclearOutagesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaNuclearOutagesUsNuclearOutagesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaNuclearOutagesUsNuclearOutagesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaNuclearOutagesUsNuclearOutagesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaNuclearOutagesUsNuclearOutagesData]: + """Transform the data.""" + return transform_dataset_data( + EiaNuclearOutagesUsNuclearOutagesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/__init__.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/__init__.py new file mode 100644 index 00000000000..438bc1b4bb3 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/__init__.py @@ -0,0 +1 @@ +"""EIA Petroleum models.""" diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_distillate_fuel_oil_and_kerosene_sales_by_end_use.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_distillate_fuel_oil_and_kerosene_sales_by_end_use.py new file mode 100644 index 00000000000..0992158555d --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_distillate_fuel_oil_and_kerosene_sales_by_end_use.py @@ -0,0 +1,235 @@ +"""Adjusted Distillate Fuel Oil and Kerosene Sales by End Use model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUseQueryParams( + EiaApiQueryParams +): + """Adjusted Distillate Fuel Oil and Kerosene Sales by End Use. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/cons/821usea + """ + + __group__ = "petroleum" + __dataset__ = "adjusted_distillate_fuel_oil_and_kerosene_sales_by_end_use" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "adj_sales_deliveries_transportation_total", + "adj_sales_deliveries_for_off_highway_construction", + "adj_sales_deliveries_for_off_highway_other", + "adj_sales_deliveries_to_commercial_consumers", + "adj_sales_deliveries_to_elect_utility_consumers", + "adj_sales_deliveries_to_farm_consumers", + "adj_sales_deliveries_to_industrial_consumers", + "adj_sales_deliveries_to_military_consumers", + "adj_sales_deliveries_to_off_highway_consumers", + "adj_sales_deliveries_to_oil_company_consumers", + "adj_sales_deliveries_to_on_highway_consumers", + "adj_sales_deliveries_to_other_end_users", + "adj_sales_deliveries_to_railroad_consumers", + "adj_sales_deliveries_to_residential_consumers", + "adj_sales_deliveries_to_vessel_bunker_consumers", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "distillate_fuel_oil", + "distillate_other_than_diesel", + "kerosene", + "no_1_distillate", + "no_2_diesel", + "no_2_diesel_high_sulfur", + "no_2_diesel_low_sulfur", + "no_2_diesel_low_sulfur_0_15_ppm", + "no_2_diesel_low_sulfur_15_500_ppm", + "no_2_distillate", + "no_2_fuel_oil_heating_oil", + "no_4_distillate", + "residual_fuel_oil", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUseData(EiaApiData): + """Adjusted Distillate Fuel Oil and Kerosene Sales by End Use. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUseFetcher( + Fetcher[ + EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUseQueryParams, + list[EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUseData], + ] +): + """Adjusted Distillate Fuel Oil and Kerosene Sales by End Use fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUseQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUseQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUseQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUseQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUseData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUseData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_sales_of_distillate_fuel_oil_by_end_use.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_sales_of_distillate_fuel_oil_by_end_use.py new file mode 100644 index 00000000000..a01a40157bf --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_sales_of_distillate_fuel_oil_by_end_use.py @@ -0,0 +1,216 @@ +"""Adjusted Sales of Distillate Fuel Oil by End Use model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUseQueryParams( + EiaApiQueryParams +): + """Adjusted Sales of Distillate Fuel Oil by End Use. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/cons/821dsta + """ + + __group__ = "petroleum" + __dataset__ = "adjusted_sales_of_distillate_fuel_oil_by_end_use" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "adj_sales_deliveries_total_to_end_users", + "adj_sales_deliveries_to_commercial_consumers", + "adj_sales_deliveries_to_elect_utility_consumers", + "adj_sales_deliveries_to_farm_consumers", + "adj_sales_deliveries_to_industrial_consumers", + "adj_sales_deliveries_to_military_consumers", + "adj_sales_deliveries_to_off_highway_consumers", + "adj_sales_deliveries_to_oil_company_consumers", + "adj_sales_deliveries_to_on_highway_consumers", + "adj_sales_deliveries_to_other_end_users", + "adj_sales_deliveries_to_railroad_consumers", + "adj_sales_deliveries_to_residential_consumers", + "adj_sales_deliveries_to_vessel_bunker_consumers", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": ["distillate_fuel_oil", "no_2_diesel"], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 780 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUseData(EiaApiData): + """Adjusted Sales of Distillate Fuel Oil by End Use. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUseFetcher( + Fetcher[ + EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUseQueryParams, + list[EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUseData], + ] +): + """Adjusted Sales of Distillate Fuel Oil by End Use fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUseQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUseQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUseQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUseQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUseData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUseData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_sales_of_kerosene_by_end_use.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_sales_of_kerosene_by_end_use.py new file mode 100644 index 00000000000..e2e55163b68 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_sales_of_kerosene_by_end_use.py @@ -0,0 +1,199 @@ +"""Adjusted Sales of Kerosene by End Use model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumAdjustedSalesOfKeroseneByEndUseQueryParams(EiaApiQueryParams): + """Adjusted Sales of Kerosene by End Use. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/cons/821kera + """ + + __group__ = "petroleum" + __dataset__ = "adjusted_sales_of_kerosene_by_end_use" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "adj_sales_deliveries_total_to_end_users", + "adj_sales_deliveries_to_commercial_consumers", + "adj_sales_deliveries_to_farm_consumers", + "adj_sales_deliveries_to_industrial_consumers", + "adj_sales_deliveries_to_other_end_users", + "adj_sales_deliveries_to_residential_consumers", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 360 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumAdjustedSalesOfKeroseneByEndUseData(EiaApiData): + """Adjusted Sales of Kerosene by End Use. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumAdjustedSalesOfKeroseneByEndUseFetcher( + Fetcher[ + EiaPetroleumAdjustedSalesOfKeroseneByEndUseQueryParams, + list[EiaPetroleumAdjustedSalesOfKeroseneByEndUseData], + ] +): + """Adjusted Sales of Kerosene by End Use fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumAdjustedSalesOfKeroseneByEndUseQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumAdjustedSalesOfKeroseneByEndUseQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumAdjustedSalesOfKeroseneByEndUseQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumAdjustedSalesOfKeroseneByEndUseQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumAdjustedSalesOfKeroseneByEndUseData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumAdjustedSalesOfKeroseneByEndUseData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_sales_of_residual_fuel_oil_by_end_use.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_sales_of_residual_fuel_oil_by_end_use.py new file mode 100644 index 00000000000..0d2730e97b4 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/adjusted_sales_of_residual_fuel_oil_by_end_use.py @@ -0,0 +1,201 @@ +"""Adjusted Sales of Residual Fuel Oil by End Use model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUseQueryParams(EiaApiQueryParams): + """Adjusted Sales of Residual Fuel Oil by End Use. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/cons/821rsda + """ + + __group__ = "petroleum" + __dataset__ = "adjusted_sales_of_residual_fuel_oil_by_end_use" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "adj_sales_deliveries_total_to_end_users", + "adj_sales_deliveries_transportation_total", + "adj_sales_deliveries_to_commercial_consumers", + "adj_sales_deliveries_to_elect_utility_consumers", + "adj_sales_deliveries_to_industrial_consumers", + "adj_sales_deliveries_to_military_consumers", + "adj_sales_deliveries_to_oil_company_consumers", + "adj_sales_deliveries_to_other_end_users", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 480 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUseData(EiaApiData): + """Adjusted Sales of Residual Fuel Oil by End Use. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUseFetcher( + Fetcher[ + EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUseQueryParams, + list[EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUseData], + ] +): + """Adjusted Sales of Residual Fuel Oil by End Use fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUseQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUseQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUseQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUseQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUseData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUseData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/average_depth_of_crude_oil_and_natural_gas_wells.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/average_depth_of_crude_oil_and_natural_gas_wells.py new file mode 100644 index 00000000000..c9eb99c69d9 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/average_depth_of_crude_oil_and_natural_gas_wells.py @@ -0,0 +1,153 @@ +"""Average Depth of Crude Oil and Natural Gas Wells model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWellsQueryParams( + EiaApiQueryParams +): + """Average Depth of Crude Oil and Natural Gas Wells. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/crd/welldep + """ + + __group__ = "petroleum" + __dataset__ = "average_depth_of_crude_oil_and_natural_gas_wells" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "average_depth_of_developmental_wells_drilled", + "average_depth_of_exploratory_wells_drilled", + "average_depth_of_exploratory_and_developmental_wells_drilled", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": ["wells_dry", "wells_gas", "wells_oil", "wells_total"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_average_depth_of_crude_oil_developmental_wells_drilled", + "us_average_depth_of_crude_oil_exploratory_wells_drilled", + "us_average_depth_of_crude_oil_exploratory_and_developmental", + "us_average_depth_of_crude_oil_natural_gas_and_dry_developmental_wells_drilled_feet_per_well", + "us_average_depth_of_crude_oil_natural_gas_and_dry_exploratory_wells_drilled_feet_per_well", + "us_average_depth_of_crude_oil_natural_gas_and_dry_exploratory_and_developmental_wells_drilled_feet_per_well", + "us_average_depth_of_dry_exploratory_and_developmental_wells", + "us_average_depth_of_dry_holes_developmental_wells_drilled", + "us_average_depth_of_dry_holes_exploratory_wells_drilled", + "us_average_depth_of_natural_gas_developmental_wells_drilled", + "us_average_depth_of_natural_gas_exploratory_wells_drilled", + "us_average_depth_of_natural_gas_exploratory_and", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWellsData(EiaApiData): + """Average Depth of Crude Oil and Natural Gas Wells. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWellsFetcher( + Fetcher[ + EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWellsQueryParams, + list[EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWellsData], + ] +): + """Average Depth of Crude Oil and Natural Gas Wells fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWellsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWellsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWellsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWellsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWellsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWellsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/biofuels_operable_production_capacity.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/biofuels_operable_production_capacity.py new file mode 100644 index 00000000000..22625a753dc --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/biofuels_operable_production_capacity.py @@ -0,0 +1,134 @@ +"""Biofuels Operable Production Capacity model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumBiofuelsOperableProductionCapacityQueryParams(EiaApiQueryParams): + """Biofuels Operable Production Capacity. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/capbio + """ + + __group__ = "petroleum" + __dataset__ = "biofuels_operable_production_capacity" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "biodiesel", + "fuel_ethanol", + "renewable_diesel_and_other_biofuels", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_biodiesel_production_capacity", + "us_fuel_ethanol_production_capacity", + "us_renewable_diesel_and_other_biofuels_production_capacity", + ], + }, + } + + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumBiofuelsOperableProductionCapacityData(EiaApiData): + """Biofuels Operable Production Capacity. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumBiofuelsOperableProductionCapacityFetcher( + Fetcher[ + EiaPetroleumBiofuelsOperableProductionCapacityQueryParams, + list[EiaPetroleumBiofuelsOperableProductionCapacityData], + ] +): + """Biofuels Operable Production Capacity fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumBiofuelsOperableProductionCapacityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumBiofuelsOperableProductionCapacityQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumBiofuelsOperableProductionCapacityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumBiofuelsOperableProductionCapacityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumBiofuelsOperableProductionCapacityData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumBiofuelsOperableProductionCapacityData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/blender_net_input.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/blender_net_input.py new file mode 100644 index 00000000000..f27e466f90e --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/blender_net_input.py @@ -0,0 +1,166 @@ +"""Blender Net Input model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumBlenderNetInputQueryParams(EiaApiQueryParams): + """Blender Net Input. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/inpt3 + """ + + __group__ = "petroleum" + __dataset__ = "blender_net_input" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "biodiesel", + "biodiesel_renewable_diesel_fuel", + "biofuel_fuels", + "biofuel_fuels_excluding_fuel_ethanol", + "conventional_cbob_gasoline_blending_components", + "conventional_gtab_gasoline_blending_components", + "conventional_gasoline_blending_components", + "conventional_other_gasoline_blending_components", + "fuel_ethanol", + "gasoline_blending_components", + "heavy_gas_oils", + "isobutane", + "kerosene_and_light_oils", + "liquified_petroleum_gases", + "mtbe", + "motor_gasoline_blending_components_reformulated_rbob", + "naphthas_and_lighter", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "other_biofuels", + "other_liquids", + "other_oxygenates", + "oxygenates", + "oxygenates_and_renewable_fuels", + "pentanes_plus", + "reformulated_gtab_gasoline_blending_components", + "reformulated_gasoline_blending_components", + "reformulated_rbob_with_alcohol_gasoline_blending_components", + "reformulated_rbob_with_ether_gasoline_blending_components", + "renewable_diesel_fuel", + "residuum", + "total_petroleum_products", + "unfinished_oils", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 840 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumBlenderNetInputData(EiaApiData): + """Blender Net Input. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumBlenderNetInputFetcher( + Fetcher[ + EiaPetroleumBlenderNetInputQueryParams, list[EiaPetroleumBlenderNetInputData] + ] +): + """Blender Net Input fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumBlenderNetInputQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaPetroleumBlenderNetInputQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaPetroleumBlenderNetInputQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumBlenderNetInputQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumBlenderNetInputData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumBlenderNetInputData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/blender_net_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/blender_net_production.py new file mode 100644 index 00000000000..5c2ce8f9961 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/blender_net_production.py @@ -0,0 +1,160 @@ +"""Blender Net Production model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumBlenderNetProductionQueryParams(EiaApiQueryParams): + """Blender Net Production. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/refp3 + """ + + __group__ = "petroleum" + __dataset__ = "blender_net_production" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "finished_motor_gasoline", + "finished_motor_gasoline_conventional_55", + "finished_motor_gasoline_reformulated_other", + "kerosene", + "kerosene_type_jet_fuel", + "lubricants", + "miscellaneous_petroleum_products", + "motor_gasoline_finished_conventional_ed55_and_lower", + "other_conventional_motor_gasoline", + "processing_gain", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + "residual_fuel_oil", + "residual_fuel_oil_0_31_to_1_00_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + "residual_fuel_oil_less_than_0_31_sulfur", + "special_naphthas", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 652 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumBlenderNetProductionData(EiaApiData): + """Blender Net Production. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumBlenderNetProductionFetcher( + Fetcher[ + EiaPetroleumBlenderNetProductionQueryParams, + list[EiaPetroleumBlenderNetProductionData], + ] +): + """Blender Net Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumBlenderNetProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumBlenderNetProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumBlenderNetProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumBlenderNetProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumBlenderNetProductionData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumBlenderNetProductionData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/costs_of_crude_oil_and_natural_gas_wells_drilled.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/costs_of_crude_oil_and_natural_gas_wells_drilled.py new file mode 100644 index 00000000000..e6d3e396a3a --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/costs_of_crude_oil_and_natural_gas_wells_drilled.py @@ -0,0 +1,152 @@ +"""Costs of Crude Oil and Natural Gas Wells Drilled model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilledQueryParams( + EiaApiQueryParams +): + """Costs of Crude Oil and Natural Gas Wells Drilled. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/crd/wellcost + """ + + __group__ = "petroleum" + __dataset__ = "costs_of_crude_oil_and_natural_gas_wells_drilled" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "nominal_cost_per_foot_of_dry_wells_drilled", + "nominal_cost_per_well_drilled", + "real_cost", + "real_cost_per_foot", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": ["wells_dry", "wells_gas", "wells_oil", "wells_total"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_nominal_cost_per_crude_oil_well_drilled", + "us_nominal_cost_per_crude_oil_natural_gas_and_dry_well", + "us_nominal_cost_per_dry_well_drilled", + "us_nominal_cost_per_foot_of_crude_oil_wells_drilled", + "us_nominal_cost_per_foot_of_crude_oil_natural_gas_and_dry", + "us_nominal_cost_per_foot_of_dry_wells_drilled", + "us_nominal_cost_per_foot_of_natural_gas_wells_drilled", + "us_nominal_cost_per_natural_gas_well_drilled", + "us_real_cost_per_crude_oil_natural_gas_and_dry_well_drilled", + "us_real_cost_per_foot_of_crude_oil_natural_gas_and_dry", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilledData(EiaApiData): + """Costs of Crude Oil and Natural Gas Wells Drilled. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilledFetcher( + Fetcher[ + EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilledQueryParams, + list[EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilledData], + ] +): + """Costs of Crude Oil and Natural Gas Wells Drilled fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilledQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilledQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilledQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilledQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilledData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilledData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_first_purchase_prices_selected_streams.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_first_purchase_prices_selected_streams.py new file mode 100644 index 00000000000..557f080ade9 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_first_purchase_prices_selected_streams.py @@ -0,0 +1,158 @@ +"""Domestic Crude Oil First Purchase Prices for Selected Crude Streams model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumCrudeFirstPurchasePricesSelectedStreamsQueryParams(EiaApiQueryParams): + """Domestic Crude Oil First Purchase Prices for Selected Crude Streams. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/dfp2 + """ + + __group__ = "petroleum" + __dataset__ = "crude_first_purchase_prices_selected_streams" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "ans_crude_oil", + "california_kern_river_crude_oil", + "california_midwest_sunset_crude_oil", + "louisiana_heavy_sweet_crude_oil", + "louisiana_light_sweet_crude_oil", + "mars_crude_oil", + "wti_crude_oil", + "west_texas_sour_crude_oil", + "wyoming_sweet_crude_oil", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["california", "texas", "usa_ak", "usa_la", "usa_wy"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alaska_north_slope_first_purchase_price", + "california_kern_river_first_purchase_price", + "california_midway_sunset_first_purchase_price", + "heavy_louisiana_sweet_first_purchase_price", + "light_louisiana_sweet_first_purchase_price", + "mars_blend_first_purchase_price", + "west_texas_intermediate_first_purchase_price", + "west_texas_sour_first_purchase_price", + "wyoming_sweet_first_purchase_price", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumCrudeFirstPurchasePricesSelectedStreamsData(EiaApiData): + """Domestic Crude Oil First Purchase Prices for Selected Crude Streams. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumCrudeFirstPurchasePricesSelectedStreamsFetcher( + Fetcher[ + EiaPetroleumCrudeFirstPurchasePricesSelectedStreamsQueryParams, + list[EiaPetroleumCrudeFirstPurchasePricesSelectedStreamsData], + ] +): + """Domestic Crude Oil First Purchase Prices for Selected Crude Streams fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumCrudeFirstPurchasePricesSelectedStreamsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumCrudeFirstPurchasePricesSelectedStreamsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumCrudeFirstPurchasePricesSelectedStreamsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumCrudeFirstPurchasePricesSelectedStreamsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumCrudeFirstPurchasePricesSelectedStreamsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumCrudeFirstPurchasePricesSelectedStreamsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_and_lease_condensate_production_by_api_gravity.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_and_lease_condensate_production_by_api_gravity.py new file mode 100644 index 00000000000..08233d6e82a --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_and_lease_condensate_production_by_api_gravity.py @@ -0,0 +1,269 @@ +"""Crude Oil and Lease Condensate Production by API Gravity model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravityQueryParams( + EiaApiQueryParams +): + """Crude Oil and Lease Condensate Production by API Gravity. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/crd/api + """ + + __group__ = "petroleum" + __dataset__ = "crude_oil_and_lease_condensate_production_by_api_gravity" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "crude_gravity_20_0_percent_or_less", + "crude_gravity_20_1_to_25_0_percent", + "crude_gravity_25_1_to_30_0_percent", + "crude_gravity_30_0_percent_or_less", + "crude_gravity_30_1_to_35_0_percent", + "crude_gravity_30_1_to_40_0_percent", + "crude_gravity_35_1_to_40_0_percent", + "crude_gravity_40_1_to_45_0_percent", + "crude_gravity_40_1_to_50_0_percent", + "crude_gravity_45_1_to_50_0_percent", + "crude_gravity_50_1_percent_or_more", + "crude_gravity_50_1_to_55_0_percent", + "crude_gravity_55_1_percent_or_more", + "crude_gravity_of_all", + "crude_gravity_of_unkown", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "na", + "ohio", + "texas", + "usa_ar", + "usa_ks", + "usa_la", + "usa_mt", + "usa_nd", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_wv", + "usa_wy", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "arkansas_crude_oil_and_lease_condensate_production_for_30_0", + "arkansas_crude_oil_and_lease_condensate_production_for_30_1", + "arkansas_crude_oil_and_lease_condensate_production_for_40_1", + "arkansas_crude_oil_and_lease_condensate_production_for_50_1", + "arkansas_crude_oil_and_lease_condensate_production_for_all", + "california_crude_oil_and_lease_condensate_production_for_30_0_or_lower_degrees_api_gravity_thousand_barrels_per_day", + "california_crude_oil_and_lease_condensate_production_for_30_1_to_40_0_degrees_api_gravity_thousand_barrels_per_day", + "california_crude_oil_and_lease_condensate_production_for_40", + "california_crude_oil_and_lease_condensate_production_for_50", + "california_crude_oil_and_lease_condensate_production_for", + "colorado_crude_oil_and_lease_condensate_production_for_30_0", + "colorado_crude_oil_and_lease_condensate_production_for_30_1", + "colorado_crude_oil_and_lease_condensate_production_for_40_1", + "colorado_crude_oil_and_lease_condensate_production_for_50_1", + "colorado_crude_oil_and_lease_condensate_production_for_all", + "federal_offshore_gulf_of_america_crude_oil_and_lease_condensate_production_for_30_0_or_lower_degrees_api_gravity_thousand_barrels_per_day", + "federal_offshore_gulf_of_america_crude_oil_and_lease_condensate_production_for_30_1_to_40_0_degrees_api_gravity_thousand_barrels_per_day", + "federal_offshore_gulf_of_america_crude_oil_and_lease_condensate_production_for_40_1_to_50_0_degrees_api_gravity_thousand_barrels_per_day", + "federal_offshore_gulf_of_america_crude_oil_and_lease_condensate_production_for_50_1_or_higher_degrees_api_gravity_thousand_barrels_per_day", + "federal_offshore_gulf_of_america_crude_oil_and_lease_condensate_production_for_all_api_gravity_thousand_barrels_per_day", + "kansas_crude_oil_and_lease_condensate_production_for_30_0", + "kansas_crude_oil_and_lease_condensate_production_for_30_1", + "kansas_crude_oil_and_lease_condensate_production_for_40_1", + "kansas_crude_oil_and_lease_condensate_production_for_50_1", + "kansas_crude_oil_and_lease_condensate_production_for_all", + "louisiana_crude_oil_and_lease_condensate_production_for_30_0_or_lower_degrees_api_gravity_thousand_barrels_per_day", + "louisiana_crude_oil_and_lease_condensate_production_for_30_1_to_40_0_degrees_api_gravity_thousand_barrels_per_day", + "louisiana_crude_oil_and_lease_condensate_production_for_40", + "louisiana_crude_oil_and_lease_condensate_production_for_50", + "louisiana_crude_oil_and_lease_condensate_production_for_all", + "lower_48_states_crude_oil_and_lease_condensate_production_for_20_0_or_lower_degrees_api_gravity_thousand_barrels_per_day", + "lower_48_states_crude_oil_and_lease_condensate_production_for_20_1_to_25_0_degrees_api_gravity_thousand_barrels_per_day", + "lower_48_states_crude_oil_and_lease_condensate_production_for_25_1_to_30_0_degrees_api_gravity_thousand_barrels_per_day", + "lower_48_states_crude_oil_and_lease_condensate_production_for_30_1_to_35_0_degrees_api_gravity_thousand_barrels_per_day", + "lower_48_states_crude_oil_and_lease_condensate_production_for_35_1_to_40_0_degrees_api_gravity_thousand_barrels_per_day", + "lower_48_states_crude_oil_and_lease_condensate_production_for_40_1_to_45_0_degrees_api_gravity_thousand_barrels_per_day", + "lower_48_states_crude_oil_and_lease_condensate_production_for_45_1_to_50_0_degrees_api_gravity_thousand_barrels_per_day", + "lower_48_states_crude_oil_and_lease_condensate_production_for_50_1_to_55_0_degrees_api_gravity_thousand_barrels_per_day", + "lower_48_states_crude_oil_and_lease_condensate_production_for_55_1_or_higher_degrees_api_gravity_thousand_barrels_per_day", + "lower_48_states_crude_oil_and_lease_condensate_production_for_unknown_api_gravity_thousand_barrels_per_day", + "lower_48_states_crude_oil_and_lease_condensate_production_for_all_api_gravity_thousand_barrels_per_day", + "montana_crude_oil_and_lease_condensate_production_for_30_0", + "montana_crude_oil_and_lease_condensate_production_for_30_1", + "montana_crude_oil_and_lease_condensate_production_for_40_1", + "montana_crude_oil_and_lease_condensate_production_for_50_1", + "montana_crude_oil_and_lease_condensate_production_for_all", + "new_mexico_crude_oil_and_lease_condensate_production_for_30_0_or_lower_degrees_api_gravity_thousand_barrels_per_day", + "new_mexico_crude_oil_and_lease_condensate_production_for_30_1_to_40_0_degrees_api_gravity_thousand_barrels_per_day", + "new_mexico_crude_oil_and_lease_condensate_production_for_40", + "new_mexico_crude_oil_and_lease_condensate_production_for_50", + "new_mexico_crude_oil_and_lease_condensate_production_for", + "north_dakota_crude_oil_and_lease_condensate_production_for_30_0_or_lower_degrees_api_gravity_thousand_barrels_per_day", + "north_dakota_crude_oil_and_lease_condensate_production_for_30_1_to_40_0_degrees_api_gravity_thousand_barrels_per_day", + "north_dakota_crude_oil_and_lease_condensate_production_for_40_1_to_50_0_degrees_api_gravity_thousand_barrels_per_day", + "north_dakota_crude_oil_and_lease_condensate_production_for_50_1_or_higher_degrees_api_gravity_thousand_barrels_per_day", + "north_dakota_crude_oil_and_lease_condensate_production_for_all_api_gravity_thousand_barrels_per_day", + "ohio_crude_oil_and_lease_condensate_production_for_30_0_or", + "ohio_crude_oil_and_lease_condensate_production_for_30_1_to", + "ohio_crude_oil_and_lease_condensate_production_for_40_1_to", + "ohio_crude_oil_and_lease_condensate_production_for_50_1_or", + "ohio_crude_oil_and_lease_condensate_production_for_all_api", + "oklahoma_crude_oil_and_lease_condensate_production_for_30_0", + "oklahoma_crude_oil_and_lease_condensate_production_for_30_1", + "oklahoma_crude_oil_and_lease_condensate_production_for_40_1", + "oklahoma_crude_oil_and_lease_condensate_production_for_50_1", + "oklahoma_crude_oil_and_lease_condensate_production_for_all", + "other_states_crude_oil_and_lease_condensate_production_for_30_0_or_lower_degrees_api_gravity_thousand_barrels_per_day", + "other_states_crude_oil_and_lease_condensate_production_for_30_1_to_40_0_degrees_api_gravity_thousand_barrels_per_day", + "other_states_crude_oil_and_lease_condensate_production_for_40_1_to_50_0_degrees_api_gravity_thousand_barrels_per_day", + "other_states_crude_oil_and_lease_condensate_production_for_50_1_or_higher_degrees_api_gravity_thousand_barrels_per_day_ull", + "other_states_crude_oil_and_lease_condensate_production_for_all_api_gravity_thousand_barrels_per_day", + "pennsylvania_crude_oil_and_lease_condensate_production_for_30_0_or_lower_degrees_api_gravity_thousand_barrels_per_day", + "pennsylvania_crude_oil_and_lease_condensate_production_for_30_1_to_40_0_degrees_api_gravity_thousand_barrels_per_day", + "pennsylvania_crude_oil_and_lease_condensate_production_for_40_1_to_50_0_degrees_api_gravity_thousand_barrels_per_day", + "pennsylvania_crude_oil_and_lease_condensate_production_for_50_1_or_higher_degrees_api_gravity_thousand_barrels_per_day", + "pennsylvania_crude_oil_and_lease_condensate_production_for_all_api_gravity_thousand_barrels_per_day", + "texas_crude_oil_and_lease_condensate_production_for_30_0_or", + "texas_crude_oil_and_lease_condensate_production_for_30_1_to", + "texas_crude_oil_and_lease_condensate_production_for_40_1_to", + "texas_crude_oil_and_lease_condensate_production_for_50_1_or", + "texas_crude_oil_and_lease_condensate_production_for_all_api", + "utah_crude_oil_and_lease_condensate_production_for_30_0_or", + "utah_crude_oil_and_lease_condensate_production_for_30_1_to", + "utah_crude_oil_and_lease_condensate_production_for_40_1_to", + "utah_crude_oil_and_lease_condensate_production_for_50_1_or", + "utah_crude_oil_and_lease_condensate_production_for_all_api", + "west_virginia_crude_oil_and_lease_condensate_production_for_30_0_or_lower_degrees_api_gravity_thousand_barrels_per_day", + "west_virginia_crude_oil_and_lease_condensate_production_for_30_1_to_40_0_degrees_api_gravity_thousand_barrels_per_day", + "west_virginia_crude_oil_and_lease_condensate_production_for_40_1_to_50_0_degrees_api_gravity_thousand_barrels_per_day", + "west_virginia_crude_oil_and_lease_condensate_production_for_50_1_or_higher_degrees_api_gravity_thousand_barrels_per_day", + "west_virginia_crude_oil_and_lease_condensate_production_for_all_api_gravity_thousand_barrels_per_day", + "wyoming_crude_oil_and_lease_condensate_production_for_30_0", + "wyoming_crude_oil_and_lease_condensate_production_for_30_1", + "wyoming_crude_oil_and_lease_condensate_production_for_40_1", + "wyoming_crude_oil_and_lease_condensate_production_for_50_1", + "wyoming_crude_oil_and_lease_condensate_production_for_all", + ], + }, + } + + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravityData(EiaApiData): + """Crude Oil and Lease Condensate Production by API Gravity. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravityFetcher( + Fetcher[ + EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravityQueryParams, + list[EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravityData], + ] +): + """Crude Oil and Lease Condensate Production by API Gravity fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravityQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravityData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravityData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_and_natural_gas_drilling_activity.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_and_natural_gas_drilling_activity.py new file mode 100644 index 00000000000..d9e6899f75c --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_and_natural_gas_drilling_activity.py @@ -0,0 +1,158 @@ +"""Crude Oil and Natural Gas Drilling Activity model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumCrudeOilAndNaturalGasDrillingActivityQueryParams(EiaApiQueryParams): + """Crude Oil and Natural Gas Drilling Activity. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/crd/drill + """ + + __group__ = "petroleum" + __dataset__ = "crude_oil_and_natural_gas_drilling_activity" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "active_well_service_rigs_in_operation", + "rotary_rigs_in_operation", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "crude_oil_and_natural_gas", + "rotary_rigs_in_operation", + "rotary_rigs_in_operation_gas", + "rotary_rigs_in_operation_oil", + ], + }, + "region": {"multiple_items_allowed": True, "choices": ["na", "us"]}, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_crude_oil_rotary_rigs_in_operation", + "us_crude_oil_and_natural_gas_active_well_service_rigs_in", + "us_crude_oil_and_natural_gas_rotary_rigs_in_operation", + "us_natural_gas_rotary_rigs_in_operation", + "us_offshore_crude_oil_and_natural_gas_rotary_rigs_in", + "us_onshore_crude_oil_and_natural_gas_rotary_rigs_in", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumCrudeOilAndNaturalGasDrillingActivityData(EiaApiData): + """Crude Oil and Natural Gas Drilling Activity. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumCrudeOilAndNaturalGasDrillingActivityFetcher( + Fetcher[ + EiaPetroleumCrudeOilAndNaturalGasDrillingActivityQueryParams, + list[EiaPetroleumCrudeOilAndNaturalGasDrillingActivityData], + ] +): + """Crude Oil and Natural Gas Drilling Activity fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumCrudeOilAndNaturalGasDrillingActivityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumCrudeOilAndNaturalGasDrillingActivityQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumCrudeOilAndNaturalGasDrillingActivityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumCrudeOilAndNaturalGasDrillingActivityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumCrudeOilAndNaturalGasDrillingActivityData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumCrudeOilAndNaturalGasDrillingActivityData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_and_natural_gas_exploratory_and_development_wells.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_and_natural_gas_exploratory_and_development_wells.py new file mode 100644 index 00000000000..096d29cc026 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_and_natural_gas_exploratory_and_development_wells.py @@ -0,0 +1,162 @@ +"""Crude Oil and Natural Gas Exploratory and Development Wells model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsQueryParams( + EiaApiQueryParams +): + """Crude Oil and Natural Gas Exploratory and Development Wells. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/crd/wellend + """ + + __group__ = "petroleum" + __dataset__ = "crude_oil_and_natural_gas_exploratory_and_development_wells" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "developmental_wells_drilled", + "exploratory_wells_drilled", + "exploratory_and_developmental_wells_drilled", + "footage_drilled_for_exploratory_and_developmental_wells", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": ["wells_dry", "wells_gas", "wells_oil", "wells_total"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_crude_oil_developmental_wells_drilled", + "us_crude_oil_exploratory_wells_drilled", + "us_crude_oil_exploratory_and_developmental_wells_drilled", + "us_crude_oil_natural_gas_and_dry_developmental_wells_drilled", + "us_crude_oil_natural_gas_and_dry_exploratory_wells_drilled", + "us_crude_oil_natural_gas_and_dry_exploratory_and", + "us_dry_developmental_wells_drilled", + "us_dry_exploratory_wells_drilled", + "us_dry_exploratory_and_developmental_wells_drilled", + "us_footage_drilled_for_crude_oil_natural_gas_and_dry", + "us_natural_gas_developmental_wells_drilled", + "us_natural_gas_exploratory_wells_drilled", + "us_natural_gas_exploratory_and_developmental_wells_drilled", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsData(EiaApiData): + """Crude Oil and Natural Gas Exploratory and Development Wells. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsFetcher( + Fetcher[ + EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsQueryParams, + list[EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsData], + ] +): + """Crude Oil and Natural Gas Exploratory and Development Wells fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_input_qualities.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_input_qualities.py new file mode 100644 index 00000000000..bde2f6e75f4 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_input_qualities.py @@ -0,0 +1,174 @@ +"""Crude Oil Input Qualities model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumCrudeOilInputQualitiesQueryParams(EiaApiQueryParams): + """Crude Oil Input Qualities. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/crq + """ + + __group__ = "petroleum" + __dataset__ = "crude_oil_input_qualities" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "oil_refinery_inputs_average_sulfur_content", + "refinery_inputs_average_api_gravity", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "appalachian_no_1_refinery_district_api_gravity_of_crude_oil", + "appalachian_no_1_refinery_district_sulfur_content_of_crude", + "east_coast_api_gravity_of_crude_oil_input_to_refineries", + "east_coast_sulfur_content_of_crude_oil_input_to_refineries", + "east_coast_refinery_district_api_gravity_of_crude_oil_input", + "east_coast_refinery_district_sulfur_content_of_crude_oil", + "gulf_coast_api_gravity_of_crude_oil_input_to_refineries", + "gulf_coast_sulfur_content_of_crude_oil_input_to_refineries", + "indiana_illinois_kentucky_refinery_district_api_gravity_of", + "indiana_illinois_kentucky_refinery_district_sulfur_content", + "louisiana_gulf_coast_refinery_district_api_gravity_of_crude", + "louisiana_gulf_coast_refinery_district_sulfur_content_of", + "midwest_api_gravity_of_crude_oil_input_to_refineries", + "midwest_sulfur_content_of_crude_oil_input_to_refineries", + "minnesota_wisconsin_north_and_south_dakota_refinery_district_api_gravity_weighted_average_of_crude_oil_input_to_refineries_degrees", + "minnesota_wisconsin_north_and_south_dakota_refinery_district_sulfur_content_weighted_average_of_crude_oil_input_to_refineries_percent", + "new_mexico_refinery_district_api_gravity_of_crude_oil_input", + "new_mexico_refinery_district_sulfur_content_of_crude_oil", + "north_louisiana_arkansas_refinery_district_api_gravity_of", + "north_louisiana_arkansas_refinery_district_sulfur_content", + "oklahoma_kansas_missouri_refinery_district_api_gravity_of", + "oklahoma_kansas_missouri_refinery_district_sulfur_content", + "rocky_mountains_api_gravity_of_crude_oil_input_to_refineries", + "rocky_mountains_sulfur_content_of_crude_oil_input_to", + "texas_gulf_coast_refinery_district_api_gravity_of_crude_oil", + "texas_gulf_coast_refinery_district_sulfur_content_of_crude", + "texas_inland_refinery_district_api_gravity_of_crude_oil", + "texas_inland_refinery_district_sulfur_content_of_crude_oil", + "us_api_gravity_of_crude_oil_input_to_refineries", + "us_sulfur_content_of_crude_oil_input_to_refineries", + "west_coast_api_gravity_of_crude_oil_input_to_refineries", + "west_coast_sulfur_content_of_crude_oil_input_to_refineries", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumCrudeOilInputQualitiesData(EiaApiData): + """Crude Oil Input Qualities. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumCrudeOilInputQualitiesFetcher( + Fetcher[ + EiaPetroleumCrudeOilInputQualitiesQueryParams, + list[EiaPetroleumCrudeOilInputQualitiesData], + ] +): + """Crude Oil Input Qualities fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumCrudeOilInputQualitiesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumCrudeOilInputQualitiesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumCrudeOilInputQualitiesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumCrudeOilInputQualitiesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumCrudeOilInputQualitiesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumCrudeOilInputQualitiesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_production.py new file mode 100644 index 00000000000..94326bb9a4a --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_production.py @@ -0,0 +1,261 @@ +"""Crude Oil Production model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumCrudeOilProductionQueryParams(EiaApiQueryParams): + """Crude Oil Production. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/crd/crpdn + """ + + __group__ = "petroleum" + __dataset__ = "crude_oil_production" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": ["ans_crude_oil", "crude_oil"], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "padd_1", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_pa", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alabama_field_production_of_crude_oil_thousand_barrels_per_day", + "alabama_field_production_of_crude_oil_thousand_barrels", + "alaska_field_production_of_crude_oil_thousand_barrels_per_day", + "alaska_field_production_of_crude_oil_thousand_barrels", + "alaska_north_slope_crude_oil_production_thousand_barrels_per_day", + "alaska_north_slope_crude_oil_production_thousand_barrels", + "alaska_south_field_production_of_crude_oil_thousand_barrels_per_day", + "alaska_south_field_production_of_crude_oil_thousand_barrels", + "arizona_field_production_of_crude_oil_thousand_barrels_per_day", + "arizona_field_production_of_crude_oil_thousand_barrels", + "arkansas_field_production_of_crude_oil_thousand_barrels_per_day", + "arkansas_field_production_of_crude_oil_thousand_barrels", + "california_field_production_of_crude_oil_thousand_barrels_per_day", + "california_field_production_of_crude_oil_thousand_barrels", + "colorado_field_production_of_crude_oil_thousand_barrels_per_day", + "colorado_field_production_of_crude_oil_thousand_barrels", + "east_coast_padd_1_field_production_of_crude_oil_thousand_barrels_per_day", + "east_coast_padd_1_field_production_of_crude_oil_thousand_barrels", + "federal_offshore_padd_5_field_production_of_crude_oil_thousand_barrels_per_day", + "federal_offshore_padd_5_field_production_of_crude_oil_thousand_barrels", + "federal_offshore_gulf_of_america_field_production_of_crude_oil_thousand_barrels_per_day", + "federal_offshore_gulf_of_america_field_production_of_crude_oil_thousand_barrels", + "florida_field_production_of_crude_oil_thousand_barrels_per_day", + "florida_field_production_of_crude_oil_thousand_barrels", + "gulf_coast_padd_3_field_production_of_crude_oil_thousand_barrels_per_day", + "gulf_coast_padd_3_field_production_of_crude_oil_thousand_barrels", + "idaho_field_production_of_crude_oil_thousand_barrels_per_day", + "idaho_field_production_of_crude_oil_thousand_barrels", + "illinois_field_production_of_crude_oil_thousand_barrels_per_day", + "illinois_field_production_of_crude_oil_thousand_barrels", + "indiana_field_production_of_crude_oil_thousand_barrels_per_day", + "indiana_field_production_of_crude_oil_thousand_barrels", + "kansas_field_production_of_crude_oil_thousand_barrels_per_day", + "kansas_field_production_of_crude_oil_thousand_barrels", + "kentucky_field_production_of_crude_oil_thousand_barrels_per_day", + "kentucky_field_production_of_crude_oil_thousand_barrels", + "louisiana_field_production_of_crude_oil_thousand_barrels_per_day", + "louisiana_field_production_of_crude_oil_thousand_barrels", + "michigan_field_production_of_crude_oil_thousand_barrels_per_day", + "michigan_field_production_of_crude_oil_thousand_barrels", + "midwest_padd_2_field_production_of_crude_oil_thousand_barrels_per_day", + "midwest_padd_2_field_production_of_crude_oil_thousand_barrels", + "mississippi_field_production_of_crude_oil_thousand_barrels_per_day", + "mississippi_field_production_of_crude_oil_thousand_barrels", + "missouri_field_production_of_crude_oil_thousand_barrels_per_day", + "missouri_field_production_of_crude_oil_thousand_barrels", + "montana_field_production_of_crude_oil_thousand_barrels_per_day", + "montana_field_production_of_crude_oil_thousand_barrels", + "nebraska_field_production_of_crude_oil_thousand_barrels_per_day", + "nebraska_field_production_of_crude_oil_thousand_barrels", + "nevada_field_production_of_crude_oil_thousand_barrels_per_day", + "nevada_field_production_of_crude_oil_thousand_barrels", + "new_mexico_field_production_of_crude_oil_thousand_barrels_per_day", + "new_mexico_field_production_of_crude_oil_thousand_barrels", + "new_york_field_production_of_crude_oil_thousand_barrels_per_day", + "new_york_field_production_of_crude_oil_thousand_barrels", + "north_dakota_field_production_of_crude_oil_thousand_barrels_per_day", + "north_dakota_field_production_of_crude_oil_thousand_barrels", + "ohio_field_production_of_crude_oil_thousand_barrels_per_day", + "ohio_field_production_of_crude_oil_thousand_barrels", + "oklahoma_field_production_of_crude_oil_thousand_barrels_per_day", + "oklahoma_field_production_of_crude_oil_thousand_barrels", + "pennsylvania_field_production_of_crude_oil_thousand_barrels_per_day", + "pennsylvania_field_production_of_crude_oil_thousand_barrels", + "rocky_mountain_padd_4_field_production_of_crude_oil_thousand_barrels_per_day", + "rocky_mountain_padd_4_field_production_of_crude_oil_thousand_barrels", + "south_dakota_field_production_of_crude_oil_thousand_barrels_per_day", + "south_dakota_field_production_of_crude_oil_thousand_barrels", + "tennessee_field_production_of_crude_oil_thousand_barrels_per_day", + "tennessee_field_production_of_crude_oil_thousand_barrels", + "texas_field_production_of_crude_oil_thousand_barrels_per_day", + "texas_field_production_of_crude_oil_thousand_barrels", + "us_field_production_of_crude_oil_thousand_barrels_per_day", + "us_field_production_of_crude_oil_thousand_barrels", + "utah_field_production_of_crude_oil_thousand_barrels_per_day", + "utah_field_production_of_crude_oil_thousand_barrels", + "virginia_field_production_of_crude_oil_thousand_barrels_per_day", + "virginia_field_production_of_crude_oil_thousand_barrels", + "west_coast_padd_5_field_production_of_crude_oil_thousand_barrels_per_day", + "west_coast_padd_5_field_production_of_crude_oil_thousand_barrels", + "west_virginia_field_production_of_crude_oil_thousand_barrels_per_day", + "west_virginia_field_production_of_crude_oil_thousand_barrels", + "wyoming_field_production_of_crude_oil_thousand_barrels_per_day", + "wyoming_field_production_of_crude_oil_thousand_barrels", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumCrudeOilProductionData(EiaApiData): + """Crude Oil Production. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumCrudeOilProductionFetcher( + Fetcher[ + EiaPetroleumCrudeOilProductionQueryParams, + list[EiaPetroleumCrudeOilProductionData], + ] +): + """Crude Oil Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumCrudeOilProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumCrudeOilProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumCrudeOilProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumCrudeOilProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumCrudeOilProductionData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumCrudeOilProductionData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_proved_reserves_reserves_changes_and_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_proved_reserves_reserves_changes_and_production.py new file mode 100644 index 00000000000..d1de19a5680 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_proved_reserves_reserves_changes_and_production.py @@ -0,0 +1,175 @@ +"""Crude Oil Proved Reserves, Reserves Changes, and Production model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumCrudeOilProvedReservesReservesChangesAndProductionQueryParams( + EiaApiQueryParams +): + """Crude Oil Proved Reserves, Reserves Changes, and Production. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/crd/pres + """ + + __group__ = "petroleum" + __dataset__ = "crude_oil_proved_reserves_reserves_changes_and_production" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "production_from_reserves", + "proved_reserves", + "reserves_acquisitions", + "reserves_adjustments", + "reserves_extensions", + "reserves_extensions_and_discoveries", + "reserves_new_field_discoveries", + "reserves_new_reservoir_discoveries_in_old_fields", + "reserves_revision_decreases", + "reserves_revision_increases", + "reserves_sales", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 572 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumCrudeOilProvedReservesReservesChangesAndProductionData(EiaApiData): + """Crude Oil Proved Reserves, Reserves Changes, and Production. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumCrudeOilProvedReservesReservesChangesAndProductionFetcher( + Fetcher[ + EiaPetroleumCrudeOilProvedReservesReservesChangesAndProductionQueryParams, + list[EiaPetroleumCrudeOilProvedReservesReservesChangesAndProductionData], + ] +): + """Crude Oil Proved Reserves, Reserves Changes, and Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumCrudeOilProvedReservesReservesChangesAndProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumCrudeOilProvedReservesReservesChangesAndProductionQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumCrudeOilProvedReservesReservesChangesAndProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumCrudeOilProvedReservesReservesChangesAndProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumCrudeOilProvedReservesReservesChangesAndProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumCrudeOilProvedReservesReservesChangesAndProductionData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_stocks_at_tank_farms_pipelines.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_stocks_at_tank_farms_pipelines.py new file mode 100644 index 00000000000..48e8fb5be9d --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_oil_stocks_at_tank_farms_pipelines.py @@ -0,0 +1,146 @@ +"""Crude Oil Stocks at Tank Farms & Pipelines model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumCrudeOilStocksAtTankFarmsPipelinesQueryParams(EiaApiQueryParams): + """Crude Oil Stocks at Tank Farms & Pipelines. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/stoc/cu + """ + + __group__ = "petroleum" + __dataset__ = "crude_oil_stocks_at_tank_farms_pipelines" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": ["ending_stocks", "stocks_at_tank_farms"], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "cushing_ok_ending_stocks_of_crude_oil", + "east_coast_crude_oil_stocks_at_tank_farms_and_pipelines", + "gulf_coast_crude_oil_stocks_at_tank_farms_and_pipelines", + "midwest_crude_oil_stocks_at_tank_farms_and_pipelines", + "rocky_mountain_crude_oil_stocks_at_tank_farms_and_pipelines", + "us_crude_oil_stocks_at_tank_farms_and_pipelines", + "west_coast_crude_oil_stocks_at_tank_farms_and_pipelines", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumCrudeOilStocksAtTankFarmsPipelinesData(EiaApiData): + """Crude Oil Stocks at Tank Farms & Pipelines. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumCrudeOilStocksAtTankFarmsPipelinesFetcher( + Fetcher[ + EiaPetroleumCrudeOilStocksAtTankFarmsPipelinesQueryParams, + list[EiaPetroleumCrudeOilStocksAtTankFarmsPipelinesData], + ] +): + """Crude Oil Stocks at Tank Farms & Pipelines fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumCrudeOilStocksAtTankFarmsPipelinesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumCrudeOilStocksAtTankFarmsPipelinesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumCrudeOilStocksAtTankFarmsPipelinesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumCrudeOilStocksAtTankFarmsPipelinesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumCrudeOilStocksAtTankFarmsPipelinesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumCrudeOilStocksAtTankFarmsPipelinesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_plus_lease_condensate_proved_reserves.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_plus_lease_condensate_proved_reserves.py new file mode 100644 index 00000000000..e0beff7f15d --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/crude_plus_lease_condensate_proved_reserves.py @@ -0,0 +1,170 @@ +"""Crude Oil plus Lease Condensate Proved Reserves, Reserves Changes, and Production model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumCrudePlusLeaseCondensateProvedReservesQueryParams(EiaApiQueryParams): + """Crude Oil plus Lease Condensate Proved Reserves, Reserves Changes, and Production. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/crd/cplc + """ + + __group__ = "petroleum" + __dataset__ = "crude_plus_lease_condensate_proved_reserves" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "production_from_reserves", + "proved_reserves", + "reserves_acquisitions", + "reserves_adjustments", + "reserves_extensions", + "reserves_extensions_and_discoveries", + "reserves_new_field_discoveries", + "reserves_new_reservoir_discoveries_in_old_fields", + "reserves_revision_decreases", + "reserves_revision_increases", + "reserves_sales", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 572 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumCrudePlusLeaseCondensateProvedReservesData(EiaApiData): + """Crude Oil plus Lease Condensate Proved Reserves, Reserves Changes, and Production. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumCrudePlusLeaseCondensateProvedReservesFetcher( + Fetcher[ + EiaPetroleumCrudePlusLeaseCondensateProvedReservesQueryParams, + list[EiaPetroleumCrudePlusLeaseCondensateProvedReservesData], + ] +): + """Crude Oil plus Lease Condensate Proved Reserves, Reserves Changes, and Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumCrudePlusLeaseCondensateProvedReservesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumCrudePlusLeaseCondensateProvedReservesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumCrudePlusLeaseCondensateProvedReservesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumCrudePlusLeaseCondensateProvedReservesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumCrudePlusLeaseCondensateProvedReservesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumCrudePlusLeaseCondensateProvedReservesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/distillate_fuel_oil_and_kerosene_sales_by_end_use.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/distillate_fuel_oil_and_kerosene_sales_by_end_use.py new file mode 100644 index 00000000000..d2a5a1bbdaa --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/distillate_fuel_oil_and_kerosene_sales_by_end_use.py @@ -0,0 +1,232 @@ +"""Distillate Fuel Oil and Kerosene Sales by End Use model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUseQueryParams( + EiaApiQueryParams +): + """Distillate Fuel Oil and Kerosene Sales by End Use. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/cons/821use + """ + + __group__ = "petroleum" + __dataset__ = "distillate_fuel_oil_and_kerosene_sales_by_end_use" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "commercial_consumption", + "electric_power_consumption", + "industrial_consumption", + "off_highway_other", + "residential_consumption", + "sales_deliveries_to_farm_consumers", + "sales_deliveries_to_military_consumers", + "sales_deliveries_to_off_highway_construction", + "sales_deliveries_to_off_highway_consumers", + "sales_deliveries_to_oil_company_consumers", + "sales_deliveries_to_on_highway_consumers", + "sales_deliveries_to_other_end_users", + "sales_deliveries_to_railroad_consumers", + "sales_deliveries_to_vessel_bunkering_consumers", + "transportation_total", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "distillate_fuel_oil", + "distillate_other_than_diesel", + "kerosene", + "no_1_distillate", + "no_2_diesel", + "no_2_diesel_high_sulfur", + "no_2_diesel_low_sulfur", + "no_2_diesel_low_sulfur_0_15_ppm", + "no_2_diesel_low_sulfur_15_500_ppm", + "no_2_distillate", + "no_2_fuel_oil_heating_oil", + "no_4_distillate", + "residual_fuel_oil", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUseData(EiaApiData): + """Distillate Fuel Oil and Kerosene Sales by End Use. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUseFetcher( + Fetcher[ + EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUseQueryParams, + list[EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUseData], + ] +): + """Distillate Fuel Oil and Kerosene Sales by End Use fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUseQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUseQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUseQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUseQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUseData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUseData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/domestic_crude_oil_first_purchase_prices_by_api_gravity.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/domestic_crude_oil_first_purchase_prices_by_api_gravity.py new file mode 100644 index 00000000000..c76c2f60b99 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/domestic_crude_oil_first_purchase_prices_by_api_gravity.py @@ -0,0 +1,147 @@ +"""Domestic Crude Oil First Purchase Prices by API Gravity model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravityQueryParams( + EiaApiQueryParams +): + """Domestic Crude Oil First Purchase Prices by API Gravity. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/dfp3 + """ + + __group__ = "petroleum" + __dataset__ = "domestic_crude_oil_first_purchase_prices_by_api_gravity" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "crude_gravity_20_0_percent_or_less", + "crude_gravity_20_1_to_25_0_percent", + "crude_gravity_25_1_to_30_0_percent", + "crude_gravity_30_1_to_35_0_percent", + "crude_gravity_35_1_to_40_0_percent", + "crude_gravity_40_1_percent_or_more", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_domestic_crude_oil_first_purchase_prices_with_api_gravity_20_0_degrees_or_less_dollars_per_barrel", + "us_domestic_crude_oil_first_purchase_prices_with_api_gravity_20_1_to_25_0_degrees_dollars_per_barrel", + "us_domestic_crude_oil_first_purchase_prices_with_api_gravity_25_1_to_30_0_degrees_dollars_per_barrel", + "us_domestic_crude_oil_first_purchase_prices_with_api_gravity_30_1_to_35_0_degrees_dollars_per_barrel", + "us_domestic_crude_oil_first_purchase_prices_with_api_gravity_35_1_to_40_0_degrees_dollars_per_barrel", + "us_domestic_crude_oil_first_purchase_prices_with_api_gravity_40_1_degrees_or_more_dollars_per_barrel", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravityData(EiaApiData): + """Domestic Crude Oil First Purchase Prices by API Gravity. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravityFetcher( + Fetcher[ + EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravityQueryParams, + list[EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravityData], + ] +): + """Domestic Crude Oil First Purchase Prices by API Gravity fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravityQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravityData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravityData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/domestic_crude_oil_first_purchase_prices_by_area.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/domestic_crude_oil_first_purchase_prices_by_area.py new file mode 100644 index 00000000000..ecd1089f8b6 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/domestic_crude_oil_first_purchase_prices_by_area.py @@ -0,0 +1,209 @@ +"""Domestic Crude Oil First Purchase Prices by Area model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumDomesticCrudeOilFirstPurchasePricesByAreaQueryParams( + EiaApiQueryParams +): + """Domestic Crude Oil First Purchase Prices by Area. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/dfp1 + """ + + __group__ = "petroleum" + __dataset__ = "domestic_crude_oil_first_purchase_prices_by_area" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": ["ans_crude_oil", "crude_oil"], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "na", + "new_york", + "ohio", + "padd_1", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_sd", + "usa_ut", + "usa_wv", + "usa_wy", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alabama_crude_oil_first_purchase_price", + "alaska_north_slope_first_purchase_price", + "alaska_other_crude_oil_first_purchase_price", + "arkansas_crude_oil_first_purchase_price", + "california_crude_oil_first_purchase_price", + "colorado_crude_oil_first_purchase_price", + "east_coast_crude_oil_first_purchase_price", + "federal_offshore_california_crude_oil_first_purchase_price", + "federal_offshore_us_gulf_coast_crude_oil_first_purchase", + "gulf_coast_crude_oil_first_purchase_price", + "illinois_crude_oil_first_purchase_price", + "indiana_crude_oil_first_purchase_price", + "kansas_crude_oil_first_purchase_price", + "kentucky_crude_oil_first_purchase_price", + "louisiana_crude_oil_first_purchase_price", + "michigan_crude_oil_first_purchase_price", + "midwest_crude_oil_first_purchase_price", + "mississippi_crude_oil_first_purchase_price", + "montana_crude_oil_first_purchase_price", + "nebraska_crude_oil_first_purchase_price", + "new_mexico_crude_oil_first_purchase_price", + "new_york_crude_oil_first_purchase_price", + "north_dakota_crude_oil_first_purchase_price", + "ohio_crude_oil_first_purchase_price", + "oklahoma_crude_oil_first_purchase_price", + "pennsylvania_crude_oil_first_purchase_price", + "rocky_mountain_crude_oil_first_purchase_price", + "south_dakota_crude_oil_first_purchase_price", + "texas_crude_oil_first_purchase_price", + "us_crude_oil_first_purchase_price", + "us_less_alaskan_north_slope_crude_oil_first_purchase_price", + "utah_crude_oil_first_purchase_price", + "west_coast_crude_oil_first_purchase_price", + "west_virginia_crude_oil_first_purchase_price", + "wyoming_crude_oil_first_purchase_price", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumDomesticCrudeOilFirstPurchasePricesByAreaData(EiaApiData): + """Domestic Crude Oil First Purchase Prices by Area. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumDomesticCrudeOilFirstPurchasePricesByAreaFetcher( + Fetcher[ + EiaPetroleumDomesticCrudeOilFirstPurchasePricesByAreaQueryParams, + list[EiaPetroleumDomesticCrudeOilFirstPurchasePricesByAreaData], + ] +): + """Domestic Crude Oil First Purchase Prices by Area fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumDomesticCrudeOilFirstPurchasePricesByAreaQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumDomesticCrudeOilFirstPurchasePricesByAreaQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumDomesticCrudeOilFirstPurchasePricesByAreaQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumDomesticCrudeOilFirstPurchasePricesByAreaQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumDomesticCrudeOilFirstPurchasePricesByAreaData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumDomesticCrudeOilFirstPurchasePricesByAreaData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/downstream_charge_capacity_of_operable_petroleum_refineries.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/downstream_charge_capacity_of_operable_petroleum_refineries.py new file mode 100644 index 00000000000..be1e12a4b41 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/downstream_charge_capacity_of_operable_petroleum_refineries.py @@ -0,0 +1,220 @@ +"""Downstream Charge Capacity of Operable Petroleum Refineries model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineriesQueryParams( + EiaApiQueryParams +): + """Downstream Charge Capacity of Operable Petroleum Refineries. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/capchg + """ + + __group__ = "petroleum" + __dataset__ = "downstream_charge_capacity_of_operable_petroleum_refineries" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "catalytic_cracking_recycle", + "catalytic_hydrocracking", + "catalytic_hydrocracking_distillate", + "catalytic_hydrocracking_gas_oil", + "catalytic_hydrocracking_residual_fuel_oil", + "catalytic_reforming", + "catalytic_reforming_high_pressure", + "catalytic_reforming_low_pressure", + "downstream_charge_capacity_thermal_cracking_other_gas_oil", + "downstream_charge_capacity_thermal_cracking_visbreaking", + "downstream_charge_capacity_vacuum_distillation", + "fuels_solvent_deaspalting", + "refinery_catalytic_cracking_fresh_feed_downstream_charge", + "refinery_catalytic_hydrotreating_diesel_downstream_charge", + "refinery_catalytic_hydrotreating_distillate_downstream", + "refinery_catalytic_hydrotreating_heavy_gas_oil_downstream", + "refinery_catalytic_hydrotreating_kerosene_jet_fuel", + "refinery_catalytic_hydrotreating_naphtha_reformer_feed", + "refinery_catalytic_hydrotreating_other_distillate", + "refinery_catalytic_hydrotreating_other_oils_downstream", + "refinery_catalytic_hydrotreating_other_residual_fuel_oil", + "refinery_catalytic_hydrotreating_residual_fuel_oil", + "refinery_desulfurization_downstream_charge_capacity", + "refinery_desulfurization_gasoline_downstream_charge_capacity", + "refinery_thermal_cracking_downstream_charge_capacity", + "refinery_thermal_cracking_coking_downstream_charge_capacity", + "refinery_thermal_cracking_delayed_coking_downstream_charge", + "refinery_thermal_cracking_fluid_coking_downstream_charge", + ], + }, + "product": {"multiple_items_allowed": True}, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "gum", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "pri", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_de", + "usa_ga", + "usa_hi", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_tn", + "usa_ut", + "usa_va", + "usa_wi", + "usa_wv", + "usa_wy", + "vir", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineriesData(EiaApiData): + """Downstream Charge Capacity of Operable Petroleum Refineries. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineriesFetcher( + Fetcher[ + EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineriesQueryParams, + list[EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineriesData], + ] +): + """Downstream Charge Capacity of Operable Petroleum Refineries fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineriesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineriesQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineriesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineriesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineriesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineriesData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/downstream_processing_of_fresh_feed_input.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/downstream_processing_of_fresh_feed_input.py new file mode 100644 index 00000000000..15b259ae883 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/downstream_processing_of_fresh_feed_input.py @@ -0,0 +1,213 @@ +"""Downstream Processing of Fresh Feed Input model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumDownstreamProcessingOfFreshFeedInputQueryParams(EiaApiQueryParams): + """Downstream Processing of Fresh Feed Input. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/dwns + """ + + __group__ = "petroleum" + __dataset__ = "downstream_processing_of_fresh_feed_input" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "catalytic_reforming_downstream_capacity", + "downstream_catalytic_cracking", + "downstream_catalytic_hydrocracking", + "downstream_delayed_fluid_coking", + ], + }, + "product": {"multiple_items_allowed": True}, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "appalachian_no_1_refining_district_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "appalachian_no_1_refining_district_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "appalachian_no_1_refining_district_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "east_coast_pad_i_downstream_processing_of_fresh_feed_input_by_catalytic_reforming_units_thousand_barrels_per_day", + "east_coast_padd_1_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "east_coast_padd_1_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "east_coast_padd_1_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "east_coast_refining_district_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "east_coast_refining_district_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "east_coast_refining_district_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "gulf_coast_padd_3_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "gulf_coast_padd_3_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "gulf_coast_padd_3_downstream_processing_of_fresh_feed_input_by_catalytic_reforming_units_thousand_barrels_per_day", + "gulf_coast_padd_3_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "midwest_padd_2_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "midwest_padd_2_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "midwest_padd_2_downstream_processing_of_fresh_feed_input_by_catalytic_reforming_units_thousand_barrels_per_day", + "midwest_padd_2_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "ref_district_indiana_illinois_kentucky_downstream", + "ref_district_minnesota_wisconsin_n_and_s_dakota_downstream", + "refining_district_appalachian_no_1_downstream_processing_of", + "refining_district_east_coast_downstream_processing_of_fresh", + "refining_district_indiana_illinois_kentucky_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "refining_district_indiana_illinois_kentucky_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "refining_district_indiana_illinois_kentucky_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "refining_district_louisiana_gulf_coast_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "refining_district_louisiana_gulf_coast_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "refining_district_louisiana_gulf_coast_downstream_processing_of_fresh_feed_input_by_catalytic_reforming_units_thousand_barrels_per_day", + "refining_district_louisiana_gulf_coast_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "refining_district_minnesota_wisconsin_n_and_s_dakota_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "refining_district_minnesota_wisconsin_n_and_s_dakota_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "refining_district_minnesota_wisconsin_n_and_s_dakota_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "refining_district_new_mexico_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "refining_district_new_mexico_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "refining_district_new_mexico_downstream_processing_of_fresh_feed_input_by_catalytic_reforming_units_thousand_barrels_per_day", + "refining_district_new_mexico_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "refining_district_north_louisiana_arkansas_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "refining_district_north_louisiana_arkansas_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "refining_district_north_louisiana_arkansas_downstream_processing_of_fresh_feed_input_by_catalytic_reforming_units_thousand_barrels_per_day", + "refining_district_north_louisiana_arkansas_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "refining_district_oklahoma_kansas_missouri_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "refining_district_oklahoma_kansas_missouri_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "refining_district_oklahoma_kansas_missouri_downstream_processing_of_fresh_feed_input_by_catalytic_reforming_units_thousand_barrels_per_day", + "refining_district_oklahoma_kansas_missouri_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "refining_district_texas_gulf_coast_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "refining_district_texas_gulf_coast_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "refining_district_texas_gulf_coast_downstream_processing_of_fresh_feed_input_by_catalytic_reforming_units_thousand_barrels_per_day", + "refining_district_texas_gulf_coast_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "refining_district_texas_inland_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "refining_district_texas_inland_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "refining_district_texas_inland_downstream_processing_of_fresh_feed_input_by_catalytic_reforming_units_thousand_barrels_per_day", + "refining_district_texas_inland_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "rocky_mountain", + "rocky_mountain_padd_4_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "rocky_mountain_padd_4_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "rocky_mountain_padd_4_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "us_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "us_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "us_downstream_processing_of_fresh_feed_input_by_catalytic_reforming_units_thousand_barrels_per_day", + "us_downstream_processing_of_fresh_feed_input_by_delayed_and", + "west_coast_padd_5_downstream_processing_of_fresh_feed_input_by_catalytic_cracking_units_thousand_barrels_per_day", + "west_coast_padd_5_downstream_processing_of_fresh_feed_input_by_catalytic_hydrocracking_units_thousand_barrels_per_day", + "west_coast_padd_5_downstream_processing_of_fresh_feed_input_by_catalytic_reforming_units_thousand_barrels_per_day", + "west_coast_padd_5_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumDownstreamProcessingOfFreshFeedInputData(EiaApiData): + """Downstream Processing of Fresh Feed Input. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumDownstreamProcessingOfFreshFeedInputFetcher( + Fetcher[ + EiaPetroleumDownstreamProcessingOfFreshFeedInputQueryParams, + list[EiaPetroleumDownstreamProcessingOfFreshFeedInputData], + ] +): + """Downstream Processing of Fresh Feed Input fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumDownstreamProcessingOfFreshFeedInputQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumDownstreamProcessingOfFreshFeedInputQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumDownstreamProcessingOfFreshFeedInputQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumDownstreamProcessingOfFreshFeedInputQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumDownstreamProcessingOfFreshFeedInputData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumDownstreamProcessingOfFreshFeedInputData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/exports.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/exports.py new file mode 100644 index 00000000000..10534c0f94e --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/exports.py @@ -0,0 +1,179 @@ +"""Exports model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumExportsQueryParams(EiaApiQueryParams): + """Exports. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/exp + """ + + __group__ = "petroleum" + __dataset__ = "exports" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "aviation_gasoline_blending_components", + "biodiesel", + "biofuel_fuels", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "ethane", + "ethane_ethylene", + "finished_motor_gasoline", + "finished_petroleum_products", + "fuel_ethanol", + "gasoline_blending_components", + "hydrogen_oxygenates_renewables_fuels_and_other_hydrocarbons", + "isobutane", + "isobutane_isobutylene", + "kerosene", + "kerosene_and_light_oils", + "kerosene_type_jet_fuel", + "liquified_petroleum_gases", + "lubricants", + "mtbe", + "miscellaneous_petroleum_products", + "naphtha_for_petrochemical_feedstock_use", + "naphthas_and_lighter", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "normal_butane_butylene", + "other_biofuels", + "other_liquids", + "other_oils_for_petrochemical_feedstock_use", + "other_oxygenates", + "oxygenates", + "pentanes_plus", + "petroleum_coke", + "propane", + "propane_and_propylene", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "renewable_diesel_fuel", + "residual_fuel_oil", + "special_naphthas", + "unfinished_oils", + "waxes", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 612 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumExportsData(EiaApiData): + """Exports. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumExportsFetcher( + Fetcher[EiaPetroleumExportsQueryParams, list[EiaPetroleumExportsData]] +): + """Exports fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaPetroleumExportsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaPetroleumExportsQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaPetroleumExportsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumExportsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumExportsData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumExportsData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/exports_by_destination.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/exports_by_destination.py new file mode 100644 index 00000000000..ad9d530c24b --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/exports_by_destination.py @@ -0,0 +1,173 @@ +"""Exports by Destination model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumExportsByDestinationQueryParams(EiaApiQueryParams): + """Exports by Destination. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/expc + """ + + __group__ = "petroleum" + __dataset__ = "exports_by_destination" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "aviation_gasoline_blending_components", + "biodiesel", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_to_2000_ppm_sulfur", + "ethane", + "finished_motor_gasoline", + "fuel_ethanol", + "gasoline_blending_components", + "isobutane", + "kerosene", + "kerosene_type_jet_fuel", + "liquified_petroleum_gases", + "lubricants", + "mtbe", + "miscellaneous_petroleum_products", + "naphtha_for_petrochemical_feedstock_use", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "other_biofuels", + "other_oils_for_petrochemical_feedstock_use", + "other_oxygenates", + "pentanes_plus", + "petroleum_coke", + "propane", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "renewable_diesel_fuel", + "residual_fuel_oil", + "special_naphthas", + "total_petroleum_products", + "unfinished_oils", + "waxes", + ], + }, + "region": {"multiple_items_allowed": True}, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values. There are 216 valid values - use the `facet_options` endpoint to list them.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumExportsByDestinationData(EiaApiData): + """Exports by Destination. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumExportsByDestinationFetcher( + Fetcher[ + EiaPetroleumExportsByDestinationQueryParams, + list[EiaPetroleumExportsByDestinationData], + ] +): + """Exports by Destination fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumExportsByDestinationQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumExportsByDestinationQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumExportsByDestinationQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumExportsByDestinationQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumExportsByDestinationData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumExportsByDestinationData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/feedstocks_consumed_for_production_of_biofuels.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/feedstocks_consumed_for_production_of_biofuels.py new file mode 100644 index 00000000000..cb95de88085 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/feedstocks_consumed_for_production_of_biofuels.py @@ -0,0 +1,182 @@ +"""Feedstocks Consumed for Production of Biofuels model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumFeedstocksConsumedForProductionOfBiofuelsQueryParams( + EiaApiQueryParams +): + """Feedstocks Consumed for Production of Biofuels. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/feedbiofuel + """ + + __group__ = "petroleum" + __dataset__ = "feedstocks_consumed_for_production_of_biofuels" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "agriculture_and_forestry_residues", + "algae_inputs_to_biodiesel_production", + "biogas", + "canola_oil_inputs_to_biodiesel_production", + "canola_oil_for_biodiesel_plants", + "canola_oil_for_renewable_diesels_plants", + "corn", + "corn_oil_inputs_to_biodiesel_production", + "corn_oil_for_biodiesel_plants", + "corn_oil_for_renewable_diesel_plants", + "dedicated_energy_crops", + "grain_sorghum", + "municipal_solid_waste", + "other_biofuel_feedstocks", + "other_agriculture_and_forestry_products", + "other_animal_fats_inputs_to_biodiesel_production", + "other_recycled_feeds", + "other_vegetable_oil_inputs_to_biodiesel_production", + "poultry_inputs_to_biodiesel_production", + "soybean_oil_inputs_to_biodiesel_production", + "soybean_oill_biodiesel_plants", + "soybean_oill_renewable_diesel_plants", + "tallow_inputs_to_biodiesel_production", + "white_grease_inputs_to_biodiesel_production", + "yard_and_food_waste", + "yellow_grease_inputs_to_biodiesel_production", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "agriculture_and_forestry_residues_inputs_to_biofuels", + "biogas_inputs_to_biofuels_production", + "canola_oil_inputs_to_biofuels_production_at_biodiesel_plants", + "canola_oil_inputs_to_biofuels_production_at_renewable", + "corn_inputs_to_biofuels_production", + "corn_oil_inputs_to_biofuels_production_at_biodiesel_plants", + "corn_oil_inputs_to_biofuels_production_at_renewable_diesel", + "dedicated_energy_crops_inputs_to_biofuels_production", + "grain_sorghum_inputs_to_biofuels_production", + "municipal_solid_waste_inputs_to_biofules_production", + "oil_from_algae_inputs_to_biofuels_production", + "other_biofuel_feedstocks_inputs_to_biofuels_production", + "other_recycled_feed_inputs_to_biofuels_production", + "other_vegetable_oil_inputs_to_biofuels_production", + "other_waste_oil_fat_and_grease_inputs_to_biofuels_production", + "other_agriculture_and_forestry_products_inputs_to_biofuels", + "poultry_inputs_to_biofuels_production", + "soybean_oil_inputs_to_biofuels_production_at_biodiesel", + "soybean_oil_inputs_to_biofuels_production_at_renewable", + "tallow_inputs_to_biofuels_production", + "total_canola_oil_inputs_to_biofuels_production", + "total_corn_oil_inputs_to_biofuels_production", + "total_soybean_oil_inputs_to_biofuels_production", + "white_grease_inputs_to_biofuels_production", + "yard_and_food_waste_inputs_to_biofuels_production", + "yellow_grease_inputs_to_biofuels_production", + ], + }, + } + + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumFeedstocksConsumedForProductionOfBiofuelsData(EiaApiData): + """Feedstocks Consumed for Production of Biofuels. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumFeedstocksConsumedForProductionOfBiofuelsFetcher( + Fetcher[ + EiaPetroleumFeedstocksConsumedForProductionOfBiofuelsQueryParams, + list[EiaPetroleumFeedstocksConsumedForProductionOfBiofuelsData], + ] +): + """Feedstocks Consumed for Production of Biofuels fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumFeedstocksConsumedForProductionOfBiofuelsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumFeedstocksConsumedForProductionOfBiofuelsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumFeedstocksConsumedForProductionOfBiofuelsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumFeedstocksConsumedForProductionOfBiofuelsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumFeedstocksConsumedForProductionOfBiofuelsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumFeedstocksConsumedForProductionOfBiofuelsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fob_costs_of_imported_crude_oil_by_api_gravity.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fob_costs_of_imported_crude_oil_by_api_gravity.py new file mode 100644 index 00000000000..77579025dae --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fob_costs_of_imported_crude_oil_by_api_gravity.py @@ -0,0 +1,146 @@ +"""FOB Costs of Imported Crude Oil by API Gravity model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumFobCostsOfImportedCrudeOilByApiGravityQueryParams(EiaApiQueryParams): + """FOB Costs of Imported Crude Oil by API Gravity. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/imc3 + """ + + __group__ = "petroleum" + __dataset__ = "fob_costs_of_imported_crude_oil_by_api_gravity" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "crude_gravity_20_0_percent_or_less", + "crude_gravity_20_1_to_25_0_percent", + "crude_gravity_25_1_to_30_0_percent", + "crude_gravity_30_1_to_35_0_percent", + "crude_gravity_35_1_to_40_0_percent", + "crude_gravity_40_1_to_45_0_percent", + "crude_gravity_45_1_percent_or_more", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_fob_costs_of_crude_with_api_gravity_20_0_degrees_or_less", + "us_fob_costs_of_crude_with_api_gravity_20_1_to_25_0_degrees", + "us_fob_costs_of_crude_with_api_gravity_25_1_to_30_0_degrees", + "us_fob_costs_of_crude_with_api_gravity_30_1_to_35_0_degrees", + "us_fob_costs_of_crude_with_api_gravity_35_1_to_40_0_degrees", + "us_fob_costs_of_crude_with_api_gravity_40_1_to_45_0_degrees", + "us_fob_costs_of_crude_with_api_gravity_45_1_degrees_or_more", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumFobCostsOfImportedCrudeOilByApiGravityData(EiaApiData): + """FOB Costs of Imported Crude Oil by API Gravity. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumFobCostsOfImportedCrudeOilByApiGravityFetcher( + Fetcher[ + EiaPetroleumFobCostsOfImportedCrudeOilByApiGravityQueryParams, + list[EiaPetroleumFobCostsOfImportedCrudeOilByApiGravityData], + ] +): + """FOB Costs of Imported Crude Oil by API Gravity fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumFobCostsOfImportedCrudeOilByApiGravityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumFobCostsOfImportedCrudeOilByApiGravityQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumFobCostsOfImportedCrudeOilByApiGravityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumFobCostsOfImportedCrudeOilByApiGravityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumFobCostsOfImportedCrudeOilByApiGravityData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumFobCostsOfImportedCrudeOilByApiGravityData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fob_costs_of_imported_crude_oil_by_area.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fob_costs_of_imported_crude_oil_by_area.py new file mode 100644 index 00000000000..48f4c77e7d7 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fob_costs_of_imported_crude_oil_by_area.py @@ -0,0 +1,142 @@ +"""FOB Costs of Imported Crude Oil by Area model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumFobCostsOfImportedCrudeOilByAreaQueryParams(EiaApiQueryParams): + """FOB Costs of Imported Crude Oil by Area. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/imc1 + """ + + __group__ = "petroleum" + __dataset__ = "fob_costs_of_imported_crude_oil_by_area" + __json_schema_extra__ = { + "region": { + "multiple_items_allowed": True, + "choices": ["ago", "col", "gbr", "mex", "na", "nga", "sau", "ven"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_fob_costs_of_angola_crude_oil", + "us_fob_costs_of_colombia_crude_oil", + "us_fob_costs_of_crude_oil", + "us_fob_costs_of_mexico_crude_oil", + "us_fob_costs_of_nigeria_crude_oil", + "us_fob_costs_of_non_opec_countries_crude_oil", + "us_fob_costs_of_opec_countries_crude_oil", + "us_fob_costs_of_persian_gulf_countries_crude_oil", + "us_fob_costs_of_saudi_arabia_crude_oil", + "us_fob_costs_of_united_kingdom_crude_oil", + "us_fob_costs_of_venezuela_crude_oil", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumFobCostsOfImportedCrudeOilByAreaData(EiaApiData): + """FOB Costs of Imported Crude Oil by Area. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumFobCostsOfImportedCrudeOilByAreaFetcher( + Fetcher[ + EiaPetroleumFobCostsOfImportedCrudeOilByAreaQueryParams, + list[EiaPetroleumFobCostsOfImportedCrudeOilByAreaData], + ] +): + """FOB Costs of Imported Crude Oil by Area fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumFobCostsOfImportedCrudeOilByAreaQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumFobCostsOfImportedCrudeOilByAreaQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumFobCostsOfImportedCrudeOilByAreaQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumFobCostsOfImportedCrudeOilByAreaQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumFobCostsOfImportedCrudeOilByAreaData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumFobCostsOfImportedCrudeOilByAreaData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fob_costs_of_imported_crude_oil_for_selected_crude_streams.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fob_costs_of_imported_crude_oil_for_selected_crude_streams.py new file mode 100644 index 00000000000..8b47b0226b7 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fob_costs_of_imported_crude_oil_for_selected_crude_streams.py @@ -0,0 +1,173 @@ +"""FOB Costs of Imported Crude Oil for Selected Crude Streams model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreamsQueryParams( + EiaApiQueryParams +): + """FOB Costs of Imported Crude Oil for Selected Crude Streams. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/imc2 + """ + + __group__ = "petroleum" + __dataset__ = "fob_costs_of_imported_crude_oil_for_selected_crude_streams" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "angolan_cabinda_crude_oil", + "canadian_bow_river_heavy_crude_oil", + "canadian_lloydminster_crude_oil", + "canadian_light_sour_blend_crude_oil", + "ecuadorian_oriente_crude_oil", + "gabon_rabi_kouanga_crude_oil", + "iraqi_basrah_light_crude_oil", + "mexican_mayan_crude_oil", + "mexican_olmeca_crude_oil", + "nigerian_forcados_blend_crude_oil", + "nigerian_qua_iboe", + "venezuelan_furial_crude_oil", + "venezuelan_leona_crude_oil", + "venezuelan_merey", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["ago", "can", "ecu", "gab", "irq", "mex", "nga", "ven"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_fob_costs_of_angolan_cabinda_crude_oil", + "us_fob_costs_of_canadian_bow_river_heavy_crude_oil", + "us_fob_costs_of_canadian_lloydminster_crude_oil", + "us_fob_costs_of_canadian_light_sour_blend_crude_oil", + "us_fob_costs_of_ecuadorian_oriente_crude_oil", + "us_fob_costs_of_gabon_rabi_kouanga_crude_oil", + "us_fob_costs_of_iraqi_basrah_light_crude_oil", + "us_fob_costs_of_mexican_mayan_crude_oil", + "us_fob_costs_of_mexican_olmeca_crude_oil", + "us_fob_costs_of_nigerian_forcados_blend_crude_oil", + "us_fob_costs_of_nigerian_qua_iboe_crude_oil", + "us_fob_costs_of_venezuelan_furrial_crude_oil", + "us_fob_costs_of_venezuelan_leona_crude_oil", + "us_fob_costs_of_venezuelan_merey_crude_oil", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreamsData(EiaApiData): + """FOB Costs of Imported Crude Oil for Selected Crude Streams. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreamsFetcher( + Fetcher[ + EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreamsQueryParams, + list[EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreamsData], + ] +): + """FOB Costs of Imported Crude Oil for Selected Crude Streams fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreamsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreamsQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreamsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreamsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreamsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreamsData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/footage_drilled_for_crude_oil_and_natural_gas_wells.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/footage_drilled_for_crude_oil_and_natural_gas_wells.py new file mode 100644 index 00000000000..c4387e8c2c7 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/footage_drilled_for_crude_oil_and_natural_gas_wells.py @@ -0,0 +1,153 @@ +"""Footage Drilled for Crude Oil and Natural Gas Wells model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWellsQueryParams( + EiaApiQueryParams +): + """Footage Drilled for Crude Oil and Natural Gas Wells. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/crd/wellfoot + """ + + __group__ = "petroleum" + __dataset__ = "footage_drilled_for_crude_oil_and_natural_gas_wells" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "footage_drilled_for_developmental_wells", + "footage_drilled_for_exploratory_wells", + "footage_drilled_for_exploratory_and_developmental_wells", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": ["wells_dry", "wells_gas", "wells_oil", "wells_total"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_footage_drilled_for_crude_oil_developmental_wells", + "us_footage_drilled_for_crude_oil_exploratory_wells", + "us_footage_drilled_for_crude_oil_exploratory_and", + "us_footage_drilled_for_crude_oil_natural_gas_and_dry_developmental_wells_thousand_feet", + "us_footage_drilled_for_crude_oil_natural_gas_and_dry_exploratory_wells_thousand_feet", + "us_footage_drilled_for_crude_oil_natural_gas_and_dry_exploratory_and_developmental_wells_thousand_feet", + "us_footage_drilled_for_dry_developmental_wells", + "us_footage_drilled_for_dry_exploratory_wells", + "us_footage_drilled_for_dry_exploratory_and_developmental", + "us_footage_drilled_for_natural_gas_developmental_wells", + "us_footage_drilled_for_natural_gas_exploratory_wells", + "us_footage_drilled_for_natural_gas_exploratory_and", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWellsData(EiaApiData): + """Footage Drilled for Crude Oil and Natural Gas Wells. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWellsFetcher( + Fetcher[ + EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWellsQueryParams, + list[EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWellsData], + ] +): + """Footage Drilled for Crude Oil and Natural Gas Wells fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWellsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWellsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWellsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWellsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWellsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWellsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fuel_consumed_at_biofuels_plants.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fuel_consumed_at_biofuels_plants.py new file mode 100644 index 00000000000..90210e69e26 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fuel_consumed_at_biofuels_plants.py @@ -0,0 +1,151 @@ +"""Fuel Consumed at Biofuels Plants model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumFuelConsumedAtBiofuelsPlantsQueryParams(EiaApiQueryParams): + """Fuel Consumed at Biofuels Plants. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/bioplfuel + """ + + __group__ = "petroleum" + __dataset__ = "fuel_consumed_at_biofuels_plants" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "biogas_consumed_at_biofuels_plants", + "coal_consumed_at_biofuels_plants", + "liquefied_petroleum_gases_consumed_at_biofuels_plants", + "natural_gas_consumed_at_biofuels_plants", + "natural_gas_for_hydrogen_feedstock_at_biofuels_plants", + "other_fuels_including_renewable_fuels_at_biofuels_plants", + "purchased_electricity_consumed_at_biofuels_plants", + "purchased_hydrogen_at_biofuels_plants", + "purchased_steam_consumed_at_biofuels_plants", + ], + }, + "product": {"multiple_items_allowed": True}, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_biogas_consumed_at_biofuels_plants", + "us_coal_consumed_at_biofuels_plants", + "us_liquefied_petroleum_gases_consumed_at_biofuels_plants", + "us_natural_gas_consumed_at_biofuels_plants", + "us_natural_gas_for_hydrogen_feedstock_at_biofuels_plants", + "us_other_fuels_including_renewable_fuels_at_biofuels_plants", + "us_purchased_electricity_consumed_at_biofuels_plants", + "us_purchased_hydrogen_at_biofuels_plants", + "us_purchased_steam_consumed_at_biofuels_plants", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumFuelConsumedAtBiofuelsPlantsData(EiaApiData): + """Fuel Consumed at Biofuels Plants. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumFuelConsumedAtBiofuelsPlantsFetcher( + Fetcher[ + EiaPetroleumFuelConsumedAtBiofuelsPlantsQueryParams, + list[EiaPetroleumFuelConsumedAtBiofuelsPlantsData], + ] +): + """Fuel Consumed at Biofuels Plants fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumFuelConsumedAtBiofuelsPlantsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumFuelConsumedAtBiofuelsPlantsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumFuelConsumedAtBiofuelsPlantsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumFuelConsumedAtBiofuelsPlantsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumFuelConsumedAtBiofuelsPlantsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumFuelConsumedAtBiofuelsPlantsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fuel_consumed_at_refineries.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fuel_consumed_at_refineries.py new file mode 100644 index 00000000000..5e24659f066 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/fuel_consumed_at_refineries.py @@ -0,0 +1,232 @@ +"""Fuel Consumed at Refineries model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumFuelConsumedAtRefineriesQueryParams(EiaApiQueryParams): + """Fuel Consumed at Refineries. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/capfuel + """ + + __group__ = "petroleum" + __dataset__ = "fuel_consumed_at_refineries" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "catalyst_petroleum_coke_consumed_at_refineries", + "coal_consumed_at_refineries", + "consumed_at_refineries", + "crude_oil_consumed_at_refineries", + "distillate_consumed_at_refineries", + "lpg_s_consumed_at_refineries", + "marketable_petroleum_coke_consumed_at_refineries", + "other_products_consumed_at_refineries", + "petroleum_coke_consumed_at_refineries", + "purchased_electricity_consumed_at_refineries", + "purchased_steam_consumed_at_refineries", + "residual_fuel_oil_consumed_at_refineries", + "still_gas_consumed_at_refineries", + ], + }, + "product": {"multiple_items_allowed": True}, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "east_coast_catalyst_petroleum_coke_consumed_at_refineries", + "east_coast_coal_consumed_at_refineries", + "east_coast_crude_oil_consumed_at_refineries", + "east_coast_distillate_consumed_at_refineries", + "east_coast_hgl_s_consumed_at_refineries", + "east_coast_marketable_petroleum_coke_consumed_at_refineries", + "east_coast_natural_gas_consumed_at_refineries", + "east_coast_other_products_consumed_at_refineries", + "east_coast_petroleum_coke_consumed_at_refineries", + "east_coast_purchased_electricity_consumed_at_refineries", + "east_coast_purchased_steam_consumed_at_refineries", + "east_coast_residual_fuel_oil_consumed_at_refineries", + "east_coast_still_gas_consumed_at_refineries", + "gulf_coast_catalyst_petroleum_coke_consumed_at_refineries", + "gulf_coast_coal_consumed_at_refineries", + "gulf_coast_crude_oil_consumed_at_refineries", + "gulf_coast_distillate_consumed_at_refineries", + "gulf_coast_hgl_s_consumed_at_refineries", + "gulf_coast_marketable_petroleum_coke_consumed_at_refineries", + "gulf_coast_natural_gas_consumed_at_refineries", + "gulf_coast_other_products_consumed_at_refineries", + "gulf_coast_petroleum_coke_consumed_at_refineries", + "gulf_coast_purchased_electricity_consumed_at_refineries", + "gulf_coast_purchased_steam_consumed_at_refineries", + "gulf_coast_residual_fuel_oil_consumed_at_refineries", + "gulf_coast_still_gas_consumed_at_refineries", + "midwest_catalyst_petroleum_coke_consumed_at_refineries", + "midwest_coal_consumed_at_refineries", + "midwest_crude_oil_consumed_at_refineries", + "midwest_distillate_consumed_at_refineries", + "midwest_hgl_s_consumed_at_refineries", + "midwest_marketable_petroleum_coke_consumed_at_refineries", + "midwest_natural_gas_consumed_at_refineries", + "midwest_other_products_consumed_at_refineries", + "midwest_petroleum_coke_consumed_at_refineries", + "midwest_purchased_electricity_consumed_at_refineries", + "midwest_purchased_steam_consumed_at_refineries", + "midwest_residual_fuel_oil_consumed_at_refineries", + "midwest_still_gas_consumed_at_refineries", + "rocky_mountain_catalyst_petroleum_coke_consumed_at", + "rocky_mountain_coal_consumed_at_refineries", + "rocky_mountain_crude_oil_consumed_at_refineries", + "rocky_mountain_distillate_consumed_at_refineries", + "rocky_mountain_hgl_s_consumed_at_refineries", + "rocky_mountain_marketable_petroleum_coke_consumed_at", + "rocky_mountain_natural_gas_consumed_at_refineries", + "rocky_mountain_other_products_consumed_at_refineries", + "rocky_mountain_petroleum_coke_consumed_at_refineries", + "rocky_mountain_purchased_electricity_consumed_at_refineries", + "rocky_mountain_purchased_steam_consumed_at_refineries", + "rocky_mountain_residual_fuel_oil_consumed_at_refineries", + "rocky_mountain_still_gas_consumed_at_refineries", + "us_catalyst_petroleum_coke_consumed_at_refineries", + "us_coal_consumed_at_refineries", + "us_crude_oil_consumed_at_refineries", + "us_distillate_consumed_at_refineries", + "us_hgl_s_consumed_at_refineries", + "us_marketable_petroleum_coke_consumed_at_refineries", + "us_natural_gas_consumed_at_refineries", + "us_other_products_consumed_at_refineries", + "us_petroleum_coke_consumed_at_refineries", + "us_purchased_electricity_consumed_at_refineries", + "us_purchased_steam_consumed_at_refineries", + "us_residual_fuel_oil_consumed_at_refineries", + "us_still_gas_consumed_at_refineries", + "west_coast_catalyst_petroleum_coke_consumed_at_refineries", + "west_coast_coal_consumed_at_refineries", + "west_coast_crude_oil_consumed_at_refineries", + "west_coast_distillate_consumed_at_refineries", + "west_coast_hgl_s_consumed_at_refineries", + "west_coast_marketable_petroleum_coke_consumed_at_refineries", + "west_coast_natural_gas_consumed_at_refineries", + "west_coast_other_products_consumed_at_refineries", + "west_coast_petroleum_coke_consumed_at_refineries", + "west_coast_purchased_electricity_consumed_at_refineries", + "west_coast_purchased_steam_consumed_at_refineries", + "west_coast_residual_fuel_oil_consumed_at_refineries", + "west_coast_still_gas_consumed_at_refineries", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumFuelConsumedAtRefineriesData(EiaApiData): + """Fuel Consumed at Refineries. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumFuelConsumedAtRefineriesFetcher( + Fetcher[ + EiaPetroleumFuelConsumedAtRefineriesQueryParams, + list[EiaPetroleumFuelConsumedAtRefineriesData], + ] +): + """Fuel Consumed at Refineries fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumFuelConsumedAtRefineriesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumFuelConsumedAtRefineriesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumFuelConsumedAtRefineriesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumFuelConsumedAtRefineriesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumFuelConsumedAtRefineriesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumFuelConsumedAtRefineriesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/gasoline_prices_by_formulation_grade_sales_type.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/gasoline_prices_by_formulation_grade_sales_type.py new file mode 100644 index 00000000000..c29504feaed --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/gasoline_prices_by_formulation_grade_sales_type.py @@ -0,0 +1,230 @@ +"""Gasoline Prices by Formulation, Grade, Sales Type model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumGasolinePricesByFormulationGradeSalesTypeQueryParams( + EiaApiQueryParams +): + """Gasoline Prices by Formulation, Grade, Sales Type. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/allmg + """ + + __group__ = "petroleum" + __dataset__ = "gasoline_prices_by_formulation_grade_sales_type" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "bulk_sales", + "dtw_sales_price", + "rack_sales_price_by_all_sellers", + "retail_sales_by_all_sellers", + "through_company_outlets_price", + "wholesale_resale_price_by_all_sellers", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "conventional_gasoline", + "conventional_premium_gasoline", + "conventional_regular_gasoline", + "gasoline_conventional_midgrade", + "gasoline_oxygenated_midgrade", + "gasoline_reformulated_midgrade", + "midgrade_gasoline", + "oxygenated_gasoline", + "oxygenated_premium_gasoline", + "oxygenated_regular_gasoline", + "premium_gasoline", + "reformulated_motor_gasoline", + "reformulated_premium_gasoline", + "reformulated_regular_gasoline", + "regular_gasoline", + "total_gasoline", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumGasolinePricesByFormulationGradeSalesTypeData(EiaApiData): + """Gasoline Prices by Formulation, Grade, Sales Type. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumGasolinePricesByFormulationGradeSalesTypeFetcher( + Fetcher[ + EiaPetroleumGasolinePricesByFormulationGradeSalesTypeQueryParams, + list[EiaPetroleumGasolinePricesByFormulationGradeSalesTypeData], + ] +): + """Gasoline Prices by Formulation, Grade, Sales Type fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumGasolinePricesByFormulationGradeSalesTypeQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumGasolinePricesByFormulationGradeSalesTypeQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumGasolinePricesByFormulationGradeSalesTypeQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumGasolinePricesByFormulationGradeSalesTypeQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumGasolinePricesByFormulationGradeSalesTypeData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumGasolinePricesByFormulationGradeSalesTypeData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/gulf_of_america_federal_offshore_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/gulf_of_america_federal_offshore_production.py new file mode 100644 index 00000000000..8aa926a6e97 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/gulf_of_america_federal_offshore_production.py @@ -0,0 +1,176 @@ +"""Gulf of America Federal Offshore Production model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumGulfOfAmericaFederalOffshoreProductionQueryParams(EiaApiQueryParams): + """Gulf of America Federal Offshore Production. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/crd/gom + """ + + __group__ = "petroleum" + __dataset__ = "gulf_of_america_federal_offshore_production" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "dry_production_from_reserves", + "dry_reserves_based_production_deepwater_percentage", + "dry_reserves_based_production_from_greater_than_200_meters", + "dry_reserves_based_production_from_less_than_200_meters", + "lease_condensate_reserves_based_production", + "lease_condensate_reserves_based_production_deepwater", + "lease_condensate_reserves_based_production_from_greater", + "lease_condensate_reserves_based_production_from_less_than", + "production_from_reserves", + "reserves_based_production_deepwater_percentage", + "reserves_based_production_from_greater_than_200_meters", + "reserves_based_production_from_less_than_200_meters", + "wet_after_lease_separation_reserves_based_production", + "wet_after_lease_separation_reserves_based_production_from_greater_than_200_meters", + "wet_after_lease_separation_reserves_based_production_from_less_than_200_meters", + "wet_after_lease_separation_reserves_based_production_from_reserves", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "crude_oil", + "natural_gas", + "natural_gas_liquids_and_liquid_refinery_gases", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "gulf_of_america_federal_offshore_crude_oil_production", + "gulf_of_america_federal_offshore_crude_oil_production_from_greater_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_crude_oil_production_from_less_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_dry_natural_gas_production_billion_cubic_feet", + "gulf_of_america_federal_offshore_dry_natural_gas_production_from_greater_than_200_meters_deep_billion_cubic_feet", + "gulf_of_america_federal_offshore_dry_natural_gas_production_from_less_than_200_meters_deep_billion_cubic_feet", + "gulf_of_america_federal_offshore_natural_gas_liquids_lease_condensate_production_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_lease_condensate_production_from_greater_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_lease_condensate_production_from_less_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_production_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_production_from_greater_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_liquids_production_from_less_than_200_meters_deep_million_barrels", + "gulf_of_america_federal_offshore_natural_gas_wet_after_lease_separation_production_billion_cubic_feet", + "gulf_of_america_federal_offshore_natural_gas_wet_after_lease_separation_production_from_greater_than_200_meters_deep_billion_cubic_feet", + "gulf_of_america_federal_offshore_natural_gas_wet_after_lease_separation_production_from_less_than_200_meters_deep_billion_cubic_feet", + "gulf_of_america_federal_offshore_percentage_of_crude_oil", + "gulf_of_america_federal_offshore_percentage_of_dry_natural", + "gulf_of_america_federal_offshore_percentage_of_natural_gas_liquids_lease_condensate_production_from_greater_than_200_meters_deep", + "gulf_of_america_federal_offshore_percentage_of_natural_gas_liquids_production_from_greater_than_200_meters_deep", + "gulf_of_america_federal_offshore_percentage_of_natural_gas_wet_after_lease_separation_production_from_greater_than_200_meters_deep", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumGulfOfAmericaFederalOffshoreProductionData(EiaApiData): + """Gulf of America Federal Offshore Production. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumGulfOfAmericaFederalOffshoreProductionFetcher( + Fetcher[ + EiaPetroleumGulfOfAmericaFederalOffshoreProductionQueryParams, + list[EiaPetroleumGulfOfAmericaFederalOffshoreProductionData], + ] +): + """Gulf of America Federal Offshore Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumGulfOfAmericaFederalOffshoreProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumGulfOfAmericaFederalOffshoreProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumGulfOfAmericaFederalOffshoreProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumGulfOfAmericaFederalOffshoreProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumGulfOfAmericaFederalOffshoreProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumGulfOfAmericaFederalOffshoreProductionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/imports_by_area_of_entry.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/imports_by_area_of_entry.py new file mode 100644 index 00000000000..0b79c1278c0 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/imports_by_area_of_entry.py @@ -0,0 +1,214 @@ +"""Imports by Area of Entry model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumImportsByAreaOfEntryQueryParams(EiaApiQueryParams): + """Imports by Area of Entry. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/imp + """ + + __group__ = "petroleum" + __dataset__ = "imports_by_area_of_entry" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "aviation_gasoline_blending_components", + "biodiesel", + "biofuel_fuels", + "conventional_cbob_gasoline_blending_components", + "conventional_gtab_gasoline_blending_components", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "conventional_other_gasoline_blending_components", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_0_to_15_ppm_sulfur_bonded", + "distillate_fuel_oil_0_to_15_ppm_sulfur_not_bonded", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur_bonded", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur_not", + "distillate_fuel_oil_greater_than_2000_ppm_sulfur", + "distillate_fuel_oil_greater_than_2000_ppm_sulfur_bonded", + "distillate_fuel_oil_greater_than_2000_ppm_sulfur_not_bonded", + "distillate_fuel_oil_greater_than_500_to_2000_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_to_2000_ppm_sulfur_bonded", + "distillate_fuel_oil_greater_than_500_to_2000_ppm_sulfur_not", + "ethane", + "ethylene", + "finished_motor_gasoline", + "finished_motor_gasoline_reformulated_other", + "finished_petroleum_products", + "fuel_ethanol", + "gasoline_blending_components", + "heavy_gas_oils", + "hydrogen_oxygenates_renewables_fuels_and_other_hydrocarbons", + "isobutane", + "isobutylene", + "kerosene", + "kerosene_and_light_oils", + "kerosene_type_jet_fuel", + "kerosene_type_jet_fuel_bonded", + "liquified_petroleum_gases", + "lubricants", + "mtbe", + "miscellaneous_petroleum_products", + "motor_gasoline_blending_components_reformulated_rbob", + "motor_gasoline_finished_conventional_ed55_and_lower", + "naphtha_for_petrochemical_feedstock_use", + "naphthas_and_lighter", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "normal_butylene", + "other_biofuels", + "other_conventional_motor_gasoline", + "other_hydrocarbons", + "other_kerosene_type_jet_fuel", + "other_liquids", + "other_oils_for_petrochemical_feedstock_use", + "other_oxygenates", + "oxygenates", + "pentanes_plus", + "petrochemical_feedstocks", + "petroleum_coke", + "propane", + "propylene", + "refinery_olefins", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + "renewable_diesel_fuel", + "residual_fuel_oil", + "residual_fuel_oil_0_31_to_1_00_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + "residual_fuel_oil_less_than_0_31_sulfur", + "residuum", + "special_naphthas", + "unfinished_oils", + "waxes", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 870 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumImportsByAreaOfEntryData(EiaApiData): + """Imports by Area of Entry. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumImportsByAreaOfEntryFetcher( + Fetcher[ + EiaPetroleumImportsByAreaOfEntryQueryParams, + list[EiaPetroleumImportsByAreaOfEntryData], + ] +): + """Imports by Area of Entry fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumImportsByAreaOfEntryQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumImportsByAreaOfEntryQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumImportsByAreaOfEntryQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumImportsByAreaOfEntryQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumImportsByAreaOfEntryData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumImportsByAreaOfEntryData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/imports_by_processing_area.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/imports_by_processing_area.py new file mode 100644 index 00000000000..cc7aa00fbf8 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/imports_by_processing_area.py @@ -0,0 +1,207 @@ +"""Imports by Processing Area model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumImportsByProcessingAreaQueryParams(EiaApiQueryParams): + """Imports by Processing Area. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/imp2 + """ + + __group__ = "petroleum" + __dataset__ = "imports_by_processing_area" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "aviation_gasoline_blending_components", + "crude_oil", + "heavy_gas_oils", + "kerosene_and_light_oils", + "naphthas_and_lighter", + "residuum", + "unfinished_oils", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "east_coast_padd_1_imports_by_padd_of_processing_of_crude_oil_thousand_barrels_per_day", + "east_coast_padd_1_imports_by_padd_of_processing_of_crude_oil_thousand_barrels", + "east_coast_padd_1_imports_by_padd_of_processing_of_heavy_gas_oils_thousand_barrels_per_day", + "east_coast_padd_1_imports_by_padd_of_processing_of_heavy_gas_oils_thousand_barrels", + "east_coast_padd_1_imports_by_padd_of_processing_of_kerosene_and_light_oils_thousand_barrels_per_day", + "east_coast_padd_1_imports_by_padd_of_processing_of_kerosene_and_light_oils_thousand_barrels", + "east_coast_padd_1_imports_by_padd_of_processing_of_naphthas_and_lighter_thousand_barrels_per_day", + "east_coast_padd_1_imports_by_padd_of_processing_of_naphthas_and_lighter_thousand_barrels", + "east_coast_padd_1_imports_by_padd_of_processing_of_residuum_thousand_barrels_per_day", + "east_coast_padd_1_imports_by_padd_of_processing_of_residuum_thousand_barrels", + "east_coast_padd_1_imports_by_padd_of_processing_of_unfinished_oils_thousand_barrels_per_day", + "east_coast_padd_1_imports_by_padd_of_processing_of_unfinished_oils_thousand_barrels", + "gulf_coast_padd_3_imports_by_padd_of_processing_of_crude_oil_thousand_barrels_per_day", + "gulf_coast_padd_3_imports_by_padd_of_processing_of_crude_oil_thousand_barrels", + "gulf_coast_padd_3_imports_by_padd_of_processing_of_heavy_gas_oils_thousand_barrels_per_day", + "gulf_coast_padd_3_imports_by_padd_of_processing_of_heavy_gas_oils_thousand_barrels", + "gulf_coast_padd_3_imports_by_padd_of_processing_of_kerosene_and_light_oils_thousand_barrels_per_day", + "gulf_coast_padd_3_imports_by_padd_of_processing_of_kerosene_and_light_oils_thousand_barrels", + "gulf_coast_padd_3_imports_by_padd_of_processing_of_naphthas_and_lighter_thousand_barrels_per_day", + "gulf_coast_padd_3_imports_by_padd_of_processing_of_naphthas_and_lighter_thousand_barrels", + "gulf_coast_padd_3_imports_by_padd_of_processing_of_residuum_thousand_barrels_per_day", + "gulf_coast_padd_3_imports_by_padd_of_processing_of_residuum_thousand_barrels", + "gulf_coast_padd_3_imports_by_padd_of_processing_of_unfinished_oils_thousand_barrels_per_day", + "gulf_coast_padd_3_imports_by_padd_of_processing_of_unfinished_oils_thousand_barrels", + "midwest_padd_2_imports_by_padd_of_processing_of_crude_oil_thousand_barrels_per_day", + "midwest_padd_2_imports_by_padd_of_processing_of_crude_oil_thousand_barrels", + "midwest_padd_2_imports_by_padd_of_processing_of_heavy_gas_oils_thousand_barrels_per_day", + "midwest_padd_2_imports_by_padd_of_processing_of_heavy_gas_oils_thousand_barrels", + "midwest_padd_2_imports_by_padd_of_processing_of_kerosene_and_light_oils_thousand_barrels_per_day", + "midwest_padd_2_imports_by_padd_of_processing_of_kerosene_and_light_oils_thousand_barrels", + "midwest_padd_2_imports_by_padd_of_processing_of_naphthas_and_lighter_thousand_barrels_per_day", + "midwest_padd_2_imports_by_padd_of_processing_of_naphthas_and_lighter_thousand_barrels", + "midwest_padd_2_imports_by_padd_of_processing_of_residuum_thousand_barrels_per_day", + "midwest_padd_2_imports_by_padd_of_processing_of_residuum_thousand_barrels", + "midwest_padd_2_imports_by_padd_of_processing_of_unfinished_oils_thousand_barrels_per_day", + "midwest_padd_2_imports_by_padd_of_processing_of_unfinished_oils_thousand_barrels", + "rocky_mountain_padd_4_imports_by_padd_of_processing_of_crude_oil_thousand_barrels_per_day", + "rocky_mountain_padd_4_imports_by_padd_of_processing_of_crude_oil_thousand_barrels", + "rocky_mountain_padd_4_imports_by_padd_of_processing_of_heavy_gas_oils_thousand_barrels_per_day", + "rocky_mountain_padd_4_imports_by_padd_of_processing_of_heavy_gas_oils_thousand_barrels", + "rocky_mountain_padd_4_imports_by_padd_of_processing_of_kerosene_and_light_oils_thousand_barrels_per_day", + "rocky_mountain_padd_4_imports_by_padd_of_processing_of_kerosene_and_light_oils_thousand_barrels", + "rocky_mountain_padd_4_imports_by_padd_of_processing_of_residuum_thousand_barrels_per_day", + "rocky_mountain_padd_4_imports_by_padd_of_processing_of_residuum_thousand_barrels", + "rocky_mountain_padd_4_imports_by_padd_of_processing_of_unfinished_oils_thousand_barrels_per_day", + "rocky_mountain_padd_4_imports_by_padd_of_processing_of_unfinished_oils_thousand_barrels", + "west_coast_padd_5_imports_by_padd_of_processing_of_crude_oil_thousand_barrels_per_day", + "west_coast_padd_5_imports_by_padd_of_processing_of_crude_oil_thousand_barrels", + "west_coast_padd_5_imports_by_padd_of_processing_of_heavy_gas_oils_thousand_barrels_per_day", + "west_coast_padd_5_imports_by_padd_of_processing_of_heavy_gas_oils_thousand_barrels", + "west_coast_padd_5_imports_by_padd_of_processing_of_kerosene_and_light_oils_thousand_barrels_per_day", + "west_coast_padd_5_imports_by_padd_of_processing_of_kerosene_and_light_oils_thousand_barrels", + "west_coast_padd_5_imports_by_padd_of_processing_of_naphthas_and_lighter_thousand_barrels_per_day", + "west_coast_padd_5_imports_by_padd_of_processing_of_naphthas_and_lighter_thousand_barrels", + "west_coast_padd_5_imports_by_padd_of_processing_of_residuum_thousand_barrels_per_day", + "west_coast_padd_5_imports_by_padd_of_processing_of_residuum_thousand_barrels", + "west_coast_padd_5_imports_by_padd_of_processing_of_unfinished_oils_thousand_barrels_per_day", + "west_coast_padd_5_imports_by_padd_of_processing_of_unfinished_oils_thousand_barrels", + "west_coast_padd_v_blending_components_av_gas_imports_for_processing_thousand_barrels_per_day", + "west_coast_padd_v_blending_components_av_gas_imports_for_processing_thousand_barrels", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumImportsByProcessingAreaData(EiaApiData): + """Imports by Processing Area. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumImportsByProcessingAreaFetcher( + Fetcher[ + EiaPetroleumImportsByProcessingAreaQueryParams, + list[EiaPetroleumImportsByProcessingAreaData], + ] +): + """Imports by Processing Area fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumImportsByProcessingAreaQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumImportsByProcessingAreaQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumImportsByProcessingAreaQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumImportsByProcessingAreaQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumImportsByProcessingAreaData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumImportsByProcessingAreaData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/imports_of_residual_fuel.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/imports_of_residual_fuel.py new file mode 100644 index 00000000000..165aaa5c790 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/imports_of_residual_fuel.py @@ -0,0 +1,182 @@ +"""Imports of Residual Fuel model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumImportsOfResidualFuelQueryParams(EiaApiQueryParams): + """Imports of Residual Fuel. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/res + """ + + __group__ = "petroleum" + __dataset__ = "imports_of_residual_fuel" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "residual_fuel_oil", + "residual_fuel_oil_0_31_to_1_00_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + "residual_fuel_oil_less_than_0_31_sulfur", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "florida", + "massachusetts", + "minnesota", + "na", + "new_york", + "ohio", + "padd_1", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ct", + "usa_de", + "usa_ga", + "usa_hi", + "usa_id", + "usa_il", + "usa_in", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_nh", + "usa_nj", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_va", + "usa_vt", + "usa_wi", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 313 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumImportsOfResidualFuelData(EiaApiData): + """Imports of Residual Fuel. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumImportsOfResidualFuelFetcher( + Fetcher[ + EiaPetroleumImportsOfResidualFuelQueryParams, + list[EiaPetroleumImportsOfResidualFuelData], + ] +): + """Imports of Residual Fuel fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumImportsOfResidualFuelQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumImportsOfResidualFuelQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumImportsOfResidualFuelQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumImportsOfResidualFuelQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumImportsOfResidualFuelData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumImportsOfResidualFuelData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/landed_costs_of_imported_crude_by_api_gravity.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/landed_costs_of_imported_crude_by_api_gravity.py new file mode 100644 index 00000000000..aea4bd5e2c2 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/landed_costs_of_imported_crude_by_api_gravity.py @@ -0,0 +1,146 @@ +"""Landed Costs of Imported Crude by API Gravity model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumLandedCostsOfImportedCrudeByApiGravityQueryParams(EiaApiQueryParams): + """Landed Costs of Imported Crude by API Gravity. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/land3 + """ + + __group__ = "petroleum" + __dataset__ = "landed_costs_of_imported_crude_by_api_gravity" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "crude_gravity_20_0_percent_or_less", + "crude_gravity_20_1_to_25_0_percent", + "crude_gravity_25_1_to_30_0_percent", + "crude_gravity_30_1_to_35_0_percent", + "crude_gravity_35_1_to_40_0_percent", + "crude_gravity_40_1_to_45_0_percent", + "crude_gravity_45_1_percent_or_more", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_landed_costs_of_crude_with_api_gravity_20_0_degrees_or", + "us_landed_costs_of_crude_with_api_gravity_20_1_to_25_0", + "us_landed_costs_of_crude_with_api_gravity_25_1_to_30_0", + "us_landed_costs_of_crude_with_api_gravity_30_1_to_35_0", + "us_landed_costs_of_crude_with_api_gravity_35_1_to_40_0", + "us_landed_costs_of_crude_with_api_gravity_40_1_to_45_0", + "us_landed_costs_of_crude_with_api_gravity_45_1_degrees_or", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumLandedCostsOfImportedCrudeByApiGravityData(EiaApiData): + """Landed Costs of Imported Crude by API Gravity. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumLandedCostsOfImportedCrudeByApiGravityFetcher( + Fetcher[ + EiaPetroleumLandedCostsOfImportedCrudeByApiGravityQueryParams, + list[EiaPetroleumLandedCostsOfImportedCrudeByApiGravityData], + ] +): + """Landed Costs of Imported Crude by API Gravity fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumLandedCostsOfImportedCrudeByApiGravityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumLandedCostsOfImportedCrudeByApiGravityQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumLandedCostsOfImportedCrudeByApiGravityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumLandedCostsOfImportedCrudeByApiGravityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumLandedCostsOfImportedCrudeByApiGravityData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumLandedCostsOfImportedCrudeByApiGravityData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/landed_costs_of_imported_crude_by_area.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/landed_costs_of_imported_crude_by_area.py new file mode 100644 index 00000000000..1d67346ece2 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/landed_costs_of_imported_crude_by_area.py @@ -0,0 +1,143 @@ +"""Landed Costs of Imported Crude by Area model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumLandedCostsOfImportedCrudeByAreaQueryParams(EiaApiQueryParams): + """Landed Costs of Imported Crude by Area. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/land1 + """ + + __group__ = "petroleum" + __dataset__ = "landed_costs_of_imported_crude_by_area" + __json_schema_extra__ = { + "region": { + "multiple_items_allowed": True, + "choices": ["ago", "can", "col", "gbr", "mex", "na", "nga", "sau", "ven"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_landed_costs_of_angola_crude_oil", + "us_landed_costs_of_canada_crude_oil", + "us_landed_costs_of_colombia_crude_oil", + "us_landed_costs_of_crude_oil", + "us_landed_costs_of_mexico_crude_oil", + "us_landed_costs_of_nigeria_crude_oil", + "us_landed_costs_of_non_opec_countries_crude_oil", + "us_landed_costs_of_opec_countries_crude_oil", + "us_landed_costs_of_persian_gulf_countries_crude_oil", + "us_landed_costs_of_saudi_arabia_crude_oil", + "us_landed_costs_of_united_kingdom_crude_oil", + "us_landed_costs_of_venezuela_crude_oil", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumLandedCostsOfImportedCrudeByAreaData(EiaApiData): + """Landed Costs of Imported Crude by Area. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumLandedCostsOfImportedCrudeByAreaFetcher( + Fetcher[ + EiaPetroleumLandedCostsOfImportedCrudeByAreaQueryParams, + list[EiaPetroleumLandedCostsOfImportedCrudeByAreaData], + ] +): + """Landed Costs of Imported Crude by Area fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumLandedCostsOfImportedCrudeByAreaQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumLandedCostsOfImportedCrudeByAreaQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumLandedCostsOfImportedCrudeByAreaQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumLandedCostsOfImportedCrudeByAreaQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumLandedCostsOfImportedCrudeByAreaData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumLandedCostsOfImportedCrudeByAreaData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/landed_costs_of_imported_crude_for_selected_crude_streams.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/landed_costs_of_imported_crude_for_selected_crude_streams.py new file mode 100644 index 00000000000..5797133b404 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/landed_costs_of_imported_crude_for_selected_crude_streams.py @@ -0,0 +1,202 @@ +"""Landed Costs of Imported Crude for Selected Crude Streams model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreamsQueryParams( + EiaApiQueryParams +): + """Landed Costs of Imported Crude for Selected Crude Streams. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/land2 + """ + + __group__ = "petroleum" + __dataset__ = "landed_costs_of_imported_crude_for_selected_crude_streams" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "algerian_saharan_blend_crude_oil", + "angolan_cabinda_crude_oil", + "brazilian_marlim_crude_oil", + "canadian_bow_river_heavy_crude_oil", + "canadian_lloydminster_crude_oil", + "canadian_light_sour_blend_crude_oil", + "ecuadorian_napo_crude_oil", + "ecuadorian_oriente_crude_oil", + "gabon_rabi_kouanga_crude_oil", + "iraqi_basrah_light_crude_oil", + "mexican_mayan_crude_oil", + "mexican_olmeca_crude_oil", + "nigerian_bonny_light_crude_oil", + "nigerian_forcados_blend_crude_oil", + "nigerian_qua_iboe", + "saudi_arabian_berri_crude_oil", + "saudi_arab_light_crude_oil", + "saudi_arab_medium_crude_oil", + "uk_brent_crude_oil", + "venezuelan_furial_crude_oil", + "venezuelan_leona_crude_oil", + "venezuelan_merey", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "ago", + "bra", + "can", + "dza", + "ecu", + "gab", + "gbr", + "irq", + "mex", + "nga", + "sau", + "ven", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_landed_costs_of_algerian_saharan_blend_crude_oil", + "us_landed_costs_of_angolan_cabinda_crude_oil", + "us_landed_costs_of_brazilian_marlim_crude_oil", + "us_landed_costs_of_canadian_bow_river_heavy_crude_oil", + "us_landed_costs_of_canadian_lloydminster_crude_oil", + "us_landed_costs_of_canadian_light_sour_blend_crude_oil", + "us_landed_costs_of_ecuadorian_napo_crude_oil", + "us_landed_costs_of_ecuadorian_oriente_crude_oil", + "us_landed_costs_of_gabon_rabi_kouanga_crude_oil", + "us_landed_costs_of_iraqi_basrah_light_crude_oil", + "us_landed_costs_of_mexican_mayan_crude_oil", + "us_landed_costs_of_mexican_olmeca_crude_oil", + "us_landed_costs_of_nigerian_bonny_light_crude_oil", + "us_landed_costs_of_nigerian_forcados_blend_crude_oil", + "us_landed_costs_of_nigerian_qua_iboe_crude_oil", + "us_landed_costs_of_saudi_arabian_berri_crude_oil", + "us_landed_costs_of_saudi_arabian_light_crude_oil", + "us_landed_costs_of_saudi_arabian_medium_crude_oil", + "us_landed_costs_of_united_kingdom_brent_crude_oil", + "us_landed_costs_of_venezuelan_furrial_crude_oil", + "us_landed_costs_of_venezuelan_leona_crude_oil", + "us_landed_costs_of_venezuelan_merey_crude_oil", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreamsData(EiaApiData): + """Landed Costs of Imported Crude for Selected Crude Streams. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreamsFetcher( + Fetcher[ + EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreamsQueryParams, + list[EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreamsData], + ] +): + """Landed Costs of Imported Crude for Selected Crude Streams fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreamsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreamsQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreamsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreamsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreamsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreamsData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/maximum_us_active_seismic_crew_counts.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/maximum_us_active_seismic_crew_counts.py new file mode 100644 index 00000000000..1fa6023f26e --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/maximum_us_active_seismic_crew_counts.py @@ -0,0 +1,150 @@ +"""Maximum US Active Seismic Crew Counts model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumMaximumUsActiveSeismicCrewCountsQueryParams(EiaApiQueryParams): + """Maximum US Active Seismic Crew Counts. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/crd/seis + """ + + __group__ = "petroleum" + __dataset__ = "maximum_us_active_seismic_crew_counts" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "maximum_number_of_active_crews_engaged_in_four_dimensional", + "maximum_number_of_active_crews_engaged_in_sismic_surveying", + "maximum_number_of_active_crews_engaged_in_three_dimensional", + "maximum_number_of_active_crews_engaged_in_two_dimensional", + ], + }, + "region": {"multiple_items_allowed": True, "choices": ["na", "us", "usa_ak"]}, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alaska_maximum_number_of_active_crews_engaged_in_four", + "alaska_maximum_number_of_active_crews_engaged_in_seismic", + "alaska_maximum_number_of_active_crews_engaged_in_three", + "alaska_maximum_number_of_active_crews_engaged_in_two", + "us_lower_48_states_offshore_maximum_number_of_active_crews_engaged_in_seismic_surveying_count", + "us_lower_48_states_onshore_maximum_number_of_active_crews_engaged_in_seismic_surveying_count", + "us_maximum_number_of_active_crews_engaged_in_seismic", + "us_lower_48_states_offshore_maximum_number_of_active_crews_engaged_in_four_dimensional_seismic_surveying_count", + "us_lower_48_states_offshore_maximum_number_of_active_crews_engaged_in_three_dimensional_seismic_surveying_count", + "us_lower_48_states_offshore_maximum_number_of_active_crews_engaged_in_two_dimensional_seismic_surveying_count", + "us_lower_48_states_onshore_maximum_number_of_active_crews_engaged_in_four_dimensional_seismic_surveying_count", + "us_lower_48_states_onshore_maximum_number_of_active_crews_engaged_in_three_dimensional_seismic_surveying_count", + "us_lower_48_states_onshore_maximum_number_of_active_crews_engaged_in_two_dimensional_seismic_surveying_count", + ], + }, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumMaximumUsActiveSeismicCrewCountsData(EiaApiData): + """Maximum US Active Seismic Crew Counts. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumMaximumUsActiveSeismicCrewCountsFetcher( + Fetcher[ + EiaPetroleumMaximumUsActiveSeismicCrewCountsQueryParams, + list[EiaPetroleumMaximumUsActiveSeismicCrewCountsData], + ] +): + """Maximum US Active Seismic Crew Counts fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumMaximumUsActiveSeismicCrewCountsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumMaximumUsActiveSeismicCrewCountsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumMaximumUsActiveSeismicCrewCountsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumMaximumUsActiveSeismicCrewCountsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumMaximumUsActiveSeismicCrewCountsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumMaximumUsActiveSeismicCrewCountsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_between_pad_districts.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_between_pad_districts.py new file mode 100644 index 00000000000..c6220f09b6d --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_between_pad_districts.py @@ -0,0 +1,196 @@ +"""Movements by Pipeline, Tanker, Barge and Rail between PAD Districts model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumMovementsBetweenPadDistrictsQueryParams(EiaApiQueryParams): + """Movements by Pipeline, Tanker, Barge and Rail between PAD Districts. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/ptb + """ + + __group__ = "petroleum" + __dataset__ = "movements_between_pad_districts" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "biodiesel", + "biodiesel_renewable_diesel_fuel", + "biofuel_fuels", + "conventional_cbob_gasoline_blending_components", + "conventional_gtab_gasoline_blending_components", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "conventional_other_gasoline_blending_components", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "ethane", + "ethane_ethylene", + "finished_motor_gasoline", + "finished_motor_gasoline_reformulated_other", + "fuel_ethanol", + "gasoline_blending_components", + "isobutane", + "isobutane_isobutylene", + "kerosene", + "kerosene_type_jet_fuel", + "liquified_petroleum_gases", + "lubricants", + "miscellaneous_petroleum_products", + "motor_gasoline_blending_components_reformulated_rbob", + "motor_gasoline_finished_conventional_ed55_and_lower", + "naphtha_for_petrochemical_feedstock_use", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "normal_butane_butylene", + "other_biofuels", + "other_conventional_motor_gasoline", + "other_oils_for_petrochemical_feedstock_use", + "pentanes_plus", + "petrochemical_feedstocks", + "petroleum_coke_marketable", + "propane", + "propane_and_propylene", + "propylene", + "refinery_olefins", + "reformulated_gtab_gasoline_blending_components", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + "reformulated_rbob_with_alcohol_gasoline_blending_components", + "reformulated_rbob_with_ether_gasoline_blending_components", + "renewable_diesel_fuel", + "residual_fuel_oil", + "special_naphthas", + "total_petroleum_products", + "unfinished_oils", + "waxes", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 740 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumMovementsBetweenPadDistrictsData(EiaApiData): + """Movements by Pipeline, Tanker, Barge and Rail between PAD Districts. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumMovementsBetweenPadDistrictsFetcher( + Fetcher[ + EiaPetroleumMovementsBetweenPadDistrictsQueryParams, + list[EiaPetroleumMovementsBetweenPadDistrictsData], + ] +): + """Movements by Pipeline, Tanker, Barge and Rail between PAD Districts fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumMovementsBetweenPadDistrictsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumMovementsBetweenPadDistrictsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumMovementsBetweenPadDistrictsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumMovementsBetweenPadDistrictsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumMovementsBetweenPadDistrictsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumMovementsBetweenPadDistrictsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_by_pipeline_between_pad_districts.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_by_pipeline_between_pad_districts.py new file mode 100644 index 00000000000..4fb46995be7 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_by_pipeline_between_pad_districts.py @@ -0,0 +1,175 @@ +"""Movements by Pipeline between PAD Districts model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumMovementsByPipelineBetweenPadDistrictsQueryParams(EiaApiQueryParams): + """Movements by Pipeline between PAD Districts. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/pipe + """ + + __group__ = "petroleum" + __dataset__ = "movements_by_pipeline_between_pad_districts" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "aviation_gasoline", + "biodiesel", + "biodiesel_renewable_diesel_fuel", + "biofuel_fuels", + "conventional_cbob_gasoline_blending_components", + "conventional_gtab_gasoline_blending_components", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "conventional_other_gasoline_blending_components", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "ethane", + "ethane_ethylene", + "finished_motor_gasoline", + "gasoline_blending_components", + "isobutane", + "isobutane_isobutylene", + "kerosene", + "kerosene_type_jet_fuel", + "liquified_petroleum_gases", + "miscellaneous_petroleum_products", + "motor_gasoline_blending_components_reformulated_rbob", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "normal_butane_butylene", + "other_conventional_motor_gasoline", + "pentanes_plus", + "propane", + "propane_and_propylene", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "reformulated_rbob_with_alcohol_gasoline_blending_components", + "total_petroleum_products", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 413 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumMovementsByPipelineBetweenPadDistrictsData(EiaApiData): + """Movements by Pipeline between PAD Districts. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumMovementsByPipelineBetweenPadDistrictsFetcher( + Fetcher[ + EiaPetroleumMovementsByPipelineBetweenPadDistrictsQueryParams, + list[EiaPetroleumMovementsByPipelineBetweenPadDistrictsData], + ] +): + """Movements by Pipeline between PAD Districts fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumMovementsByPipelineBetweenPadDistrictsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumMovementsByPipelineBetweenPadDistrictsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumMovementsByPipelineBetweenPadDistrictsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumMovementsByPipelineBetweenPadDistrictsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumMovementsByPipelineBetweenPadDistrictsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumMovementsByPipelineBetweenPadDistrictsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_by_rail_between_pad_districts.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_by_rail_between_pad_districts.py new file mode 100644 index 00000000000..cf88e85ea81 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_by_rail_between_pad_districts.py @@ -0,0 +1,146 @@ +"""Movements of Crude Oil and Selected Products by Rail between PAD Districts model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumMovementsByRailBetweenPadDistrictsQueryParams(EiaApiQueryParams): + """Movements of Crude Oil and Selected Products by Rail between PAD Districts. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/rail + """ + + __group__ = "petroleum" + __dataset__ = "movements_by_rail_between_pad_districts" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "biodiesel", + "crude_oil", + "fuel_ethanol", + "isobutane", + "normal_butane", + "petroleum_coke_marketable", + "propane", + "propylene", + "renewable_diesel_fuel", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 144 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumMovementsByRailBetweenPadDistrictsData(EiaApiData): + """Movements of Crude Oil and Selected Products by Rail between PAD Districts. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumMovementsByRailBetweenPadDistrictsFetcher( + Fetcher[ + EiaPetroleumMovementsByRailBetweenPadDistrictsQueryParams, + list[EiaPetroleumMovementsByRailBetweenPadDistrictsData], + ] +): + """Movements of Crude Oil and Selected Products by Rail between PAD Districts fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumMovementsByRailBetweenPadDistrictsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumMovementsByRailBetweenPadDistrictsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumMovementsByRailBetweenPadDistrictsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumMovementsByRailBetweenPadDistrictsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumMovementsByRailBetweenPadDistrictsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumMovementsByRailBetweenPadDistrictsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_by_tanker_and_barge_between_pad_districts.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_by_tanker_and_barge_between_pad_districts.py new file mode 100644 index 00000000000..9da98470c1b --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_by_tanker_and_barge_between_pad_districts.py @@ -0,0 +1,200 @@ +"""Movements by Tanker and Barge between PAD Districts model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumMovementsByTankerAndBargeBetweenPadDistrictsQueryParams( + EiaApiQueryParams +): + """Movements by Tanker and Barge between PAD Districts. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/tb + """ + + __group__ = "petroleum" + __dataset__ = "movements_by_tanker_and_barge_between_pad_districts" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "biodiesel", + "biodiesel_renewable_diesel_fuel", + "biofuel_fuels", + "conventional_cbob_gasoline_blending_components", + "conventional_gtab_gasoline_blending_components", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "conventional_other_gasoline_blending_components", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "finished_motor_gasoline", + "finished_motor_gasoline_reformulated_other", + "fuel_ethanol", + "gasoline_blending_components", + "isobutane", + "kerosene", + "kerosene_type_jet_fuel", + "liquified_petroleum_gases", + "lubricants", + "miscellaneous_petroleum_products", + "motor_gasoline_blending_components_reformulated_rbob", + "motor_gasoline_finished_conventional_ed55_and_lower", + "naphtha_for_petrochemical_feedstock_use", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "normal_butane", + "other_biofuels", + "other_conventional_motor_gasoline", + "other_oils_for_petrochemical_feedstock_use", + "petrochemical_feedstocks", + "propane", + "propane_and_propylene", + "reformulated_gtab_gasoline_blending_components", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + "reformulated_rbob_with_alcohol_gasoline_blending_components", + "reformulated_rbob_with_ether_gasoline_blending_components", + "renewable_diesel_fuel", + "residual_fuel_oil", + "residual_fuel_oil_0_31_to_1_00_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + "residual_fuel_oil_less_than_0_31_sulfur", + "special_naphthas", + "total_petroleum_products", + "unfinished_oils", + "waxes", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_5", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 545 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumMovementsByTankerAndBargeBetweenPadDistrictsData(EiaApiData): + """Movements by Tanker and Barge between PAD Districts. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumMovementsByTankerAndBargeBetweenPadDistrictsFetcher( + Fetcher[ + EiaPetroleumMovementsByTankerAndBargeBetweenPadDistrictsQueryParams, + list[EiaPetroleumMovementsByTankerAndBargeBetweenPadDistrictsData], + ] +): + """Movements by Tanker and Barge between PAD Districts fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumMovementsByTankerAndBargeBetweenPadDistrictsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumMovementsByTankerAndBargeBetweenPadDistrictsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumMovementsByTankerAndBargeBetweenPadDistrictsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumMovementsByTankerAndBargeBetweenPadDistrictsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumMovementsByTankerAndBargeBetweenPadDistrictsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumMovementsByTankerAndBargeBetweenPadDistrictsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_of_crude_oil_and_selected_products_by_rail.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_of_crude_oil_and_selected_products_by_rail.py new file mode 100644 index 00000000000..f782da07ab2 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/movements_of_crude_oil_and_selected_products_by_rail.py @@ -0,0 +1,157 @@ +"""Movements of Crude Oil and Selected Products by Rail model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRailQueryParams( + EiaApiQueryParams +): + """Movements of Crude Oil and Selected Products by Rail. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/railNA + """ + + __group__ = "petroleum" + __dataset__ = "movements_of_crude_oil_and_selected_products_by_rail" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "biodiesel", + "crude_oil", + "fuel_ethanol", + "isobutane", + "normal_butane", + "petroleum_coke_marketable", + "propane", + "propylene", + "renewable_diesel_fuel", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "can", + "na", + "padd_1", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "us", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 399 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRailData(EiaApiData): + """Movements of Crude Oil and Selected Products by Rail. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRailFetcher( + Fetcher[ + EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRailQueryParams, + list[EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRailData], + ] +): + """Movements of Crude Oil and Selected Products by Rail fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRailQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRailQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRailQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRailQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRailData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRailData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/natural_gas_feedstock_for_hydrogen.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/natural_gas_feedstock_for_hydrogen.py new file mode 100644 index 00000000000..7ec1feacf82 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/natural_gas_feedstock_for_hydrogen.py @@ -0,0 +1,138 @@ +"""Natural Gas Used as Feedstock for Hydrogen Production at Refineries model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumNaturalGasFeedstockForHydrogenQueryParams(EiaApiQueryParams): + """Natural Gas Used as Feedstock for Hydrogen Production at Refineries. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/feedng + """ + + __group__ = "petroleum" + __dataset__ = "natural_gas_feedstock_for_hydrogen" + __json_schema_extra__ = { + "product": {"multiple_items_allowed": True}, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "east_coast_natural_gas_used_as_feedstock_for_hydrogen", + "gulf_coast_natural_gas_used_as_feedstock_for_hydrogen", + "midwest_natural_gas_used_as_feedstock_for_hydrogen", + "rocky_mountain_natural_gas_used_as_feedstock_for_hydrogen", + "us_natural_gas_used_as_feedstock_for_hydrogen_production", + "west_coast_natural_gas_used_as_feedstock_for_hydrogen", + ], + }, + } + + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumNaturalGasFeedstockForHydrogenData(EiaApiData): + """Natural Gas Used as Feedstock for Hydrogen Production at Refineries. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumNaturalGasFeedstockForHydrogenFetcher( + Fetcher[ + EiaPetroleumNaturalGasFeedstockForHydrogenQueryParams, + list[EiaPetroleumNaturalGasFeedstockForHydrogenData], + ] +): + """Natural Gas Used as Feedstock for Hydrogen Production at Refineries fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumNaturalGasFeedstockForHydrogenQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumNaturalGasFeedstockForHydrogenQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumNaturalGasFeedstockForHydrogenQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumNaturalGasFeedstockForHydrogenQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumNaturalGasFeedstockForHydrogenData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumNaturalGasFeedstockForHydrogenData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/natural_gas_plant_field_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/natural_gas_plant_field_production.py new file mode 100644 index 00000000000..761dd3acb67 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/natural_gas_plant_field_production.py @@ -0,0 +1,145 @@ +"""Natural Gas Plant Field Production model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumNaturalGasPlantFieldProductionQueryParams(EiaApiQueryParams): + """Natural Gas Plant Field Production. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/gp + """ + + __group__ = "petroleum" + __dataset__ = "natural_gas_plant_field_production" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "condensate_and_scrubber_oil", + "ethane", + "isobutane", + "liquified_petroleum_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "pentanes_plus", + "propane", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 284 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumNaturalGasPlantFieldProductionData(EiaApiData): + """Natural Gas Plant Field Production. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumNaturalGasPlantFieldProductionFetcher( + Fetcher[ + EiaPetroleumNaturalGasPlantFieldProductionQueryParams, + list[EiaPetroleumNaturalGasPlantFieldProductionData], + ] +): + """Natural Gas Plant Field Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumNaturalGasPlantFieldProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumNaturalGasPlantFieldProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumNaturalGasPlantFieldProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumNaturalGasPlantFieldProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumNaturalGasPlantFieldProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumNaturalGasPlantFieldProductionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/natural_gas_plant_stocks.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/natural_gas_plant_stocks.py new file mode 100644 index 00000000000..6ad9ae20999 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/natural_gas_plant_stocks.py @@ -0,0 +1,149 @@ +"""Natural Gas Plant Stocks model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumNaturalGasPlantStocksQueryParams(EiaApiQueryParams): + """Natural Gas Plant Stocks. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/stoc/gp + """ + + __group__ = "petroleum" + __dataset__ = "natural_gas_plant_stocks" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "condensate_and_scrubber_oil", + "ethane", + "ethane_ethylene", + "isobutane", + "isobutane_isobutylene", + "liquified_petroleum_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "normal_butane_butylene", + "pentanes_plus", + "propane", + "propane_and_propylene", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 198 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumNaturalGasPlantStocksData(EiaApiData): + """Natural Gas Plant Stocks. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumNaturalGasPlantStocksFetcher( + Fetcher[ + EiaPetroleumNaturalGasPlantStocksQueryParams, + list[EiaPetroleumNaturalGasPlantStocksData], + ] +): + """Natural Gas Plant Stocks fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumNaturalGasPlantStocksQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumNaturalGasPlantStocksQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumNaturalGasPlantStocksQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumNaturalGasPlantStocksQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumNaturalGasPlantStocksData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumNaturalGasPlantStocksData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/net_receipts_between_pad_districts.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/net_receipts_between_pad_districts.py new file mode 100644 index 00000000000..50a55b73e8f --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/net_receipts_between_pad_districts.py @@ -0,0 +1,212 @@ +"""Net Receipts by Pipeline, Tanker, Barge and Rail between PAD Districts model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumNetReceiptsBetweenPadDistrictsQueryParams(EiaApiQueryParams): + """Net Receipts by Pipeline, Tanker, Barge and Rail between PAD Districts. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/netr + """ + + __group__ = "petroleum" + __dataset__ = "net_receipts_between_pad_districts" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "net_receipts_by_pipeline_tanker_barge_and_rail", + "receipts_by_pipeline_tanker_barge_and_rail", + "shipments_by_pipeline_tanker_barge_and_rail", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "biodiesel", + "biodiesel_renewable_diesel_fuel", + "biofuel_fuels", + "conventional_cbob_gasoline_blending_components", + "conventional_gtab_gasoline_blending_components", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "conventional_other_gasoline_blending_components", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "ethane", + "ethane_ethylene", + "ethylene", + "finished_motor_gasoline", + "finished_motor_gasoline_conventional_55", + "finished_motor_gasoline_reformulated_other", + "fuel_ethanol", + "gasoline_blending_components", + "isobutane", + "isobutane_isobutylene", + "isobutylene", + "kerosene", + "kerosene_type_jet_fuel", + "liquified_petroleum_gases", + "lubricants", + "miscellaneous_petroleum_products", + "motor_gasoline_blending_components_reformulated_rbob", + "motor_gasoline_finished_conventional_ed55_and_lower", + "naphtha_for_petrochemical_feedstock_use", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "normal_butane_butylene", + "normal_butylene", + "other_biofuels", + "other_conventional_motor_gasoline", + "other_oils_for_petrochemical_feedstock_use", + "pentanes_plus", + "petrochemical_feedstocks", + "petroleum_coke_marketable", + "propane", + "propane_and_propylene", + "propylene", + "refinery_olefins", + "reformulated_gtab_gasoline_blending_components", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + "reformulated_rbob_with_alcohol_gasoline_blending_components", + "reformulated_rbob_with_ether_gasoline_blending_components", + "renewable_diesel_fuel", + "residual_fuel_oil", + "special_naphthas", + "total_petroleum_products", + "unfinished_oils", + "waxes", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 914 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumNetReceiptsBetweenPadDistrictsData(EiaApiData): + """Net Receipts by Pipeline, Tanker, Barge and Rail between PAD Districts. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumNetReceiptsBetweenPadDistrictsFetcher( + Fetcher[ + EiaPetroleumNetReceiptsBetweenPadDistrictsQueryParams, + list[EiaPetroleumNetReceiptsBetweenPadDistrictsData], + ] +): + """Net Receipts by Pipeline, Tanker, Barge and Rail between PAD Districts fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumNetReceiptsBetweenPadDistrictsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumNetReceiptsBetweenPadDistrictsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumNetReceiptsBetweenPadDistrictsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumNetReceiptsBetweenPadDistrictsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumNetReceiptsBetweenPadDistrictsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumNetReceiptsBetweenPadDistrictsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/no2_distillate_prices_by_sales_type.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/no2_distillate_prices_by_sales_type.py new file mode 100644 index 00000000000..b953d2c0239 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/no2_distillate_prices_by_sales_type.py @@ -0,0 +1,191 @@ +"""No 2 Distillate Prices by Sales Type model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumNo2DistillatePricesBySalesTypeQueryParams(EiaApiQueryParams): + """No 2 Distillate Prices by Sales Type. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/dist + """ + + __group__ = "petroleum" + __dataset__ = "no2_distillate_prices_by_sales_type" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "industrial_price", + "other_end_users_by_all_sellers", + "price_delivered_to_commercial_sectors", + "residential_price_by_all_sellers", + "retail_sales_by_all_sellers", + "through_company_outlets_price", + "wholesale_resale_price_by_all_sellers", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "no_2_diesel", + "no_2_diesel_high_sulfur", + "no_2_diesel_low_sulfur_0_15_ppm", + "no_2_diesel_low_sulfur_15_500_ppm", + "no_2_distillate", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "us", + "usa_ak", + "usa_ct", + "usa_dc", + "usa_de", + "usa_id", + "usa_il", + "usa_in", + "usa_md", + "usa_me", + "usa_mi", + "usa_nh", + "usa_nj", + "usa_or", + "usa_pa", + "usa_ri", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 582 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumNo2DistillatePricesBySalesTypeData(EiaApiData): + """No 2 Distillate Prices by Sales Type. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumNo2DistillatePricesBySalesTypeFetcher( + Fetcher[ + EiaPetroleumNo2DistillatePricesBySalesTypeQueryParams, + list[EiaPetroleumNo2DistillatePricesBySalesTypeData], + ] +): + """No 2 Distillate Prices by Sales Type fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumNo2DistillatePricesBySalesTypeQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumNo2DistillatePricesBySalesTypeQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumNo2DistillatePricesBySalesTypeQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumNo2DistillatePricesBySalesTypeQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumNo2DistillatePricesBySalesTypeData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumNo2DistillatePricesBySalesTypeData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/number_and_capacity_of_petroleum_refineries.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/number_and_capacity_of_petroleum_refineries.py new file mode 100644 index 00000000000..d54c070c58c --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/number_and_capacity_of_petroleum_refineries.py @@ -0,0 +1,221 @@ +"""Number and Capacity of Petroleum Refineries model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumNumberAndCapacityOfPetroleumRefineriesQueryParams(EiaApiQueryParams): + """Number and Capacity of Petroleum Refineries. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/cap1 + """ + + __group__ = "petroleum" + __dataset__ = "number_and_capacity_of_petroleum_refineries" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "atmospheric_crude_distillation_capacity", + "atmospheric_crude_distillation_capacity_idle", + "atmospheric_crude_distillation_capacity_operating", + "catalytic_cracking_recycle", + "catalytic_hydrocracking", + "catalytic_hydrocracking_distillate", + "catalytic_hydrocracking_gas_oil", + "catalytic_hydrocracking_residual_fuel_oil", + "catalytic_reforming", + "catalytic_reforming_high_pressure", + "catalytic_reforming_low_pressure", + "downstream_charge_capacity_thermal_cracking_other_gas_oil", + "downstream_charge_capacity_thermal_cracking_visbreaking", + "downstream_charge_capacity_vacuum_distillation", + "fuels_solvent_deaspalting", + "idle_refineries", + "operable_refineries", + "operating_refineries", + "refinery_catalytic_cracking_fresh_feed_downstream_charge", + "refinery_catalytic_hydrotreating_diesel_downstream_charge", + "refinery_catalytic_hydrotreating_distillate_downstream", + "refinery_catalytic_hydrotreating_heavy_gas_oil_downstream", + "refinery_catalytic_hydrotreating_kerosene_jet_fuel", + "refinery_catalytic_hydrotreating_naphtha_reformer_feed", + "refinery_catalytic_hydrotreating_other_distillate", + "refinery_catalytic_hydrotreating_other_oils_downstream", + "refinery_catalytic_hydrotreating_other_residual_fuel_oil", + "refinery_catalytic_hydrotreating_residual_fuel_oil", + "refinery_desulfurization_downstream_charge_capacity", + "refinery_desulfurization_gasoline_downstream_charge_capacity", + "refinery_thermal_cracking_downstream_charge_capacity", + "refinery_thermal_cracking_coking_downstream_charge_capacity", + "refinery_thermal_cracking_delayed_coking_downstream_charge", + "refinery_thermal_cracking_fluid_coking_downstream_charge", + ], + }, + "product": {"multiple_items_allowed": True}, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "gum", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "pri", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_de", + "usa_ga", + "usa_hi", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_tn", + "usa_ut", + "usa_va", + "usa_wi", + "usa_wv", + "usa_wy", + "vir", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumNumberAndCapacityOfPetroleumRefineriesData(EiaApiData): + """Number and Capacity of Petroleum Refineries. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumNumberAndCapacityOfPetroleumRefineriesFetcher( + Fetcher[ + EiaPetroleumNumberAndCapacityOfPetroleumRefineriesQueryParams, + list[EiaPetroleumNumberAndCapacityOfPetroleumRefineriesData], + ] +): + """Number and Capacity of Petroleum Refineries fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumNumberAndCapacityOfPetroleumRefineriesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumNumberAndCapacityOfPetroleumRefineriesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumNumberAndCapacityOfPetroleumRefineriesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumNumberAndCapacityOfPetroleumRefineriesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumNumberAndCapacityOfPetroleumRefineriesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumNumberAndCapacityOfPetroleumRefineriesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/nymex_futures_prices.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/nymex_futures_prices.py new file mode 100644 index 00000000000..9de652aede0 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/nymex_futures_prices.py @@ -0,0 +1,173 @@ +"""NYMEX Futures Prices (Futures prices after April 5, 2024, are not available) model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumNymexFuturesPricesQueryParams(EiaApiQueryParams): + """NYMEX Futures Prices (Futures prices after April 5, 2024, are not available). EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/fut + """ + + __group__ = "petroleum" + __dataset__ = "nymex_futures_prices" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "future_contract_1", + "future_contract_2", + "future_contract_3", + "future_contract_4", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "crude_oil", + "no_2_fuel_oil_heating_oil", + "propane", + "reformulated_regular_gasoline", + "regular_gasoline", + ], + }, + "region": {"multiple_items_allowed": True, "choices": ["na", "new_york_city"]}, + "series": { + "multiple_items_allowed": True, + "choices": [ + "cushing_ok_crude_oil_future_contract_1", + "cushing_ok_crude_oil_future_contract_2", + "cushing_ok_crude_oil_future_contract_3", + "cushing_ok_crude_oil_future_contract_4", + "mont_belvieu_tx_propane_future_contract_1", + "mont_belvieu_tx_propane_future_contract_2", + "mont_belvieu_tx_propane_future_contract_3", + "mont_belvieu_tx_propane_future_contract_4", + "new_york_harbor_no_2_heating_oil_future_contract_1", + "new_york_harbor_no_2_heating_oil_future_contract_2", + "new_york_harbor_no_2_heating_oil_future_contract_3", + "new_york_harbor_no_2_heating_oil_future_contract_4", + "new_york_harbor_reformulated_rbob_regular_gasoline_future_contract_1_dollars_per_gallon", + "new_york_harbor_reformulated_rbob_regular_gasoline_future_contract_2_dollars_per_gallon", + "new_york_harbor_reformulated_rbob_regular_gasoline_future_contract_3_dollars_per_gallon", + "new_york_harbor_reformulated_rbob_regular_gasoline_future_contract_4_dollars_per_gallon", + "new_york_harbor_regular_gasoline_future_contract_1", + "new_york_harbor_regular_gasoline_future_contract_2", + "new_york_harbor_regular_gasoline_future_contract_3", + "new_york_harbor_regular_gasoline_future_contract_4", + ], + }, + } + + frequency: Literal["annual", "daily", "monthly", "weekly"] | None = Field( + default=None, + description="The data frequency. The default is 'weekly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumNymexFuturesPricesData(EiaApiData): + """NYMEX Futures Prices (Futures prices after April 5, 2024, are not available). EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumNymexFuturesPricesFetcher( + Fetcher[ + EiaPetroleumNymexFuturesPricesQueryParams, + list[EiaPetroleumNymexFuturesPricesData], + ] +): + """NYMEX Futures Prices (Futures prices after April 5, 2024, are not available) fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumNymexFuturesPricesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumNymexFuturesPricesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumNymexFuturesPricesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumNymexFuturesPricesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumNymexFuturesPricesData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumNymexFuturesPricesData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/oxygenate_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/oxygenate_production.py new file mode 100644 index 00000000000..b4a61ac8be6 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/oxygenate_production.py @@ -0,0 +1,204 @@ +"""Oxygenate Production model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumOxygenateProductionQueryParams(EiaApiQueryParams): + """Oxygenate Production. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/oxy + """ + + __group__ = "petroleum" + __dataset__ = "oxygenate_production" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "captive_plants", + "merchant_plants", + "oxygenate_plant_production", + "renewable_fuels_plant_and_oxygenate_plant_net_production", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": ["fuel_ethanol", "mtbe", "other_oxygenates", "oxygenates"], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "east_coast_padd_1_mtbe_oxygenate_captive_facilities_production_thousand_barrels_per_day", + "east_coast_padd_1_mtbe_oxygenate_captive_facilities_production_thousand_barrels", + "east_coast_padd_1_mtbe_oxygenate_merchant_facilities_production_thousand_barrels_per_day", + "east_coast_padd_1_mtbe_oxygenate_merchant_facilities_production_thousand_barrels", + "east_coast_padd_1_oxygenate_plant_production_of_fuel_ethanol_thousand_barrels_per_day", + "east_coast_padd_1_oxygenate_plant_production_of_fuel_ethanol_thousand_barrels", + "east_coast_padd_1_oxygenate_plant_production_of_mtbe_thousand_barrels_per_day", + "east_coast_padd_1_oxygenate_plant_production_of_mtbe_thousand_barrels", + "gulf_coast_padd_3_biofuels_plant_net_production_of_other_oxygenates_thousand_barrels_per_day", + "gulf_coast_padd_3_biofuels_plant_net_production_of_other_oxygenates_thousand_barrels", + "gulf_coast_padd_3_mtbe_oxygenate_captive_facilities_production_thousand_barrels_per_day", + "gulf_coast_padd_3_mtbe_oxygenate_captive_facilities_production_thousand_barrels", + "gulf_coast_padd_3_mtbe_oxygenate_merchant_facilities_production_thousand_barrels_per_day", + "gulf_coast_padd_3_mtbe_oxygenate_merchant_facilities_production_thousand_barrels", + "gulf_coast_padd_3_oxygenate_plant_production_of_fuel_ethanol_thousand_barrels_per_day", + "gulf_coast_padd_3_oxygenate_plant_production_of_fuel_ethanol_thousand_barrels", + "gulf_coast_padd_3_oxygenate_plant_production_of_mtbe_thousand_barrels_per_day", + "gulf_coast_padd_3_oxygenate_plant_production_of_mtbe_thousand_barrels", + "gulf_coast_padd_3_oxygenate_plant_production_of_oxygenates_excluding_fuel_ethanol_thousand_barrels_per_day", + "gulf_coast_padd_3_oxygenate_plant_production_of_oxygenates_excluding_fuel_ethanol_thousand_barrels", + "midwest_padd_2_biofuels_plant_net_production_of_other_oxygenates_thousand_barrels_per_day", + "midwest_padd_2_biofuels_plant_net_production_of_other_oxygenates_thousand_barrels", + "midwest_padd_2_mtbe_oxygenate_captive_facilities_production_thousand_barrels_per_day", + "midwest_padd_2_mtbe_oxygenate_captive_facilities_production_thousand_barrels", + "midwest_padd_2_mtbe_oxygenate_merchant_facilities_production_thousand_barrels_per_day", + "midwest_padd_2_mtbe_oxygenate_merchant_facilities_production_thousand_barrels", + "midwest_padd_2_oxygenate_plant_production_of_fuel_ethanol_thousand_barrels_per_day", + "midwest_padd_2_oxygenate_plant_production_of_fuel_ethanol_thousand_barrels", + "midwest_padd_2_oxygenate_plant_production_of_oxygenates_excluding_fuel_ethanol_thousand_barrels_per_day", + "midwest_padd_2_oxygenate_plant_production_of_oxygenates_excluding_fuel_ethanol_thousand_barrels", + "rocky_mountain_padd_4_mtbe_oxygenate_captive_facilities_production_thousand_barrels_per_day", + "rocky_mountain_padd_4_mtbe_oxygenate_captive_facilities_production_thousand_barrels", + "rocky_mountain_padd_4_mtbe_oxygenate_merchant_facilities_production_thousand_barrels_per_day", + "rocky_mountain_padd_4_mtbe_oxygenate_merchant_facilities_production_thousand_barrels", + "rocky_mountain_padd_4_oxygenate_plant_production_of_fuel_ethanol_thousand_barrels_per_day", + "rocky_mountain_padd_4_oxygenate_plant_production_of_fuel_ethanol_thousand_barrels", + "us_biofuels_plant_net_production_of_other_oxygenates_thousand_barrels_per_day", + "us_biofuels_plant_net_production_of_other_oxygenates_thousand_barrels", + "us_mtbe_oxygenate_captive_facilities_production_thousand_barrels_per_day", + "us_mtbe_oxygenate_captive_facilities_production_thousand_barrels", + "us_mtbe_oxygenate_merchant_facilities_production_thousand_barrels_per_day", + "us_mtbe_oxygenate_merchant_facilities_production_thousand_barrels", + "us_oxygenate_plant_production_of_fuel_ethanol_thousand_barrels_per_day", + "us_oxygenate_plant_production_of_fuel_ethanol_thousand_barrels", + "us_oxygenate_plant_production_of_mtbe_thousand_barrels_per_day", + "us_oxygenate_plant_production_of_mtbe_thousand_barrels", + "us_oxygenate_plant_production_of_oxygenates_excluding_fuel_ethanol_thousand_barrels_per_day", + "us_oxygenate_plant_production_of_oxygenates_excluding_fuel_ethanol_thousand_barrels", + "west_coast_padd_5_mtbe_oxygenate_captive_facilities_production_thousand_barrels_per_day", + "west_coast_padd_5_mtbe_oxygenate_captive_facilities_production_thousand_barrels", + "west_coast_padd_5_mtbe_oxygenate_merchant_facilities_production_thousand_barrels_per_day", + "west_coast_padd_5_mtbe_oxygenate_merchant_facilities_production_thousand_barrels", + "west_coast_padd_5_oxygenate_plant_production_of_fuel_ethanol_thousand_barrels_per_day", + "west_coast_padd_5_oxygenate_plant_production_of_fuel_ethanol_thousand_barrels", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumOxygenateProductionData(EiaApiData): + """Oxygenate Production. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumOxygenateProductionFetcher( + Fetcher[ + EiaPetroleumOxygenateProductionQueryParams, + list[EiaPetroleumOxygenateProductionData], + ] +): + """Oxygenate Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumOxygenateProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumOxygenateProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumOxygenateProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumOxygenateProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumOxygenateProductionData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumOxygenateProductionData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/pad_district_exports_by_destination.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/pad_district_exports_by_destination.py new file mode 100644 index 00000000000..6dc8abab04d --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/pad_district_exports_by_destination.py @@ -0,0 +1,172 @@ +"""PAD District Exports by Destination model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumPadDistrictExportsByDestinationQueryParams(EiaApiQueryParams): + """PAD District Exports by Destination. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/expcp + """ + + __group__ = "petroleum" + __dataset__ = "pad_district_exports_by_destination" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "aviation_gasoline_blending_components", + "biodiesel", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_to_2000_ppm_sulfur", + "ethane", + "finished_motor_gasoline", + "fuel_ethanol", + "gasoline_blending_components", + "isobutane", + "kerosene", + "kerosene_type_jet_fuel", + "lubricants", + "mtbe", + "miscellaneous_petroleum_products", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "other_biofuels", + "other_oils_for_petrochemical_feedstock_use", + "other_oxygenates", + "petroleum_coke", + "propane", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "renewable_diesel_fuel", + "residual_fuel_oil", + "special_naphthas", + "total_petroleum_products", + "unfinished_oils", + "waxes", + ], + }, + "region": {"multiple_items_allowed": True}, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values. There are 727 valid values - use the `facet_options` endpoint to list them.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumPadDistrictExportsByDestinationData(EiaApiData): + """PAD District Exports by Destination. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumPadDistrictExportsByDestinationFetcher( + Fetcher[ + EiaPetroleumPadDistrictExportsByDestinationQueryParams, + list[EiaPetroleumPadDistrictExportsByDestinationData], + ] +): + """PAD District Exports by Destination fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumPadDistrictExportsByDestinationQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumPadDistrictExportsByDestinationQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumPadDistrictExportsByDestinationQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumPadDistrictExportsByDestinationQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumPadDistrictExportsByDestinationData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumPadDistrictExportsByDestinationData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/pad_district_imports_by_country_of_origin.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/pad_district_imports_by_country_of_origin.py new file mode 100644 index 00000000000..a9ec17075d8 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/pad_district_imports_by_country_of_origin.py @@ -0,0 +1,193 @@ +"""PAD District Imports by Country of Origin model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumPadDistrictImportsByCountryOfOriginQueryParams(EiaApiQueryParams): + """PAD District Imports by Country of Origin. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/impcp + """ + + __group__ = "petroleum" + __dataset__ = "pad_district_imports_by_country_of_origin" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": ["imports", "imports_by_padd_of_processing"], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "aviation_gasoline_blending_components", + "biodiesel", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_2000_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_to_2000_ppm_sulfur", + "ethane", + "ethylene", + "finished_motor_gasoline", + "fuel_ethanol", + "gasoline_blending_components", + "isobutane", + "isobutylene", + "kerosene", + "kerosene_type_jet_fuel", + "liquified_petroleum_gases", + "lubricants", + "mtbe", + "miscellaneous_petroleum_products", + "naphtha_for_petrochemical_feedstock_use", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "normal_butylene", + "other_biofuels", + "other_oils_for_petrochemical_feedstock_use", + "other_oxygenates", + "pentanes_plus", + "petroleum_coke_marketable", + "propane", + "propylene", + "refinery_olefins", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "renewable_diesel_fuel", + "residual_fuel_oil", + "residual_fuel_oil_0_31_to_1_00_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + "residual_fuel_oil_less_than_0_31_sulfur", + "special_naphthas", + "total_petroleum_products", + "unfinished_oils", + "waxes", + ], + }, + "region": {"multiple_items_allowed": True}, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values. There are 443 valid values - use the `facet_options` endpoint to list them.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumPadDistrictImportsByCountryOfOriginData(EiaApiData): + """PAD District Imports by Country of Origin. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumPadDistrictImportsByCountryOfOriginFetcher( + Fetcher[ + EiaPetroleumPadDistrictImportsByCountryOfOriginQueryParams, + list[EiaPetroleumPadDistrictImportsByCountryOfOriginData], + ] +): + """PAD District Imports by Country of Origin fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumPadDistrictImportsByCountryOfOriginQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumPadDistrictImportsByCountryOfOriginQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumPadDistrictImportsByCountryOfOriginQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumPadDistrictImportsByCountryOfOriginQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumPadDistrictImportsByCountryOfOriginData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumPadDistrictImportsByCountryOfOriginData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/percentages_of_total_imported_crude_oil_by_api_gravity.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/percentages_of_total_imported_crude_oil_by_api_gravity.py new file mode 100644 index 00000000000..8376d8d47a1 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/percentages_of_total_imported_crude_oil_by_api_gravity.py @@ -0,0 +1,149 @@ +"""Percentages of Total Imported Crude Oil by API Gravity model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravityQueryParams( + EiaApiQueryParams +): + """Percentages of Total Imported Crude Oil by API Gravity. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/ipct + """ + + __group__ = "petroleum" + __dataset__ = "percentages_of_total_imported_crude_oil_by_api_gravity" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "crude_gravity_20_0_percent_or_less", + "crude_gravity_20_1_to_25_0_percent", + "crude_gravity_25_1_to_30_0_percent", + "crude_gravity_30_1_to_35_0_percent", + "crude_gravity_35_1_to_40_0_percent", + "crude_gravity_40_1_to_45_0_percent", + "crude_gravity_45_1_percent_or_more", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_percent_total_imported_by_api_gravity_of_crude_gravity_20_0_percent_or_less", + "us_percent_total_imported_by_api_gravity_of_crude_gravity_20_1_to_25_0_percent", + "us_percent_total_imported_by_api_gravity_of_crude_gravity_25_1_to_30_0_percent", + "us_percent_total_imported_by_api_gravity_of_crude_gravity_30_1_to_35_0_percent", + "us_percent_total_imported_by_api_gravity_of_crude_gravity_35_1_to_40_0_percent", + "us_percent_total_imported_by_api_gravity_of_crude_gravity_40_1_to_45_0", + "us_percent_total_imported_by_api_gravity_of_crude_gravity_45_1_or_more", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravityData(EiaApiData): + """Percentages of Total Imported Crude Oil by API Gravity. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravityFetcher( + Fetcher[ + EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravityQueryParams, + list[EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravityData], + ] +): + """Percentages of Total Imported Crude Oil by API Gravity fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravityQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravityData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravityData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/prices_sales_volumes_stocks_by_state.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/prices_sales_volumes_stocks_by_state.py new file mode 100644 index 00000000000..d35db2e6088 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/prices_sales_volumes_stocks_by_state.py @@ -0,0 +1,234 @@ +"""Prices, Sales Volumes & Stocks by State model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumPricesSalesVolumesStocksByStateQueryParams(EiaApiQueryParams): + """Prices, Sales Volumes & Stocks by State. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/sum/mkt + """ + + __group__ = "petroleum" + __dataset__ = "prices_sales_volumes_stocks_by_state" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "all_sales_deliveries", + "residential_price_by_all_sellers", + "retail_sales_by_all_sellers", + "retail_sales_by_refiners_and_gas_plants", + "stocks_at_refineries_bulk_terminals_and_natural_gas_plants", + "through_company_outlets_price", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "aviation_gasoline", + "conventional_motor_gasoline", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "finished_motor_gasoline", + "gasoline_blending_components", + "kerosene", + "kerosene_type_jet_fuel", + "midgrade_gasoline", + "no_1_distillate", + "no_2_diesel", + "no_2_distillate", + "no_2_fuel_oil_heating_oil", + "no_4_distillate", + "premium_gasoline", + "propane", + "reformulated_motor_gasoline", + "regular_gasoline", + "residual_fuel_oil", + "total_gasoline", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumPricesSalesVolumesStocksByStateData(EiaApiData): + """Prices, Sales Volumes & Stocks by State. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumPricesSalesVolumesStocksByStateFetcher( + Fetcher[ + EiaPetroleumPricesSalesVolumesStocksByStateQueryParams, + list[EiaPetroleumPricesSalesVolumesStocksByStateData], + ] +): + """Prices, Sales Volumes & Stocks by State fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumPricesSalesVolumesStocksByStateQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumPricesSalesVolumesStocksByStateQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumPricesSalesVolumesStocksByStateQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumPricesSalesVolumesStocksByStateQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumPricesSalesVolumesStocksByStateData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumPricesSalesVolumesStocksByStateData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/prime_supplier_sales_volumes.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/prime_supplier_sales_volumes.py new file mode 100644 index 00000000000..535038b2f8d --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/prime_supplier_sales_volumes.py @@ -0,0 +1,230 @@ +"""Prime Supplier Sales Volumes model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumPrimeSupplierSalesVolumesQueryParams(EiaApiQueryParams): + """Prime Supplier Sales Volumes. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/cons/prim + """ + + __group__ = "petroleum" + __dataset__ = "prime_supplier_sales_volumes" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "aviation_gasoline", + "conventional_gasoline", + "conventional_premium_gasoline", + "conventional_regular_gasoline", + "gasoline_conventional_midgrade", + "gasoline_oxygenated_midgrade", + "gasoline_reformulated_midgrade", + "kerosene", + "kerosene_type_jet_fuel", + "midgrade_gasoline", + "naphtha_type_jet_fuel", + "no_1_distillate", + "no_2_diesel", + "no_2_diesel_high_sulfur", + "no_2_diesel_low_sulfur_0_15_ppm", + "no_2_diesel_low_sulfur_15_500_ppm", + "no_2_distillate", + "no_2_fuel_oil_heating_oil", + "no_4_distillate", + "oxygenated_gasoline", + "oxygenated_premium_gasoline", + "oxygenated_regular_gasoline", + "premium_gasoline", + "propane", + "reformulated_motor_gasoline", + "reformulated_premium_gasoline", + "reformulated_regular_gasoline", + "regular_gasoline", + "residual_fuel_oil", + "residual_fuel_oil_0_to_1_0_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + "special_distillate_plus_kerosene", + "total_gasoline", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumPrimeSupplierSalesVolumesData(EiaApiData): + """Prime Supplier Sales Volumes. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumPrimeSupplierSalesVolumesFetcher( + Fetcher[ + EiaPetroleumPrimeSupplierSalesVolumesQueryParams, + list[EiaPetroleumPrimeSupplierSalesVolumesData], + ] +): + """Prime Supplier Sales Volumes fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumPrimeSupplierSalesVolumesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumPrimeSupplierSalesVolumesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumPrimeSupplierSalesVolumesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumPrimeSupplierSalesVolumesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumPrimeSupplierSalesVolumesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumPrimeSupplierSalesVolumesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/product_supplied.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/product_supplied.py new file mode 100644 index 00000000000..dca2701c995 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/product_supplied.py @@ -0,0 +1,191 @@ +"""Product Supplied model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumProductSuppliedQueryParams(EiaApiQueryParams): + """Product Supplied. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/cons/psup + """ + + __group__ = "petroleum" + __dataset__ = "product_supplied" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "aviation_gasoline_blending_components", + "biodiesel", + "biodiesel_renewable_diesel_fuel", + "biofuel_fuels", + "biofuel_fuels_excluding_fuel_ethanol", + "condensate_and_scrubber_oil", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "ethane", + "ethane_ethylene", + "ethylene", + "finished_motor_gasoline", + "finished_petroleum_products", + "fuel_ethanol", + "gasoline_blending_components", + "hydrogen_oxygenates_renewables_fuels_and_other_hydrocarbons", + "isobutane", + "isobutane_isobutylene", + "isobutylene", + "kerosene", + "kerosene_type_jet_fuel", + "liquified_petroleum_gases", + "lubricants", + "miscellaneous_petroleum_products", + "naphtha_for_petrochemical_feedstock_use", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "normal_butane_butylene", + "normal_butylene", + "other_biofuels", + "other_hydrocarbons", + "other_liquids", + "other_oils_for_petrochemical_feedstock_use", + "pentanes_plus", + "petrochemical_feedstocks", + "petroleum_coke", + "petroleum_coke_catalyst", + "petroleum_coke_marketable", + "propane", + "propane_and_propylene", + "propylene", + "refinery_olefins", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "renewable_diesel_fuel", + "residual_fuel_oil", + "special_naphthas", + "still_gas", + "unfinished_oils", + "waxes", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 716 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumProductSuppliedData(EiaApiData): + """Product Supplied. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumProductSuppliedFetcher( + Fetcher[ + EiaPetroleumProductSuppliedQueryParams, list[EiaPetroleumProductSuppliedData] + ] +): + """Product Supplied fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumProductSuppliedQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaPetroleumProductSuppliedQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaPetroleumProductSuppliedQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumProductSuppliedQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumProductSuppliedData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumProductSuppliedData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/production_capacity_of_operable_petroleum_refineries.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/production_capacity_of_operable_petroleum_refineries.py new file mode 100644 index 00000000000..4d34a065bb0 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/production_capacity_of_operable_petroleum_refineries.py @@ -0,0 +1,201 @@ +"""Production Capacity of Operable Petroleum Refineries model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumProductionCapacityOfOperablePetroleumRefineriesQueryParams( + EiaApiQueryParams +): + """Production Capacity of Operable Petroleum Refineries. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/capprod + """ + + __group__ = "petroleum" + __dataset__ = "production_capacity_of_operable_petroleum_refineries" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "production_capacity_of_alkylates", + "production_capacity_of_aromatics", + "production_capacity_of_asphalt_and_road_oil", + "production_capacity_of_hydrogen", + "production_capacity_of_isobutane", + "production_capacity_of_isomers", + "production_capacity_of_isooctane", + "production_capacity_of_isopentane_isohexane", + "production_capacity_of_lubricants", + "production_capacity_of_marketable_coke", + "production_capacity_of_sulfur", + ], + }, + "product": {"multiple_items_allowed": True}, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "gum", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "pri", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_de", + "usa_ga", + "usa_hi", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_tn", + "usa_ut", + "usa_va", + "usa_wi", + "usa_wv", + "usa_wy", + "vir", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 539 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumProductionCapacityOfOperablePetroleumRefineriesData(EiaApiData): + """Production Capacity of Operable Petroleum Refineries. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumProductionCapacityOfOperablePetroleumRefineriesFetcher( + Fetcher[ + EiaPetroleumProductionCapacityOfOperablePetroleumRefineriesQueryParams, + list[EiaPetroleumProductionCapacityOfOperablePetroleumRefineriesData], + ] +): + """Production Capacity of Operable Petroleum Refineries fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumProductionCapacityOfOperablePetroleumRefineriesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumProductionCapacityOfOperablePetroleumRefineriesQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumProductionCapacityOfOperablePetroleumRefineriesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumProductionCapacityOfOperablePetroleumRefineriesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumProductionCapacityOfOperablePetroleumRefineriesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumProductionCapacityOfOperablePetroleumRefineriesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/propane_prices_by_sales_type.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/propane_prices_by_sales_type.py new file mode 100644 index 00000000000..c8120106f6b --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/propane_prices_by_sales_type.py @@ -0,0 +1,230 @@ +"""Propane (Consumer Grade) Prices by Sales Type model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumPropanePricesBySalesTypeQueryParams(EiaApiQueryParams): + """Propane (Consumer Grade) Prices by Sales Type. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/prop + """ + + __group__ = "petroleum" + __dataset__ = "propane_prices_by_sales_type" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "industrial_price", + "other_end_users_by_all_sellers", + "price_delivered_to_commercial_sectors", + "residential_price_by_all_sellers", + "retail_sales_by_all_sellers", + "sales_to_petrochemical_plants_price", + "through_company_outlets_price", + "wholesale_resale_price_by_all_sellers", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "us", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "central_atlantic_propane_commercial_price_by_all_sellers", + "central_atlantic_propane_industrial_price_by_all_sellers", + "central_atlantic_propane_other_end_users_price_by_all", + "central_atlantic_propane_residential_price_by_all_sellers", + "central_atlantic_propane_retail_sales_by_all_sellers", + "central_atlantic_propane_sales_to_petrochemical_plants", + "central_atlantic_propane_through_company_outlets_price_by", + "central_atlantic_propane_wholesale_resale_price_by_all", + "east_coast_propane_commercial_price_by_all_sellers", + "east_coast_propane_industrial_price_by_all_sellers", + "east_coast_propane_other_end_users_price_by_all_sellers", + "east_coast_propane_residential_price_by_all_sellers", + "east_coast_propane_retail_sales_by_all_sellers", + "east_coast_propane_sales_to_petrochemical_plants_price_by", + "east_coast_propane_through_company_outlets_price_by_all", + "east_coast_propane_wholesale_resale_price_by_all_sellers", + "gulf_coast_propane_commercial_price_by_all_sellers", + "gulf_coast_propane_industrial_price_by_all_sellers", + "gulf_coast_propane_other_end_users_price_by_all_sellers", + "gulf_coast_propane_residential_price_by_all_sellers", + "gulf_coast_propane_retail_sales_by_all_sellers", + "gulf_coast_propane_sales_to_petrochemical_plants_price_by", + "gulf_coast_propane_through_company_outlets_price_by_all", + "gulf_coast_propane_wholesale_resale_price_by_all_sellers", + "lower_atlantic_propane_commercial_price_by_all_sellers", + "lower_atlantic_propane_industrial_price_by_all_sellers", + "lower_atlantic_propane_other_end_users_price_by_all_sellers", + "lower_atlantic_propane_residential_price_by_all_sellers", + "lower_atlantic_propane_retail_sales_by_all_sellers", + "lower_atlantic_propane_sales_to_petrochemical_plants_price", + "lower_atlantic_propane_through_company_outlets_price_by_all", + "lower_atlantic_propane_wholesale_resale_price_by_all_sellers", + "midwest_propane_commercial_price_by_all_sellers", + "midwest_propane_industrial_price_by_all_sellers", + "midwest_propane_other_end_users_price_by_all_sellers", + "midwest_propane_residential_price_by_all_sellers", + "midwest_propane_retail_sales_by_all_sellers", + "midwest_propane_sales_to_petrochemical_plants_price_by_all", + "midwest_propane_through_company_outlets_price_by_all_sellers", + "midwest_propane_wholesale_resale_price_by_all_sellers", + "new_england_propane_commercial_price_by_all_sellers", + "new_england_propane_industrial_price_by_all_sellers", + "new_england_propane_other_end_users_price_by_all_sellers", + "new_england_propane_residential_price_by_all_sellers", + "new_england_propane_retail_sales_by_all_sellers", + "new_england_propane_sales_to_petrochemical_plants_price_by", + "new_england_propane_through_company_outlets_price_by_all", + "new_england_propane_wholesale_resale_price_by_all_sellers", + "rocky_mountain_propane_commercial_price_by_all_sellers", + "rocky_mountain_propane_industrial_price_by_all_sellers", + "rocky_mountain_propane_other_end_users_price_by_all_sellers", + "rocky_mountain_propane_residential_price_by_all_sellers", + "rocky_mountain_propane_retail_sales_by_all_sellers", + "rocky_mountain_propane_sales_to_petrochemical_plants_price", + "rocky_mountain_propane_through_company_outlets_price_by_all", + "rocky_mountain_propane_wholesale_resale_price_by_all_sellers", + "us_propane_commercial_price_by_all_sellers", + "us_propane_industrial_price_by_all_sellers", + "us_propane_other_end_users_price_by_all_sellers", + "us_propane_residential_price_by_all_sellers", + "us_propane_retail_sales_by_all_sellers", + "us_propane_sales_to_petrochemical_plants_price_by_all", + "us_propane_through_company_outlets_price_by_all_sellers", + "us_propane_wholesale_resale_price_by_all_sellers", + "west_coast_propane_commercial_price_by_all_sellers", + "west_coast_propane_industrial_price_by_all_sellers", + "west_coast_propane_other_end_users_price_by_all_sellers", + "west_coast_propane_residential_price_by_all_sellers", + "west_coast_propane_retail_sales_by_all_sellers", + "west_coast_propane_sales_to_petrochemical_plants_price_by", + "west_coast_propane_through_company_outlets_price_by_all", + "west_coast_propane_wholesale_resale_price_by_all_sellers", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumPropanePricesBySalesTypeData(EiaApiData): + """Propane (Consumer Grade) Prices by Sales Type. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumPropanePricesBySalesTypeFetcher( + Fetcher[ + EiaPetroleumPropanePricesBySalesTypeQueryParams, + list[EiaPetroleumPropanePricesBySalesTypeData], + ] +): + """Propane (Consumer Grade) Prices by Sales Type fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumPropanePricesBySalesTypeQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumPropanePricesBySalesTypeQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumPropanePricesBySalesTypeQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumPropanePricesBySalesTypeQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumPropanePricesBySalesTypeData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumPropanePricesBySalesTypeData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/proved_nonproducing_reserves.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/proved_nonproducing_reserves.py new file mode 100644 index 00000000000..2bc7b3428ea --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/proved_nonproducing_reserves.py @@ -0,0 +1,178 @@ +"""Proved Nonproducing Reserves model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumProvedNonproducingReservesQueryParams(EiaApiQueryParams): + """Proved Nonproducing Reserves. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/crd/nprod + """ + + __group__ = "petroleum" + __dataset__ = "proved_nonproducing_reserves" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "associated_dissolved_reserves_in_nonproducing_reservoirs", + "lease_condensate_reserves_in_nonproducing_reservoirs", + "nonassociated_reserves_in_nonproducing_reservoirs", + "reserves_in_nonproducing_reservoirs", + "wet_after_lease_separation_reserves_in_nonproducing", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "crude_oil", + "natural_gas", + "natural_gas_liquids_and_liquid_refinery_gases", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "na", + "new_york", + "ohio", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_mi", + "usa_ms", + "usa_mt", + "usa_nd", + "usa_ne", + "usa_nm", + "usa_ok", + "usa_pa", + "usa_ut", + "usa_va", + "usa_wv", + "usa_wy", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 270 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumProvedNonproducingReservesData(EiaApiData): + """Proved Nonproducing Reserves. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumProvedNonproducingReservesFetcher( + Fetcher[ + EiaPetroleumProvedNonproducingReservesQueryParams, + list[EiaPetroleumProvedNonproducingReservesData], + ] +): + """Proved Nonproducing Reserves fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumProvedNonproducingReservesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumProvedNonproducingReservesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumProvedNonproducingReservesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumProvedNonproducingReservesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumProvedNonproducingReservesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumProvedNonproducingReservesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_acquisition_cost_of_crude_oil.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_acquisition_cost_of_crude_oil.py new file mode 100644 index 00000000000..6ec711ca97e --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_acquisition_cost_of_crude_oil.py @@ -0,0 +1,161 @@ +"""Refiner Acquisition Cost of Crude Oil model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefinerAcquisitionCostOfCrudeOilQueryParams(EiaApiQueryParams): + """Refiner Acquisition Cost of Crude Oil. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/rac2 + """ + + __group__ = "petroleum" + __dataset__ = "refiner_acquisition_cost_of_crude_oil" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "composite_acquisition_cost", + "domestic_acquisition_cost", + "imported_acquisition_cost", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "east_coast_crude_oil_composite_acquisition_cost_by_refiners", + "east_coast_crude_oil_domestic_acquisition_cost_by_refiners", + "east_coast_crude_oil_imported_acquisition_cost_by_refiners", + "gulf_coast_crude_oil_composite_acquisition_cost_by_refiners", + "gulf_coast_crude_oil_domestic_acquisition_cost_by_refiners", + "gulf_coast_crude_oil_imported_acquisition_cost_by_refiners", + "midwest_crude_oil_composite_acquisition_cost_by_refiners", + "midwest_crude_oil_domestic_acquisition_cost_by_refiners", + "midwest_crude_oil_imported_acquisition_cost_by_refiners", + "rocky_mountain_crude_oil_composite_acquisition_cost_by", + "rocky_mountain_crude_oil_domestic_acquisition_cost_by", + "rocky_mountain_crude_oil_imported_acquisition_cost_by", + "us_crude_oil_composite_acquisition_cost_by_refiners", + "us_crude_oil_domestic_acquisition_cost_by_refiners", + "us_crude_oil_imported_acquisition_cost_by_refiners", + "west_coast_crude_oil_composite_acquisition_cost_by_refiners", + "west_coast_crude_oil_domestic_acquisition_cost_by_refiners", + "west_coast_crude_oil_imported_acquisition_cost_by_refiners", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumRefinerAcquisitionCostOfCrudeOilData(EiaApiData): + """Refiner Acquisition Cost of Crude Oil. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefinerAcquisitionCostOfCrudeOilFetcher( + Fetcher[ + EiaPetroleumRefinerAcquisitionCostOfCrudeOilQueryParams, + list[EiaPetroleumRefinerAcquisitionCostOfCrudeOilData], + ] +): + """Refiner Acquisition Cost of Crude Oil fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumRefinerAcquisitionCostOfCrudeOilQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumRefinerAcquisitionCostOfCrudeOilQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefinerAcquisitionCostOfCrudeOilQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefinerAcquisitionCostOfCrudeOilQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefinerAcquisitionCostOfCrudeOilData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumRefinerAcquisitionCostOfCrudeOilData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_gasoline_prices_by_grade_and_sales_type.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_gasoline_prices_by_grade_and_sales_type.py new file mode 100644 index 00000000000..497de883f07 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_gasoline_prices_by_grade_and_sales_type.py @@ -0,0 +1,219 @@ +"""Refiner Gasoline Prices by Grade and Sales Type model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefinerGasolinePricesByGradeAndSalesTypeQueryParams( + EiaApiQueryParams +): + """Refiner Gasoline Prices by Grade and Sales Type. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/refmg + """ + + __group__ = "petroleum" + __dataset__ = "refiner_gasoline_prices_by_grade_and_sales_type" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "bulk_sales_by_refiners_and_gas_plants", + "dtw_sales_price_by_refiners_and_gas_plants", + "other_end_users_by_refiners_and_gas_plants", + "rack_sales_price_by_refiners_and_gas_plants", + "retail_sales_by_refiners_and_gas_plants", + "through_company_outlets_price_by_refiners_and_gas_plants", + "wholesale_resale_price_by_refiners_and_gas_plants", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "midgrade_gasoline", + "premium_gasoline", + "regular_gasoline", + "total_gasoline", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 736 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumRefinerGasolinePricesByGradeAndSalesTypeData(EiaApiData): + """Refiner Gasoline Prices by Grade and Sales Type. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefinerGasolinePricesByGradeAndSalesTypeFetcher( + Fetcher[ + EiaPetroleumRefinerGasolinePricesByGradeAndSalesTypeQueryParams, + list[EiaPetroleumRefinerGasolinePricesByGradeAndSalesTypeData], + ] +): + """Refiner Gasoline Prices by Grade and Sales Type fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumRefinerGasolinePricesByGradeAndSalesTypeQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumRefinerGasolinePricesByGradeAndSalesTypeQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefinerGasolinePricesByGradeAndSalesTypeQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefinerGasolinePricesByGradeAndSalesTypeQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefinerGasolinePricesByGradeAndSalesTypeData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumRefinerGasolinePricesByGradeAndSalesTypeData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_motor_gasoline_sales_volumes.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_motor_gasoline_sales_volumes.py new file mode 100644 index 00000000000..cfd85335abb --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_motor_gasoline_sales_volumes.py @@ -0,0 +1,219 @@ +"""Refiner Motor Gasoline Sales Volumes model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefinerMotorGasolineSalesVolumesQueryParams(EiaApiQueryParams): + """Refiner Motor Gasoline Sales Volumes. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/cons/refmg + """ + + __group__ = "petroleum" + __dataset__ = "refiner_motor_gasoline_sales_volumes" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "bulk_sales", + "dtw_sales_volume", + "rack_sales_volume", + "retail_sales_by_refiners_and_gas_plants", + "through_company_outlets_volume_by_refiners_and_gas_plants", + "wholesale_resale_volume_by_refiners_and_gas_plants", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "conventional_gasoline", + "midgrade_gasoline", + "oxygenated_gasoline", + "premium_gasoline", + "reformulated_motor_gasoline", + "regular_gasoline", + "total_gasoline", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumRefinerMotorGasolineSalesVolumesData(EiaApiData): + """Refiner Motor Gasoline Sales Volumes. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefinerMotorGasolineSalesVolumesFetcher( + Fetcher[ + EiaPetroleumRefinerMotorGasolineSalesVolumesQueryParams, + list[EiaPetroleumRefinerMotorGasolineSalesVolumesData], + ] +): + """Refiner Motor Gasoline Sales Volumes fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumRefinerMotorGasolineSalesVolumesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumRefinerMotorGasolineSalesVolumesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefinerMotorGasolineSalesVolumesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefinerMotorGasolineSalesVolumesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefinerMotorGasolineSalesVolumesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumRefinerMotorGasolineSalesVolumesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_petroleum_product_prices_by_sales_type.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_petroleum_product_prices_by_sales_type.py new file mode 100644 index 00000000000..2993a5cd520 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_petroleum_product_prices_by_sales_type.py @@ -0,0 +1,226 @@ +"""Refiner Petroleum Product Prices by Sales Type model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefinerPetroleumProductPricesBySalesTypeQueryParams( + EiaApiQueryParams +): + """Refiner Petroleum Product Prices by Sales Type. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/refoth + """ + + __group__ = "petroleum" + __dataset__ = "refiner_petroleum_product_prices_by_sales_type" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "retail_sales_by_refiners_and_gas_plants", + "wholesale_resale_price_by_refiners_and_gas_plants", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "aviation_gasoline", + "kerosene", + "kerosene_type_jet_fuel", + "no_1_distillate", + "no_2_diesel", + "no_2_diesel_high_sulfur", + "no_2_diesel_low_sulfur_0_15_ppm", + "no_2_diesel_low_sulfur_15_500_ppm", + "no_2_distillate", + "no_2_fuel_oil_heating_oil", + "no_4_distillate", + "propane", + "residual_fuel_oil", + "residual_fuel_oil_0_to_1_0_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + "total_gasoline", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 796 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumRefinerPetroleumProductPricesBySalesTypeData(EiaApiData): + """Refiner Petroleum Product Prices by Sales Type. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefinerPetroleumProductPricesBySalesTypeFetcher( + Fetcher[ + EiaPetroleumRefinerPetroleumProductPricesBySalesTypeQueryParams, + list[EiaPetroleumRefinerPetroleumProductPricesBySalesTypeData], + ] +): + """Refiner Petroleum Product Prices by Sales Type fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumRefinerPetroleumProductPricesBySalesTypeQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumRefinerPetroleumProductPricesBySalesTypeQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefinerPetroleumProductPricesBySalesTypeQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefinerPetroleumProductPricesBySalesTypeQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefinerPetroleumProductPricesBySalesTypeData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumRefinerPetroleumProductPricesBySalesTypeData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_residual_fuel_oil_and_no4_fuel_sales_volumes.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_residual_fuel_oil_and_no4_fuel_sales_volumes.py new file mode 100644 index 00000000000..ac904c46d99 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_residual_fuel_oil_and_no4_fuel_sales_volumes.py @@ -0,0 +1,239 @@ +"""Refiner Residual Fuel Oil and No 4 Fuel Sales Volumes model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumesQueryParams( + EiaApiQueryParams +): + """Refiner Residual Fuel Oil and No 4 Fuel Sales Volumes. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/cons/refres + """ + + __group__ = "petroleum" + __dataset__ = "refiner_residual_fuel_oil_and_no4_fuel_sales_volumes" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "retail_sales_by_refiners_and_gas_plants", + "wholesale_resale_volume_by_refiners_and_gas_plants", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "no_4_distillate", + "residual_fuel_oil", + "residual_fuel_oil_0_to_1_0_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "us", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "central_atlantic_no_4_distillate_retail_sales_by_refiners", + "central_atlantic_no_4_distillate_wholesale_resale_volume_by", + "central_atlantic_residual_fuel_oil_retail_sales_by_refiners", + "central_atlantic_padd_1b_residual_fuel_oil_sulfur_greater_than_1_retail_sales_by_refiners_thousand_gallons_per_day", + "central_atlantic_padd_1b_residual_fuel_oil_sulfur_greater_than_1_wholesale_resale_volume_by_refiners_thousand_gallons_per_day", + "central_atlantic_padd_1b_residual_fuel_oil_sulfur_less_than_or_equal_to_1_retail_sales_by_refiners_thousand_gallons_per_day", + "central_atlantic_padd_1b_residual_fuel_oil_sulfur_less_than_or_equal_to_1_wholesale_resale_volume_by_refiners_thousand_gallons_per_day", + "central_atlantic_residual_fuel_oil_wholesale_resale_volume", + "east_coast_no_4_distillate_retail_sales_by_refiners", + "east_coast_no_4_distillate_wholesale_resale_volume_by", + "east_coast_residual_fuel_oil_retail_sales_by_refiners", + "east_coast_residual_fuel_oil_sulfur_greater_than_1_retail", + "east_coast_residual_fuel_oil_sulfur_greater_than_1", + "east_coast_padd_1_residual_fuel_oil_sulfur_less_than_or_equal_to_1_retail_sales_by_refiners_thousand_gallons_per_day", + "east_coast_padd_1_residual_fuel_oil_sulfur_less_than_or_equal_to_1_wholesale_resale_volume_by_refiners_thousand_gallons_per_day", + "east_coast_residual_fuel_oil_wholesale_resale_volume_by", + "gulf_coast_no_4_distillate_retail_sales_by_refiners", + "gulf_coast_no_4_distillate_wholesale_resale_volume_by", + "gulf_coast_residual_fuel_oil_retail_sales_by_refiners", + "gulf_coast_residual_fuel_oil_sulfur_greater_than_1_retail", + "gulf_coast_residual_fuel_oil_sulfur_greater_than_1", + "gulf_coast_padd_3_residual_fuel_oil_sulfur_less_than_or_equal_to_1_retail_sales_by_refiners_thousand_gallons_per_day", + "gulf_coast_padd_3_residual_fuel_oil_sulfur_less_than_or_equal_to_1_wholesale_resale_volume_by_refiners_thousand_gallons_per_day", + "gulf_coast_residual_fuel_oil_wholesale_resale_volume_by", + "lower_atlantic_no_4_distillate_retail_sales_by_refiners", + "lower_atlantic_no_4_distillate_wholesale_resale_volume_by", + "lower_atlantic_residual_fuel_oil_retail_sales_by_refiners", + "lower_atlantic_padd_1c_residual_fuel_oil_sulfur_greater_than_1_retail_sales_by_refiners_thousand_gallons_per_day", + "lower_atlantic_padd_1c_residual_fuel_oil_sulfur_greater_than_1_wholesale_resale_volume_by_refiners_thousand_gallons_per_day", + "lower_atlantic_padd_1c_residual_fuel_oil_sulfur_less_than_or_equal_to_1_retail_sales_by_refiners_thousand_gallons_per_day", + "lower_atlantic_padd_1c_residual_fuel_oil_sulfur_less_than_or_equal_to_1_wholesale_resale_volume_by_refiners_thousand_gallons_per_day", + "lower_atlantic_residual_fuel_oil_wholesale_resale_volume_by", + "midwest_no_4_distillate_retail_sales_by_refiners", + "midwest_no_4_distillate_wholesale_resale_volume_by_refiners", + "midwest_residual_fuel_oil_retail_sales_by_refiners", + "midwest_residual_fuel_oil_sulfur_greater_than_1_retail", + "midwest_residual_fuel_oil_sulfur_greater_than_1_wholesale", + "midwest_padd_2_residual_fuel_oil_sulfur_less_than_or_equal_to_1_retail_sales_by_refiners_thousand_gallons_per_day", + "midwest_padd_2_residual_fuel_oil_sulfur_less_than_or_equal_to_1_wholesale_resale_volume_by_refiners_thousand_gallons_per_day", + "midwest_residual_fuel_oil_wholesale_resale_volume_by", + "new_england_no_4_distillate_retail_sales_by_refiners", + "new_england_no_4_distillate_wholesale_resale_volume_by", + "new_england_residual_fuel_oil_retail_sales_by_refiners", + "new_england_residual_fuel_oil_sulfur_greater_than_1_retail", + "new_england_residual_fuel_oil_sulfur_greater_than_1", + "new_england_padd_1a_residual_fuel_oil_sulfur_less_than_or_equal_to_1_retail_sales_by_refiners_thousand_gallons_per_day", + "new_england_padd_1a_residual_fuel_oil_sulfur_less_than_or_equal_to_1_wholesale_resale_volume_by_refiners_thousand_gallons_per_day", + "new_england_residual_fuel_oil_wholesale_resale_volume_by", + "rocky_mountain_no_4_distillate_retail_sales_by_refiners", + "rocky_mountain_no_4_distillate_wholesale_resale_volume_by", + "rocky_mountain_residual_fuel_oil_retail_sales_by_refiners", + "rocky_mountain_padd_4_residual_fuel_oil_sulfur_greater_than_1_retail_sales_by_refiners_thousand_gallons_per_day", + "rocky_mountain_padd_4_residual_fuel_oil_sulfur_greater_than_1_wholesale_resale_volume_by_refiners_thousand_gallons_per_day", + "rocky_mountain_padd_4_residual_fuel_oil_sulfur_less_than_or_equal_to_1_retail_sales_by_refiners_thousand_gallons_per_day", + "rocky_mountain_padd_4_residual_fuel_oil_sulfur_less_than_or_equal_to_1_wholesale_resale_volume_by_refiners_thousand_gallons_per_day", + "rocky_mountain_residual_fuel_oil_wholesale_resale_volume_by", + "us_no_4_distillate_retail_sales_by_refiners", + "us_no_4_distillate_wholesale_resale_volume_by_refiners", + "us_residual_fuel_oil_retail_sales_by_refiners", + "us_residual_fuel_oil_sulfur_greater_than_1_retail_sales_by", + "us_residual_fuel_oil_sulfur_greater_than_1_wholesale_resale", + "us_residual_fuel_oil_sulfur_less_than_or_equal_to_1_retail", + "us_residual_fuel_oil_sulfur_less_than_or_equal_to_1", + "us_residual_fuel_oil_wholesale_resale_volume_by_refiners", + "west_coast_no_4_distillate_retail_sales_by_refiners", + "west_coast_no_4_distillate_wholesale_resale_volume_by", + "west_coast_residual_fuel_oil_retail_sales_by_refiners", + "west_coast_residual_fuel_oil_sulfur_greater_than_1_retail", + "west_coast_residual_fuel_oil_sulfur_greater_than_1", + "west_coast_padd_5_residual_fuel_oil_sulfur_less_than_or_equal_to_1_retail_sales_by_refiners_thousand_gallons_per_day", + "west_coast_padd_5_residual_fuel_oil_sulfur_less_than_or_equal_to_1_wholesale_resale_volume_by_refiners_thousand_gallons_per_day", + "west_coast_residual_fuel_oil_wholesale_resale_volume_by", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumesData(EiaApiData): + """Refiner Residual Fuel Oil and No 4 Fuel Sales Volumes. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumesFetcher( + Fetcher[ + EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumesQueryParams, + list[EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumesData], + ] +): + """Refiner Residual Fuel Oil and No 4 Fuel Sales Volumes fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_sales_volumes_of_other_petroleum_products.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_sales_volumes_of_other_petroleum_products.py new file mode 100644 index 00000000000..7e72193cced --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refiner_sales_volumes_of_other_petroleum_products.py @@ -0,0 +1,221 @@ +"""Refiner Sales Volumes of Other Petroleum Products model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProductsQueryParams( + EiaApiQueryParams +): + """Refiner Sales Volumes of Other Petroleum Products. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/cons/refoth + """ + + __group__ = "petroleum" + __dataset__ = "refiner_sales_volumes_of_other_petroleum_products" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "retail_sales_by_refiners_and_gas_plants", + "wholesale_resale_volume_by_refiners_and_gas_plants", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "aviation_gasoline", + "kerosene", + "kerosene_type_jet_fuel", + "no_1_distillate", + "no_2_diesel", + "no_2_diesel_high_sulfur", + "no_2_diesel_low_sulfur_0_15_ppm", + "no_2_diesel_low_sulfur_15_500_ppm", + "no_2_distillate", + "no_2_fuel_oil_heating_oil", + "propane", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProductsData(EiaApiData): + """Refiner Sales Volumes of Other Petroleum Products. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProductsFetcher( + Fetcher[ + EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProductsQueryParams, + list[EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProductsData], + ] +): + """Refiner Sales Volumes of Other Petroleum Products fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProductsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProductsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProductsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProductsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProductsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProductsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_blender_net_input.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_blender_net_input.py new file mode 100644 index 00000000000..847da7aed0c --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_blender_net_input.py @@ -0,0 +1,175 @@ +"""Refinery & Blender Net Input model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefineryBlenderNetInputQueryParams(EiaApiQueryParams): + """Refinery & Blender Net Input. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/inpt + """ + + __group__ = "petroleum" + __dataset__ = "refinery_blender_net_input" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "aviation_gasoline_blending_components", + "biodiesel", + "biodiesel_renewable_diesel_fuel", + "biofuel_fuels", + "biofuel_fuels_excluding_fuel_ethanol", + "conventional_cbob_gasoline_blending_components", + "conventional_gtab_gasoline_blending_components", + "conventional_gasoline_blending_components", + "conventional_other_gasoline_blending_components", + "crude_oil", + "crude_oil_and_petroleum_products", + "fuel_ethanol", + "gasoline_blending_components", + "heavy_gas_oils", + "hydrogen", + "hydrogen_oxygenates_renewables_fuels_and_other_hydrocarbons", + "isobutane", + "kerosene_and_light_oils", + "liquified_petroleum_gases", + "mtbe", + "motor_gasoline_blending_components_reformulated_rbob", + "naphthas_and_lighter", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "other_biofuels", + "other_hydrocarbons", + "other_liquids", + "other_oxygenates", + "oxygenates", + "pentanes_plus", + "reformulated_gtab_gasoline_blending_components", + "reformulated_gasoline_blending_components", + "reformulated_rbob_with_alcohol_gasoline_blending_components", + "reformulated_rbob_with_ether_gasoline_blending_components", + "renewable_diesel_fuel", + "residuum", + "unfinished_oils", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumRefineryBlenderNetInputData(EiaApiData): + """Refinery & Blender Net Input. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefineryBlenderNetInputFetcher( + Fetcher[ + EiaPetroleumRefineryBlenderNetInputQueryParams, + list[EiaPetroleumRefineryBlenderNetInputData], + ] +): + """Refinery & Blender Net Input fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumRefineryBlenderNetInputQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumRefineryBlenderNetInputQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefineryBlenderNetInputQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefineryBlenderNetInputQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefineryBlenderNetInputData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumRefineryBlenderNetInputData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_blender_net_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_blender_net_production.py new file mode 100644 index 00000000000..3c8743c2c26 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_blender_net_production.py @@ -0,0 +1,186 @@ +"""Refinery & Blender Net Production model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefineryBlenderNetProductionQueryParams(EiaApiQueryParams): + """Refinery & Blender Net Production. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/refp + """ + + __group__ = "petroleum" + __dataset__ = "refinery_blender_net_production" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "ethane", + "ethane_ethylene", + "ethylene", + "finished_motor_gasoline", + "finished_motor_gasoline_conventional_55", + "finished_motor_gasoline_reformulated_other", + "isobutane", + "isobutane_isobutylene", + "isobutylene", + "kerosene", + "kerosene_type_jet_fuel", + "liquified_petroleum_gases", + "lubricants", + "miscellaneous_petroleum_products", + "motor_gasoline_finished_conventional_ed55_and_lower", + "naphtha_for_petrochemical_feedstock_use", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "normal_butane", + "normal_butane_butylene", + "normal_butylene", + "other_conventional_motor_gasoline", + "other_oils_for_petrochemical_feedstock_use", + "petrochemical_feedstocks", + "petroleum_coke", + "petroleum_coke_catalyst", + "petroleum_coke_marketable", + "processing_gain", + "propane", + "propane_and_propylene", + "propylene", + "refinery_olefins", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + "residual_fuel_oil", + "residual_fuel_oil_0_31_to_1_00_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + "residual_fuel_oil_less_than_0_31_sulfur", + "special_naphthas", + "still_gas", + "waxes", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumRefineryBlenderNetProductionData(EiaApiData): + """Refinery & Blender Net Production. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefineryBlenderNetProductionFetcher( + Fetcher[ + EiaPetroleumRefineryBlenderNetProductionQueryParams, + list[EiaPetroleumRefineryBlenderNetProductionData], + ] +): + """Refinery & Blender Net Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumRefineryBlenderNetProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumRefineryBlenderNetProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefineryBlenderNetProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefineryBlenderNetProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefineryBlenderNetProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumRefineryBlenderNetProductionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_bulk_terminal_and_natural_gas_plant_stocks_by_state.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_bulk_terminal_and_natural_gas_plant_stocks_by_state.py new file mode 100644 index 00000000000..8e00fa54486 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_bulk_terminal_and_natural_gas_plant_stocks_by_state.py @@ -0,0 +1,212 @@ +"""Refinery, Bulk Terminal, and Natural Gas Plant Stocks by State model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByStateQueryParams( + EiaApiQueryParams +): + """Refinery, Bulk Terminal, and Natural Gas Plant Stocks by State. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/stoc/st + """ + + __group__ = "petroleum" + __dataset__ = "refinery_bulk_terminal_and_natural_gas_plant_stocks_by_state" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "finished_motor_gasoline", + "gasoline_blending_components", + "kerosene", + "propane", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "residual_fuel_oil", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 691 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByStateData(EiaApiData): + """Refinery, Bulk Terminal, and Natural Gas Plant Stocks by State. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByStateFetcher( + Fetcher[ + EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByStateQueryParams, + list[EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByStateData], + ] +): + """Refinery, Bulk Terminal, and Natural Gas Plant Stocks by State fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByStateQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByStateQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByStateQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByStateQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByStateData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByStateData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_net_input.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_net_input.py new file mode 100644 index 00000000000..b3bef1c40c3 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_net_input.py @@ -0,0 +1,177 @@ +"""Refinery Net Input model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefineryNetInputQueryParams(EiaApiQueryParams): + """Refinery Net Input. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/inpt2 + """ + + __group__ = "petroleum" + __dataset__ = "refinery_net_input" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": ["refinery_net_input", "refinery_receipts_of_alaskan_oil"], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "aviation_gasoline_blending_components", + "biodiesel", + "biodiesel_renewable_diesel_fuel", + "biofuel_fuels", + "biofuel_fuels_excluding_fuel_ethanol", + "conventional_cbob_gasoline_blending_components", + "conventional_gtab_gasoline_blending_components", + "conventional_gasoline_blending_components", + "conventional_other_gasoline_blending_components", + "crude_oil", + "crude_oil_and_petroleum_products", + "fuel_ethanol", + "gasoline_blending_components", + "heavy_gas_oils", + "hydrogen", + "hydrogen_oxygenates_renewables_fuels_and_other_hydrocarbons", + "isobutane", + "kerosene_and_light_oils", + "liquified_petroleum_gases", + "mtbe", + "motor_gasoline_blending_components_reformulated_rbob", + "naphthas_and_lighter", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "other_biofuels", + "other_hydrocarbons", + "other_liquids", + "other_oxygenates", + "oxygenates", + "pentanes_plus", + "reformulated_gasoline_blending_components", + "reformulated_rbob_with_alcohol_gasoline_blending_components", + "reformulated_rbob_with_ether_gasoline_blending_components", + "renewable_diesel_fuel", + "residuum", + "unfinished_oils", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumRefineryNetInputData(EiaApiData): + """Refinery Net Input. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefineryNetInputFetcher( + Fetcher[ + EiaPetroleumRefineryNetInputQueryParams, list[EiaPetroleumRefineryNetInputData] + ] +): + """Refinery Net Input fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumRefineryNetInputQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaPetroleumRefineryNetInputQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefineryNetInputQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefineryNetInputQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefineryNetInputData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumRefineryNetInputData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_net_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_net_production.py new file mode 100644 index 00000000000..59183a0326b --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_net_production.py @@ -0,0 +1,192 @@ +"""Refinery Net Production model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefineryNetProductionQueryParams(EiaApiQueryParams): + """Refinery Net Production. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/refp2 + """ + + __group__ = "petroleum" + __dataset__ = "refinery_net_production" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "commercial_kerosene_type_jet_fuel", + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "ethane", + "ethane_ethylene", + "ethylene", + "finished_motor_gasoline", + "finished_motor_gasoline_conventional_55", + "finished_motor_gasoline_reformulated_other", + "isobutane", + "isobutane_isobutylene", + "isobutylene", + "kerosene", + "kerosene_type_jet_fuel", + "liquified_petroleum_gases", + "lubricants", + "military_kerosene_type_jet_fuel", + "miscellaneous_petroleum_products", + "miscellaneous_petroleum_products_for_fuel_use", + "miscellaneous_petroleum_products_for_nonfuel_use", + "motor_gasoline_finished_conventional_ed55_and_lower", + "naphtha_for_petrochemical_feedstock_use", + "naphthenic_lubricants", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "normal_butane", + "normal_butane_butylene", + "normal_butylene", + "other_conventional_motor_gasoline", + "other_oils_for_petrochemical_feedstock_use", + "paraffinic_lubricants", + "petrochemical_feedstocks", + "petroleum_coke", + "petroleum_coke_catalyst", + "petroleum_coke_marketable", + "processing_gain", + "propane", + "propane_and_propylene", + "propylene", + "refinery_olefins", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + "residual_fuel_oil", + "residual_fuel_oil_0_31_to_1_00_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + "residual_fuel_oil_less_than_0_31_sulfur", + "special_naphthas", + "still_gas", + "waxes", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumRefineryNetProductionData(EiaApiData): + """Refinery Net Production. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefineryNetProductionFetcher( + Fetcher[ + EiaPetroleumRefineryNetProductionQueryParams, + list[EiaPetroleumRefineryNetProductionData], + ] +): + """Refinery Net Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumRefineryNetProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumRefineryNetProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefineryNetProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefineryNetProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefineryNetProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumRefineryNetProductionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_receipts_of_crude_oil_by_method_of_transportation.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_receipts_of_crude_oil_by_method_of_transportation.py new file mode 100644 index 00000000000..d46a59f7ce6 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_receipts_of_crude_oil_by_method_of_transportation.py @@ -0,0 +1,160 @@ +"""Refinery Receipts of Crude Oil by Method of Transportation model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportationQueryParams( + EiaApiQueryParams +): + """Refinery Receipts of Crude Oil by Method of Transportation. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/caprec + """ + + __group__ = "petroleum" + __dataset__ = "refinery_receipts_of_crude_oil_by_method_of_transportation" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "crude_oil_refinery_receipts", + "crude_oil_refinery_receipts_by_barge", + "crude_oil_refinery_receipts_by_pipeline", + "crude_oil_refinery_receipts_by_tank_car", + "crude_oil_refinery_receipts_by_tanker", + "crude_oil_refinery_receipts_by_truck", + "domestic_crude_oil_refinery_receipts", + "domestic_crude_oil_refinery_receipts_by_barge", + "domestic_crude_oil_refinery_receipts_by_pipeline", + "domestic_crude_oil_refinery_receipts_by_tank_car", + "domestic_crude_oil_refinery_receipts_by_tanker", + "domestic_crude_oil_refinery_receipts_by_truck", + "foreign_crude_oil_barge_refinery_receipts", + "foreign_crude_oil_refinery_receipts", + "foreign_crude_oil_refinery_receipts_by_pipeline", + "foreign_crude_oil_refinery_receipts_by_tank_car", + "foreign_crude_oil_refinery_receipts_by_tanker", + "foreign_crude_oil_refinery_receipts_by_truck", + ], + }, + "product": {"multiple_items_allowed": True}, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 108 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportationData(EiaApiData): + """Refinery Receipts of Crude Oil by Method of Transportation. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportationFetcher( + Fetcher[ + EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportationQueryParams, + list[EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportationData], + ] +): + """Refinery Receipts of Crude Oil by Method of Transportation fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportationQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportationQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportationQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportationQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportationData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportationData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_stocks.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_stocks.py new file mode 100644 index 00000000000..a91bf455d0e --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_stocks.py @@ -0,0 +1,203 @@ +"""Refinery Stocks model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefineryStocksQueryParams(EiaApiQueryParams): + """Refinery Stocks. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/stoc/ref + """ + + __group__ = "petroleum" + __dataset__ = "refinery_stocks" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "aviation_gasoline_blending_components", + "biodiesel_renewable_diesel_fuel", + "biofuel_fuels", + "conventional_cbob_gasoline_blending_components", + "conventional_gtab_gasoline_blending_components", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "conventional_other_gasoline_blending_components", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "ethane", + "ethane_ethylene", + "ethylene", + "finished_motor_gasoline", + "finished_motor_gasoline_reformulated_other", + "fuel_ethanol", + "gasoline_blending_components", + "heavy_gas_oils", + "hydrogen_oxygenates_renewables_fuels_and_other_hydrocarbons", + "isobutane", + "isobutane_isobutylene", + "isobutylene", + "kerosene", + "kerosene_and_light_oils", + "kerosene_type_jet_fuel", + "liquified_petroleum_gases", + "lubricants", + "mtbe", + "miscellaneous_petroleum_products", + "motor_gasoline_blending_components_reformulated_rbob", + "motor_gasoline_finished_conventional_ed55_and_lower", + "naphtha_for_petrochemical_feedstock_use", + "naphthas_and_lighter", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "normal_butane_butylene", + "normal_butylene", + "other_biofuels", + "other_conventional_motor_gasoline", + "other_hydrocarbons", + "other_oils_for_petrochemical_feedstock_use", + "other_oxygenates", + "oxygenates", + "pentanes_plus", + "petrochemical_feedstocks", + "petroleum_coke", + "petroleum_coke_marketable", + "propane", + "propane_and_propylene", + "propylene", + "refinery_olefins", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + "reformulated_rbob_with_alcohol_gasoline_blending_components", + "reformulated_rbob_with_ether_gasoline_blending_components", + "residual_fuel_oil", + "residual_fuel_oil_0_31_to_1_00_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + "residual_fuel_oil_less_than_0_31_sulfur", + "residuum", + "special_naphthas", + "total_petroleum_products", + "unfinished_oils", + "waxes", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumRefineryStocksData(EiaApiData): + """Refinery Stocks. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefineryStocksFetcher( + Fetcher[EiaPetroleumRefineryStocksQueryParams, list[EiaPetroleumRefineryStocksData]] +): + """Refinery Stocks fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumRefineryStocksQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaPetroleumRefineryStocksQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefineryStocksQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefineryStocksQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefineryStocksData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumRefineryStocksData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_utilization_and_capacity.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_utilization_and_capacity.py new file mode 100644 index 00000000000..a0f3440e71a --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_utilization_and_capacity.py @@ -0,0 +1,225 @@ +"""Refinery Utilization and Capacity model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefineryUtilizationAndCapacityQueryParams(EiaApiQueryParams): + """Refinery Utilization and Capacity. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/unc + """ + + __group__ = "petroleum" + __dataset__ = "refinery_utilization_and_capacity" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "utilization_refinery_operable_capacity", + "refinery_idle_operable_capacity", + "refinery_net_input", + "refinery_operable_capacity", + "refinery_operating_capacity", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "appalachian_no_1_refinery_district_gross_inputs_to", + "appalachian_no_1_refining_district_idle_crude_oil", + "appalachian_no_1_refining_district_operable_crude_oil", + "appalachian_no_1_refining_district_operating_crude_oil", + "appalachian_no_1_refining_district_percent_utilization_of", + "east_coast_gross_inputs_to_atmospheric_crude_oil", + "east_coast_idle_crude_oil_distillation_capacity", + "east_coast_operable_crude_oil_distillation_capacity", + "east_coast_operating_crude_oil_distillation_capacity", + "east_coast_percent_utilization_of_refinery_operable_capacity", + "east_coast_refining_district_idle_crude_oil_distillation", + "east_coast_refining_district_operable_crude_oil", + "east_coast_refining_district_operating_crude_oil", + "east_coast_refining_district_percent_utilization_of", + "gulf_coast_gross_inputs_to_refineries", + "gulf_coast_idle_crude_oil_distillation_capacity", + "gulf_coast_operable_crude_oil_distillation_capacity", + "gulf_coast_operating_crude_oil_distillation_capacity", + "gulf_coast_percent_utilization_of_refinery_operable_capacity", + "indiana_illinois_kentucky_refinery_district_gross_inputs_to", + "indiana_illinois_and_kentucky_refining_district_idle_crude", + "indiana_illinois_and_kentucky_refining_district_operable", + "indiana_illinois_and_kentucky_refining_district_operating", + "indiana_illinois_and_kentucky_refining_district_percent", + "louisiana_gulf_coast_refinery_district_gross_inputs_to", + "louisiana_gulf_coast_refining_district_idle_crude_oil", + "louisiana_gulf_coast_refining_district_operable_crude_oil", + "louisiana_gulf_coast_refining_district_operating_crude_oil", + "louisiana_gulf_coast_refining_district_percent_utilization", + "midwest_gross_inputs_to_refineries", + "midwest_idle_crude_oil_distillation_capacity", + "midwest_operable_crude_oil_distillation_capacity", + "midwest_operating_crude_oil_distillation_capacity", + "midwest_percent_utilization_of_refinery_operable_capacity", + "minnesota_wisconsin_north_and_south_dakota_refinery", + "minnesota_wisconsin_north_and_south_dakota_refining_district_idle_crude_oil_distillation_capacity_thousand_barrels_per_day", + "minnesota_wisconsin_north_and_south_dakota_refining_district_operable_crude_oil_distillation_capacity_thousand_barrels_per_calendar_day", + "minnesota_wisconsin_north_and_south_dakota_refining_district_operating_crude_oil_distillation_capacity_thousand_barrels_per_day", + "minnesota_wisconsin_north_and_south_dakota_refining_district_percent_utilization_of_refinery_operable_capacity", + "new_mexico_refining_district_idle_crude_oil_distillation", + "new_mexico_refining_district_operable_crude_oil", + "new_mexico_refining_district_operating_crude_oil", + "new_mexico_refining_district_percent_utilization_of", + "north_louisiana_and_arkansas_refining_district_idle_crude", + "north_louisiana_and_arkansas_refining_district_operable", + "north_louisiana_and_arkansas_refining_district_operating", + "north_louisiana_arkansas_refining_district_percent", + "oklahoma_kansas_missouri_refining_district_percent", + "oklahoma_kansas_and_missouri_refining_district_idle_crude", + "oklahoma_kansas_and_missouri_refining_district_operable", + "oklahoma_kansas_and_missouri_refining_district_operating", + "refining_district_east_coast_refinery_district_gross_inputs", + "refining_district_new_mexico_gross_inputs_to_atmospheric", + "refining_district_north_louisiana_arkansas_gross_inputs_to", + "refining_district_oklahoma_kansas_missouri_gross_inputs_to", + "refining_district_texas_gulf_coast_gross_inputs_to", + "rocky_mountains_gross_inputs_to_refineries", + "rocky_mountains_idle_crude_oil_distillation_capacity", + "rocky_mountains_operable_crude_oil_distillation_capacity", + "rocky_mountains_operating_crude_oil_distillation_capacity", + "rocky_mountains_percent_utilization_of_refinery_operable", + "texas_gulf_coast_refining_district_idle_crude_oil", + "texas_gulf_coast_refining_district_operable_crude_oil", + "texas_gulf_coast_refining_district_operating_crude_oil", + "texas_gulf_coast_refining_district_percent_utilization_of", + "texas_inland_refinery_district_gross_inputs_to_refineries", + "texas_inland_refining_district_idle_crude_oil_distillation", + "texas_inland_refining_district_operable_crude_oil", + "texas_inland_refining_district_operating_crude_oil", + "texas_inland_refining_district_percent_utilization_of", + "u_s_idle_crude_oil_distillation_capacity", + "u_s_operable_crude_oil_distillation_capacity", + "u_s_operating_crude_oil_distillation_capacity", + "us_gross_inputs_to_refineries", + "us_percent_utilization_of_refinery_operable_capacity", + "west_coast_gross_inputs_to_refineries", + "west_coast_idle_crude_oil_distillation_capacity", + "west_coast_operable_crude_oil_distillation_capacity", + "west_coast_operating_crude_oil_distillation_capacity", + "west_coast_percent_utilization_of_refinery_operable_capacity", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumRefineryUtilizationAndCapacityData(EiaApiData): + """Refinery Utilization and Capacity. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefineryUtilizationAndCapacityFetcher( + Fetcher[ + EiaPetroleumRefineryUtilizationAndCapacityQueryParams, + list[EiaPetroleumRefineryUtilizationAndCapacityData], + ] +): + """Refinery Utilization and Capacity fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumRefineryUtilizationAndCapacityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumRefineryUtilizationAndCapacityQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefineryUtilizationAndCapacityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefineryUtilizationAndCapacityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefineryUtilizationAndCapacityData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumRefineryUtilizationAndCapacityData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_yield.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_yield.py new file mode 100644 index 00000000000..cefeeb1df71 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/refinery_yield.py @@ -0,0 +1,144 @@ +"""Refinery Yield model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumRefineryYieldQueryParams(EiaApiQueryParams): + """Refinery Yield. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/pct + """ + + __group__ = "petroleum" + __dataset__ = "refinery_yield" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "distillate_fuel_oil", + "finished_motor_gasoline", + "kerosene", + "kerosene_type_jet_fuel", + "lubricants", + "miscellaneous_petroleum_products", + "naphtha_for_petrochemical_feedstock_use", + "natural_gas_liquids_and_liquid_refinery_gases", + "other_oils_for_petrochemical_feedstock_use", + "petroleum_coke", + "processing_gain", + "residual_fuel_oil", + "special_naphthas", + "still_gas", + "waxes", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 262 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumRefineryYieldData(EiaApiData): + """Refinery Yield. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumRefineryYieldFetcher( + Fetcher[EiaPetroleumRefineryYieldQueryParams, list[EiaPetroleumRefineryYieldData]] +): + """Refinery Yield fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaPetroleumRefineryYieldQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaPetroleumRefineryYieldQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaPetroleumRefineryYieldQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumRefineryYieldQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumRefineryYieldData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumRefineryYieldData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/residual_fuel_oil_prices_by_sales_type.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/residual_fuel_oil_prices_by_sales_type.py new file mode 100644 index 00000000000..5654cc98e5a --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/residual_fuel_oil_prices_by_sales_type.py @@ -0,0 +1,211 @@ +"""Residual Fuel Oil Prices by Sales Type model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumResidualFuelOilPricesBySalesTypeQueryParams(EiaApiQueryParams): + """Residual Fuel Oil Prices by Sales Type. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/resid + """ + + __group__ = "petroleum" + __dataset__ = "residual_fuel_oil_prices_by_sales_type" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "retail_sales_by_all_sellers", + "wholesale_resale_price_by_all_sellers", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "residual_fuel_oil", + "residual_fuel_oil_0_to_1_0_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 360 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumResidualFuelOilPricesBySalesTypeData(EiaApiData): + """Residual Fuel Oil Prices by Sales Type. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumResidualFuelOilPricesBySalesTypeFetcher( + Fetcher[ + EiaPetroleumResidualFuelOilPricesBySalesTypeQueryParams, + list[EiaPetroleumResidualFuelOilPricesBySalesTypeData], + ] +): + """Residual Fuel Oil Prices by Sales Type fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumResidualFuelOilPricesBySalesTypeQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumResidualFuelOilPricesBySalesTypeQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumResidualFuelOilPricesBySalesTypeQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumResidualFuelOilPricesBySalesTypeQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumResidualFuelOilPricesBySalesTypeData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumResidualFuelOilPricesBySalesTypeData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/sales_of_distillate_fuel_oil_by_end_use.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/sales_of_distillate_fuel_oil_by_end_use.py new file mode 100644 index 00000000000..ded685ec577 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/sales_of_distillate_fuel_oil_by_end_use.py @@ -0,0 +1,214 @@ +"""Sales of Distillate Fuel Oil by End Use model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumSalesOfDistillateFuelOilByEndUseQueryParams(EiaApiQueryParams): + """Sales of Distillate Fuel Oil by End Use. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/cons/821dst + """ + + __group__ = "petroleum" + __dataset__ = "sales_of_distillate_fuel_oil_by_end_use" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "commercial_consumption", + "electric_power_consumption", + "industrial_consumption", + "residential_consumption", + "retail_deliveries", + "sales_deliveries_to_farm_consumers", + "sales_deliveries_to_military_consumers", + "sales_deliveries_to_off_highway_consumers", + "sales_deliveries_to_oil_company_consumers", + "sales_deliveries_to_on_highway_consumers", + "sales_deliveries_to_other_end_users", + "sales_deliveries_to_railroad_consumers", + "sales_deliveries_to_vessel_bunkering_consumers", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": ["distillate_fuel_oil", "no_2_diesel"], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 780 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumSalesOfDistillateFuelOilByEndUseData(EiaApiData): + """Sales of Distillate Fuel Oil by End Use. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumSalesOfDistillateFuelOilByEndUseFetcher( + Fetcher[ + EiaPetroleumSalesOfDistillateFuelOilByEndUseQueryParams, + list[EiaPetroleumSalesOfDistillateFuelOilByEndUseData], + ] +): + """Sales of Distillate Fuel Oil by End Use fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumSalesOfDistillateFuelOilByEndUseQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumSalesOfDistillateFuelOilByEndUseQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumSalesOfDistillateFuelOilByEndUseQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumSalesOfDistillateFuelOilByEndUseQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumSalesOfDistillateFuelOilByEndUseData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumSalesOfDistillateFuelOilByEndUseData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/sales_of_kerosene_by_end_use.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/sales_of_kerosene_by_end_use.py new file mode 100644 index 00000000000..a6c50bd1986 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/sales_of_kerosene_by_end_use.py @@ -0,0 +1,199 @@ +"""Sales of Kerosene by End Use model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumSalesOfKeroseneByEndUseQueryParams(EiaApiQueryParams): + """Sales of Kerosene by End Use. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/cons/821ker + """ + + __group__ = "petroleum" + __dataset__ = "sales_of_kerosene_by_end_use" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "commercial_consumption", + "industrial_consumption", + "residential_consumption", + "retail_deliveries", + "sales_deliveries_to_farm_consumers", + "sales_deliveries_to_other_end_users", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 360 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumSalesOfKeroseneByEndUseData(EiaApiData): + """Sales of Kerosene by End Use. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumSalesOfKeroseneByEndUseFetcher( + Fetcher[ + EiaPetroleumSalesOfKeroseneByEndUseQueryParams, + list[EiaPetroleumSalesOfKeroseneByEndUseData], + ] +): + """Sales of Kerosene by End Use fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumSalesOfKeroseneByEndUseQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumSalesOfKeroseneByEndUseQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumSalesOfKeroseneByEndUseQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumSalesOfKeroseneByEndUseQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumSalesOfKeroseneByEndUseData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumSalesOfKeroseneByEndUseData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/sales_of_residual_fuel_oil_by_end_use.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/sales_of_residual_fuel_oil_by_end_use.py new file mode 100644 index 00000000000..179c53c3401 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/sales_of_residual_fuel_oil_by_end_use.py @@ -0,0 +1,201 @@ +"""Sales of Residual Fuel Oil by End Use model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumSalesOfResidualFuelOilByEndUseQueryParams(EiaApiQueryParams): + """Sales of Residual Fuel Oil by End Use. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/cons/821rsd + """ + + __group__ = "petroleum" + __dataset__ = "sales_of_residual_fuel_oil_by_end_use" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "commercial_consumption", + "electric_power_consumption", + "industrial_consumption", + "retail_deliveries", + "sales_deliveries_to_military_consumers", + "sales_deliveries_to_oil_company_consumers", + "sales_deliveries_to_other_end_users", + "sales_deliveries_to_vessel_bunkering_consumers", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + "usa_wv", + "usa_wy", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 480 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumSalesOfResidualFuelOilByEndUseData(EiaApiData): + """Sales of Residual Fuel Oil by End Use. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumSalesOfResidualFuelOilByEndUseFetcher( + Fetcher[ + EiaPetroleumSalesOfResidualFuelOilByEndUseQueryParams, + list[EiaPetroleumSalesOfResidualFuelOilByEndUseData], + ] +): + """Sales of Residual Fuel Oil by End Use fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumSalesOfResidualFuelOilByEndUseQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumSalesOfResidualFuelOilByEndUseQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumSalesOfResidualFuelOilByEndUseQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumSalesOfResidualFuelOilByEndUseQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumSalesOfResidualFuelOilByEndUseData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumSalesOfResidualFuelOilByEndUseData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/shell_storage_capacity_at_operable_refineries.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/shell_storage_capacity_at_operable_refineries.py new file mode 100644 index 00000000000..f1bfa536c55 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/shell_storage_capacity_at_operable_refineries.py @@ -0,0 +1,167 @@ +"""Shell Storage Capacity at Operable Refineries model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumShellStorageCapacityAtOperableRefineriesQueryParams( + EiaApiQueryParams +): + """Shell Storage Capacity at Operable Refineries. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/capshell + """ + + __group__ = "petroleum" + __dataset__ = "shell_storage_capacity_at_operable_refineries" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil_shell_storage_capacity_at_refineries", + "biomass_based_diesel_fuel_shell_storage_capacity_at", + "crude_oil_shell_storage_capacity_at_refineries", + "distillate_fuel_oil_shell_storage_capacity_at_refineries", + "distillate_fuel_oil_15_ppm_sulfur_and_under_shell_storage", + "distillate_fuel_oil_greater_than_15_ppm_sulfur_to_500_ppm", + "distillate_fuel_oil_greater_than_500_ppm_sulfur_shell", + "finished_conventional_motor_gasoline_shell_storage_capacity", + "finished_motor_gasoline_shell_storage_capacity_at_refineries", + "finished_petroleum_products_shell_storage_capacity_at", + "finished_reformulated_motor_gasoline_shell_storage_capacity", + "fuel_ethanol_shell_storage_capacity_at_refineries", + "kerosene_shell_storage_capacity_at_refineries", + "kerosene_type_jet_fuel_shell_storage_capacity_at_refineries", + "liquefied_petroleum_gases_shell_storage_capacity_at", + "lubricants_shell_storage_capacity_at_refineries", + "mtbe_shell_storage_capacity_at_refineries", + "motor_gasoline_blending_components_shell_storage_capacity", + "normal_butane_butylene_shell_storage_capacity_at_refineries", + "other_liquids_shell_storage_capacity_at_refineries", + "other_oxygenates_shell_storage_capacity_at_refineries", + "other_petroleum_products_shell_storage_capacity_at", + "other_renewable_diesel_fuel_shell_storage_capacity_at", + "other_renewable_fuels_shell_storage_capacity_at_refineries", + "oxygenates_shell_storage_capacity_at_refineries", + "propane_propylene_shell_storage_capacity_at_refineries", + "residual_fuel_oil_shell_storage_capacity_at_refineries", + "shell_storage_capacity_at_refineries", + ], + }, + "product": {"multiple_items_allowed": True}, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 168 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumShellStorageCapacityAtOperableRefineriesData(EiaApiData): + """Shell Storage Capacity at Operable Refineries. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumShellStorageCapacityAtOperableRefineriesFetcher( + Fetcher[ + EiaPetroleumShellStorageCapacityAtOperableRefineriesQueryParams, + list[EiaPetroleumShellStorageCapacityAtOperableRefineriesData], + ] +): + """Shell Storage Capacity at Operable Refineries fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumShellStorageCapacityAtOperableRefineriesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumShellStorageCapacityAtOperableRefineriesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumShellStorageCapacityAtOperableRefineriesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumShellStorageCapacityAtOperableRefineriesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumShellStorageCapacityAtOperableRefineriesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumShellStorageCapacityAtOperableRefineriesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/spot_prices.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/spot_prices.py new file mode 100644 index 00000000000..748229d4c5f --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/spot_prices.py @@ -0,0 +1,151 @@ +"""Spot Prices model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumSpotPricesQueryParams(EiaApiQueryParams): + """Spot Prices. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/spt + """ + + __group__ = "petroleum" + __dataset__ = "spot_prices" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "carb_diesel", + "conventional_regular_gasoline", + "kerosene_type_jet_fuel", + "no_2_diesel_low_sulfur", + "no_2_fuel_oil_heating_oil", + "propane", + "reformulated_regular_gasoline", + "uk_brent_crude_oil", + "wti_crude_oil", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["los_angeles", "na", "new_york_city"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "cushing_ok_wti_spot_price_fob", + "europe_brent_spot_price_fob", + "los_angeles_reformulated_rbob_regular_gasoline_spot_price", + "los_angeles_ca_ultra_low_sulfur_carb_diesel_spot_price", + "mont_belvieu_tx_propane_spot_price_fob", + "new_york_harbor_conventional_gasoline_regular_spot_price_fob", + "new_york_harbor_no_2_heating_oil_spot_price_fob", + "new_york_harbor_ultra_low_sulfur_no_2_diesel_spot_price", + "us_gulf_coast_conventional_gasoline_regular_spot_price_fob", + "us_gulf_coast_kerosene_type_jet_fuel_spot_price_fob", + "us_gulf_coast_ultra_low_sulfur_no_2_diesel_spot_price", + ], + }, + } + + frequency: Literal["annual", "daily", "monthly", "weekly"] | None = Field( + default=None, + description="The data frequency. The default is 'weekly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumSpotPricesData(EiaApiData): + """Spot Prices. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumSpotPricesFetcher( + Fetcher[EiaPetroleumSpotPricesQueryParams, list[EiaPetroleumSpotPricesData]] +): + """Spot Prices fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaPetroleumSpotPricesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaPetroleumSpotPricesQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaPetroleumSpotPricesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumSpotPricesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumSpotPricesData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumSpotPricesData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/stocks_by_type.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/stocks_by_type.py new file mode 100644 index 00000000000..9af85a5644a --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/stocks_by_type.py @@ -0,0 +1,231 @@ +"""Stocks by Type model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumStocksByTypeQueryParams(EiaApiQueryParams): + """Stocks by Type. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/stoc/typ + """ + + __group__ = "petroleum" + __dataset__ = "stocks_by_type" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "ending_stocks", + "ending_stocks_excluding_spr", + "ending_stocks_excluding_spr_and_lease", + "ending_stocks_spr", + "natural_gas_plant_stocks", + "stocks_at_bulk_terminals", + "stocks_at_leases", + "stocks_at_refineries", + "stocks_at_tank_farms", + "stocks_in_pipelines", + "stocks_in_transit_from_alaska", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "aviation_gasoline_blending_components", + "biodiesel", + "biodiesel_renewable_diesel_fuel", + "biofuel_fuels", + "biofuel_fuels_excluding_fuel_ethanol", + "condensate_and_scrubber_oil", + "conventional_cbob_gasoline_blending_components", + "conventional_gtab_gasoline_blending_components", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "conventional_other_gasoline_blending_components", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "ethane", + "ethane_ethylene", + "ethylene", + "finished_motor_gasoline", + "finished_motor_gasoline_conventional_55", + "finished_motor_gasoline_reformulated_other", + "finished_petroleum_products", + "fuel_ethanol", + "gasoline_blending_components", + "heavy_gas_oils", + "hydrogen_oxygenates_renewables_fuels_and_other_hydrocarbons", + "isobutane", + "isobutane_isobutylene", + "isobutylene", + "kerosene", + "kerosene_and_light_oils", + "kerosene_type_jet_fuel", + "liquified_petroleum_gases", + "lubricants", + "mtbe", + "miscellaneous_petroleum_products", + "motor_gasoline_blending_components_reformulated_rbob", + "motor_gasoline_finished_conventional_ed55_and_lower", + "naphtha_for_petrochemical_feedstock_use", + "naphthas_and_lighter", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "normal_butane_butylene", + "normal_butylene", + "other_biofuels", + "other_conventional_motor_gasoline", + "other_hydrocarbons", + "other_liquids", + "other_oils_for_petrochemical_feedstock_use", + "other_oxygenates", + "oxygenates", + "pentanes_plus", + "petrochemical_feedstocks", + "petroleum_coke", + "propane", + "propane_and_propylene", + "propane_fractionated_and_ready_for_sale", + "propylene", + "propylene_nonfuel_use", + "refinery_grade_butane", + "refinery_olefins", + "reformulated_gtab_gasoline_blending_components", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + "reformulated_rbob_with_alcohol_gasoline_blending_components", + "reformulated_rbob_with_ether_gasoline_blending_components", + "renewable_diesel_fuel", + "residual_fuel_oil", + "residual_fuel_oil_0_31_to_1_00_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + "residual_fuel_oil_less_than_0_31_sulfur", + "residuum", + "special_naphthas", + "total_petroleum_products", + "unfinished_oils", + "waxes", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumStocksByTypeData(EiaApiData): + """Stocks by Type. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumStocksByTypeFetcher( + Fetcher[EiaPetroleumStocksByTypeQueryParams, list[EiaPetroleumStocksByTypeData]] +): + """Stocks by Type fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaPetroleumStocksByTypeQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaPetroleumStocksByTypeQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaPetroleumStocksByTypeQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumStocksByTypeQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumStocksByTypeData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumStocksByTypeData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/stocks_of_selected_products.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/stocks_of_selected_products.py new file mode 100644 index 00000000000..0c03c878aba --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/stocks_of_selected_products.py @@ -0,0 +1,220 @@ +"""Stocks of Motor Gasoline, Distillate Fuel Oil, Residual Fuel Oil, Propane and Propylene model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumStocksOfSelectedProductsQueryParams(EiaApiQueryParams): + """Stocks of Motor Gasoline, Distillate Fuel Oil, Residual Fuel Oil, Propane and Propylene. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/stoc/ts + """ + + __group__ = "petroleum" + __dataset__ = "stocks_of_selected_products" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "propane_and_propylene", + "residual_fuel_oil", + "total_gasoline", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "us", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "central_atlantic_padd_1b_ending_stocks_of_distillate_fuel_oil_thousand_barrels", + "central_atlantic_ending_stocks_of_distillate_fuel_oil_0_to", + "central_atlantic_padd_1b_ending_stocks_of_distillate_fuel_oil_greater_than_500_ppm_sulfur_thousand_barrels", + "central_atlantic_padd_1b_ending_stocks_of_distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur_thousand_barrels", + "central_atlantic_ending_stocks_of_propane_and_propylene", + "central_atlantic_ending_stocks_of_residual_fuel_oil", + "central_atlantic_ending_stocks_of_total_gasoline", + "east_coast_ending_stocks_of_distillate_fuel_oil", + "east_coast_ending_stocks_of_distillate_fuel_oil_0_to_15_ppm", + "east_coast_padd_1_ending_stocks_of_distillate_fuel_oil_greater_than_500_ppm_sulfur_thousand_barrels", + "east_coast_padd_1_ending_stocks_of_distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur_thousand_barrels", + "east_coast_ending_stocks_of_propane_and_propylene", + "east_coast_ending_stocks_of_residual_fuel_oil", + "east_coast_ending_stocks_of_total_gasoline", + "gulf_coast_ending_stocks_of_distillate_fuel_oil", + "gulf_coast_ending_stocks_of_distillate_fuel_oil_0_to_15_ppm", + "gulf_coast_padd_3_ending_stocks_of_distillate_fuel_oil_greater_than_500_ppm_sulfur_thousand_barrels", + "gulf_coast_padd_3_ending_stocks_of_distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur_thousand_barrels", + "gulf_coast_ending_stocks_of_propane_and_propylene", + "gulf_coast_ending_stocks_of_residual_fuel_oil", + "gulf_coast_ending_stocks_of_total_gasoline", + "lower_atlantic_ending_stocks_of_distillate_fuel_oil", + "lower_atlantic_ending_stocks_of_distillate_fuel_oil_0_to_15", + "lower_atlantic_padd_1c_ending_stocks_of_distillate_fuel_oil_greater_than_500_ppm_sulfur_thousand_barrels", + "lower_atlantic_padd_1c_ending_stocks_of_distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur_thousand_barrels", + "lower_atlantic_ending_stocks_of_propane_and_propylene", + "lower_atlantic_ending_stocks_of_residual_fuel_oil", + "lower_atlantic_ending_stocks_of_total_gasoline", + "midwest_ending_stocks_of_distillate_fuel_oil", + "midwest_ending_stocks_of_distillate_fuel_oil_0_to_15_ppm", + "midwest_padd_2_ending_stocks_of_distillate_fuel_oil_greater_than_500_ppm_sulfur_thousand_barrels", + "midwest_padd_2_ending_stocks_of_distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur_thousand_barrels", + "midwest_ending_stocks_of_propane_and_propylene", + "midwest_ending_stocks_of_residual_fuel_oil", + "midwest_ending_stocks_of_total_gasoline", + "new_england_ending_stocks_of_distillate_fuel_oil_0_to_15", + "new_england_padd_1a_ending_stocks_of_distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur_thousand_barrels", + "new_england_ending_stocks_of_distillate_fuel_oil", + "new_england_padd_1a_ending_stocks_of_distillate_fuel_oil_greater_than_500_ppm_sulfur_thousand_barrels", + "new_england_ending_stocks_of_propane_and_propylene", + "new_england_ending_stocks_of_residual_fuel_oil", + "new_england_ending_stocks_of_total_gasoline", + "rocky_mountain_ending_stocks_of_distillate_fuel_oil", + "rocky_mountain_ending_stocks_of_distillate_fuel_oil_0_to_15", + "rocky_mountain_padd_4_ending_stocks_of_distillate_fuel_oil_greater_than_500_ppm_sulfur_thousand_barrels", + "rocky_mountain_padd_4_ending_stocks_of_distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur_thousand_barrels", + "rocky_mountain_ending_stocks_of_propane_and_propylene", + "rocky_mountain_ending_stocks_of_residual_fuel_oil", + "rocky_mountain_ending_stocks_of_total_gasoline", + "us_ending_stocks_of_distillate_fuel_oil", + "us_ending_stocks_of_distillate_fuel_oil_0_to_15_ppm_sulfur", + "us_ending_stocks_of_distillate_fuel_oil_greater_than_500", + "us_ending_stocks_of_distillate_fuel_oil_greater_than_15_to", + "us_ending_stocks_of_propane_and_propylene", + "us_ending_stocks_of_residual_fuel_oil", + "us_ending_stocks_of_total_gasoline", + "west_coast_ending_stocks_of_distillate_fuel_oil", + "west_coast_ending_stocks_of_distillate_fuel_oil_0_to_15_ppm", + "west_coast_padd_5_ending_stocks_of_distillate_fuel_oil_greater_than_500_ppm_sulfur_thousand_barrels", + "west_coast_padd_5_ending_stocks_of_distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur_thousand_barrels", + "west_coast_ending_stocks_of_propane_and_propylene", + "west_coast_ending_stocks_of_residual_fuel_oil", + "west_coast_ending_stocks_of_total_gasoline", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumStocksOfSelectedProductsData(EiaApiData): + """Stocks of Motor Gasoline, Distillate Fuel Oil, Residual Fuel Oil, Propane and Propylene. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumStocksOfSelectedProductsFetcher( + Fetcher[ + EiaPetroleumStocksOfSelectedProductsQueryParams, + list[EiaPetroleumStocksOfSelectedProductsData], + ] +): + """Stocks of Motor Gasoline, Distillate Fuel Oil, Residual Fuel Oil, Propane and Propylene fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumStocksOfSelectedProductsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumStocksOfSelectedProductsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumStocksOfSelectedProductsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumStocksOfSelectedProductsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumStocksOfSelectedProductsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumStocksOfSelectedProductsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/supply_and_disposition.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/supply_and_disposition.py new file mode 100644 index 00000000000..3f37a730715 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/supply_and_disposition.py @@ -0,0 +1,213 @@ +"""Supply and Disposition model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumSupplyAndDispositionQueryParams(EiaApiQueryParams): + """Supply and Disposition. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/sum/snd + """ + + __group__ = "petroleum" + __dataset__ = "supply_and_disposition" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "ending_stocks", + "exports", + "field_production", + "imports", + "net_receipts_by_pipeline_tanker_barge_and_rail", + "product_supplied", + "refinery_and_blender_net_input", + "refinery_and_blender_net_production", + "renewable_fuels_plant_and_oxygenate_plant_net_production", + "stock_change", + "supply_adjustment", + "transfers_to_crude_oil_supply", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "aviation_gasoline_blending_components", + "biodiesel", + "biofuel_fuels", + "biofuel_fuels_excluding_fuel_ethanol", + "condensate_and_scrubber_oil", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "ethane", + "ethylene", + "finished_motor_gasoline", + "finished_petroleum_products", + "fuel_ethanol", + "gasoline_blending_components", + "hydrogen", + "hydrogen_oxygenates_renewables_fuels_and_other_hydrocarbons", + "isobutane", + "isobutylene", + "kerosene", + "kerosene_type_jet_fuel", + "lubricants", + "miscellaneous_petroleum_products", + "naphtha_for_petrochemical_feedstock_use", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "normal_butylene", + "other_biofuels", + "other_hydrocarbons", + "other_liquids", + "other_oils_for_petrochemical_feedstock_use", + "oxygenates", + "petrochemical_feedstocks", + "petroleum_coke", + "petroleum_coke_catalyst", + "petroleum_coke_marketable", + "propane", + "propylene", + "refinery_olefins", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "renewable_diesel_fuel", + "residual_fuel_oil", + "residual_fuel_oil_0_31_to_1_00_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + "residual_fuel_oil_less_than_0_31_sulfur", + "special_naphthas", + "still_gas", + "unfinished_oils", + "waxes", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumSupplyAndDispositionData(EiaApiData): + """Supply and Disposition. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumSupplyAndDispositionFetcher( + Fetcher[ + EiaPetroleumSupplyAndDispositionQueryParams, + list[EiaPetroleumSupplyAndDispositionData], + ] +): + """Supply and Disposition fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumSupplyAndDispositionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumSupplyAndDispositionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumSupplyAndDispositionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumSupplyAndDispositionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumSupplyAndDispositionData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumSupplyAndDispositionData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_biodiesel_production_capacity_sales_and_stocks.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_biodiesel_production_capacity_sales_and_stocks.py new file mode 100644 index 00000000000..15615dde162 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_biodiesel_production_capacity_sales_and_stocks.py @@ -0,0 +1,198 @@ +"""US Biodiesel Production, Capacity, Sales, and Stocks - discontinued model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumUsBiodieselProductionCapacitySalesAndStocksQueryParams( + EiaApiQueryParams +): + """US Biodiesel Production, Capacity, Sales, and Stocks - discontinued. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/sum/b100 + """ + + __group__ = "petroleum" + __dataset__ = "us_biodiesel_production_capacity_sales_and_stocks" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "biodiesel_production", + "biodiesel_production_capacity", + "ending_stocks", + "number_of_producers_for_biodiesel_production", + "sales_of_b100_included_biodiesel_blends", + "sales_of_biodiesel_b100", + "stock_change", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "california", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "texas", + "us", + "usa_ak", + "usa_al", + "usa_ar", + "usa_az", + "usa_ct", + "usa_ga", + "usa_hi", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_la", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_nm", + "usa_nv", + "usa_ok", + "usa_or", + "usa_pa", + "usa_ri", + "usa_sc", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_wi", + "usa_wv", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 104 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumUsBiodieselProductionCapacitySalesAndStocksData(EiaApiData): + """US Biodiesel Production, Capacity, Sales, and Stocks - discontinued. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumUsBiodieselProductionCapacitySalesAndStocksFetcher( + Fetcher[ + EiaPetroleumUsBiodieselProductionCapacitySalesAndStocksQueryParams, + list[EiaPetroleumUsBiodieselProductionCapacitySalesAndStocksData], + ] +): + """US Biodiesel Production, Capacity, Sales, and Stocks - discontinued fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumUsBiodieselProductionCapacitySalesAndStocksQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumUsBiodieselProductionCapacitySalesAndStocksQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumUsBiodieselProductionCapacitySalesAndStocksQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumUsBiodieselProductionCapacitySalesAndStocksQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumUsBiodieselProductionCapacitySalesAndStocksData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumUsBiodieselProductionCapacitySalesAndStocksData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_crude_oil_supply_disposition.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_crude_oil_supply_disposition.py new file mode 100644 index 00000000000..8648c4c3eb7 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_crude_oil_supply_disposition.py @@ -0,0 +1,188 @@ +"""US Crude Oil Supply & Disposition model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumUsCrudeOilSupplyDispositionQueryParams(EiaApiQueryParams): + """US Crude Oil Supply & Disposition. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/sum/crdsnd + """ + + __group__ = "petroleum" + __dataset__ = "us_crude_oil_supply_disposition" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "days_of_petroleum_net_imports", + "ending_stocks", + "ending_stocks_excluding_spr", + "ending_stocks_spr", + "exports", + "field_production", + "imports", + "imports_excluding_spr", + "imports_spr", + "imports_by_others_for_spr", + "percent_of_crude_oil_stocks", + "percent_of_total_petroleum_stocks", + "product_supplied", + "refinery_and_blender_net_input", + "spr_receipts_detail_domestic", + "spr_receipts_detail_receipts", + "spr_stock_change", + "stock_change", + "stock_change_excluding_spr", + "stocks_at_leases", + "stocks_at_refineries", + "stocks_at_tank_farms", + "stocks_in_transit_from_alaska", + "supply_adjustment", + ], + }, + "region": {"multiple_items_allowed": True, "choices": ["na", "us", "usa_ak"]}, + "series": { + "multiple_items_allowed": True, + "choices": [ + "alaska_field_production_of_crude_oil", + "cushing_ok_ending_stocks_of_crude_oil", + "lower_48_states_field_production_of_crude_oil", + "us_crude_oil_imports_excluding_spr", + "us_crude_oil_imports_for_spr_by_others_from_all_countries", + "us_crude_oil_spr_imports_from_all_countries", + "us_crude_oil_spr_stock_change", + "us_crude_oil_stock_change", + "us_crude_oil_stock_change_excluding_spr", + "us_crude_oil_stocks_at_leases", + "us_crude_oil_stocks_at_refineries", + "us_crude_oil_stocks_at_tank_farms_and_pipelines", + "us_crude_oil_stocks_in_transit_from_alaska", + "us_crude_oil_spr_receipts_detail_domestic", + "us_crude_oil_spr_receipts_detail_receipts", + "us_ending_stocks_excluding_spr_of_crude_oil", + "us_ending_stocks_of_crude_oil", + "us_ending_stocks_of_crude_oil_in_spr", + "us_exports_of_crude_oil", + "us_field_production_of_crude_oil", + "us_imports_of_crude_oil", + "us_percent_of_crude_oil_stocks_held_in_spr", + "us_percent_of_total_petroleum_stocks_held_in_spr", + "us_product_supplied_of_crude_oil", + "us_refinery_and_blender_net_input_of_crude_oil", + "us_spr_stocks_as_days_of_supply_of_total_petroleum_net", + "us_supply_adjustment_of_crude_oil", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumUsCrudeOilSupplyDispositionData(EiaApiData): + """US Crude Oil Supply & Disposition. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumUsCrudeOilSupplyDispositionFetcher( + Fetcher[ + EiaPetroleumUsCrudeOilSupplyDispositionQueryParams, + list[EiaPetroleumUsCrudeOilSupplyDispositionData], + ] +): + """US Crude Oil Supply & Disposition fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumUsCrudeOilSupplyDispositionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumUsCrudeOilSupplyDispositionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumUsCrudeOilSupplyDispositionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumUsCrudeOilSupplyDispositionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumUsCrudeOilSupplyDispositionData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumUsCrudeOilSupplyDispositionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_imports_by_country_of_origin.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_imports_by_country_of_origin.py new file mode 100644 index 00000000000..85b6fd0c092 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_imports_by_country_of_origin.py @@ -0,0 +1,185 @@ +"""US Imports by Country of Origin model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumUsImportsByCountryOfOriginQueryParams(EiaApiQueryParams): + """US Imports by Country of Origin. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/impcus + """ + + __group__ = "petroleum" + __dataset__ = "us_imports_by_country_of_origin" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "aviation_gasoline_blending_components", + "biodiesel", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_2000_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_to_2000_ppm_sulfur", + "ethane", + "ethylene", + "finished_motor_gasoline", + "fuel_ethanol", + "gasoline_blending_components", + "isobutane", + "isobutylene", + "kerosene", + "kerosene_type_jet_fuel", + "liquified_petroleum_gases", + "lubricants", + "mtbe", + "miscellaneous_petroleum_products", + "naphtha_for_petrochemical_feedstock_use", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "normal_butylene", + "other_biofuels", + "other_oils_for_petrochemical_feedstock_use", + "other_oxygenates", + "pentanes_plus", + "petroleum_coke_marketable", + "propane", + "propylene", + "refinery_olefins", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "renewable_diesel_fuel", + "residual_fuel_oil", + "residual_fuel_oil_0_31_to_1_00_sulfur", + "residual_fuel_oil_greater_than_1_sulfur", + "residual_fuel_oil_less_than_0_31_sulfur", + "special_naphthas", + "total_petroleum_products", + "unfinished_oils", + "waxes", + ], + }, + "region": {"multiple_items_allowed": True}, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values. There are 140 valid values - use the `facet_options` endpoint to list them.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumUsImportsByCountryOfOriginData(EiaApiData): + """US Imports by Country of Origin. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumUsImportsByCountryOfOriginFetcher( + Fetcher[ + EiaPetroleumUsImportsByCountryOfOriginQueryParams, + list[EiaPetroleumUsImportsByCountryOfOriginData], + ] +): + """US Imports by Country of Origin fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumUsImportsByCountryOfOriginQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumUsImportsByCountryOfOriginQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumUsImportsByCountryOfOriginQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumUsImportsByCountryOfOriginQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumUsImportsByCountryOfOriginData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumUsImportsByCountryOfOriginData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_net_imports_by_country.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_net_imports_by_country.py new file mode 100644 index 00000000000..e14085b9eda --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_net_imports_by_country.py @@ -0,0 +1,181 @@ +"""US Net Imports by Country model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumUsNetImportsByCountryQueryParams(EiaApiQueryParams): + """US Net Imports by Country. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/neti + """ + + __group__ = "petroleum" + __dataset__ = "us_net_imports_by_country" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "aviation_gasoline", + "aviation_gasoline_blending_components", + "biodiesel", + "conventional_gasoline_blending_components", + "conventional_motor_gasoline", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_2000_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_to_2000_ppm_sulfur", + "ethane", + "ethylene", + "finished_motor_gasoline", + "fuel_ethanol", + "gasoline_blending_components", + "isobutane", + "isobutylene", + "kerosene", + "kerosene_type_jet_fuel", + "liquified_petroleum_gases", + "lubricants", + "mtbe", + "miscellaneous_petroleum_products", + "naphtha_for_petrochemical_feedstock_use", + "natural_gas_liquids_and_liquid_refinery_gases", + "natural_gas_plant_liquids", + "natural_gasoline", + "normal_butane", + "normal_butylene", + "other_biofuels", + "other_oils_for_petrochemical_feedstock_use", + "other_oxygenates", + "pentanes_plus", + "petroleum_coke", + "propane", + "propylene", + "refinery_olefins", + "reformulated_gasoline_blending_components", + "reformulated_motor_gasoline", + "renewable_diesel_fuel", + "residual_fuel_oil", + "special_naphthas", + "total_petroleum_products", + "unfinished_oils", + "waxes", + ], + }, + "region": {"multiple_items_allowed": True}, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values. There are 213 valid values - use the `facet_options` endpoint to list them.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaPetroleumUsNetImportsByCountryData(EiaApiData): + """US Net Imports by Country. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumUsNetImportsByCountryFetcher( + Fetcher[ + EiaPetroleumUsNetImportsByCountryQueryParams, + list[EiaPetroleumUsNetImportsByCountryData], + ] +): + """US Net Imports by Country fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumUsNetImportsByCountryQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumUsNetImportsByCountryQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumUsNetImportsByCountryQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumUsNetImportsByCountryQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumUsNetImportsByCountryData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumUsNetImportsByCountryData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_refiner_gasoline_prices_by_formulation_grade_sales_type.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_refiner_gasoline_prices_by_formulation_grade_sales_type.py new file mode 100644 index 00000000000..8ac84db1525 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_refiner_gasoline_prices_by_formulation_grade_sales_type.py @@ -0,0 +1,236 @@ +"""US Refiner Gasoline Prices by Formulation, Grade, Sales Type model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesTypeQueryParams( + EiaApiQueryParams +): + """US Refiner Gasoline Prices by Formulation, Grade, Sales Type. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/refmg2 + """ + + __group__ = "petroleum" + __dataset__ = "us_refiner_gasoline_prices_by_formulation_grade_sales_type" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "bulk_sales_by_refiners_and_gas_plants", + "dtw_sales_price_by_refiners_and_gas_plants", + "rack_sales_price_by_refiners_and_gas_plants", + "retail_sales_by_refiners_and_gas_plants", + "through_company_outlets_price_by_refiners_and_gas_plants", + "wholesale_resale_price_by_refiners_and_gas_plants", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "conventional_gasoline", + "conventional_premium_gasoline", + "conventional_regular_gasoline", + "gasoline_conventional_midgrade", + "gasoline_oxygenated_midgrade", + "gasoline_reformulated_midgrade", + "oxygenated_gasoline", + "oxygenated_premium_gasoline", + "oxygenated_regular_gasoline", + "reformulated_motor_gasoline", + "reformulated_premium_gasoline", + "reformulated_regular_gasoline", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_conventional_gasoline_bulk_sales_price_by_refiners", + "us_conventional_gasoline_dtw_sales_price_by_refiners", + "us_conventional_gasoline_midgrade_bulk_sales_price_by", + "us_conventional_gasoline_midgrade_dtw_sales_price_by", + "us_conventional_gasoline_midgrade_rack_sales_price_by", + "us_conventional_gasoline_midgrade_retail_sales_by_refiners", + "us_conventional_gasoline_midgrade_through_company_outlets", + "us_conventional_gasoline_midgrade_wholesale_resale_price_by", + "us_conventional_gasoline_premium_bulk_sales_price_by", + "us_conventional_gasoline_premium_dtw_sales_price_by_refiners", + "us_conventional_gasoline_premium_rack_sales_price_by", + "us_conventional_gasoline_premium_retail_sales_by_refiners", + "us_conventional_gasoline_premium_through_company_outlets", + "us_conventional_gasoline_premium_wholesale_resale_price_by", + "us_conventional_gasoline_rack_sales_price_by_refiners", + "us_conventional_gasoline_regular_bulk_sales_price_by", + "us_conventional_gasoline_regular_dtw_sales_price_by_refiners", + "us_conventional_gasoline_regular_rack_sales_price_by", + "us_conventional_gasoline_regular_retail_sales_by_refiners", + "us_conventional_gasoline_regular_through_company_outlets", + "us_conventional_gasoline_regular_wholesale_resale_price_by", + "us_conventional_gasoline_retail_sales_by_refiners", + "us_conventional_gasoline_through_company_outlets_price_by", + "us_conventional_gasoline_wholesale_resale_price_by_refiners", + "us_oxygenated_gasoline_bulk_sales_price_by_refiners", + "us_oxygenated_gasoline_dtw_sales_price_by_refiners", + "us_oxygenated_gasoline_midgrade_bulk_sales_price_by_refiners", + "us_oxygenated_gasoline_midgrade_dtw_sales_price_by_refiners", + "us_oxygenated_gasoline_midgrade_rack_sales_price_by_refiners", + "us_oxygenated_gasoline_midgrade_retail_sales_by_refiners", + "us_oxygenated_gasoline_midgrade_through_company_outlets", + "us_oxygenated_gasoline_midgrade_wholesale_resale_price_by", + "us_oxygenated_gasoline_premium_bulk_sales_price_by_refiners", + "us_oxygenated_gasoline_premium_dtw_sales_price_by_refiners", + "us_oxygenated_gasoline_premium_rack_sales_price_by_refiners", + "us_oxygenated_gasoline_premium_retail_sales_by_refiners", + "us_oxygenated_gasoline_premium_through_company_outlets", + "us_oxygenated_gasoline_premium_wholesale_resale_price_by", + "us_oxygenated_gasoline_rack_sales_price_by_refiners", + "us_oxygenated_gasoline_regular_bulk_sales_price_by_refiners", + "us_oxygenated_gasoline_regular_dtw_sales_price_by_refiners", + "us_oxygenated_gasoline_regular_rack_sales_price_by_refiners", + "us_oxygenated_gasoline_regular_retail_sales_by_refiners", + "us_oxygenated_gasoline_regular_through_company_outlets", + "us_oxygenated_gasoline_regular_wholesale_resale_price_by", + "us_oxygenated_gasoline_retail_sales_by_refiners", + "us_oxygenated_gasoline_through_company_outlets_price_by", + "us_oxygenated_gasoline_wholesale_resale_price_by_refiners", + "us_reformulated_gasoline_bulk_sales_price_by_refiners", + "us_reformulated_gasoline_dtw_sales_price_by_refiners", + "us_reformulated_gasoline_midgrade_bulk_sales_price_by", + "us_reformulated_gasoline_midgrade_dtw_sales_price_by", + "us_reformulated_gasoline_midgrade_rack_sales_price_by", + "us_reformulated_gasoline_midgrade_retail_sales_by_refiners", + "us_reformulated_gasoline_midgrade_through_company_outlets", + "us_reformulated_gasoline_midgrade_wholesale_resale_price_by", + "us_reformulated_gasoline_premium_bulk_sales_price_by", + "us_reformulated_gasoline_premium_dtw_sales_price_by_refiners", + "us_reformulated_gasoline_premium_rack_sales_price_by", + "us_reformulated_gasoline_premium_retail_sales_by_refiners", + "us_reformulated_gasoline_premium_through_company_outlets", + "us_reformulated_gasoline_premium_wholesale_resale_price_by", + "us_reformulated_gasoline_rack_sales_price_by_refiners", + "us_reformulated_gasoline_regular_bulk_sales_price_by", + "us_reformulated_gasoline_regular_dtw_sales_price_by_refiners", + "us_reformulated_gasoline_regular_rack_sales_price_by", + "us_reformulated_gasoline_regular_retail_sales_by_refiners", + "us_reformulated_gasoline_regular_through_company_outlets", + "us_reformulated_gasoline_regular_wholesale_resale_price_by", + "us_reformulated_gasoline_retail_sales_by_refiners", + "us_reformulated_gasoline_through_company_outlets_price_by", + "us_reformulated_gasoline_wholesale_resale_price_by_refiners", + ], + }, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesTypeData(EiaApiData): + """US Refiner Gasoline Prices by Formulation, Grade, Sales Type. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesTypeFetcher( + Fetcher[ + EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesTypeQueryParams, + list[EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesTypeData], + ] +): + """US Refiner Gasoline Prices by Formulation, Grade, Sales Type fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesTypeQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesTypeQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesTypeQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesTypeQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesTypeData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesTypeData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_weekly_product_supplied.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_weekly_product_supplied.py new file mode 100644 index 00000000000..ed885c3664c --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/us_weekly_product_supplied.py @@ -0,0 +1,146 @@ +"""US Weekly Product Supplied model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumUsWeeklyProductSuppliedQueryParams(EiaApiQueryParams): + """US Weekly Product Supplied. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/cons/wpsup + """ + + __group__ = "petroleum" + __dataset__ = "us_weekly_product_supplied" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "distillate_fuel_oil", + "finished_motor_gasoline", + "kerosene_type_jet_fuel", + "other_oils", + "propane_and_propylene", + "residual_fuel_oil", + "total_petroleum_products", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_product_supplied_of_distillate_fuel_oil", + "us_product_supplied_of_finished_motor_gasoline", + "us_product_supplied_of_kerosene_type_jet_fuel", + "us_product_supplied_of_other_oils", + "us_product_supplied_of_petroleum_products", + "us_product_supplied_of_propane_and_propylene", + "us_product_supplied_of_residual_fuel_oil", + ], + }, + } + + frequency: Literal["four-week-average", "weekly"] | None = Field( + default=None, + description="The data frequency. The default is 'weekly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumUsWeeklyProductSuppliedData(EiaApiData): + """US Weekly Product Supplied. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumUsWeeklyProductSuppliedFetcher( + Fetcher[ + EiaPetroleumUsWeeklyProductSuppliedQueryParams, + list[EiaPetroleumUsWeeklyProductSuppliedData], + ] +): + """US Weekly Product Supplied fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumUsWeeklyProductSuppliedQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumUsWeeklyProductSuppliedQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumUsWeeklyProductSuppliedQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumUsWeeklyProductSuppliedQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumUsWeeklyProductSuppliedData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumUsWeeklyProductSuppliedData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_blender_net_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_blender_net_production.py new file mode 100644 index 00000000000..9a67cc38e54 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_blender_net_production.py @@ -0,0 +1,175 @@ +"""Weekly Blender Net Production model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumWeeklyBlenderNetProductionQueryParams(EiaApiQueryParams): + """Weekly Blender Net Production. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/wprodb + """ + + __group__ = "petroleum" + __dataset__ = "weekly_blender_net_production" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "finished_motor_gasoline", + "finished_motor_gasoline_conventional_55", + "finished_motor_gasoline_reformulated_other", + "kerosene", + "kerosene_type_jet_fuel", + "motor_gasoline_finished_conventional_ed55_and_lower", + "other_conventional_motor_gasoline", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "east_coast_blender_net_production_of_finished_motor_gasoline", + "gulf_coast_blender_net_production_of_finished_motor_gasoline", + "midwest_blender_net_production_of_finished_motor_gasoline", + "rocky_mountain_blender_net_production_of_finished_motor", + "us_blender_net_production_of_conventional_motor_gasoline_thousand_barrels_per_day", + "us_blender_net_production_of_conventional_motor_gasoline_with_fuel_ethanol_thousand_barrels_per_day", + "us_blender_net_production_of_distillate_fuel_oil", + "us_blender_net_production_of_distillate_fuel_oil_0_to_15", + "us_blender_net_production_of_distillate_fuel_oil_greater_than_500_ppm_sulfur_thousand_barrels_per_day", + "us_blender_net_production_of_distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur_thousand_barrels_per_day", + "us_blender_net_production_of_finished_motor_gasoline", + "us_blender_net_production_of_kerosene", + "us_blender_net_production_of_kerosene_type_jet_fuel", + "us_blender_net_production_of_motor_gasoline_finished_conventional_ed55_and_lower_thousand_barrels_per_day", + "us_blender_net_production_of_motor_gasoline_finished_conventional_greater_than_ed55_thousand_barrels_per_day", + "us_blender_net_production_of_other_conventional_motor", + "us_blender_net_production_of_other_reformulated_motor", + "us_blender_net_production_of_reformulated_motor_gasoline_thousand_barrels_per_day", + "us_blender_net_production_of_reformulated_motor_gasoline_with_fuel_alcohol_thousand_barrels_per_day", + "west_coast_blender_net_production_of_finished_motor_gasoline", + ], + }, + } + + frequency: Literal["four-week-average", "weekly"] | None = Field( + default=None, + description="The data frequency. The default is 'weekly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumWeeklyBlenderNetProductionData(EiaApiData): + """Weekly Blender Net Production. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumWeeklyBlenderNetProductionFetcher( + Fetcher[ + EiaPetroleumWeeklyBlenderNetProductionQueryParams, + list[EiaPetroleumWeeklyBlenderNetProductionData], + ] +): + """Weekly Blender Net Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumWeeklyBlenderNetProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumWeeklyBlenderNetProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumWeeklyBlenderNetProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumWeeklyBlenderNetProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumWeeklyBlenderNetProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumWeeklyBlenderNetProductionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_crude_imports_by_top_10_origins.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_crude_imports_by_top_10_origins.py new file mode 100644 index 00000000000..9934852ce2f --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_crude_imports_by_top_10_origins.py @@ -0,0 +1,170 @@ +"""Weekly Preliminary Crude Imports by Top 10 Countries of Origin (ranking based on 2024 Petroleum Supply Monthly data) model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumWeeklyCrudeImportsByTop10OriginsQueryParams(EiaApiQueryParams): + """Weekly Preliminary Crude Imports by Top 10 Countries of Origin (ranking based on 2024 Petroleum Supply Monthly data). EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/wimpc + """ + + __group__ = "petroleum" + __dataset__ = "weekly_crude_imports_by_top_10_origins" + __json_schema_extra__ = { + "region": { + "multiple_items_allowed": True, + "choices": [ + "ago", + "bra", + "can", + "cog", + "col", + "dza", + "ecu", + "gbr", + "gnq", + "irq", + "kwt", + "lby", + "mex", + "nga", + "nor", + "rus", + "sau", + "tto", + "ven", + ], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "us_imports_from_algeria_of_crude_oil", + "us_imports_from_angola_of_crude_oil", + "us_imports_from_brazil_of_crude_oil", + "us_imports_from_canada_of_crude_oil", + "us_imports_from_colombia_of_crude_oil", + "us_imports_from_congo_of_crude_oil", + "us_imports_from_ecuador_of_crude_oil", + "us_imports_from_equatorial_guinea_of_crude_oil", + "us_imports_from_iraq_of_crude_oil", + "us_imports_from_kuwait_of_crude_oil", + "us_imports_from_libya_of_crude_oil", + "us_imports_from_mexico_of_crude_oil", + "us_imports_from_nigeria_of_crude_oil", + "us_imports_from_norway_of_crude_oil", + "us_imports_from_russia_of_crude_oil", + "us_imports_from_saudi_arabia_of_crude_oil", + "us_imports_from_trinidad_and_tobago_of_crude_oil", + "us_imports_from_united_kingdom_of_crude_oil", + "us_imports_from_venezuela_of_crude_oil", + ], + }, + } + + frequency: Literal["four-week-average", "weekly"] | None = Field( + default=None, + description="The data frequency. The default is 'weekly'.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumWeeklyCrudeImportsByTop10OriginsData(EiaApiData): + """Weekly Preliminary Crude Imports by Top 10 Countries of Origin (ranking based on 2024 Petroleum Supply Monthly data). EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumWeeklyCrudeImportsByTop10OriginsFetcher( + Fetcher[ + EiaPetroleumWeeklyCrudeImportsByTop10OriginsQueryParams, + list[EiaPetroleumWeeklyCrudeImportsByTop10OriginsData], + ] +): + """Weekly Preliminary Crude Imports by Top 10 Countries of Origin (ranking based on 2024 Petroleum Supply Monthly data) fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumWeeklyCrudeImportsByTop10OriginsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumWeeklyCrudeImportsByTop10OriginsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumWeeklyCrudeImportsByTop10OriginsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumWeeklyCrudeImportsByTop10OriginsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumWeeklyCrudeImportsByTop10OriginsData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumWeeklyCrudeImportsByTop10OriginsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_ethanol_plant_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_ethanol_plant_production.py new file mode 100644 index 00000000000..46a7ed94b8c --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_ethanol_plant_production.py @@ -0,0 +1,137 @@ +"""Weekly Ethanol Plant Production model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumWeeklyEthanolPlantProductionQueryParams(EiaApiQueryParams): + """Weekly Ethanol Plant Production. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/wprode + """ + + __group__ = "petroleum" + __dataset__ = "weekly_ethanol_plant_production" + __json_schema_extra__ = { + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "east_coast_oxygenate_plant_production_of_fuel_ethanol", + "gulf_coast_oxygenate_plant_production_of_fuel_ethanol", + "midwest_oxygenate_plant_production_of_fuel_ethanol", + "rocky_mountain_oxygenate_plant_production_of_fuel_ethanol", + "us_oxygenate_plant_production_of_fuel_ethanol", + "west_coast_oxygenate_plant_production_of_fuel_ethanol", + ], + }, + } + + frequency: Literal["four-week-average", "weekly"] | None = Field( + default=None, + description="The data frequency. The default is 'weekly'.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumWeeklyEthanolPlantProductionData(EiaApiData): + """Weekly Ethanol Plant Production. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumWeeklyEthanolPlantProductionFetcher( + Fetcher[ + EiaPetroleumWeeklyEthanolPlantProductionQueryParams, + list[EiaPetroleumWeeklyEthanolPlantProductionData], + ] +): + """Weekly Ethanol Plant Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumWeeklyEthanolPlantProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumWeeklyEthanolPlantProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumWeeklyEthanolPlantProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumWeeklyEthanolPlantProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumWeeklyEthanolPlantProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumWeeklyEthanolPlantProductionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_heating_oil_and_propane_prices.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_heating_oil_and_propane_prices.py new file mode 100644 index 00000000000..53a3f027f71 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_heating_oil_and_propane_prices.py @@ -0,0 +1,194 @@ +"""Weekly Heating Oil and Propane Prices model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumWeeklyHeatingOilAndPropanePricesQueryParams(EiaApiQueryParams): + """Weekly Heating Oil and Propane Prices. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/wfr + """ + + __group__ = "petroleum" + __dataset__ = "weekly_heating_oil_and_propane_prices" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "price_delivered_to_residential_consumers", + "wholesale_resale_price", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": ["no_2_fuel_oil_heating_oil", "propane"], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "colorado", + "florida", + "massachusetts", + "minnesota", + "new_york", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "texas", + "us", + "usa_al", + "usa_ar", + "usa_ct", + "usa_dc", + "usa_de", + "usa_ga", + "usa_ia", + "usa_id", + "usa_il", + "usa_in", + "usa_ks", + "usa_ky", + "usa_md", + "usa_me", + "usa_mi", + "usa_mo", + "usa_ms", + "usa_mt", + "usa_nc", + "usa_nd", + "usa_ne", + "usa_nh", + "usa_nj", + "usa_ok", + "usa_pa", + "usa_ri", + "usa_sd", + "usa_tn", + "usa_ut", + "usa_va", + "usa_vt", + "usa_wi", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["monthly", "weekly"] | None = Field( + default=None, + description="The data frequency. The default is 'weekly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 141 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumWeeklyHeatingOilAndPropanePricesData(EiaApiData): + """Weekly Heating Oil and Propane Prices. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumWeeklyHeatingOilAndPropanePricesFetcher( + Fetcher[ + EiaPetroleumWeeklyHeatingOilAndPropanePricesQueryParams, + list[EiaPetroleumWeeklyHeatingOilAndPropanePricesData], + ] +): + """Weekly Heating Oil and Propane Prices fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumWeeklyHeatingOilAndPropanePricesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumWeeklyHeatingOilAndPropanePricesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumWeeklyHeatingOilAndPropanePricesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumWeeklyHeatingOilAndPropanePricesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumWeeklyHeatingOilAndPropanePricesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumWeeklyHeatingOilAndPropanePricesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_imports_exports.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_imports_exports.py new file mode 100644 index 00000000000..9f3d98cc9df --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_imports_exports.py @@ -0,0 +1,182 @@ +"""Weekly Imports & Exports model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumWeeklyImportsExportsQueryParams(EiaApiQueryParams): + """Weekly Imports & Exports. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/move/wkly + """ + + __group__ = "petroleum" + __dataset__ = "weekly_imports_exports" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "exports", + "imports", + "imports_excluding_spr", + "imports_by_others_for_spr", + "imports_by_spr", + "net_imports", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "conventional_cbob_gasoline_blending_components", + "conventional_gtab_gasoline_blending_components", + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "conventional_other_gasoline_blending_components", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_2000_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_to_2000_ppm_sulfur", + "finished_motor_gasoline", + "finished_motor_gasoline_conventional_55", + "finished_motor_gasoline_reformulated_other", + "fuel_ethanol", + "gasoline_blending_components", + "kerosene", + "kerosene_type_jet_fuel", + "motor_gasoline_blending_components_reformulated_rbob", + "motor_gasoline_finished_conventional_ed55_and_lower", + "ngpls_lrgs", + "other_conventional_motor_gasoline", + "other_oils", + "other_oils_excluding_fuel_ethanol", + "propane_and_propylene", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + "reformulated_rbob_with_alcohol_gasoline_blending_components", + "reformulated_rbob_with_ether_gasoline_blending_components", + "residual_fuel_oil", + "total_gasoline", + "total_petroleum_products", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["na", "padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["four-week-average", "weekly"] | None = Field( + default=None, + description="The data frequency. The default is 'weekly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 197 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumWeeklyImportsExportsData(EiaApiData): + """Weekly Imports & Exports. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumWeeklyImportsExportsFetcher( + Fetcher[ + EiaPetroleumWeeklyImportsExportsQueryParams, + list[EiaPetroleumWeeklyImportsExportsData], + ] +): + """Weekly Imports & Exports fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumWeeklyImportsExportsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumWeeklyImportsExportsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumWeeklyImportsExportsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumWeeklyImportsExportsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumWeeklyImportsExportsData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumWeeklyImportsExportsData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_inputs_utilization.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_inputs_utilization.py new file mode 100644 index 00000000000..76905141866 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_inputs_utilization.py @@ -0,0 +1,221 @@ +"""Weekly Inputs & Utilization model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumWeeklyInputsUtilizationQueryParams(EiaApiQueryParams): + """Weekly Inputs & Utilization. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/wiup + """ + + __group__ = "petroleum" + __dataset__ = "weekly_inputs_utilization" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "utilization_refinery_operable_capacity", + "refinery_net_input", + "refinery_operable_capacity", + "refinery_and_blender_net_input", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "conventional_cbob_gasoline_blending_components", + "conventional_gtab_gasoline_blending_components", + "conventional_other_gasoline_blending_components", + "crude_oil", + "fuel_ethanol", + "gasoline_blending_components", + "gross_inputs", + "motor_gasoline_blending_components_reformulated_rbob", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "east_coast_gross_inputs_into_refineries", + "east_coast_operable_crude_oil_distillation_capacity", + "east_coast_percent_utilization_of_refinery_operable_capacity", + "east_coast_refiner_net_input_of_crude_oil", + "east_coast_padd_1_refiner_and_blender_net_input_of_conventional_cbob_gasoline_blending_components_thousand_barrels_per_day", + "east_coast_padd_1_refiner_and_blender_net_input_of_conventional_gtab_gasoline_blending_components_thousand_barrels_per_day", + "east_coast_padd_1_refiner_and_blender_net_input_of_conventional_other_gasoline_blending_components_thousand_barrels_per_day", + "east_coast_refiner_and_blender_net_input_of_fuel_ethanol", + "east_coast_refiner_and_blender_net_input_of_gasoline", + "east_coast_refiner_and_blender_net_input_of_motor_gasoline", + "gulf_coast_gross_inputs_into_refineries", + "gulf_coast_operable_crude_oil_distillation_capacity", + "gulf_coast_percent_utilization_of_refinery_operable_capacity", + "gulf_coast_refiner_net_input_of_crude_oil", + "gulf_coast_padd_3_refiner_and_blender_net_input_of_conventional_cbob_gasoline_blending_components_thousand_barrels_per_day", + "gulf_coast_padd_3_refiner_and_blender_net_input_of_conventional_gtab_gasoline_blending_components_thousand_barrels_per_day", + "gulf_coast_padd_3_refiner_and_blender_net_input_of_conventional_other_gasoline_blending_components_thousand_barrels_per_day", + "gulf_coast_refiner_and_blender_net_input_of_fuel_ethanol", + "gulf_coast_refiner_and_blender_net_input_of_gasoline", + "gulf_coast_refiner_and_blender_net_input_of_motor_gasoline", + "midwest_gross_inputs_into_refineries", + "midwest_operable_crude_oil_distillation_capacity", + "midwest_percent_utilization_of_refinery_operable_capacity", + "midwest_refiner_net_input_of_crude_oil", + "midwest_refiner_and_blender_net_input_of_conventional_cbob", + "midwest_refiner_and_blender_net_input_of_conventional_gtab", + "midwest_refiner_and_blender_net_input_of_conventional_other", + "midwest_refiner_and_blender_net_input_of_fuel_ethanol", + "midwest_refiner_and_blender_net_input_of_gasoline_blending", + "midwest_refiner_and_blender_net_input_of_motor_gasoline", + "rocky_mountain_gross_inputs_into_refineries", + "rocky_mountain_refiner_net_input_of_crude_oil", + "rocky_mountain_padd_4_refiner_and_blender_net_input_of_conventional_cbob_gasoline_blending_components_thousand_barrels_per_day", + "rocky_mountain_padd_4_refiner_and_blender_net_input_of_conventional_gtab_gasoline_blending_components_thousand_barrels_per_day", + "rocky_mountain_padd_4_refiner_and_blender_net_input_of_conventional_other_gasoline_blending_components_thousand_barrels_per_day", + "rocky_mountain_refiner_and_blender_net_input_of_fuel_ethanol", + "rocky_mountain_refiner_and_blender_net_input_of_gasoline", + "rocky_mountain_refiner_and_blender_net_input_of_motor", + "rocky_mountains_operable_crude_oil_distillation_capacity", + "rocky_mountains_percent_utilization_of_refinery_operable", + "u_s_operable_crude_oil_distillation_capacity", + "us_gross_inputs_into_refineries", + "us_percent_utilization_of_refinery_operable_capacity", + "us_refiner_net_input_of_crude_oil", + "us_refiner_and_blender_net_input_of_conventional_cbob", + "us_refiner_and_blender_net_input_of_conventional_gtab", + "us_refiner_and_blender_net_input_of_conventional_other", + "us_refiner_and_blender_net_input_of_fuel_ethanol", + "us_refiner_and_blender_net_input_of_gasoline_blending", + "us_refiner_and_blender_net_input_of_motor_gasoline_blending", + "west_coast_gross_inputs_into_refineries", + "west_coast_operable_crude_oil_distillation_capacity", + "west_coast_percent_utilization_of_refinery_operable_capacity", + "west_coast_refiner_net_input_of_crude_oil", + "west_coast_padd_5_refiner_and_blender_net_input_of_conventional_cbob_gasoline_blending_components_thousand_barrels_per_day", + "west_coast_padd_5_refiner_and_blender_net_input_of_conventional_gtab_gasoline_blending_components_thousand_barrels_per_day", + "west_coast_padd_5_refiner_and_blender_net_input_of_conventional_other_gasoline_blending_components_thousand_barrels_per_day", + "west_coast_refiner_and_blender_net_input_of_fuel_ethanol", + "west_coast_refiner_and_blender_net_input_of_gasoline", + "west_coast_refiner_and_blender_net_input_of_motor_gasoline", + ], + }, + } + + frequency: Literal["four-week-average", "weekly"] | None = Field( + default=None, + description="The data frequency. The default is 'weekly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumWeeklyInputsUtilizationData(EiaApiData): + """Weekly Inputs & Utilization. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumWeeklyInputsUtilizationFetcher( + Fetcher[ + EiaPetroleumWeeklyInputsUtilizationQueryParams, + list[EiaPetroleumWeeklyInputsUtilizationData], + ] +): + """Weekly Inputs & Utilization fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumWeeklyInputsUtilizationQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumWeeklyInputsUtilizationQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumWeeklyInputsUtilizationQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumWeeklyInputsUtilizationQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumWeeklyInputsUtilizationData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumWeeklyInputsUtilizationData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_refiner_blender_net_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_refiner_blender_net_production.py new file mode 100644 index 00000000000..2ee17e31197 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_refiner_blender_net_production.py @@ -0,0 +1,178 @@ +"""Weekly Refiner & Blender Net Production model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumWeeklyRefinerBlenderNetProductionQueryParams(EiaApiQueryParams): + """Weekly Refiner & Blender Net Production. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/wprodrb + """ + + __group__ = "petroleum" + __dataset__ = "weekly_refiner_blender_net_production" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "all_plants", + "production", + "refinery_and_blender_net_production", + "supply_adjustment", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "commercial_kerosene_type_jet_fuel", + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "finished_motor_gasoline", + "finished_motor_gasoline_conventional_55", + "finished_motor_gasoline_reformulated_other", + "kerosene_type_jet_fuel", + "military_kerosene_type_jet_fuel", + "motor_gasoline_finished_conventional_ed55_and_lower", + "other_conventional_motor_gasoline", + "propane_and_propylene", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + "residual_fuel_oil", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "na", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "us", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["four-week-average", "weekly"] | None = Field( + default=None, + description="The data frequency. The default is 'weekly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 112 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumWeeklyRefinerBlenderNetProductionData(EiaApiData): + """Weekly Refiner & Blender Net Production. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumWeeklyRefinerBlenderNetProductionFetcher( + Fetcher[ + EiaPetroleumWeeklyRefinerBlenderNetProductionQueryParams, + list[EiaPetroleumWeeklyRefinerBlenderNetProductionData], + ] +): + """Weekly Refiner & Blender Net Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumWeeklyRefinerBlenderNetProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumWeeklyRefinerBlenderNetProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumWeeklyRefinerBlenderNetProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumWeeklyRefinerBlenderNetProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumWeeklyRefinerBlenderNetProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumWeeklyRefinerBlenderNetProductionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_refiner_net_production.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_refiner_net_production.py new file mode 100644 index 00000000000..a99478ad7b0 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_refiner_net_production.py @@ -0,0 +1,177 @@ +"""Weekly Refiner Net Production model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumWeeklyRefinerNetProductionQueryParams(EiaApiQueryParams): + """Weekly Refiner Net Production. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/wprodr + """ + + __group__ = "petroleum" + __dataset__ = "weekly_refiner_net_production" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "finished_motor_gasoline", + "finished_motor_gasoline_conventional_55", + "finished_motor_gasoline_reformulated_other", + "kerosene", + "kerosene_type_jet_fuel", + "motor_gasoline_finished_conventional_ed55_and_lower", + "other_conventional_motor_gasoline", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + "residual_fuel_oil", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": { + "multiple_items_allowed": True, + "choices": [ + "east_coast_refiner_net_production_of_finished_motor_gasoline", + "gulf_coast_refiner_net_production_of_finished_motor_gasoline", + "midwest_refiner_net_production_of_finished_motor_gasoline", + "rocky_mountain_refiner_net_production_of_finished_motor", + "us_refiner_net_production_of_conventional_motor_gasoline_thousand_barrels_per_day", + "us_refiner_net_production_of_conventional_motor_gasoline_with_fuel_ethanol_thousand_barrels_per_day", + "us_refiner_net_production_of_distillate_fuel_oil", + "us_refiner_net_production_of_distillate_fuel_oil_0_to_15", + "us_refiner_net_production_of_distillate_fuel_oil_greater_than_500_ppm_sulfur_thousand_barrels_per_day", + "us_refiner_net_production_of_distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur_thousand_barrels_per_day", + "us_refiner_net_production_of_finished_conventional_motor", + "us_refiner_net_production_of_finished_motor_gasoline", + "us_refiner_net_production_of_kerosene", + "us_refiner_net_production_of_kerosene_type_jet_fuel", + "us_refiner_net_production_of_motor_gasoline_finished", + "us_refiner_net_production_of_other_conventional_motor", + "us_refiner_net_production_of_other_reformulated_motor", + "us_refiner_net_production_of_reformulated_motor_gasoline_thousand_barrels_per_day", + "us_refiner_net_production_of_reformulated_motor_gasoline_with_fuel_alcohol_thousand_barrels_per_day", + "us_refiner_net_production_of_residual_fuel_oil", + "west_coast_refiner_net_production_of_finished_motor_gasoline", + ], + }, + } + + frequency: Literal["four-week-average", "weekly"] | None = Field( + default=None, + description="The data frequency. The default is 'weekly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values.", + ) + + +class EiaPetroleumWeeklyRefinerNetProductionData(EiaApiData): + """Weekly Refiner Net Production. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumWeeklyRefinerNetProductionFetcher( + Fetcher[ + EiaPetroleumWeeklyRefinerNetProductionQueryParams, + list[EiaPetroleumWeeklyRefinerNetProductionData], + ] +): + """Weekly Refiner Net Production fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumWeeklyRefinerNetProductionQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumWeeklyRefinerNetProductionQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumWeeklyRefinerNetProductionQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumWeeklyRefinerNetProductionQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumWeeklyRefinerNetProductionData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumWeeklyRefinerNetProductionData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_retail_gasoline_and_diesel_prices.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_retail_gasoline_and_diesel_prices.py new file mode 100644 index 00000000000..e51e4b70342 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_retail_gasoline_and_diesel_prices.py @@ -0,0 +1,181 @@ +"""Weekly Retail Gasoline and Diesel Prices model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumWeeklyRetailGasolineAndDieselPricesQueryParams(EiaApiQueryParams): + """Weekly Retail Gasoline and Diesel Prices. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pri/gnd + """ + + __group__ = "petroleum" + __dataset__ = "weekly_retail_gasoline_and_diesel_prices" + __json_schema_extra__ = { + "product": { + "multiple_items_allowed": True, + "choices": [ + "conventional_gasoline", + "conventional_premium_gasoline", + "conventional_regular_gasoline", + "gasoline_conventional_midgrade", + "gasoline_reformulated_midgrade", + "midgrade_gasoline", + "no_2_diesel", + "no_2_diesel_low_sulfur_0_15_ppm", + "no_2_diesel_low_sulfur_15_500_ppm", + "premium_gasoline", + "reformulated_motor_gasoline", + "reformulated_premium_gasoline", + "reformulated_regular_gasoline", + "regular_gasoline", + "total_gasoline", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "boston", + "california", + "chicago", + "cleveland", + "colorado", + "denver", + "florida", + "houston", + "los_angeles", + "massachusetts", + "miami", + "minnesota", + "new_york", + "new_york_city", + "ohio", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "padd_5_except_california", + "san_francisco", + "seattle", + "texas", + "us", + "washington", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly", "weekly"] | None = Field( + default=None, + description="The data frequency. The default is 'weekly'.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 311 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumWeeklyRetailGasolineAndDieselPricesData(EiaApiData): + """Weekly Retail Gasoline and Diesel Prices. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumWeeklyRetailGasolineAndDieselPricesFetcher( + Fetcher[ + EiaPetroleumWeeklyRetailGasolineAndDieselPricesQueryParams, + list[EiaPetroleumWeeklyRetailGasolineAndDieselPricesData], + ] +): + """Weekly Retail Gasoline and Diesel Prices fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumWeeklyRetailGasolineAndDieselPricesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumWeeklyRetailGasolineAndDieselPricesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumWeeklyRetailGasolineAndDieselPricesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumWeeklyRetailGasolineAndDieselPricesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumWeeklyRetailGasolineAndDieselPricesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumWeeklyRetailGasolineAndDieselPricesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_stocks.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_stocks.py new file mode 100644 index 00000000000..b43e13f2c46 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_stocks.py @@ -0,0 +1,183 @@ +"""Weekly Stocks model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumWeeklyStocksQueryParams(EiaApiQueryParams): + """Weekly Stocks. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/stoc/wstk + """ + + __group__ = "petroleum" + __dataset__ = "weekly_stocks" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "ending_stocks", + "ending_stocks_excluding_propylene_at_terminal", + "ending_stocks_excluding_spr", + "ending_stocks_excluding_spr_and_lease", + "ending_stocks_spr", + "stocks_at_bulk_terminals", + "stocks_in_transit_from_alaska", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "conventional_cbob_gasoline_blending_components", + "conventional_gtab_gasoline_blending_components", + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "conventional_other_gasoline_blending_components", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "finished_motor_gasoline", + "finished_motor_gasoline_conventional_55", + "fuel_ethanol", + "gasoline_blending_components", + "kerosene", + "kerosene_type_jet_fuel", + "motor_gasoline_blending_components_reformulated_rbob", + "ngpls_lrgs", + "other_conventional_motor_gasoline", + "other_oils", + "propane_and_propylene", + "propane_fractionated_and_ready_for_sale", + "propylene_nonfuel_use", + "reformulated_gtab_gasoline_blending_components", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + "reformulated_rbob_with_alcohol_gasoline_blending_components", + "reformulated_rbob_with_ether_gasoline_blending_components", + "residual_fuel_oil", + "total_gasoline", + "unfinished_oils", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "na", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "us", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 205 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumWeeklyStocksData(EiaApiData): + """Weekly Stocks. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumWeeklyStocksFetcher( + Fetcher[EiaPetroleumWeeklyStocksQueryParams, list[EiaPetroleumWeeklyStocksData]] +): + """Weekly Stocks fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaPetroleumWeeklyStocksQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaPetroleumWeeklyStocksQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaPetroleumWeeklyStocksQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumWeeklyStocksQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumWeeklyStocksData]: + """Transform the data.""" + return transform_dataset_data(EiaPetroleumWeeklyStocksData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_supply_estimates.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_supply_estimates.py new file mode 100644 index 00000000000..e50f49498b2 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/weekly_supply_estimates.py @@ -0,0 +1,224 @@ +"""Weekly Supply Estimates model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumWeeklySupplyEstimatesQueryParams(EiaApiQueryParams): + """Weekly Supply Estimates. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/sum/sndw + """ + + __group__ = "petroleum" + __dataset__ = "weekly_supply_estimates" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "utilization_refinery_operable_capacity", + "all_plants", + "days_of_supply", + "ending_stocks", + "ending_stocks_excluding_propylene_at_terminal", + "ending_stocks_excluding_spr", + "ending_stocks_excluding_spr_and_lease", + "ending_stocks_spr", + "exports", + "field_production", + "imports", + "imports_excluding_spr", + "imports_by_others_for_spr", + "imports_by_spr", + "net_imports", + "oxygenate_plant_production", + "product_supplied", + "production", + "refinery_net_input", + "refinery_operable_capacity", + "refinery_and_blender_net_input", + "refinery_and_blender_net_production", + "stocks_at_bulk_terminals", + "stocks_in_transit_from_alaska", + "supply_adjustment", + ], + }, + "product": { + "multiple_items_allowed": True, + "choices": [ + "asphalt_and_road_oil", + "commercial_kerosene_type_jet_fuel", + "conventional_cbob_gasoline_blending_components", + "conventional_gtab_gasoline_blending_components", + "conventional_motor_gasoline", + "conventional_motor_gasoline_with_alcohol", + "conventional_other_gasoline_blending_components", + "crude_oil", + "crude_oil_and_petroleum_products", + "distillate_fuel_oil", + "distillate_fuel_oil_0_to_15_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "distillate_fuel_oil_greater_than_2000_ppm_sulfur", + "distillate_fuel_oil_greater_than_500_to_2000_ppm_sulfur", + "finished_motor_gasoline", + "finished_motor_gasoline_conventional_55", + "finished_motor_gasoline_reformulated_other", + "fuel_ethanol", + "gasoline_blending_components", + "gross_inputs", + "kerosene", + "kerosene_type_jet_fuel", + "military_kerosene_type_jet_fuel", + "motor_gasoline_blending_components_reformulated_rbob", + "motor_gasoline_finished_conventional_ed55_and_lower", + "ngpls_lrgs", + "other_conventional_motor_gasoline", + "other_oils", + "other_oils_excluding_fuel_ethanol", + "propane_and_propylene", + "propane_fractionated_and_ready_for_sale", + "propylene_nonfuel_use", + "reformulated_motor_gasoline", + "reformulated_motor_gasoline_with_alcohol", + "reformulated_motor_gasoline_non_oxygentated", + "reformulated_rbob_with_alcohol_gasoline_blending_components", + "reformulated_rbob_with_ether_gasoline_blending_components", + "residual_fuel_oil", + "total_gasoline", + "total_petroleum_products", + "unfinished_oils", + ], + }, + "region": { + "multiple_items_allowed": True, + "choices": [ + "na", + "padd_1", + "padd_1a", + "padd_1b", + "padd_1c", + "padd_2", + "padd_3", + "padd_4", + "padd_5", + "us", + "usa_ak", + ], + }, + "series": {"multiple_items_allowed": True}, + } + + frequency: Literal["four-week-average", "weekly"] | None = Field( + default=None, + description="The data frequency. The default is 'weekly'.", + ) + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 608 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumWeeklySupplyEstimatesData(EiaApiData): + """Weekly Supply Estimates. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumWeeklySupplyEstimatesFetcher( + Fetcher[ + EiaPetroleumWeeklySupplyEstimatesQueryParams, + list[EiaPetroleumWeeklySupplyEstimatesData], + ] +): + """Weekly Supply Estimates fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumWeeklySupplyEstimatesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumWeeklySupplyEstimatesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumWeeklySupplyEstimatesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumWeeklySupplyEstimatesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumWeeklySupplyEstimatesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumWeeklySupplyEstimatesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/working_storage_capacity_at_operable_refineries.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/working_storage_capacity_at_operable_refineries.py new file mode 100644 index 00000000000..b74f3757802 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum/working_storage_capacity_at_operable_refineries.py @@ -0,0 +1,167 @@ +"""Working Storage Capacity at Operable Refineries model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaPetroleumWorkingStorageCapacityAtOperableRefineriesQueryParams( + EiaApiQueryParams +): + """Working Storage Capacity at Operable Refineries. EIA petroleum gas survey data + + Source: https://www.eia.gov/opendata/browser/petroleum/pnp/capwork + """ + + __group__ = "petroleum" + __dataset__ = "working_storage_capacity_at_operable_refineries" + __json_schema_extra__ = { + "process": { + "multiple_items_allowed": True, + "choices": [ + "working_storage_capacity", + "working_storage_capacity_for_asphalt_and_road_oil", + "working_storage_capacity_for_biomass_based_diesel_fuel", + "working_storage_capacity_for_crude_oil", + "working_storage_capacity_for_distillate_fuel_oil", + "working_storage_capacity_for_distillate_fuel_oil_15_ppm", + "working_storage_capacity_for_distillate_fuel_oil_15_to_500", + "working_storage_capacity_for_distillate_fuel_oil_500_ppm", + "working_storage_capacity_for_finished_conventional_gasoline", + "working_storage_capacity_for_finished_gasoline", + "working_storage_capacity_for_finished_reformulated_gasoline", + "working_storage_capacity_for_fuel_ethanol", + "working_storage_capacity_for_gasoline_blending_components", + "working_storage_capacity_for_kerosene", + "working_storage_capacity_for_kerosene_type_jet_fuel", + "working_storage_capacity_for_liquefied_petroleum_products", + "working_storage_capacity_for_lubricants", + "working_storage_capacity_for_mtbe", + "working_storage_capacity_for_normal_butane_butylene", + "working_storage_capacity_for_other_liquids", + "working_storage_capacity_for_other_oxygenates", + "working_storage_capacity_for_other_products", + "working_storage_capacity_for_other_renewable_diesel_fuel", + "working_storage_capacity_for_other_renewable_fuels", + "working_storage_capacity_for_oxygenates", + "working_storage_capacity_for_petroleum_products", + "working_storage_capacity_for_propane_propylene", + "working_storage_capacity_for_residual_fuel_oil", + ], + }, + "product": {"multiple_items_allowed": True}, + "region": { + "multiple_items_allowed": True, + "choices": ["padd_1", "padd_2", "padd_3", "padd_4", "padd_5", "us"], + }, + "series": {"multiple_items_allowed": True}, + } + + process: str | None = Field( + default=None, + description="Process filter. Accepts a comma-separated list of values.", + ) + product: str | None = Field( + default=None, + description="Product filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + region: str | None = Field( + default=None, + description="DuoArea filter. Accepts a comma-separated list of values.", + ) + series: str | None = Field( + default=None, + description="Series filter. Accepts a comma-separated list of values. There are 168 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaPetroleumWorkingStorageCapacityAtOperableRefineriesData(EiaApiData): + """Working Storage Capacity at Operable Refineries. EIA petroleum gas survey data""" + + process: str | None = Field( + default=None, + description="Process code.", + ) + process_name: str | None = Field( + default=None, + description="Process name.", + ) + product: str | None = Field( + default=None, + description="Product code.", + ) + product_name: str | None = Field( + default=None, + description="Product name.", + ) + region: str | None = Field( + default=None, + description="DuoArea code.", + ) + region_name: str | None = Field( + default=None, + description="DuoArea name.", + ) + series: str | None = Field( + default=None, + description="Series code.", + ) + series_name: str | None = Field( + default=None, + description="Series name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + units: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaPetroleumWorkingStorageCapacityAtOperableRefineriesFetcher( + Fetcher[ + EiaPetroleumWorkingStorageCapacityAtOperableRefineriesQueryParams, + list[EiaPetroleumWorkingStorageCapacityAtOperableRefineriesData], + ] +): + """Working Storage Capacity at Operable Refineries fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaPetroleumWorkingStorageCapacityAtOperableRefineriesQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaPetroleumWorkingStorageCapacityAtOperableRefineriesQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaPetroleumWorkingStorageCapacityAtOperableRefineriesQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaPetroleumWorkingStorageCapacityAtOperableRefineriesQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaPetroleumWorkingStorageCapacityAtOperableRefineriesData]: + """Transform the data.""" + return transform_dataset_data( + EiaPetroleumWorkingStorageCapacityAtOperableRefineriesData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum_status_report.py b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum_status_report.py index af23007bfd2..206778d99c8 100644 --- a/openbb_platform/providers/eia/openbb_us_eia/models/petroleum_status_report.py +++ b/openbb_platform/providers/eia/openbb_us_eia/models/petroleum_status_report.py @@ -1,7 +1,5 @@ """EIA Weekly Petroleum Status Report model.""" -# pylint: disable=unused-argument - from typing import Any from openbb_core.app.model.abstract.error import OpenBBError @@ -11,6 +9,8 @@ from openbb_core.provider.standard_models.petroleum_status_report import ( PetroleumStatusReportQueryParams, ) from openbb_core.provider.utils.errors import EmptyDataError +from pydantic import Field + from openbb_us_eia.utils.constants import ( WpsrCategoryChoices, WpsrCategoryType, @@ -18,7 +18,6 @@ from openbb_us_eia.utils.constants import ( WpsrTableChoices, WpsrTableMap, ) -from pydantic import Field WpsrTableChoicesString = "\n ".join(WpsrTableChoices) @@ -31,7 +30,7 @@ class EiaPetroleumStatusReportQueryParams(PetroleumStatusReportQueryParams): __json_schema_extra__ = { "category": { - "multiiple_items_allowed": False, + "multiple_items_allowed": False, "choices": WpsrCategoryChoices, }, "table": { @@ -75,7 +74,6 @@ class EiaPetroleumStatusReportFetcher( @staticmethod def transform_query(params: dict[str, Any]) -> EiaPetroleumStatusReportQueryParams: """Transform the query parameters.""" - # pylint: disable=import-outside-toplevel from warnings import warn category = params.get("category", "balance_sheet") @@ -117,7 +115,6 @@ class EiaPetroleumStatusReportFetcher( **kwargs: Any, ) -> dict: """Extract the data from the EIA website.""" - # pylint: disable=import-outside-toplevel from openbb_us_eia.utils.helpers import download_excel_file url = WpsrFileMap.get(query.category, "balance_sheet") @@ -136,20 +133,22 @@ class EiaPetroleumStatusReportFetcher( **kwargs: Any, ) -> list[EiaPetroleumStatusReportData]: """Transform the data.""" - # pylint: disable=import-outside-toplevel - import concurrent.futures # noqa + import concurrent.futures import re from functools import lru_cache + from warnings import warn + from numpy import nan from pandas import Categorical, ExcelFile, concat, read_excel - from warnings import warn category = query.category _tables = ( - query.table.split(",") # type: ignore + query.table.split(",") if query.table - else ["stocks"] if category == "weekly_estimates" else ["all"] + else ["stocks"] + if category == "weekly_estimates" + else ["all"] ) all_tables = list(WpsrTableMap[category]) tables = all_tables if "all" in _tables else _tables @@ -226,7 +225,7 @@ class EiaPetroleumStatusReportFetcher( results = concat(dfs) - if len(results) < 1: + if len(results) < 1: # pragma: no cover raise EmptyDataError("The data is empty.") results = results.sort_values(by=["date", "table", "order"]).replace( @@ -237,5 +236,5 @@ class EiaPetroleumStatusReportFetcher( EiaPetroleumStatusReportData.model_validate(d) for d in results.to_dict(orient="records") ] - except Exception as e: # pylint: disable=broad-except + except Exception as e: raise OpenBBError(f"Error transforming the data -> {e}") from e diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/registry.py b/openbb_platform/providers/eia/openbb_us_eia/models/registry.py new file mode 100644 index 00000000000..564f11ca3a1 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/registry.py @@ -0,0 +1,779 @@ +"""Registry of EIA dataset fetchers.""" + +from openbb_us_eia.models.aeo import EiaAeoFetcher +from openbb_us_eia.models.coal.aggregate_production import ( + EiaCoalAggregateProductionFetcher, +) +from openbb_us_eia.models.coal.by_mine_by_plant import EiaCoalByMineByPlantFetcher +from openbb_us_eia.models.coal.consumption_and_quality import ( + EiaCoalConsumptionAndQualityFetcher, +) +from openbb_us_eia.models.coal.exports_imports_quantity_price import ( + EiaCoalExportsImportsQuantityPriceFetcher, +) +from openbb_us_eia.models.coal.market_sales_price import EiaCoalMarketSalesPriceFetcher +from openbb_us_eia.models.coal.mine_aggregates import EiaCoalMineAggregatesFetcher +from openbb_us_eia.models.coal.mine_production import EiaCoalMineProductionFetcher +from openbb_us_eia.models.coal.mine_state_aggregates import ( + EiaCoalMineStateAggregatesFetcher, +) +from openbb_us_eia.models.coal.plant_aggregates import EiaCoalPlantAggregatesFetcher +from openbb_us_eia.models.coal.plant_state_aggregates import ( + EiaCoalPlantStateAggregatesFetcher, +) +from openbb_us_eia.models.coal.price_by_rank import EiaCoalPriceByRankFetcher +from openbb_us_eia.models.coal.receipts import EiaCoalReceiptsFetcher +from openbb_us_eia.models.coal.reserves_capacity import EiaCoalReservesCapacityFetcher +from openbb_us_eia.models.crude_oil_imports import EiaCrudeOilImportsFetcher +from openbb_us_eia.models.densified_biomass.capacity_by_region import ( + EiaDensifiedBiomassCapacityByRegionFetcher, +) +from openbb_us_eia.models.densified_biomass.characteristics_by_region import ( + EiaDensifiedBiomassCharacteristicsByRegionFetcher, +) +from openbb_us_eia.models.densified_biomass.export_sales_and_price import ( + EiaDensifiedBiomassExportSalesAndPriceFetcher, +) +from openbb_us_eia.models.densified_biomass.feedstocks_and_costs import ( + EiaDensifiedBiomassFeedstocksAndCostsFetcher, +) +from openbb_us_eia.models.densified_biomass.inventories_by_region import ( + EiaDensifiedBiomassInventoriesByRegionFetcher, +) +from openbb_us_eia.models.densified_biomass.production_by_region import ( + EiaDensifiedBiomassProductionByRegionFetcher, +) +from openbb_us_eia.models.densified_biomass.sales_and_price_by_region import ( + EiaDensifiedBiomassSalesAndPriceByRegionFetcher, +) +from openbb_us_eia.models.densified_biomass.wood_pellet_plant_capacity import ( + EiaDensifiedBiomassWoodPelletPlantCapacityFetcher, +) +from openbb_us_eia.models.electricity.electric_power_operations import ( + EiaElectricityElectricPowerOperationsFetcher, +) +from openbb_us_eia.models.electricity.electric_power_operations_for_individual_power_plants import ( + EiaElectricityElectricPowerOperationsForIndividualPowerPlantsFetcher, +) +from openbb_us_eia.models.electricity.electricity_sales_to_ultimate_customers import ( + EiaElectricityElectricitySalesToUltimateCustomersFetcher, +) +from openbb_us_eia.models.electricity.inventory_of_operable_generators import ( + EiaElectricityInventoryOfOperableGeneratorsFetcher, +) +from openbb_us_eia.models.electricity_grid.demand import EiaElectricityGridDemandFetcher +from openbb_us_eia.models.electricity_grid.demand_by_subregion import ( + EiaElectricityGridDemandBySubregionFetcher, +) +from openbb_us_eia.models.electricity_grid.generation_by_fuel import ( + EiaElectricityGridGenerationByFuelFetcher, +) +from openbb_us_eia.models.electricity_grid.interchange import ( + EiaElectricityGridInterchangeFetcher, +) +from openbb_us_eia.models.ieo import EiaIeoFetcher +from openbb_us_eia.models.international import EiaInternationalFetcher +from openbb_us_eia.models.natural_gas.associated_dissolved_proved_reserves import ( + EiaNaturalGasAssociatedDissolvedProvedReservesFetcher, +) +from openbb_us_eia.models.natural_gas.average_depth_of_crude_oil_and_natural_gas_wells import ( + EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWellsFetcher, +) +from openbb_us_eia.models.natural_gas.coalbed_methane import ( + EiaNaturalGasCoalbedMethaneFetcher, +) +from openbb_us_eia.models.natural_gas.coalbed_methane_production import ( + EiaNaturalGasCoalbedMethaneProductionFetcher, +) +from openbb_us_eia.models.natural_gas.costs_of_crude_oil_and_natural_gas_wells_drilled import ( + EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilledFetcher, +) +from openbb_us_eia.models.natural_gas.crude_oil_and_natural_gas_drilling_activity import ( + EiaNaturalGasCrudeOilAndNaturalGasDrillingActivityFetcher, +) +from openbb_us_eia.models.natural_gas.crude_oil_and_natural_gas_exploratory_and_development_wells import ( + EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsFetcher, +) +from openbb_us_eia.models.natural_gas.crude_oil_plus_lease_condensate import ( + EiaNaturalGasCrudeOilPlusLeaseCondensateFetcher, +) +from openbb_us_eia.models.natural_gas.dry_natural_gas_proved_reserves import ( + EiaNaturalGasDryNaturalGasProvedReservesFetcher, +) +from openbb_us_eia.models.natural_gas.federal_offshore_gulf_of_america_proved_reserves import ( + EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReservesFetcher, +) +from openbb_us_eia.models.natural_gas.footage_drilled_for_crude_oil_and_natural_gas_wells import ( + EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWellsFetcher, +) +from openbb_us_eia.models.natural_gas.gulf_of_america_federal_offshore_production import ( + EiaNaturalGasGulfOfAmericaFederalOffshoreProductionFetcher, +) +from openbb_us_eia.models.natural_gas.heat_content_of_natural_gas_consumed import ( + EiaNaturalGasHeatContentOfNaturalGasConsumedFetcher, +) +from openbb_us_eia.models.natural_gas.international_interstate_movements_of_natural_gas_by_state import ( + EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByStateFetcher, +) +from openbb_us_eia.models.natural_gas.lease_condensate import ( + EiaNaturalGasLeaseCondensateFetcher, +) +from openbb_us_eia.models.natural_gas.lease_condensate_production import ( + EiaNaturalGasLeaseCondensateProductionFetcher, +) +from openbb_us_eia.models.natural_gas.lng_storage_additions_and_withdrawals import ( + EiaNaturalGasLngStorageAdditionsAndWithdrawalsFetcher, +) +from openbb_us_eia.models.natural_gas.maximum_us_active_seismic_crew_counts import ( + EiaNaturalGasMaximumUsActiveSeismicCrewCountsFetcher, +) +from openbb_us_eia.models.natural_gas.natural_gas_annual_supply_disposition_by_state import ( + EiaNaturalGasNaturalGasAnnualSupplyDispositionByStateFetcher, +) +from openbb_us_eia.models.natural_gas.natural_gas_consumption_by_end_use import ( + EiaNaturalGasNaturalGasConsumptionByEndUseFetcher, +) +from openbb_us_eia.models.natural_gas.natural_gas_delivered_for_the_account_of_others import ( + EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthersFetcher, +) +from openbb_us_eia.models.natural_gas.natural_gas_gross_withdrawals_and_production import ( + EiaNaturalGasNaturalGasGrossWithdrawalsAndProductionFetcher, +) +from openbb_us_eia.models.natural_gas.natural_gas_liquids_proved_reserves import ( + EiaNaturalGasNaturalGasLiquidsProvedReservesFetcher, +) +from openbb_us_eia.models.natural_gas.natural_gas_plant_liquids_production import ( + EiaNaturalGasNaturalGasPlantLiquidsProductionFetcher, +) +from openbb_us_eia.models.natural_gas.natural_gas_plant_processing import ( + EiaNaturalGasNaturalGasPlantProcessingFetcher, +) +from openbb_us_eia.models.natural_gas.natural_gas_prices import ( + EiaNaturalGasNaturalGasPricesFetcher, +) +from openbb_us_eia.models.natural_gas.natural_gas_proved_reserves_wet_after_lease_separation import ( + EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparationFetcher, +) +from openbb_us_eia.models.natural_gas.natural_gas_reserves_summary_as_of_dec_31 import ( + EiaNaturalGasNaturalGasReservesSummaryAsOfDec31Fetcher, +) +from openbb_us_eia.models.natural_gas.natural_gas_spot_and_futures_prices import ( + EiaNaturalGasNaturalGasSpotAndFuturesPricesFetcher, +) +from openbb_us_eia.models.natural_gas.natural_gas_summary import ( + EiaNaturalGasNaturalGasSummaryFetcher, +) +from openbb_us_eia.models.natural_gas.natural_gas_wellhead_value_and_marketed_production import ( + EiaNaturalGasNaturalGasWellheadValueAndMarketedProductionFetcher, +) +from openbb_us_eia.models.natural_gas.nonassociated_proved_reserves import ( + EiaNaturalGasNonassociatedProvedReservesFetcher, +) +from openbb_us_eia.models.natural_gas.number_of_gas_producing_oil_wells import ( + EiaNaturalGasNumberOfGasProducingOilWellsFetcher, +) +from openbb_us_eia.models.natural_gas.number_of_natural_gas_consumers import ( + EiaNaturalGasNumberOfNaturalGasConsumersFetcher, +) +from openbb_us_eia.models.natural_gas.number_of_producing_gas_wells import ( + EiaNaturalGasNumberOfProducingGasWellsFetcher, +) +from openbb_us_eia.models.natural_gas.offshore_gross_withdrawals_of_natural_gas import ( + EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGasFetcher, +) +from openbb_us_eia.models.natural_gas.plant_liquids_in_proved_reserves import ( + EiaNaturalGasPlantLiquidsInProvedReservesFetcher, +) +from openbb_us_eia.models.natural_gas.proved_nonproducing_reserves import ( + EiaNaturalGasProvedNonproducingReservesFetcher, +) +from openbb_us_eia.models.natural_gas.residential_and_commercial_prices_selected_states import ( + EiaNaturalGasResidentialAndCommercialPricesSelectedStatesFetcher, +) +from openbb_us_eia.models.natural_gas.shale_gas import EiaNaturalGasShaleGasFetcher +from openbb_us_eia.models.natural_gas.shale_gas_production import ( + EiaNaturalGasShaleGasProductionFetcher, +) +from openbb_us_eia.models.natural_gas.share_of_total_us_natural_gas_delivered_to_consumers import ( + EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumersFetcher, +) +from openbb_us_eia.models.natural_gas.supplemental_gas_supplies import ( + EiaNaturalGasSupplementalGasSuppliesFetcher, +) +from openbb_us_eia.models.natural_gas.underground_natural_gas_storage_by_all_operators import ( + EiaNaturalGasUndergroundNaturalGasStorageByAllOperatorsFetcher, +) +from openbb_us_eia.models.natural_gas.underground_natural_gas_storage_capacity import ( + EiaNaturalGasUndergroundNaturalGasStorageCapacityFetcher, +) +from openbb_us_eia.models.natural_gas.us_natural_gas_exports_and_re_exports_by_country import ( + EiaNaturalGasUsNaturalGasExportsAndReExportsByCountryFetcher, +) +from openbb_us_eia.models.natural_gas.us_natural_gas_exports_and_re_exports_by_point_of_exit import ( + EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExitFetcher, +) +from openbb_us_eia.models.natural_gas.us_natural_gas_imports_by_country import ( + EiaNaturalGasUsNaturalGasImportsByCountryFetcher, +) +from openbb_us_eia.models.natural_gas.us_natural_gas_imports_by_point_of_entry import ( + EiaNaturalGasUsNaturalGasImportsByPointOfEntryFetcher, +) +from openbb_us_eia.models.natural_gas.us_natural_gas_imports_exports_by_state import ( + EiaNaturalGasUsNaturalGasImportsExportsByStateFetcher, +) +from openbb_us_eia.models.natural_gas.us_natural_gas_monthly_supply_and_disposition_balance import ( + EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalanceFetcher, +) +from openbb_us_eia.models.natural_gas.us_underground_natural_gas_storage_by_storage_type import ( + EiaNaturalGasUsUndergroundNaturalGasStorageByStorageTypeFetcher, +) +from openbb_us_eia.models.natural_gas.weekly_working_gas_in_underground_storage import ( + EiaNaturalGasWeeklyWorkingGasInUndergroundStorageFetcher, +) +from openbb_us_eia.models.nuclear_outages.facility_level_nuclear_outages import ( + EiaNuclearOutagesFacilityLevelNuclearOutagesFetcher, +) +from openbb_us_eia.models.nuclear_outages.generator_level_nuclear_outages import ( + EiaNuclearOutagesGeneratorLevelNuclearOutagesFetcher, +) +from openbb_us_eia.models.nuclear_outages.us_nuclear_outages import ( + EiaNuclearOutagesUsNuclearOutagesFetcher, +) +from openbb_us_eia.models.petroleum.adjusted_distillate_fuel_oil_and_kerosene_sales_by_end_use import ( + EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUseFetcher, +) +from openbb_us_eia.models.petroleum.adjusted_sales_of_distillate_fuel_oil_by_end_use import ( + EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUseFetcher, +) +from openbb_us_eia.models.petroleum.adjusted_sales_of_kerosene_by_end_use import ( + EiaPetroleumAdjustedSalesOfKeroseneByEndUseFetcher, +) +from openbb_us_eia.models.petroleum.adjusted_sales_of_residual_fuel_oil_by_end_use import ( + EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUseFetcher, +) +from openbb_us_eia.models.petroleum.average_depth_of_crude_oil_and_natural_gas_wells import ( + EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWellsFetcher, +) +from openbb_us_eia.models.petroleum.biofuels_operable_production_capacity import ( + EiaPetroleumBiofuelsOperableProductionCapacityFetcher, +) +from openbb_us_eia.models.petroleum.blender_net_input import ( + EiaPetroleumBlenderNetInputFetcher, +) +from openbb_us_eia.models.petroleum.blender_net_production import ( + EiaPetroleumBlenderNetProductionFetcher, +) +from openbb_us_eia.models.petroleum.costs_of_crude_oil_and_natural_gas_wells_drilled import ( + EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilledFetcher, +) +from openbb_us_eia.models.petroleum.crude_first_purchase_prices_selected_streams import ( + EiaPetroleumCrudeFirstPurchasePricesSelectedStreamsFetcher, +) +from openbb_us_eia.models.petroleum.crude_oil_and_lease_condensate_production_by_api_gravity import ( + EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravityFetcher, +) +from openbb_us_eia.models.petroleum.crude_oil_and_natural_gas_drilling_activity import ( + EiaPetroleumCrudeOilAndNaturalGasDrillingActivityFetcher, +) +from openbb_us_eia.models.petroleum.crude_oil_and_natural_gas_exploratory_and_development_wells import ( + EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsFetcher, +) +from openbb_us_eia.models.petroleum.crude_oil_input_qualities import ( + EiaPetroleumCrudeOilInputQualitiesFetcher, +) +from openbb_us_eia.models.petroleum.crude_oil_production import ( + EiaPetroleumCrudeOilProductionFetcher, +) +from openbb_us_eia.models.petroleum.crude_oil_proved_reserves_reserves_changes_and_production import ( + EiaPetroleumCrudeOilProvedReservesReservesChangesAndProductionFetcher, +) +from openbb_us_eia.models.petroleum.crude_oil_stocks_at_tank_farms_pipelines import ( + EiaPetroleumCrudeOilStocksAtTankFarmsPipelinesFetcher, +) +from openbb_us_eia.models.petroleum.crude_plus_lease_condensate_proved_reserves import ( + EiaPetroleumCrudePlusLeaseCondensateProvedReservesFetcher, +) +from openbb_us_eia.models.petroleum.distillate_fuel_oil_and_kerosene_sales_by_end_use import ( + EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUseFetcher, +) +from openbb_us_eia.models.petroleum.domestic_crude_oil_first_purchase_prices_by_api_gravity import ( + EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravityFetcher, +) +from openbb_us_eia.models.petroleum.domestic_crude_oil_first_purchase_prices_by_area import ( + EiaPetroleumDomesticCrudeOilFirstPurchasePricesByAreaFetcher, +) +from openbb_us_eia.models.petroleum.downstream_charge_capacity_of_operable_petroleum_refineries import ( + EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineriesFetcher, +) +from openbb_us_eia.models.petroleum.downstream_processing_of_fresh_feed_input import ( + EiaPetroleumDownstreamProcessingOfFreshFeedInputFetcher, +) +from openbb_us_eia.models.petroleum.exports import EiaPetroleumExportsFetcher +from openbb_us_eia.models.petroleum.exports_by_destination import ( + EiaPetroleumExportsByDestinationFetcher, +) +from openbb_us_eia.models.petroleum.feedstocks_consumed_for_production_of_biofuels import ( + EiaPetroleumFeedstocksConsumedForProductionOfBiofuelsFetcher, +) +from openbb_us_eia.models.petroleum.fob_costs_of_imported_crude_oil_by_api_gravity import ( + EiaPetroleumFobCostsOfImportedCrudeOilByApiGravityFetcher, +) +from openbb_us_eia.models.petroleum.fob_costs_of_imported_crude_oil_by_area import ( + EiaPetroleumFobCostsOfImportedCrudeOilByAreaFetcher, +) +from openbb_us_eia.models.petroleum.fob_costs_of_imported_crude_oil_for_selected_crude_streams import ( + EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreamsFetcher, +) +from openbb_us_eia.models.petroleum.footage_drilled_for_crude_oil_and_natural_gas_wells import ( + EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWellsFetcher, +) +from openbb_us_eia.models.petroleum.fuel_consumed_at_biofuels_plants import ( + EiaPetroleumFuelConsumedAtBiofuelsPlantsFetcher, +) +from openbb_us_eia.models.petroleum.fuel_consumed_at_refineries import ( + EiaPetroleumFuelConsumedAtRefineriesFetcher, +) +from openbb_us_eia.models.petroleum.gasoline_prices_by_formulation_grade_sales_type import ( + EiaPetroleumGasolinePricesByFormulationGradeSalesTypeFetcher, +) +from openbb_us_eia.models.petroleum.gulf_of_america_federal_offshore_production import ( + EiaPetroleumGulfOfAmericaFederalOffshoreProductionFetcher, +) +from openbb_us_eia.models.petroleum.imports_by_area_of_entry import ( + EiaPetroleumImportsByAreaOfEntryFetcher, +) +from openbb_us_eia.models.petroleum.imports_by_processing_area import ( + EiaPetroleumImportsByProcessingAreaFetcher, +) +from openbb_us_eia.models.petroleum.imports_of_residual_fuel import ( + EiaPetroleumImportsOfResidualFuelFetcher, +) +from openbb_us_eia.models.petroleum.landed_costs_of_imported_crude_by_api_gravity import ( + EiaPetroleumLandedCostsOfImportedCrudeByApiGravityFetcher, +) +from openbb_us_eia.models.petroleum.landed_costs_of_imported_crude_by_area import ( + EiaPetroleumLandedCostsOfImportedCrudeByAreaFetcher, +) +from openbb_us_eia.models.petroleum.landed_costs_of_imported_crude_for_selected_crude_streams import ( + EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreamsFetcher, +) +from openbb_us_eia.models.petroleum.maximum_us_active_seismic_crew_counts import ( + EiaPetroleumMaximumUsActiveSeismicCrewCountsFetcher, +) +from openbb_us_eia.models.petroleum.movements_between_pad_districts import ( + EiaPetroleumMovementsBetweenPadDistrictsFetcher, +) +from openbb_us_eia.models.petroleum.movements_by_pipeline_between_pad_districts import ( + EiaPetroleumMovementsByPipelineBetweenPadDistrictsFetcher, +) +from openbb_us_eia.models.petroleum.movements_by_rail_between_pad_districts import ( + EiaPetroleumMovementsByRailBetweenPadDistrictsFetcher, +) +from openbb_us_eia.models.petroleum.movements_by_tanker_and_barge_between_pad_districts import ( + EiaPetroleumMovementsByTankerAndBargeBetweenPadDistrictsFetcher, +) +from openbb_us_eia.models.petroleum.movements_of_crude_oil_and_selected_products_by_rail import ( + EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRailFetcher, +) +from openbb_us_eia.models.petroleum.natural_gas_feedstock_for_hydrogen import ( + EiaPetroleumNaturalGasFeedstockForHydrogenFetcher, +) +from openbb_us_eia.models.petroleum.natural_gas_plant_field_production import ( + EiaPetroleumNaturalGasPlantFieldProductionFetcher, +) +from openbb_us_eia.models.petroleum.natural_gas_plant_stocks import ( + EiaPetroleumNaturalGasPlantStocksFetcher, +) +from openbb_us_eia.models.petroleum.net_receipts_between_pad_districts import ( + EiaPetroleumNetReceiptsBetweenPadDistrictsFetcher, +) +from openbb_us_eia.models.petroleum.no2_distillate_prices_by_sales_type import ( + EiaPetroleumNo2DistillatePricesBySalesTypeFetcher, +) +from openbb_us_eia.models.petroleum.number_and_capacity_of_petroleum_refineries import ( + EiaPetroleumNumberAndCapacityOfPetroleumRefineriesFetcher, +) +from openbb_us_eia.models.petroleum.nymex_futures_prices import ( + EiaPetroleumNymexFuturesPricesFetcher, +) +from openbb_us_eia.models.petroleum.oxygenate_production import ( + EiaPetroleumOxygenateProductionFetcher, +) +from openbb_us_eia.models.petroleum.pad_district_exports_by_destination import ( + EiaPetroleumPadDistrictExportsByDestinationFetcher, +) +from openbb_us_eia.models.petroleum.pad_district_imports_by_country_of_origin import ( + EiaPetroleumPadDistrictImportsByCountryOfOriginFetcher, +) +from openbb_us_eia.models.petroleum.percentages_of_total_imported_crude_oil_by_api_gravity import ( + EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravityFetcher, +) +from openbb_us_eia.models.petroleum.prices_sales_volumes_stocks_by_state import ( + EiaPetroleumPricesSalesVolumesStocksByStateFetcher, +) +from openbb_us_eia.models.petroleum.prime_supplier_sales_volumes import ( + EiaPetroleumPrimeSupplierSalesVolumesFetcher, +) +from openbb_us_eia.models.petroleum.product_supplied import ( + EiaPetroleumProductSuppliedFetcher, +) +from openbb_us_eia.models.petroleum.production_capacity_of_operable_petroleum_refineries import ( + EiaPetroleumProductionCapacityOfOperablePetroleumRefineriesFetcher, +) +from openbb_us_eia.models.petroleum.propane_prices_by_sales_type import ( + EiaPetroleumPropanePricesBySalesTypeFetcher, +) +from openbb_us_eia.models.petroleum.proved_nonproducing_reserves import ( + EiaPetroleumProvedNonproducingReservesFetcher, +) +from openbb_us_eia.models.petroleum.refiner_acquisition_cost_of_crude_oil import ( + EiaPetroleumRefinerAcquisitionCostOfCrudeOilFetcher, +) +from openbb_us_eia.models.petroleum.refiner_gasoline_prices_by_grade_and_sales_type import ( + EiaPetroleumRefinerGasolinePricesByGradeAndSalesTypeFetcher, +) +from openbb_us_eia.models.petroleum.refiner_motor_gasoline_sales_volumes import ( + EiaPetroleumRefinerMotorGasolineSalesVolumesFetcher, +) +from openbb_us_eia.models.petroleum.refiner_petroleum_product_prices_by_sales_type import ( + EiaPetroleumRefinerPetroleumProductPricesBySalesTypeFetcher, +) +from openbb_us_eia.models.petroleum.refiner_residual_fuel_oil_and_no4_fuel_sales_volumes import ( + EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumesFetcher, +) +from openbb_us_eia.models.petroleum.refiner_sales_volumes_of_other_petroleum_products import ( + EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProductsFetcher, +) +from openbb_us_eia.models.petroleum.refinery_blender_net_input import ( + EiaPetroleumRefineryBlenderNetInputFetcher, +) +from openbb_us_eia.models.petroleum.refinery_blender_net_production import ( + EiaPetroleumRefineryBlenderNetProductionFetcher, +) +from openbb_us_eia.models.petroleum.refinery_bulk_terminal_and_natural_gas_plant_stocks_by_state import ( + EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByStateFetcher, +) +from openbb_us_eia.models.petroleum.refinery_net_input import ( + EiaPetroleumRefineryNetInputFetcher, +) +from openbb_us_eia.models.petroleum.refinery_net_production import ( + EiaPetroleumRefineryNetProductionFetcher, +) +from openbb_us_eia.models.petroleum.refinery_receipts_of_crude_oil_by_method_of_transportation import ( + EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportationFetcher, +) +from openbb_us_eia.models.petroleum.refinery_stocks import ( + EiaPetroleumRefineryStocksFetcher, +) +from openbb_us_eia.models.petroleum.refinery_utilization_and_capacity import ( + EiaPetroleumRefineryUtilizationAndCapacityFetcher, +) +from openbb_us_eia.models.petroleum.refinery_yield import ( + EiaPetroleumRefineryYieldFetcher, +) +from openbb_us_eia.models.petroleum.residual_fuel_oil_prices_by_sales_type import ( + EiaPetroleumResidualFuelOilPricesBySalesTypeFetcher, +) +from openbb_us_eia.models.petroleum.sales_of_distillate_fuel_oil_by_end_use import ( + EiaPetroleumSalesOfDistillateFuelOilByEndUseFetcher, +) +from openbb_us_eia.models.petroleum.sales_of_kerosene_by_end_use import ( + EiaPetroleumSalesOfKeroseneByEndUseFetcher, +) +from openbb_us_eia.models.petroleum.sales_of_residual_fuel_oil_by_end_use import ( + EiaPetroleumSalesOfResidualFuelOilByEndUseFetcher, +) +from openbb_us_eia.models.petroleum.shell_storage_capacity_at_operable_refineries import ( + EiaPetroleumShellStorageCapacityAtOperableRefineriesFetcher, +) +from openbb_us_eia.models.petroleum.spot_prices import EiaPetroleumSpotPricesFetcher +from openbb_us_eia.models.petroleum.stocks_by_type import ( + EiaPetroleumStocksByTypeFetcher, +) +from openbb_us_eia.models.petroleum.stocks_of_selected_products import ( + EiaPetroleumStocksOfSelectedProductsFetcher, +) +from openbb_us_eia.models.petroleum.supply_and_disposition import ( + EiaPetroleumSupplyAndDispositionFetcher, +) +from openbb_us_eia.models.petroleum.us_biodiesel_production_capacity_sales_and_stocks import ( + EiaPetroleumUsBiodieselProductionCapacitySalesAndStocksFetcher, +) +from openbb_us_eia.models.petroleum.us_crude_oil_supply_disposition import ( + EiaPetroleumUsCrudeOilSupplyDispositionFetcher, +) +from openbb_us_eia.models.petroleum.us_imports_by_country_of_origin import ( + EiaPetroleumUsImportsByCountryOfOriginFetcher, +) +from openbb_us_eia.models.petroleum.us_net_imports_by_country import ( + EiaPetroleumUsNetImportsByCountryFetcher, +) +from openbb_us_eia.models.petroleum.us_refiner_gasoline_prices_by_formulation_grade_sales_type import ( + EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesTypeFetcher, +) +from openbb_us_eia.models.petroleum.us_weekly_product_supplied import ( + EiaPetroleumUsWeeklyProductSuppliedFetcher, +) +from openbb_us_eia.models.petroleum.weekly_blender_net_production import ( + EiaPetroleumWeeklyBlenderNetProductionFetcher, +) +from openbb_us_eia.models.petroleum.weekly_crude_imports_by_top_10_origins import ( + EiaPetroleumWeeklyCrudeImportsByTop10OriginsFetcher, +) +from openbb_us_eia.models.petroleum.weekly_ethanol_plant_production import ( + EiaPetroleumWeeklyEthanolPlantProductionFetcher, +) +from openbb_us_eia.models.petroleum.weekly_heating_oil_and_propane_prices import ( + EiaPetroleumWeeklyHeatingOilAndPropanePricesFetcher, +) +from openbb_us_eia.models.petroleum.weekly_imports_exports import ( + EiaPetroleumWeeklyImportsExportsFetcher, +) +from openbb_us_eia.models.petroleum.weekly_inputs_utilization import ( + EiaPetroleumWeeklyInputsUtilizationFetcher, +) +from openbb_us_eia.models.petroleum.weekly_refiner_blender_net_production import ( + EiaPetroleumWeeklyRefinerBlenderNetProductionFetcher, +) +from openbb_us_eia.models.petroleum.weekly_refiner_net_production import ( + EiaPetroleumWeeklyRefinerNetProductionFetcher, +) +from openbb_us_eia.models.petroleum.weekly_retail_gasoline_and_diesel_prices import ( + EiaPetroleumWeeklyRetailGasolineAndDieselPricesFetcher, +) +from openbb_us_eia.models.petroleum.weekly_stocks import EiaPetroleumWeeklyStocksFetcher +from openbb_us_eia.models.petroleum.weekly_supply_estimates import ( + EiaPetroleumWeeklySupplyEstimatesFetcher, +) +from openbb_us_eia.models.petroleum.working_storage_capacity_at_operable_refineries import ( + EiaPetroleumWorkingStorageCapacityAtOperableRefineriesFetcher, +) +from openbb_us_eia.models.seds import EiaSedsFetcher +from openbb_us_eia.models.state_electricity_profiles.advanced_metering_infrastructure import ( + EiaStateElectricityProfilesAdvancedMeteringInfrastructureFetcher, +) +from openbb_us_eia.models.state_electricity_profiles.costs_and_savings_from_energy_efficiency_programs import ( + EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyProgramsFetcher, +) +from openbb_us_eia.models.state_electricity_profiles.electricity_net_metering_customers_and_capacity import ( + EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacityFetcher, +) +from openbb_us_eia.models.state_electricity_profiles.emissions_by_state_by_fuel import ( + EiaStateElectricityProfilesEmissionsByStateByFuelFetcher, +) +from openbb_us_eia.models.state_electricity_profiles.generating_capacity import ( + EiaStateElectricityProfilesGeneratingCapacityFetcher, +) +from openbb_us_eia.models.state_electricity_profiles.state_rankings_for_key_statistics import ( + EiaStateElectricityProfilesStateRankingsForKeyStatisticsFetcher, +) +from openbb_us_eia.models.state_electricity_profiles.supply_and_disposition_of_electricity import ( + EiaStateElectricityProfilesSupplyAndDispositionOfElectricityFetcher, +) +from openbb_us_eia.models.total_energy import EiaTotalEnergyFetcher + +DATASET_FETCHERS = { + "EiaAeo": EiaAeoFetcher, + "EiaCoalAggregateProduction": EiaCoalAggregateProductionFetcher, + "EiaCoalByMineByPlant": EiaCoalByMineByPlantFetcher, + "EiaCoalConsumptionAndQuality": EiaCoalConsumptionAndQualityFetcher, + "EiaCoalExportsImportsQuantityPrice": EiaCoalExportsImportsQuantityPriceFetcher, + "EiaCoalMarketSalesPrice": EiaCoalMarketSalesPriceFetcher, + "EiaCoalMineAggregates": EiaCoalMineAggregatesFetcher, + "EiaCoalMineProduction": EiaCoalMineProductionFetcher, + "EiaCoalMineStateAggregates": EiaCoalMineStateAggregatesFetcher, + "EiaCoalPlantAggregates": EiaCoalPlantAggregatesFetcher, + "EiaCoalPlantStateAggregates": EiaCoalPlantStateAggregatesFetcher, + "EiaCoalPriceByRank": EiaCoalPriceByRankFetcher, + "EiaCoalReceipts": EiaCoalReceiptsFetcher, + "EiaCoalReservesCapacity": EiaCoalReservesCapacityFetcher, + "EiaCrudeOilImports": EiaCrudeOilImportsFetcher, + "EiaDensifiedBiomassCapacityByRegion": EiaDensifiedBiomassCapacityByRegionFetcher, + "EiaDensifiedBiomassCharacteristicsByRegion": EiaDensifiedBiomassCharacteristicsByRegionFetcher, + "EiaDensifiedBiomassExportSalesAndPrice": EiaDensifiedBiomassExportSalesAndPriceFetcher, + "EiaDensifiedBiomassFeedstocksAndCosts": EiaDensifiedBiomassFeedstocksAndCostsFetcher, + "EiaDensifiedBiomassInventoriesByRegion": EiaDensifiedBiomassInventoriesByRegionFetcher, + "EiaDensifiedBiomassProductionByRegion": EiaDensifiedBiomassProductionByRegionFetcher, + "EiaDensifiedBiomassSalesAndPriceByRegion": EiaDensifiedBiomassSalesAndPriceByRegionFetcher, + "EiaDensifiedBiomassWoodPelletPlantCapacity": EiaDensifiedBiomassWoodPelletPlantCapacityFetcher, + "EiaElectricityElectricPowerOperations": EiaElectricityElectricPowerOperationsFetcher, + "EiaElectricityElectricPowerOperationsForIndividualPowerPlants": EiaElectricityElectricPowerOperationsForIndividualPowerPlantsFetcher, + "EiaElectricityElectricitySalesToUltimateCustomers": EiaElectricityElectricitySalesToUltimateCustomersFetcher, + "EiaElectricityGridDemand": EiaElectricityGridDemandFetcher, + "EiaElectricityGridDemandBySubregion": EiaElectricityGridDemandBySubregionFetcher, + "EiaElectricityGridGenerationByFuel": EiaElectricityGridGenerationByFuelFetcher, + "EiaElectricityGridInterchange": EiaElectricityGridInterchangeFetcher, + "EiaElectricityInventoryOfOperableGenerators": EiaElectricityInventoryOfOperableGeneratorsFetcher, + "EiaIeo": EiaIeoFetcher, + "EiaInternational": EiaInternationalFetcher, + "EiaNaturalGasAssociatedDissolvedProvedReserves": EiaNaturalGasAssociatedDissolvedProvedReservesFetcher, + "EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWells": EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWellsFetcher, + "EiaNaturalGasCoalbedMethane": EiaNaturalGasCoalbedMethaneFetcher, + "EiaNaturalGasCoalbedMethaneProduction": EiaNaturalGasCoalbedMethaneProductionFetcher, + "EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilled": EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilledFetcher, + "EiaNaturalGasCrudeOilAndNaturalGasDrillingActivity": EiaNaturalGasCrudeOilAndNaturalGasDrillingActivityFetcher, + "EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWells": EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsFetcher, + "EiaNaturalGasCrudeOilPlusLeaseCondensate": EiaNaturalGasCrudeOilPlusLeaseCondensateFetcher, + "EiaNaturalGasDryNaturalGasProvedReserves": EiaNaturalGasDryNaturalGasProvedReservesFetcher, + "EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReserves": EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReservesFetcher, + "EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWells": EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWellsFetcher, + "EiaNaturalGasGulfOfAmericaFederalOffshoreProduction": EiaNaturalGasGulfOfAmericaFederalOffshoreProductionFetcher, + "EiaNaturalGasHeatContentOfNaturalGasConsumed": EiaNaturalGasHeatContentOfNaturalGasConsumedFetcher, + "EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByState": EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByStateFetcher, + "EiaNaturalGasLeaseCondensate": EiaNaturalGasLeaseCondensateFetcher, + "EiaNaturalGasLeaseCondensateProduction": EiaNaturalGasLeaseCondensateProductionFetcher, + "EiaNaturalGasLngStorageAdditionsAndWithdrawals": EiaNaturalGasLngStorageAdditionsAndWithdrawalsFetcher, + "EiaNaturalGasMaximumUsActiveSeismicCrewCounts": EiaNaturalGasMaximumUsActiveSeismicCrewCountsFetcher, + "EiaNaturalGasNaturalGasAnnualSupplyDispositionByState": EiaNaturalGasNaturalGasAnnualSupplyDispositionByStateFetcher, + "EiaNaturalGasNaturalGasConsumptionByEndUse": EiaNaturalGasNaturalGasConsumptionByEndUseFetcher, + "EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthers": EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthersFetcher, + "EiaNaturalGasNaturalGasGrossWithdrawalsAndProduction": EiaNaturalGasNaturalGasGrossWithdrawalsAndProductionFetcher, + "EiaNaturalGasNaturalGasLiquidsProvedReserves": EiaNaturalGasNaturalGasLiquidsProvedReservesFetcher, + "EiaNaturalGasNaturalGasPlantLiquidsProduction": EiaNaturalGasNaturalGasPlantLiquidsProductionFetcher, + "EiaNaturalGasNaturalGasPlantProcessing": EiaNaturalGasNaturalGasPlantProcessingFetcher, + "EiaNaturalGasNaturalGasPrices": EiaNaturalGasNaturalGasPricesFetcher, + "EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparation": EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparationFetcher, + "EiaNaturalGasNaturalGasReservesSummaryAsOfDec31": EiaNaturalGasNaturalGasReservesSummaryAsOfDec31Fetcher, + "EiaNaturalGasNaturalGasSpotAndFuturesPrices": EiaNaturalGasNaturalGasSpotAndFuturesPricesFetcher, + "EiaNaturalGasNaturalGasSummary": EiaNaturalGasNaturalGasSummaryFetcher, + "EiaNaturalGasNaturalGasWellheadValueAndMarketedProduction": EiaNaturalGasNaturalGasWellheadValueAndMarketedProductionFetcher, + "EiaNaturalGasNonassociatedProvedReserves": EiaNaturalGasNonassociatedProvedReservesFetcher, + "EiaNaturalGasNumberOfGasProducingOilWells": EiaNaturalGasNumberOfGasProducingOilWellsFetcher, + "EiaNaturalGasNumberOfNaturalGasConsumers": EiaNaturalGasNumberOfNaturalGasConsumersFetcher, + "EiaNaturalGasNumberOfProducingGasWells": EiaNaturalGasNumberOfProducingGasWellsFetcher, + "EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGas": EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGasFetcher, + "EiaNaturalGasPlantLiquidsInProvedReserves": EiaNaturalGasPlantLiquidsInProvedReservesFetcher, + "EiaNaturalGasProvedNonproducingReserves": EiaNaturalGasProvedNonproducingReservesFetcher, + "EiaNaturalGasResidentialAndCommercialPricesSelectedStates": EiaNaturalGasResidentialAndCommercialPricesSelectedStatesFetcher, + "EiaNaturalGasShaleGas": EiaNaturalGasShaleGasFetcher, + "EiaNaturalGasShaleGasProduction": EiaNaturalGasShaleGasProductionFetcher, + "EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumers": EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumersFetcher, + "EiaNaturalGasSupplementalGasSupplies": EiaNaturalGasSupplementalGasSuppliesFetcher, + "EiaNaturalGasUndergroundNaturalGasStorageByAllOperators": EiaNaturalGasUndergroundNaturalGasStorageByAllOperatorsFetcher, + "EiaNaturalGasUndergroundNaturalGasStorageCapacity": EiaNaturalGasUndergroundNaturalGasStorageCapacityFetcher, + "EiaNaturalGasUsNaturalGasExportsAndReExportsByCountry": EiaNaturalGasUsNaturalGasExportsAndReExportsByCountryFetcher, + "EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExit": EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExitFetcher, + "EiaNaturalGasUsNaturalGasImportsByCountry": EiaNaturalGasUsNaturalGasImportsByCountryFetcher, + "EiaNaturalGasUsNaturalGasImportsByPointOfEntry": EiaNaturalGasUsNaturalGasImportsByPointOfEntryFetcher, + "EiaNaturalGasUsNaturalGasImportsExportsByState": EiaNaturalGasUsNaturalGasImportsExportsByStateFetcher, + "EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalance": EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalanceFetcher, + "EiaNaturalGasUsUndergroundNaturalGasStorageByStorageType": EiaNaturalGasUsUndergroundNaturalGasStorageByStorageTypeFetcher, + "EiaNaturalGasWeeklyWorkingGasInUndergroundStorage": EiaNaturalGasWeeklyWorkingGasInUndergroundStorageFetcher, + "EiaNuclearOutagesFacilityLevelNuclearOutages": EiaNuclearOutagesFacilityLevelNuclearOutagesFetcher, + "EiaNuclearOutagesGeneratorLevelNuclearOutages": EiaNuclearOutagesGeneratorLevelNuclearOutagesFetcher, + "EiaNuclearOutagesUsNuclearOutages": EiaNuclearOutagesUsNuclearOutagesFetcher, + "EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUse": EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUseFetcher, + "EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUse": EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUseFetcher, + "EiaPetroleumAdjustedSalesOfKeroseneByEndUse": EiaPetroleumAdjustedSalesOfKeroseneByEndUseFetcher, + "EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUse": EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUseFetcher, + "EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWells": EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWellsFetcher, + "EiaPetroleumBiofuelsOperableProductionCapacity": EiaPetroleumBiofuelsOperableProductionCapacityFetcher, + "EiaPetroleumBlenderNetInput": EiaPetroleumBlenderNetInputFetcher, + "EiaPetroleumBlenderNetProduction": EiaPetroleumBlenderNetProductionFetcher, + "EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilled": EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilledFetcher, + "EiaPetroleumCrudeFirstPurchasePricesSelectedStreams": EiaPetroleumCrudeFirstPurchasePricesSelectedStreamsFetcher, + "EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravity": EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravityFetcher, + "EiaPetroleumCrudeOilAndNaturalGasDrillingActivity": EiaPetroleumCrudeOilAndNaturalGasDrillingActivityFetcher, + "EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWells": EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWellsFetcher, + "EiaPetroleumCrudeOilInputQualities": EiaPetroleumCrudeOilInputQualitiesFetcher, + "EiaPetroleumCrudeOilProduction": EiaPetroleumCrudeOilProductionFetcher, + "EiaPetroleumCrudeOilProvedReservesReservesChangesAndProduction": EiaPetroleumCrudeOilProvedReservesReservesChangesAndProductionFetcher, + "EiaPetroleumCrudeOilStocksAtTankFarmsPipelines": EiaPetroleumCrudeOilStocksAtTankFarmsPipelinesFetcher, + "EiaPetroleumCrudePlusLeaseCondensateProvedReserves": EiaPetroleumCrudePlusLeaseCondensateProvedReservesFetcher, + "EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUse": EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUseFetcher, + "EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravity": EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravityFetcher, + "EiaPetroleumDomesticCrudeOilFirstPurchasePricesByArea": EiaPetroleumDomesticCrudeOilFirstPurchasePricesByAreaFetcher, + "EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineries": EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineriesFetcher, + "EiaPetroleumDownstreamProcessingOfFreshFeedInput": EiaPetroleumDownstreamProcessingOfFreshFeedInputFetcher, + "EiaPetroleumExports": EiaPetroleumExportsFetcher, + "EiaPetroleumExportsByDestination": EiaPetroleumExportsByDestinationFetcher, + "EiaPetroleumFeedstocksConsumedForProductionOfBiofuels": EiaPetroleumFeedstocksConsumedForProductionOfBiofuelsFetcher, + "EiaPetroleumFobCostsOfImportedCrudeOilByApiGravity": EiaPetroleumFobCostsOfImportedCrudeOilByApiGravityFetcher, + "EiaPetroleumFobCostsOfImportedCrudeOilByArea": EiaPetroleumFobCostsOfImportedCrudeOilByAreaFetcher, + "EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreams": EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreamsFetcher, + "EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWells": EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWellsFetcher, + "EiaPetroleumFuelConsumedAtBiofuelsPlants": EiaPetroleumFuelConsumedAtBiofuelsPlantsFetcher, + "EiaPetroleumFuelConsumedAtRefineries": EiaPetroleumFuelConsumedAtRefineriesFetcher, + "EiaPetroleumGasolinePricesByFormulationGradeSalesType": EiaPetroleumGasolinePricesByFormulationGradeSalesTypeFetcher, + "EiaPetroleumGulfOfAmericaFederalOffshoreProduction": EiaPetroleumGulfOfAmericaFederalOffshoreProductionFetcher, + "EiaPetroleumImportsByAreaOfEntry": EiaPetroleumImportsByAreaOfEntryFetcher, + "EiaPetroleumImportsByProcessingArea": EiaPetroleumImportsByProcessingAreaFetcher, + "EiaPetroleumImportsOfResidualFuel": EiaPetroleumImportsOfResidualFuelFetcher, + "EiaPetroleumLandedCostsOfImportedCrudeByApiGravity": EiaPetroleumLandedCostsOfImportedCrudeByApiGravityFetcher, + "EiaPetroleumLandedCostsOfImportedCrudeByArea": EiaPetroleumLandedCostsOfImportedCrudeByAreaFetcher, + "EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreams": EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreamsFetcher, + "EiaPetroleumMaximumUsActiveSeismicCrewCounts": EiaPetroleumMaximumUsActiveSeismicCrewCountsFetcher, + "EiaPetroleumMovementsBetweenPadDistricts": EiaPetroleumMovementsBetweenPadDistrictsFetcher, + "EiaPetroleumMovementsByPipelineBetweenPadDistricts": EiaPetroleumMovementsByPipelineBetweenPadDistrictsFetcher, + "EiaPetroleumMovementsByRailBetweenPadDistricts": EiaPetroleumMovementsByRailBetweenPadDistrictsFetcher, + "EiaPetroleumMovementsByTankerAndBargeBetweenPadDistricts": EiaPetroleumMovementsByTankerAndBargeBetweenPadDistrictsFetcher, + "EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRail": EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRailFetcher, + "EiaPetroleumNaturalGasFeedstockForHydrogen": EiaPetroleumNaturalGasFeedstockForHydrogenFetcher, + "EiaPetroleumNaturalGasPlantFieldProduction": EiaPetroleumNaturalGasPlantFieldProductionFetcher, + "EiaPetroleumNaturalGasPlantStocks": EiaPetroleumNaturalGasPlantStocksFetcher, + "EiaPetroleumNetReceiptsBetweenPadDistricts": EiaPetroleumNetReceiptsBetweenPadDistrictsFetcher, + "EiaPetroleumNo2DistillatePricesBySalesType": EiaPetroleumNo2DistillatePricesBySalesTypeFetcher, + "EiaPetroleumNumberAndCapacityOfPetroleumRefineries": EiaPetroleumNumberAndCapacityOfPetroleumRefineriesFetcher, + "EiaPetroleumNymexFuturesPrices": EiaPetroleumNymexFuturesPricesFetcher, + "EiaPetroleumOxygenateProduction": EiaPetroleumOxygenateProductionFetcher, + "EiaPetroleumPadDistrictExportsByDestination": EiaPetroleumPadDistrictExportsByDestinationFetcher, + "EiaPetroleumPadDistrictImportsByCountryOfOrigin": EiaPetroleumPadDistrictImportsByCountryOfOriginFetcher, + "EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravity": EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravityFetcher, + "EiaPetroleumPricesSalesVolumesStocksByState": EiaPetroleumPricesSalesVolumesStocksByStateFetcher, + "EiaPetroleumPrimeSupplierSalesVolumes": EiaPetroleumPrimeSupplierSalesVolumesFetcher, + "EiaPetroleumProductSupplied": EiaPetroleumProductSuppliedFetcher, + "EiaPetroleumProductionCapacityOfOperablePetroleumRefineries": EiaPetroleumProductionCapacityOfOperablePetroleumRefineriesFetcher, + "EiaPetroleumPropanePricesBySalesType": EiaPetroleumPropanePricesBySalesTypeFetcher, + "EiaPetroleumProvedNonproducingReserves": EiaPetroleumProvedNonproducingReservesFetcher, + "EiaPetroleumRefinerAcquisitionCostOfCrudeOil": EiaPetroleumRefinerAcquisitionCostOfCrudeOilFetcher, + "EiaPetroleumRefinerGasolinePricesByGradeAndSalesType": EiaPetroleumRefinerGasolinePricesByGradeAndSalesTypeFetcher, + "EiaPetroleumRefinerMotorGasolineSalesVolumes": EiaPetroleumRefinerMotorGasolineSalesVolumesFetcher, + "EiaPetroleumRefinerPetroleumProductPricesBySalesType": EiaPetroleumRefinerPetroleumProductPricesBySalesTypeFetcher, + "EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumes": EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumesFetcher, + "EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProducts": EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProductsFetcher, + "EiaPetroleumRefineryBlenderNetInput": EiaPetroleumRefineryBlenderNetInputFetcher, + "EiaPetroleumRefineryBlenderNetProduction": EiaPetroleumRefineryBlenderNetProductionFetcher, + "EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByState": EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByStateFetcher, + "EiaPetroleumRefineryNetInput": EiaPetroleumRefineryNetInputFetcher, + "EiaPetroleumRefineryNetProduction": EiaPetroleumRefineryNetProductionFetcher, + "EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportation": EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportationFetcher, + "EiaPetroleumRefineryStocks": EiaPetroleumRefineryStocksFetcher, + "EiaPetroleumRefineryUtilizationAndCapacity": EiaPetroleumRefineryUtilizationAndCapacityFetcher, + "EiaPetroleumRefineryYield": EiaPetroleumRefineryYieldFetcher, + "EiaPetroleumResidualFuelOilPricesBySalesType": EiaPetroleumResidualFuelOilPricesBySalesTypeFetcher, + "EiaPetroleumSalesOfDistillateFuelOilByEndUse": EiaPetroleumSalesOfDistillateFuelOilByEndUseFetcher, + "EiaPetroleumSalesOfKeroseneByEndUse": EiaPetroleumSalesOfKeroseneByEndUseFetcher, + "EiaPetroleumSalesOfResidualFuelOilByEndUse": EiaPetroleumSalesOfResidualFuelOilByEndUseFetcher, + "EiaPetroleumShellStorageCapacityAtOperableRefineries": EiaPetroleumShellStorageCapacityAtOperableRefineriesFetcher, + "EiaPetroleumSpotPrices": EiaPetroleumSpotPricesFetcher, + "EiaPetroleumStocksByType": EiaPetroleumStocksByTypeFetcher, + "EiaPetroleumStocksOfSelectedProducts": EiaPetroleumStocksOfSelectedProductsFetcher, + "EiaPetroleumSupplyAndDisposition": EiaPetroleumSupplyAndDispositionFetcher, + "EiaPetroleumUsBiodieselProductionCapacitySalesAndStocks": EiaPetroleumUsBiodieselProductionCapacitySalesAndStocksFetcher, + "EiaPetroleumUsCrudeOilSupplyDisposition": EiaPetroleumUsCrudeOilSupplyDispositionFetcher, + "EiaPetroleumUsImportsByCountryOfOrigin": EiaPetroleumUsImportsByCountryOfOriginFetcher, + "EiaPetroleumUsNetImportsByCountry": EiaPetroleumUsNetImportsByCountryFetcher, + "EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesType": EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesTypeFetcher, + "EiaPetroleumUsWeeklyProductSupplied": EiaPetroleumUsWeeklyProductSuppliedFetcher, + "EiaPetroleumWeeklyBlenderNetProduction": EiaPetroleumWeeklyBlenderNetProductionFetcher, + "EiaPetroleumWeeklyCrudeImportsByTop10Origins": EiaPetroleumWeeklyCrudeImportsByTop10OriginsFetcher, + "EiaPetroleumWeeklyEthanolPlantProduction": EiaPetroleumWeeklyEthanolPlantProductionFetcher, + "EiaPetroleumWeeklyHeatingOilAndPropanePrices": EiaPetroleumWeeklyHeatingOilAndPropanePricesFetcher, + "EiaPetroleumWeeklyImportsExports": EiaPetroleumWeeklyImportsExportsFetcher, + "EiaPetroleumWeeklyInputsUtilization": EiaPetroleumWeeklyInputsUtilizationFetcher, + "EiaPetroleumWeeklyRefinerBlenderNetProduction": EiaPetroleumWeeklyRefinerBlenderNetProductionFetcher, + "EiaPetroleumWeeklyRefinerNetProduction": EiaPetroleumWeeklyRefinerNetProductionFetcher, + "EiaPetroleumWeeklyRetailGasolineAndDieselPrices": EiaPetroleumWeeklyRetailGasolineAndDieselPricesFetcher, + "EiaPetroleumWeeklyStocks": EiaPetroleumWeeklyStocksFetcher, + "EiaPetroleumWeeklySupplyEstimates": EiaPetroleumWeeklySupplyEstimatesFetcher, + "EiaPetroleumWorkingStorageCapacityAtOperableRefineries": EiaPetroleumWorkingStorageCapacityAtOperableRefineriesFetcher, + "EiaSeds": EiaSedsFetcher, + "EiaStateElectricityProfilesAdvancedMeteringInfrastructure": EiaStateElectricityProfilesAdvancedMeteringInfrastructureFetcher, + "EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyPrograms": EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyProgramsFetcher, + "EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacity": EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacityFetcher, + "EiaStateElectricityProfilesEmissionsByStateByFuel": EiaStateElectricityProfilesEmissionsByStateByFuelFetcher, + "EiaStateElectricityProfilesGeneratingCapacity": EiaStateElectricityProfilesGeneratingCapacityFetcher, + "EiaStateElectricityProfilesStateRankingsForKeyStatistics": EiaStateElectricityProfilesStateRankingsForKeyStatisticsFetcher, + "EiaStateElectricityProfilesSupplyAndDispositionOfElectricity": EiaStateElectricityProfilesSupplyAndDispositionOfElectricityFetcher, + "EiaTotalEnergy": EiaTotalEnergyFetcher, +} diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/seds.py b/openbb_platform/providers/eia/openbb_us_eia/models/seds.py new file mode 100644 index 00000000000..c93f8d59493 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/seds.py @@ -0,0 +1,151 @@ +"""State Energy Data System (SEDS) model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaSedsQueryParams(EiaApiQueryParams): + """State Energy Data System (SEDS). Estimated production, consumption, price, and expenditure data for all energy sources by state and sector. Source: https://www.eia.gov/state/seds/seds-technical-notes-complete.php Product: SEDS (https://www.eia.gov/state/seds/) + + Source: https://www.eia.gov/opendata/browser/seds + """ + + __group__ = "seds" + __dataset__ = "seds" + __json_schema_extra__ = { + "series": {"multiple_items_allowed": True}, + "state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "district_of_columbia", + "federal_offshore_gulf_of_america", + "federal_offshore_pacific", + "florida", + "georgia", + "hawaii", + "idaho", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "minnesota", + "mississippi", + "missouri", + "montana", + "nebraska", + "nevada", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pennsylvania", + "rhode_island", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "united_states", + "utah", + "vermont", + "virginia", + "washington", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + } + + series: str | None = Field( + default=None, + description="Unique series identifier filter. Accepts a comma-separated list of values. There are 968 valid values - use the `facet_options` endpoint to list them.", + ) + state: str | None = Field( + default=None, + description="State name filter. Accepts a comma-separated list of values.", + ) + + +class EiaSedsData(EiaApiData): + """State Energy Data System (SEDS). Estimated production, consumption, price, and expenditure data for all energy sources by state and sector. Source: https://www.eia.gov/state/seds/seds-technical-notes-complete.php Product: SEDS (https://www.eia.gov/state/seds/)""" + + series: str | None = Field( + default=None, + description="Unique series identifier code.", + ) + series_name: str | None = Field( + default=None, + description="Unique series identifier name.", + ) + state: str | None = Field( + default=None, + description="State name code.", + ) + state_name: str | None = Field( + default=None, + description="State name name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + unit: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaSedsFetcher(Fetcher[EiaSedsQueryParams, list[EiaSedsData]]): + """State Energy Data System (SEDS) fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaSedsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaSedsQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaSedsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaSedsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaSedsData]: + """Transform the data.""" + return transform_dataset_data(EiaSedsData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/short_term_energy_outlook.py b/openbb_platform/providers/eia/openbb_us_eia/models/short_term_energy_outlook.py index bdf6a9b14b7..82d6b377d59 100644 --- a/openbb_platform/providers/eia/openbb_us_eia/models/short_term_energy_outlook.py +++ b/openbb_platform/providers/eia/openbb_us_eia/models/short_term_energy_outlook.py @@ -1,6 +1,4 @@ -"""EIA Short Term Energy Outlook Model.""" - -# pylint: disable=unused-argument,too-many-branches,too-many-statements,too-many-locals +"""EIA Short Term Energy Outlook model.""" from typing import Any, Literal from warnings import warn @@ -13,12 +11,13 @@ from openbb_core.provider.standard_models.short_term_energy_outlook import ( ) from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS from openbb_core.provider.utils.errors import EmptyDataError +from pydantic import Field + from openbb_us_eia.utils.constants import ( SteoTableMap, SteoTableNames, SteoTableType, ) -from pydantic import Field class EiaShortTermEnergyOutlookQueryParams(ShortTermEnergyOutlookQueryParams): @@ -111,9 +110,10 @@ class EiaShortTermEnergyOutlookFetcher( **kwargs: Any, ) -> list[dict]: """Extract the data from the EIA API.""" - # pylint: disable=import-outside-toplevel - import asyncio # noqa + import asyncio + from openbb_core.provider.utils.helpers import amake_request + from openbb_us_eia.utils.helpers import response_callback api_key = credentials.get("eia_api_key") if credentials else "" @@ -128,7 +128,6 @@ class EiaShortTermEnergyOutlookFetcher( start_date: str = "" end_date: str = "" - # Format the dates based on the frequency. def resample_to_quarter(dt) -> str: """Resample a date to a string formatted as 'YYYY-QX'.""" year = dt.year @@ -149,7 +148,6 @@ class EiaShortTermEnergyOutlookFetcher( elif query.end_date is not None and frequency == "annual": end_date = f"&end={query.end_date.strftime('%Y')}" - # We chunk the request to avoid pagination and make the query execution faster. symbols = ( query.symbol.upper().split(",") if query.symbol @@ -182,33 +180,41 @@ class EiaShortTermEnergyOutlookFetcher( async def get_one(url): """Response callback function.""" res = await amake_request(url, response_callback=response_callback) - data = res.get("response", {}).get("data", []) # type: ignore + data = res.get("response", {}).get("data", []) # ty: ignore[unresolved-attribute] if not data: - series_id = res.get("request", {}).get("params", {}).get("facets", {}).get("seriesId", []) # type: ignore + series_id = ( + res.get("request", {}) # ty: ignore[unresolved-attribute] + .get("params", {}) + .get("facets", {}) + .get("seriesId", []) + ) masked_url = url.replace(api_key, "API_KEY") messages.append(f"No data returned for {series_id or masked_url}") if data: results.extend(data) - response_total = int(res.get("response", {}).get("total", 0)) # type: ignore + response_total = int(res.get("response", {}).get("total", 0)) # ty: ignore[unresolved-attribute] n_results = len(data) - # After conservatively chunking the request, we may still need to paginate. - # This is mostly out of an abundance of caution. if response_total > 5000 and n_results == 5000: offset = 5000 url = url.replace("&offset=0", f"&offset={offset}") while n_results < response_total: additional_response = await amake_request(url) - additional_data = additional_response.get("response", {}).get("data", []) # type: ignore + additional_data = additional_response.get( # ty: ignore[unresolved-attribute] + "response", {} + ).get("data", []) if not additional_data: series_id = ( - res.get("request", {}).get("params", {}).get("facets", {}).get("seriesId", []) # type: ignore + res.get("request", {}) # ty: ignore[unresolved-attribute] + .get("params", {}) + .get("facets", {}) + .get("seriesId", []) ) masked_url = url.replace(api_key, "API_KEY") messages.append( f"No additional data returned for {series_id or masked_url}" ) - if additional_data: - results.extend(additional_data) + break + results.extend(additional_data) n_results += len(additional_data) url = url.replace(f"&offset={offset}", f"&offset={offset + 5000}") offset += 5000 @@ -218,7 +224,7 @@ class EiaShortTermEnergyOutlookFetcher( except Exception as e: raise OpenBBError(f"Error fetching data from the EIA API -> {e}") from e - if not results and not messages: + if not results and not messages: # pragma: no cover raise EmptyDataError( "The request was returned empty with no error messages." ) @@ -236,8 +242,9 @@ class EiaShortTermEnergyOutlookFetcher( **kwargs: Any, ) -> list[EiaShortTermEnergyOutlookData]: """Transform the data.""" - # pylint: disable=import-outside-toplevel - from pandas import Categorical, DataFrame, to_datetime + from pandas import Categorical, DataFrame + + from openbb_us_eia.utils.catalog import parse_period symbols = ( query.symbol.upper().split(",") @@ -252,9 +259,15 @@ class EiaShortTermEnergyOutlookFetcher( seen.add(symbol) symbols = unique_symbols + period_formats = { + "month": "YYYY-MM", + "quarter": 'YYYY-"Q"Q', + "annual": "YYYY", + } + period_format = period_formats[query.frequency] table = query.table df = DataFrame(data) - df.period = to_datetime(df.period).dt.date + df.period = df.period.map(lambda p: parse_period(str(p), period_format)) df.seriesId = Categorical(df.seriesId, categories=symbols, ordered=True) df = df.sort_values(["period", "seriesId"]) df = df.reset_index(drop=True) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/__init__.py b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/__init__.py new file mode 100644 index 00000000000..a2033747f9e --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/__init__.py @@ -0,0 +1 @@ +"""EIA State Electricity Profiles models.""" diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/advanced_metering_infrastructure.py b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/advanced_metering_infrastructure.py new file mode 100644 index 00000000000..8ce588cc5b8 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/advanced_metering_infrastructure.py @@ -0,0 +1,188 @@ +"""Advanced Metering Infrastructure model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaStateElectricityProfilesAdvancedMeteringInfrastructureQueryParams( + EiaApiQueryParams +): + """Advanced Metering Infrastructure. Advanced meterting counts by technology, state, and sector Source: Forms EIA-861, EIA-861S Product: State Electricity Profiles, Table 12 + + Source: https://www.eia.gov/opendata/browser/electricity/state-electricity-profiles/meters + """ + + __group__ = "state_electricity_profiles" + __dataset__ = "advanced_metering_infrastructure" + __json_schema_extra__ = { + "sector": { + "multiple_items_allowed": True, + "choices": [ + "all_sectors", + "commercial", + "industrial", + "residential", + "transportation", + ], + }, + "state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "district_of_columbia", + "florida", + "georgia", + "hawaii", + "idaho", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "minnesota", + "mississippi", + "missouri", + "montana", + "nebraska", + "nevada", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pennsylvania", + "rhode_island", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "united_states", + "utah", + "vermont", + "virginia", + "washington", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + "technology": { + "multiple_items_allowed": True, + "choices": [ + "advanced_metering_infrastructure", + "all_meters", + "automated_meter_reading", + "standard_meters", + ], + }, + } + + sector: str | None = Field( + default=None, + description="sector filter. Accepts a comma-separated list of values.", + ) + state: str | None = Field( + default=None, + description="State filter. Accepts a comma-separated list of values.", + ) + technology: str | None = Field( + default=None, + description="Meter Technology filter. Accepts a comma-separated list of values.", + ) + + +class EiaStateElectricityProfilesAdvancedMeteringInfrastructureData(EiaApiData): + """Advanced Metering Infrastructure. Advanced meterting counts by technology, state, and sector Source: Forms EIA-861, EIA-861S Product: State Electricity Profiles, Table 12""" + + sector: str | None = Field( + default=None, + description="sector code.", + ) + sector_name: str | None = Field( + default=None, + description="sector name.", + ) + state: str | None = Field( + default=None, + description="State code.", + ) + state_name: str | None = Field( + default=None, + description="State name.", + ) + technology: str | None = Field( + default=None, + description="Meter Technology code.", + ) + technology_name: str | None = Field( + default=None, + description="Meter Technology name.", + ) + meters: float | None = Field( + default=None, + description="Meter Count (number of meters). Withheld or unavailable values return as null.", + ) + + +class EiaStateElectricityProfilesAdvancedMeteringInfrastructureFetcher( + Fetcher[ + EiaStateElectricityProfilesAdvancedMeteringInfrastructureQueryParams, + list[EiaStateElectricityProfilesAdvancedMeteringInfrastructureData], + ] +): + """Advanced Metering Infrastructure fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaStateElectricityProfilesAdvancedMeteringInfrastructureQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaStateElectricityProfilesAdvancedMeteringInfrastructureQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaStateElectricityProfilesAdvancedMeteringInfrastructureQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaStateElectricityProfilesAdvancedMeteringInfrastructureQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaStateElectricityProfilesAdvancedMeteringInfrastructureData]: + """Transform the data.""" + return transform_dataset_data( + EiaStateElectricityProfilesAdvancedMeteringInfrastructureData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/costs_and_savings_from_energy_efficiency_programs.py b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/costs_and_savings_from_energy_efficiency_programs.py new file mode 100644 index 00000000000..b55c7d0e041 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/costs_and_savings_from_energy_efficiency_programs.py @@ -0,0 +1,219 @@ +"""Costs and Savings from Energy Efficiency Programs model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyProgramsQueryParams( + EiaApiQueryParams +): + """Costs and Savings from Energy Efficiency Programs. Costs and savings from energy efficiency programs by state and sector Source: Form EIA-861 Product: State Electricity Profiles, Table 13 + + Source: https://www.eia.gov/opendata/browser/electricity/state-electricity-profiles/energy-efficiency + """ + + __group__ = "state_electricity_profiles" + __dataset__ = "costs_and_savings_from_energy_efficiency_programs" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "all_other_costs", + "customer_incentive", + "energy_savings", + "potential_peak_savings", + ], + }, + "sector": { + "multiple_items_allowed": True, + "choices": [ + "all_sectors", + "commercial", + "industrial", + "residential", + "transportation", + ], + }, + "state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "district_of_columbia", + "florida", + "georgia", + "hawaii", + "idaho", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "minnesota", + "mississippi", + "missouri", + "montana", + "nebraska", + "nevada", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pennsylvania", + "rhode_island", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "united_states", + "utah", + "vermont", + "virginia", + "washington", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + "time_period": { + "multiple_items_allowed": True, + "choices": ["expected_life_cycle_of_programs", "reporting_year"], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: all_other_costs (thousand dollars); customer_incentive = Cost of Customer Incentives (thousand dollars); energy_savings = Annual Energy Savings (megawatthours); potential_peak_savings = Peak Demand Savings (megawatts).", + ) + sector: str | None = Field( + default=None, + description="Sector filter. Accepts a comma-separated list of values.", + ) + state: str | None = Field( + default=None, + description="State filter. Accepts a comma-separated list of values.", + ) + time_period: Literal["expected_life_cycle_of_programs", "reporting_year"] | None = ( + Field( + default=None, + description="Time Period Included in Costs and Savings filter.", + ) + ) + + +class EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyProgramsData( + EiaApiData +): + """Costs and Savings from Energy Efficiency Programs. Costs and savings from energy efficiency programs by state and sector Source: Form EIA-861 Product: State Electricity Profiles, Table 13""" + + sector: str | None = Field( + default=None, + description="Sector code.", + ) + sector_name: str | None = Field( + default=None, + description="Sector name.", + ) + state: str | None = Field( + default=None, + description="State code.", + ) + state_name: str | None = Field( + default=None, + description="State name.", + ) + time_period: str | None = Field( + default=None, + description="Time Period Included in Costs and Savings code.", + ) + time_period_name: str | None = Field( + default=None, + description="Time Period Included in Costs and Savings name.", + ) + all_other_costs: float | None = Field( + default=None, + description="All Other Costs (thousand dollars). Withheld or unavailable values return as null.", + ) + customer_incentive: float | None = Field( + default=None, + description="Cost of Customer Incentives (thousand dollars). Withheld or unavailable values return as null.", + ) + energy_savings: float | None = Field( + default=None, + description="Annual Energy Savings (megawatthours). Withheld or unavailable values return as null.", + ) + potential_peak_savings: float | None = Field( + default=None, + description="Peak Demand Savings (megawatts). Withheld or unavailable values return as null.", + ) + + +class EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyProgramsFetcher( + Fetcher[ + EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyProgramsQueryParams, + list[ + EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyProgramsData + ], + ] +): + """Costs and Savings from Energy Efficiency Programs fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyProgramsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyProgramsQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyProgramsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyProgramsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[ + EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyProgramsData + ]: + """Transform the data.""" + return transform_dataset_data( + EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyProgramsData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/electricity_net_metering_customers_and_capacity.py b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/electricity_net_metering_customers_and_capacity.py new file mode 100644 index 00000000000..3253523fdca --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/electricity_net_metering_customers_and_capacity.py @@ -0,0 +1,136 @@ +"""Electricity Net Metering: Customers and Capacity model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacityQueryParams( + EiaApiQueryParams +): + """Electricity Net Metering: Customers and Capacity. Electricity net metering customer counts and capacity by state, sector, and generating technology. Source: Form EIA-861 Product: State Electricity Profiles, Table 11 + + Source: https://www.eia.gov/opendata/browser/electricity/state-electricity-profiles/net-metering + """ + + __group__ = "state_electricity_profiles" + __dataset__ = "electricity_net_metering_customers_and_capacity" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": ["capacity", "customers"], + }, + "sector": {"multiple_items_allowed": True}, + "state": {"multiple_items_allowed": True}, + "technology": {"multiple_items_allowed": True}, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: capacity (megawatts); customers = Customer Count (number of customers).", + ) + sector: str | None = Field( + default=None, + description="sector filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + state: str | None = Field( + default=None, + description="state filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + technology: str | None = Field( + default=None, + description="Technology used to Generate Electricity filter. Accepts a comma-separated list of values. Use the `facet_options` endpoint for the valid values.", + ) + + +class EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacityData( + EiaApiData +): + """Electricity Net Metering: Customers and Capacity. Electricity net metering customer counts and capacity by state, sector, and generating technology. Source: Form EIA-861 Product: State Electricity Profiles, Table 11""" + + sector: str | None = Field( + default=None, + description="sector code.", + ) + sector_name: str | None = Field( + default=None, + description="sector name.", + ) + state: str | None = Field( + default=None, + description="state code.", + ) + state_name: str | None = Field( + default=None, + description="state name.", + ) + technology: str | None = Field( + default=None, + description="Technology used to Generate Electricity code.", + ) + technology_name: str | None = Field( + default=None, + description="Technology used to Generate Electricity name.", + ) + capacity: float | None = Field( + default=None, + description="Capacity (megawatts). Withheld or unavailable values return as null.", + ) + customers: float | None = Field( + default=None, + description="Customer Count (number of customers). Withheld or unavailable values return as null.", + ) + + +class EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacityFetcher( + Fetcher[ + EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacityQueryParams, + list[EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacityData], + ] +): + """Electricity Net Metering: Customers and Capacity fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> ( + EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacityQueryParams + ): + """Transform the query parameters.""" + return transform_dataset_query( + EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacityQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[ + EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacityData + ]: + """Transform the data.""" + return transform_dataset_data( + EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacityData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/emissions_by_state_by_fuel.py b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/emissions_by_state_by_fuel.py new file mode 100644 index 00000000000..47fbfa89c8a --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/emissions_by_state_by_fuel.py @@ -0,0 +1,194 @@ +"""Emissions from Energy Consumption at Conventional Power Plants and Combined-Heat-and-Power Plants model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaStateElectricityProfilesEmissionsByStateByFuelQueryParams(EiaApiQueryParams): + """Emissions from Energy Consumption at Conventional Power Plants and Combined-Heat-and-Power Plants. Emissions from electricity generation and the production of useful thermal output at conventional power plants and combined-heat-and-power plants. See Electric Power Annual, Technical Notes for a description of the sources and methodology used to develop the emissions estimates. Sources: Forms EIA-860, EIA-923, and calculations made by the Office of Energy Production, Conversion & Delivery (EPCD) Product: State Electricity Profiles, Table 7 + + Source: https://www.eia.gov/opendata/browser/electricity/state-electricity-profiles/emissions-by-state-by-fuel + """ + + __group__ = "state_electricity_profiles" + __dataset__ = "emissions_by_state_by_fuel" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "co2_rate_lbs_mwh", + "co2_thousand_metric_tons", + "nox_rate_lbs_mwh", + "nox_short_tons", + "so2_rate_lbs_mwh", + "so2_short_tons", + ], + }, + "fuel": { + "multiple_items_allowed": True, + "choices": ["coal", "natural_gas", "other", "petroleum", "total"], + }, + "state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "district_of_columbia", + "florida", + "georgia", + "hawaii", + "idaho", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "minnesota", + "mississippi", + "missouri", + "montana", + "nebraska", + "nevada", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pennsylvania", + "rhode_island", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "united_states", + "utah", + "vermont", + "virginia", + "washington", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: co2_rate_lbs_mwh = CO2 Emissions Rate per MWh (pounds per megawatthour); co2_thousand_metric_tons = CO2 Emissions (thousand metric tons); nox_rate_lbs_mwh = NOx Emissions Rate per MWh (pounds per megawatthour); nox_short_tons = NOx Emissions (short tons); so2_rate_lbs_mwh = SO2 Emissions Rate per MWh (pounds per megawatthour); so2_short_tons = SO2 Emissions (short tons).", + ) + fuel: Literal["coal", "natural_gas", "other", "petroleum", "total"] | None = Field( + default=None, + description="Energy Source filter.", + ) + state: str | None = Field( + default=None, + description="State filter. Accepts a comma-separated list of values.", + ) + + +class EiaStateElectricityProfilesEmissionsByStateByFuelData(EiaApiData): + """Emissions from Energy Consumption at Conventional Power Plants and Combined-Heat-and-Power Plants. Emissions from electricity generation and the production of useful thermal output at conventional power plants and combined-heat-and-power plants. See Electric Power Annual, Technical Notes for a description of the sources and methodology used to develop the emissions estimates. Sources: Forms EIA-860, EIA-923, and calculations made by the Office of Energy Production, Conversion & Delivery (EPCD) Product: State Electricity Profiles, Table 7""" + + fuel: str | None = Field( + default=None, + description="Energy Source code.", + ) + fuel_name: str | None = Field( + default=None, + description="Energy Source name.", + ) + state: str | None = Field( + default=None, + description="State code.", + ) + state_name: str | None = Field( + default=None, + description="State name.", + ) + co2_rate_lbs_mwh: float | None = Field( + default=None, + description="CO2 Emissions Rate per MWh (pounds per megawatthour). Withheld or unavailable values return as null.", + ) + co2_thousand_metric_tons: float | None = Field( + default=None, + description="CO2 Emissions (thousand metric tons). Withheld or unavailable values return as null.", + ) + nox_rate_lbs_mwh: float | None = Field( + default=None, + description="NOx Emissions Rate per MWh (pounds per megawatthour). Withheld or unavailable values return as null.", + ) + nox_short_tons: float | None = Field( + default=None, + description="NOx Emissions (short tons). Withheld or unavailable values return as null.", + ) + so2_rate_lbs_mwh: float | None = Field( + default=None, + description="SO2 Emissions Rate per MWh (pounds per megawatthour). Withheld or unavailable values return as null.", + ) + so2_short_tons: float | None = Field( + default=None, + description="SO2 Emissions (short tons). Withheld or unavailable values return as null.", + ) + + +class EiaStateElectricityProfilesEmissionsByStateByFuelFetcher( + Fetcher[ + EiaStateElectricityProfilesEmissionsByStateByFuelQueryParams, + list[EiaStateElectricityProfilesEmissionsByStateByFuelData], + ] +): + """Emissions from Energy Consumption at Conventional Power Plants and Combined-Heat-and-Power Plants fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaStateElectricityProfilesEmissionsByStateByFuelQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaStateElectricityProfilesEmissionsByStateByFuelQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaStateElectricityProfilesEmissionsByStateByFuelQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaStateElectricityProfilesEmissionsByStateByFuelQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaStateElectricityProfilesEmissionsByStateByFuelData]: + """Transform the data.""" + return transform_dataset_data( + EiaStateElectricityProfilesEmissionsByStateByFuelData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/generating_capacity.py b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/generating_capacity.py new file mode 100644 index 00000000000..dcc645adcaf --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/generating_capacity.py @@ -0,0 +1,209 @@ +"""Generating Capacity model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaStateElectricityProfilesGeneratingCapacityQueryParams(EiaApiQueryParams): + """Generating Capacity. Electric generating capacity (summer capacity) by state, energy source, and sector. Source: Form EIA-860 Product: State Electricity Profiles, Table 4 + + Source: https://www.eia.gov/opendata/browser/electricity/state-electricity-profiles/capability + """ + + __group__ = "state_electricity_profiles" + __dataset__ = "generating_capacity" + __json_schema_extra__ = { + "energy_source": { + "multiple_items_allowed": True, + "choices": [ + "all", + "battery", + "coal", + "geothermal", + "hydroelectric", + "natural_gas", + "natural_gas_cc", + "natural_gas_gt", + "natural_gas_ic", + "natural_gas_oth", + "natural_gas_st", + "nuclear", + "other", + "other_biomass", + "other_gas", + "petroleum", + "petroleum_gt", + "petroleum_ic", + "petroleum_oth", + "petroleum_st", + "pumped_storage", + "solar", + "solar_pv", + "solar_th", + "wind", + "wood", + ], + }, + "producer_type": { + "multiple_items_allowed": True, + "choices": [ + "all_sectors", + "electric_utilities", + "independent_power_producers", + ], + }, + "state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "district_of_columbia", + "florida", + "georgia", + "hawaii", + "idaho", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "minnesota", + "mississippi", + "missouri", + "montana", + "nebraska", + "nevada", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pennsylvania", + "rhode_island", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "united_states", + "utah", + "vermont", + "virginia", + "washington", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + } + + energy_source: str | None = Field( + default=None, + description="Energy Source filter. Accepts a comma-separated list of values.", + ) + producer_type: ( + Literal["all_sectors", "electric_utilities", "independent_power_producers"] + | None + ) = Field( + default=None, + description="Sector filter.", + ) + state: str | None = Field( + default=None, + description="State filter. Accepts a comma-separated list of values.", + ) + + +class EiaStateElectricityProfilesGeneratingCapacityData(EiaApiData): + """Generating Capacity. Electric generating capacity (summer capacity) by state, energy source, and sector. Source: Form EIA-860 Product: State Electricity Profiles, Table 4""" + + energy_source: str | None = Field( + default=None, + description="Energy Source code.", + ) + energy_source_name: str | None = Field( + default=None, + description="Energy Source name.", + ) + producer_type: str | None = Field( + default=None, + description="Sector code.", + ) + producer_type_name: str | None = Field( + default=None, + description="Sector name.", + ) + state: str | None = Field( + default=None, + description="State code.", + ) + state_name: str | None = Field( + default=None, + description="State name.", + ) + capability: float | None = Field( + default=None, + description="Net Summer Capacity (megawatts). Withheld or unavailable values return as null.", + ) + + +class EiaStateElectricityProfilesGeneratingCapacityFetcher( + Fetcher[ + EiaStateElectricityProfilesGeneratingCapacityQueryParams, + list[EiaStateElectricityProfilesGeneratingCapacityData], + ] +): + """Generating Capacity fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaStateElectricityProfilesGeneratingCapacityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaStateElectricityProfilesGeneratingCapacityQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaStateElectricityProfilesGeneratingCapacityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaStateElectricityProfilesGeneratingCapacityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaStateElectricityProfilesGeneratingCapacityData]: + """Transform the data.""" + return transform_dataset_data( + EiaStateElectricityProfilesGeneratingCapacityData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/state_rankings_for_key_statistics.py b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/state_rankings_for_key_statistics.py new file mode 100644 index 00000000000..5a020c7b46b --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/state_rankings_for_key_statistics.py @@ -0,0 +1,325 @@ +"""State Rankings for Key Statistics model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaStateElectricityProfilesStateRankingsForKeyStatisticsQueryParams( + EiaApiQueryParams +): + """State Rankings for Key Statistics. State rankings for key electricity statistics by state Source: Forms EIA-860, EIA-861, EIA-923 Product: State Electricity Profiles, Table 1 + + Source: https://www.eia.gov/opendata/browser/electricity/state-electricity-profiles/summary + """ + + __group__ = "state_electricity_profiles" + __dataset__ = "state_rankings_for_key_statistics" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "average_retail_price", + "average_retail_price_rank", + "capacity_elec_utilities", + "capacity_elect_utilities_rank", + "capacity_ipp", + "capacity_ipp_rank", + "carbon_dioxide", + "carbon_dioxide_lbs", + "carbon_dioxide_rank", + "carbon_dioxide_rank_lbs", + "direct_use", + "direct_use_rank", + "eop_sales", + "eop_sales_rank", + "fsp_sales_rank", + "fsp_service_provider_sales", + "generation_elect_utils", + "generation_elect_utils_rank", + "generation_ipp", + "generation_ipp_rank", + "net_generation", + "net_generation_rank", + "net_summer_capacity", + "net_summer_capacity_rank", + "nitrogen_oxide", + "nitrogen_oxide_lbs", + "nitrogen_oxide_rank", + "nitrogen_oxide_rank_lbs", + "prime_source", + "sulfer_dioxide", + "sulfer_dioxide_lbs", + "sulfer_dioxide_rank", + "sulfer_dioxide_rank_lbs", + "total_retail_sales", + "total_retail_sales_rank", + ], + }, + "state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "district_of_columbia", + "florida", + "georgia", + "hawaii", + "idaho", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "minnesota", + "mississippi", + "missouri", + "montana", + "nebraska", + "nevada", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pennsylvania", + "rhode_island", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "united_states", + "utah", + "vermont", + "virginia", + "washington", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: average_retail_price = Average Retail Price of Electricity (cents per kilowatthour); average_retail_price_rank = Average Retail Price of Electricity (U.S. Rank) (rank); capacity_elec_utilities = Net Summer Capacity, Electric Power Sector (megawatts); capacity_elect_utilities_rank = Average Retail Price of Electricity (U.S. Rank) (rank); capacity_ipp = Net Summer Capacity, Independent Power Producers and Industrial / Commercial Sectors (megawatts); capacity_ipp_rank = Net Summer Capacity, Independent Power Producers and Industrial / Commercial Sectors (U.S. Rank) (rank); carbon_dioxide = CO2 Emissions (thousand metric tons); carbon_dioxide_lbs = CO2 Emissions Rate per MWh (pounds per megawatthour); carbon_dioxide_rank = CO2 Emissions (U.S. Rank) (rank); carbon_dioxide_rank_lbs = CO2 Emissions Rate per MWh (U.S. Rank) (rank); direct_use = Direct Use of Generation by Commercial and Industrial Facilities (megawatthours); direct_use_rank = Direct Use of Generation by Commercial and Industrial Facilities (U.S. Rank) (rank); eop_sales = Retail Sales of Electrcity by Energy-Only Providers (megawatthours); eop_sales_rank = Retail Sales of Electrcity by Energy-Only Providers (U.S. Rank) (rank); fsp_sales_rank = Retail Sales of Electrcity by Full Service Providers and Electricity Sold Directly by Commercial and Industrial Facilities (U.S. Rank) (rank); fsp_service_provider_sales = Retail Sales of Electrcity by Full Service Providers and Electricity Sold Directly by Commercial and Industrial Facilities (megawatthours); generation_elect_utils = Net Generation, Electric Power Sector (megawatthours); generation_elect_utils_rank = Net Generation, Electric Power Sector (U.S. Rank) (rank); generation_ipp = Net Generation, Independent Power Producers and Industrial / Commercial Sectors (megawatthours); generation_ipp_rank = Net Generation, Independent Power Producers and Industrial / Commercial Sectors (U.S. Rank) (rank); net_generation = Net Generation, All Sectors (megawatthours); net_generation_rank = Net Generation, All Sectors (U.S. Rank) (rank); net_summer_capacity = Net Summer Capacity, All Sectors (megawatts); net_summer_capacity_rank = Net Summer Capacity, All Sectors (U.S. Rank) (rank); nitrogen_oxide = NOx Emissions (short tons); nitrogen_oxide_lbs = NOx Emissions Rate per MWh (pounds per megawatthour); nitrogen_oxide_rank = NOx Emissions (U.S. Rank) (rank); nitrogen_oxide_rank_lbs = NOx Emissions Rate per MWh (U.S. Rank) (rank); prime_source; sulfer_dioxide = SO2 Emissions (short tons); sulfer_dioxide_lbs = SO2 Emissions Rate per MWh (pounds per megawatthour); sulfer_dioxide_rank = SO2 Emissions (U.S. Rank) (rank); sulfer_dioxide_rank_lbs = SO2 Emissions Rate per MWh (U.S. Rank) (rank); total_retail_sales = Retail Sales of Electricity, Total Electric Industry (megawatthours); total_retail_sales_rank = Retail Sales of Electricity, Total Electric Industry (U.S. Rank) (rank).", + ) + state: str | None = Field( + default=None, + description="State filter. Accepts a comma-separated list of values.", + ) + + +class EiaStateElectricityProfilesStateRankingsForKeyStatisticsData(EiaApiData): + """State Rankings for Key Statistics. State rankings for key electricity statistics by state Source: Forms EIA-860, EIA-861, EIA-923 Product: State Electricity Profiles, Table 1""" + + state: str | None = Field( + default=None, + description="State code.", + ) + state_name: str | None = Field( + default=None, + description="State name.", + ) + average_retail_price: float | None = Field( + default=None, + description="Average Retail Price of Electricity (cents per kilowatthour). Withheld or unavailable values return as null.", + ) + average_retail_price_rank: float | None = Field( + default=None, + description="Average Retail Price of Electricity (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + capacity_elec_utilities: float | None = Field( + default=None, + description="Net Summer Capacity, Electric Power Sector (megawatts). Withheld or unavailable values return as null.", + ) + capacity_elect_utilities_rank: float | None = Field( + default=None, + description="Average Retail Price of Electricity (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + capacity_ipp: float | None = Field( + default=None, + description="Net Summer Capacity, Independent Power Producers and Industrial / Commercial Sectors (megawatts). Withheld or unavailable values return as null.", + ) + capacity_ipp_rank: float | None = Field( + default=None, + description="Net Summer Capacity, Independent Power Producers and Industrial / Commercial Sectors (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + carbon_dioxide: float | None = Field( + default=None, + description="CO2 Emissions (thousand metric tons). Withheld or unavailable values return as null.", + ) + carbon_dioxide_lbs: float | None = Field( + default=None, + description="CO2 Emissions Rate per MWh (pounds per megawatthour). Withheld or unavailable values return as null.", + ) + carbon_dioxide_rank: float | None = Field( + default=None, + description="CO2 Emissions (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + carbon_dioxide_rank_lbs: float | None = Field( + default=None, + description="CO2 Emissions Rate per MWh (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + direct_use: float | None = Field( + default=None, + description="Direct Use of Generation by Commercial and Industrial Facilities (megawatthours). Withheld or unavailable values return as null.", + ) + direct_use_rank: float | None = Field( + default=None, + description="Direct Use of Generation by Commercial and Industrial Facilities (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + eop_sales: float | None = Field( + default=None, + description="Retail Sales of Electrcity by Energy-Only Providers (megawatthours). Withheld or unavailable values return as null.", + ) + eop_sales_rank: float | None = Field( + default=None, + description="Retail Sales of Electrcity by Energy-Only Providers (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + fsp_sales_rank: float | None = Field( + default=None, + description="Retail Sales of Electrcity by Full Service Providers and Electricity Sold Directly by Commercial and Industrial Facilities (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + fsp_service_provider_sales: float | None = Field( + default=None, + description="Retail Sales of Electrcity by Full Service Providers and Electricity Sold Directly by Commercial and Industrial Facilities (megawatthours). Withheld or unavailable values return as null.", + ) + generation_elect_utils: float | None = Field( + default=None, + description="Net Generation, Electric Power Sector (megawatthours). Withheld or unavailable values return as null.", + ) + generation_elect_utils_rank: float | None = Field( + default=None, + description="Net Generation, Electric Power Sector (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + generation_ipp: float | None = Field( + default=None, + description="Net Generation, Independent Power Producers and Industrial / Commercial Sectors (megawatthours). Withheld or unavailable values return as null.", + ) + generation_ipp_rank: float | None = Field( + default=None, + description="Net Generation, Independent Power Producers and Industrial / Commercial Sectors (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + net_generation: float | None = Field( + default=None, + description="Net Generation, All Sectors (megawatthours). Withheld or unavailable values return as null.", + ) + net_generation_rank: float | None = Field( + default=None, + description="Net Generation, All Sectors (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + net_summer_capacity: float | None = Field( + default=None, + description="Net Summer Capacity, All Sectors (megawatts). Withheld or unavailable values return as null.", + ) + net_summer_capacity_rank: float | None = Field( + default=None, + description="Net Summer Capacity, All Sectors (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + nitrogen_oxide: float | None = Field( + default=None, + description="NOx Emissions (short tons). Withheld or unavailable values return as null.", + ) + nitrogen_oxide_lbs: float | None = Field( + default=None, + description="NOx Emissions Rate per MWh (pounds per megawatthour). Withheld or unavailable values return as null.", + ) + nitrogen_oxide_rank: float | None = Field( + default=None, + description="NOx Emissions (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + nitrogen_oxide_rank_lbs: float | None = Field( + default=None, + description="NOx Emissions Rate per MWh (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + prime_source: str | None = Field( + default=None, + description="Prime Source", + ) + sulfer_dioxide: float | None = Field( + default=None, + description="SO2 Emissions (short tons). Withheld or unavailable values return as null.", + ) + sulfer_dioxide_lbs: float | None = Field( + default=None, + description="SO2 Emissions Rate per MWh (pounds per megawatthour). Withheld or unavailable values return as null.", + ) + sulfer_dioxide_rank: float | None = Field( + default=None, + description="SO2 Emissions (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + sulfer_dioxide_rank_lbs: float | None = Field( + default=None, + description="SO2 Emissions Rate per MWh (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + total_retail_sales: float | None = Field( + default=None, + description="Retail Sales of Electricity, Total Electric Industry (megawatthours). Withheld or unavailable values return as null.", + ) + total_retail_sales_rank: float | None = Field( + default=None, + description="Retail Sales of Electricity, Total Electric Industry (U.S. Rank) (rank). Withheld or unavailable values return as null.", + ) + + +class EiaStateElectricityProfilesStateRankingsForKeyStatisticsFetcher( + Fetcher[ + EiaStateElectricityProfilesStateRankingsForKeyStatisticsQueryParams, + list[EiaStateElectricityProfilesStateRankingsForKeyStatisticsData], + ] +): + """State Rankings for Key Statistics fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaStateElectricityProfilesStateRankingsForKeyStatisticsQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaStateElectricityProfilesStateRankingsForKeyStatisticsQueryParams, params + ) + + @staticmethod + async def aextract_data( + query: EiaStateElectricityProfilesStateRankingsForKeyStatisticsQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaStateElectricityProfilesStateRankingsForKeyStatisticsQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaStateElectricityProfilesStateRankingsForKeyStatisticsData]: + """Transform the data.""" + return transform_dataset_data( + EiaStateElectricityProfilesStateRankingsForKeyStatisticsData, query, data + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/supply_and_disposition_of_electricity.py b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/supply_and_disposition_of_electricity.py new file mode 100644 index 00000000000..de9f5f5ae62 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/state_electricity_profiles/supply_and_disposition_of_electricity.py @@ -0,0 +1,258 @@ +"""Supply and disposition of electricity model.""" + +from typing import Any + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaStateElectricityProfilesSupplyAndDispositionOfElectricityQueryParams( + EiaApiQueryParams +): + """Supply and disposition of electricity. Supply and disposition of electricity by state. Sources: Forms EIA-860, EIA-861, and EIA-923 Product: State Electricity Profiles, Table 10 + + Source: https://www.eia.gov/opendata/browser/electricity/state-electricity-profiles/source-disposition + """ + + __group__ = "state_electricity_profiles" + __dataset__ = "supply_and_disposition_of_electricity" + __json_schema_extra__ = { + "data_type": { + "multiple_items_allowed": True, + "choices": [ + "combined_heat_and_pwr_comm", + "combined_heat_and_pwr_elect", + "combined_heat_and_pwr_indust", + "direct_use", + "elect_pwr_sector_gen_subtotal", + "electric_utilities", + "energy_only_providers", + "estimated_losses", + "facility_direct", + "full_service_providers", + "independent_power_producers", + "indust_and_comm_gen_subtotal", + "net_interstate_trade", + "net_trade_index", + "total_disposition", + "total_elect_indust", + "total_international_exports", + "total_international_imports", + "total_net_generation", + "total_supply", + "unaccounted", + ], + }, + "state": { + "multiple_items_allowed": True, + "choices": [ + "alabama", + "alaska", + "arizona", + "arkansas", + "california", + "colorado", + "connecticut", + "delaware", + "district_of_columbia", + "florida", + "georgia", + "hawaii", + "idaho", + "illinois", + "indiana", + "iowa", + "kansas", + "kentucky", + "louisiana", + "maine", + "maryland", + "massachusetts", + "michigan", + "minnesota", + "mississippi", + "missouri", + "montana", + "nebraska", + "nevada", + "new_hampshire", + "new_jersey", + "new_mexico", + "new_york", + "north_carolina", + "north_dakota", + "ohio", + "oklahoma", + "oregon", + "pennsylvania", + "rhode_island", + "south_carolina", + "south_dakota", + "tennessee", + "texas", + "united_states", + "utah", + "vermont", + "virginia", + "washington", + "west_virginia", + "wisconsin", + "wyoming", + ], + }, + } + + data_type: str | None = Field( + default=None, + description="Data column(s) to return, comma-separated. The default returns every column. Choices: combined_heat_and_pwr_comm = Net Generation from Commercial Sector (megawatthours); combined_heat_and_pwr_elect = Net Generation from Independent Power Producers, Combined Heat and Power (megawatthours); combined_heat_and_pwr_indust = Net Generation from Industrial Sector (megawatthours); direct_use = Direct Use of Generation by Commercial and Industrial Facilities (megawatthours); elect_pwr_sector_gen_subtotal = Net Generation from Electric Power Sector (megawatthours); electric_utilities = Net Generation from Electric Utilities (megawatthours); energy_only_providers = Retail Sales of Electrcity by Energy-Only Providers (megawatthours); estimated_losses = Estimated Losses Incurred in Transmission and Distribution (megawatthours); facility_direct = Retail Sales of Electricity Sold Directly by Commercial and Industrial Facilities (megawatthours); full_service_providers = Retail Sales of Electricity by Full Service Providers (megawatthours); independent_power_producers = Net Generation from Independent Power Producers, Non-Combined Heat and Power (megawatthours); indust_and_comm_gen_subtotal = Net Generation from Industrial and Commercial Sectors (megawatthours); net_interstate_trade = Net Interstate Imports (megawatthours); net_trade_index = Net Trade Index Ratio (ratio); total_disposition (megawatthours); total_elect_indust = Retail Sales of Electricity, Total Electric Industry (megawatthours); total_international_exports (megawatthours); total_international_imports (megawatthours); total_net_generation = Net Generation from All Sectors (megawatthours); total_supply (megawatthours); unaccounted = Unaccounted Electricity (megawatthours).", + ) + state: str | None = Field( + default=None, + description="State filter. Accepts a comma-separated list of values.", + ) + + +class EiaStateElectricityProfilesSupplyAndDispositionOfElectricityData(EiaApiData): + """Supply and disposition of electricity. Supply and disposition of electricity by state. Sources: Forms EIA-860, EIA-861, and EIA-923 Product: State Electricity Profiles, Table 10""" + + state: str | None = Field( + default=None, + description="State code.", + ) + state_name: str | None = Field( + default=None, + description="State name.", + ) + combined_heat_and_pwr_comm: float | None = Field( + default=None, + description="Net Generation from Commercial Sector (megawatthours). Withheld or unavailable values return as null.", + ) + combined_heat_and_pwr_elect: float | None = Field( + default=None, + description="Net Generation from Independent Power Producers, Combined Heat and Power (megawatthours). Withheld or unavailable values return as null.", + ) + combined_heat_and_pwr_indust: float | None = Field( + default=None, + description="Net Generation from Industrial Sector (megawatthours). Withheld or unavailable values return as null.", + ) + direct_use: float | None = Field( + default=None, + description="Direct Use of Generation by Commercial and Industrial Facilities (megawatthours). Withheld or unavailable values return as null.", + ) + elect_pwr_sector_gen_subtotal: float | None = Field( + default=None, + description="Net Generation from Electric Power Sector (megawatthours). Withheld or unavailable values return as null.", + ) + electric_utilities: float | None = Field( + default=None, + description="Net Generation from Electric Utilities (megawatthours). Withheld or unavailable values return as null.", + ) + energy_only_providers: float | None = Field( + default=None, + description="Retail Sales of Electrcity by Energy-Only Providers (megawatthours). Withheld or unavailable values return as null.", + ) + estimated_losses: float | None = Field( + default=None, + description="Estimated Losses Incurred in Transmission and Distribution (megawatthours). Withheld or unavailable values return as null.", + ) + facility_direct: float | None = Field( + default=None, + description="Retail Sales of Electricity Sold Directly by Commercial and Industrial Facilities (megawatthours). Withheld or unavailable values return as null.", + ) + full_service_providers: float | None = Field( + default=None, + description="Retail Sales of Electricity by Full Service Providers (megawatthours). Withheld or unavailable values return as null.", + ) + independent_power_producers: float | None = Field( + default=None, + description="Net Generation from Independent Power Producers, Non-Combined Heat and Power (megawatthours). Withheld or unavailable values return as null.", + ) + indust_and_comm_gen_subtotal: float | None = Field( + default=None, + description="Net Generation from Industrial and Commercial Sectors (megawatthours). Withheld or unavailable values return as null.", + ) + net_interstate_trade: float | None = Field( + default=None, + description="Net Interstate Imports (megawatthours). Withheld or unavailable values return as null.", + ) + net_trade_index: float | None = Field( + default=None, + description="Net Trade Index Ratio (ratio). Withheld or unavailable values return as null.", + ) + total_disposition: float | None = Field( + default=None, + description="Total Disposition (megawatthours). Withheld or unavailable values return as null.", + ) + total_elect_indust: float | None = Field( + default=None, + description="Retail Sales of Electricity, Total Electric Industry (megawatthours). Withheld or unavailable values return as null.", + ) + total_international_exports: float | None = Field( + default=None, + description="Total International Exports (megawatthours). Withheld or unavailable values return as null.", + ) + total_international_imports: float | None = Field( + default=None, + description="Total International Imports (megawatthours). Withheld or unavailable values return as null.", + ) + total_net_generation: float | None = Field( + default=None, + description="Net Generation from All Sectors (megawatthours). Withheld or unavailable values return as null.", + ) + total_supply: float | None = Field( + default=None, + description="Total Supply (megawatthours). Withheld or unavailable values return as null.", + ) + unaccounted: float | None = Field( + default=None, + description="Unaccounted Electricity (megawatthours). Withheld or unavailable values return as null.", + ) + + +class EiaStateElectricityProfilesSupplyAndDispositionOfElectricityFetcher( + Fetcher[ + EiaStateElectricityProfilesSupplyAndDispositionOfElectricityQueryParams, + list[EiaStateElectricityProfilesSupplyAndDispositionOfElectricityData], + ] +): + """Supply and disposition of electricity fetcher.""" + + @staticmethod + def transform_query( + params: dict[str, Any], + ) -> EiaStateElectricityProfilesSupplyAndDispositionOfElectricityQueryParams: + """Transform the query parameters.""" + return transform_dataset_query( + EiaStateElectricityProfilesSupplyAndDispositionOfElectricityQueryParams, + params, + ) + + @staticmethod + async def aextract_data( + query: EiaStateElectricityProfilesSupplyAndDispositionOfElectricityQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaStateElectricityProfilesSupplyAndDispositionOfElectricityQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaStateElectricityProfilesSupplyAndDispositionOfElectricityData]: + """Transform the data.""" + return transform_dataset_data( + EiaStateElectricityProfilesSupplyAndDispositionOfElectricityData, + query, + data, + ) diff --git a/openbb_platform/providers/eia/openbb_us_eia/models/total_energy.py b/openbb_platform/providers/eia/openbb_us_eia/models/total_energy.py new file mode 100644 index 00000000000..b0c760c2c19 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/models/total_energy.py @@ -0,0 +1,86 @@ +"""Total Energy model.""" + +from typing import Any, Literal + +from openbb_core.provider.abstract.fetcher import Fetcher +from pydantic import Field + +from openbb_us_eia.utils.api_query import ( + EiaApiData, + EiaApiQueryParams, + extract_dataset_data, + transform_dataset_data, + transform_dataset_query, +) + + +class EiaTotalEnergyQueryParams(EiaApiQueryParams): + """Total Energy. These data represent the most recent comprehensive energy statistics integrated across all energy sources. The data includes total energy production, consumption, stocks, and trade; energy prices; overviews of petroleum, natural gas, coal, electricity, nuclear energy, renewable energy, and carbon dioxide emissions; and data unit conversions values. Source: https://www.eia.gov/totalenergy/data/monthly/pdf/mer_a_doc.pdf Report: MER (https://www.eia.gov/totalenergy/data/monthly/) + + Source: https://www.eia.gov/opendata/browser/total-energy + """ + + __group__ = "total_energy" + __dataset__ = "total_energy" + __json_schema_extra__ = { + "msn": {"multiple_items_allowed": True}, + } + + frequency: Literal["annual", "monthly"] | None = Field( + default=None, + description="The data frequency. The default is 'monthly'.", + ) + msn: str | None = Field( + default=None, + description="Unique series identifier filter. Accepts a comma-separated list of values. There are 984 valid values - use the `facet_options` endpoint to list them.", + ) + + +class EiaTotalEnergyData(EiaApiData): + """Total Energy. These data represent the most recent comprehensive energy statistics integrated across all energy sources. The data includes total energy production, consumption, stocks, and trade; energy prices; overviews of petroleum, natural gas, coal, electricity, nuclear energy, renewable energy, and carbon dioxide emissions; and data unit conversions values. Source: https://www.eia.gov/totalenergy/data/monthly/pdf/mer_a_doc.pdf Report: MER (https://www.eia.gov/totalenergy/data/monthly/)""" + + msn: str | None = Field( + default=None, + description="Unique series identifier code.", + ) + msn_name: str | None = Field( + default=None, + description="Unique series identifier name.", + ) + value: float | None = Field( + default=None, + description="Value. Withheld or unavailable values return as null.", + ) + unit: str | None = Field( + default=None, + description="Unit of the value.", + ) + + +class EiaTotalEnergyFetcher( + Fetcher[EiaTotalEnergyQueryParams, list[EiaTotalEnergyData]] +): + """Total Energy fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> EiaTotalEnergyQueryParams: + """Transform the query parameters.""" + return transform_dataset_query(EiaTotalEnergyQueryParams, params) + + @staticmethod + async def aextract_data( + query: EiaTotalEnergyQueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: EiaTotalEnergyQueryParams, + data: dict, + **kwargs: Any, + ) -> list[EiaTotalEnergyData]: + """Transform the data.""" + return transform_dataset_data(EiaTotalEnergyData, query, data) diff --git a/openbb_platform/providers/eia/openbb_us_eia/py.typed b/openbb_platform/providers/eia/openbb_us_eia/py.typed new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openbb_platform/providers/eia/openbb_us_eia/rss.py b/openbb_platform/providers/eia/openbb_us_eia/rss.py new file mode 100644 index 00000000000..2d975bc08a5 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/rss.py @@ -0,0 +1,74 @@ +"""EIA RSS feed HTML widget.""" + +from typing import Annotated + +from fastapi import Depends +from fastapi.responses import HTMLResponse +from openbb_core.app.router import Router + +from openbb_us_eia.browsers import _mcp_url, request_info +from openbb_us_eia.utils.rss import ( + EIA_RSS_FEEDS, + build_feed, + feed_choices, + render_rss_html, +) + +router = Router(prefix="", description="EIA RSS feeds.") + + +async def rss_feed( + info: Annotated[dict, Depends(request_info)], + feed: str = "today_in_energy", + theme: str = "dark", +) -> HTMLResponse: + """Articles, releases, testimony, and fuel-price updates from EIA's RSS feeds.""" + from openbb_core.provider.utils.helpers import get_async_requests_session + + from openbb_us_eia.utils.rss import fetch_feed + + if feed not in EIA_RSS_FEEDS: + feed = "today_in_energy" + + proxy_base = info["url"].rsplit("/rss_feed", 1)[0] + "/eia_proxy" + async with await get_async_requests_session() as session: + parsed = await fetch_feed(session, EIA_RSS_FEEDS[feed]["url"]) + + data = build_feed(feed, parsed, 50, proxy_base) + data["endpoint"] = info["url"] + return HTMLResponse(content=render_rss_html(data, theme)) + + +router._api_router.add_api_route( + path="/rss_feed", + endpoint=rss_feed, + methods=["GET"], + response_class=HTMLResponse, + openapi_extra={ + "widget_config": { + "name": "EIA RSS Feeds", + "description": "Articles, releases, testimony, and fuel-price updates" + " from the U.S. Energy Information Administration RSS feeds.", + "category": "EIA", + "subCategory": "News & Feeds", + "source": ["EIA"], + "type": "iframe", + "widgetId": "eia_rss_feeds_us_eia_obb", + "gridData": {"w": 40, "h": 20}, + "params": [ + { + "paramName": "feed", + "label": "Feed", + "type": "tabs", + "value": "today_in_energy", + "description": "The EIA RSS feed to display.", + "show": True, + "options": feed_choices(), + }, + {"paramName": "theme", "show": False}, + ], + "refetchInterval": 900000, + "storage": {"mcpUrl": _mcp_url()}, + } + }, +) diff --git a/openbb_platform/providers/eia/openbb_us_eia/utils/api_query.py b/openbb_platform/providers/eia/openbb_us_eia/utils/api_query.py new file mode 100644 index 00000000000..5753ca5e14e --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/utils/api_query.py @@ -0,0 +1,465 @@ +"""Shared query, pagination, and transform utilities for EIA APIv2 dataset models.""" + +import re +from datetime import ( + date as dateType, + datetime, +) +from typing import Any, Literal, TypeVar + +from openbb_core.provider.abstract.data import Data +from openbb_core.provider.abstract.query_params import QueryParams +from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS +from pydantic import Field + +API_BASE = "https://api.eia.gov/v2" +PAGE_SIZE = 5000 +MAX_AUTO_ROWS = 500_000 + +FACET_NAME_COLUMNS = { + "duoarea": ("area-name",), + "series": ("series-description",), + "msn": ("seriesDescription",), + "seriesId": ("seriesDescription", "seriesName"), + "tableId": ("tableName",), +} + +from openbb_us_eia.utils.catalog import snake_case as _snake + + +class EiaApiQueryParams(QueryParams): + """Base query parameters shared by all EIA APIv2 dataset models.""" + + __group__ = "" + __dataset__ = "" + + start_date: dateType | None = Field( + default=None, + description=QUERY_DESCRIPTIONS.get("start_date", ""), + ) + end_date: dateType | None = Field( + default=None, + description=QUERY_DESCRIPTIONS.get("end_date", ""), + ) + sort: Literal["asc", "desc"] = Field( + default="asc", + description="Sort the results by date.", + ) + limit: int | None = Field( + default=None, + gt=0, + description="Maximum number of rows to return." + " The default returns all rows, paginating requests as needed.", + ) + + @property + def dataset_key(self) -> str: + """Resolve the catalog dataset slug for this query.""" + if self.__dataset__: + return self.__dataset__ + for field in ("dataset", "release"): + value = getattr(self, field, None) + if value is not None: + return str(value) + from openbb_us_eia.utils.catalog import dataset_choices + + return dataset_choices(self.__group__)[0] + + @property + def facet_values(self) -> dict[str, str | None]: + """Collect the facet filter fields declared by the concrete model.""" + from openbb_us_eia.utils.catalog import STANDARD_FIELDS + + return { + name: getattr(self, name) + for name in type(self).model_fields + if name not in STANDARD_FIELDS + } + + +class EiaApiData(Data): + """Base data row for EIA APIv2 datasets.""" + + date: dateType | datetime = Field( + description="Start of the period the record covers." + " Hourly frequencies return a timestamp." + ) + + +Q = TypeVar("Q", bound=EiaApiQueryParams) +D = TypeVar("D", bound=EiaApiData) + + +def transform_dataset_query( + query_cls: type[Q], + params: dict[str, Any], +) -> Q: + """Validate raw parameters against the model and the dataset catalog. + + Parameters + ---------- + query_cls : type[Q] + The dataset's query parameter model. + params : dict[str, Any] + Raw parameters from the caller. + + Returns + ------- + Q + The validated query. + """ + from openbb_core.app.model.abstract.error import OpenBBError + + from openbb_us_eia.utils import catalog + + known = set(query_cls.model_fields) + unknown = sorted(set(params) - known) + if unknown: + filters = ", ".join( + name + for name in query_cls.model_fields + if name not in catalog.STANDARD_FIELDS + ) + raise OpenBBError( + ValueError( + f"Unknown parameter(s): {', '.join(unknown)}." + f" Valid filters for this dataset: {filters or 'none'}" + ) + ) + query = query_cls(**params) + spec = catalog.get_dataset(query.__group__, query.dataset_key) + frequency, _ = catalog.resolve_frequency(spec, getattr(query, "frequency", None)) + catalog.resolve_data_columns(spec, getattr(query, "data_type", None)) + catalog.resolve_facets( + spec, + frequency, + query.facet_values, + choices=catalog.get_group(query.__group__)["choices"], + ) + return query + + +async def extract_dataset_data( + query: EiaApiQueryParams, + credentials: dict[str, str] | None, +) -> dict: + """Request every page of a dataset query from the EIA API. + + Parameters + ---------- + query : EiaApiQueryParams + The validated query. + credentials : dict[str, str] | None + Credentials holding 'eia_api_key'. + + Returns + ------- + dict + Mapping with 'rows', 'total', and 'date_format' keys. + """ + from openbb_core.provider.utils.helpers import amake_request, amake_requests + + from openbb_us_eia.utils import catalog + from openbb_us_eia.utils.helpers import build_data_url, response_callback + + api_key = credentials.get("eia_api_key", "") if credentials else "" + spec = catalog.get_dataset(query.__group__, query.dataset_key) + frequency, freq_spec = catalog.resolve_frequency( + spec, getattr(query, "frequency", None) + ) + request = { + "path": freq_spec["path"], + "api_key": api_key, + "frequency": frequency, + "data_columns": catalog.resolve_data_columns( + spec, getattr(query, "data_type", None) + ), + "facets": catalog.resolve_facets( + spec, + frequency, + query.facet_values, + choices=catalog.get_group(query.__group__)["choices"], + ), + "facet_params": { + detail["id"]: canonical for canonical, detail in spec["facets"].items() + }, + "coverage": (spec.get("start_period"), spec.get("end_period")), + "start": ( + catalog.format_period(query.start_date, freq_spec["format"]) + if query.start_date + else None + ), + "end": ( + catalog.format_period(query.end_date, freq_spec["format"]) + if query.end_date + else None + ), + "sort": query.sort, + } + return await paginate( + build_data_url, + request, + limit=query.limit, + amake_request=amake_request, + amake_requests=amake_requests, + response_callback=response_callback, + ) + + +def transform_dataset_data( + data_cls: type[D], + query: EiaApiQueryParams, + data: dict, +) -> list[D]: + """Normalize column names, parse periods, sort, and validate the rows. + + Parameters + ---------- + data_cls : type[D] + The dataset's data model. + query : EiaApiQueryParams + The validated query. + data : dict + Extraction result with 'rows' and 'date_format' keys. + + Returns + ------- + list[D] + The validated data rows. + """ + from openbb_us_eia.utils import catalog + + spec = catalog.get_dataset(query.__group__, query.dataset_key) + _, freq_spec = catalog.resolve_frequency(spec, getattr(query, "frequency", None)) + date_format = data.get("date_format") or freq_spec["format"] + rows = transform_rows(spec, data["rows"], date_format) + rows.sort(key=lambda row: row["date"], reverse=query.sort == "desc") + if query.limit is not None: + rows = rows[: query.limit] + return [data_cls(**row) for row in rows] + + +async def paginate( + build_url, + request: dict, + limit: int | None, + amake_request, + amake_requests, + response_callback, +) -> dict: + """Fetch every page of an EIA data request. + + Parameters + ---------- + build_url : Callable + Renders a request dict plus offset/length into a URL. + request : dict + The prepared request description. + limit : int | None + Maximum number of rows to fetch; None fetches all rows. + amake_request, amake_requests : Callable + Async HTTP helpers, injected for testability. + response_callback : Callable + Response callback converting an aiohttp response to JSON. + + Returns + ------- + dict + Mapping with 'rows', 'total', and 'date_format' keys. + """ + from openbb_core.app.model.abstract.error import OpenBBError + from openbb_core.provider.utils.errors import EmptyDataError + + first_length = PAGE_SIZE if limit is None else min(limit, PAGE_SIZE) + url = build_url(request, offset=0, length=first_length) + response = await amake_request(url, response_callback=response_callback) + payload = response.get("response", {}) # type: ignore[union-attr] + rows = list(payload.get("data", [])) + total = int(payload.get("total") or 0) + date_format = payload.get("dateFormat") + + if total == 0 or not rows: + raise EmptyDataError( + await empty_result_message(request, amake_request, response_callback) + ) + + target = total if limit is None else min(limit, total) + if limit is None and total > MAX_AUTO_ROWS: + raise OpenBBError( + f"The unfiltered request matches {total} rows, above the automatic" + f" pagination ceiling of {MAX_AUTO_ROWS}. Narrow the request with" + " facet filters or dates, or set an explicit limit." + ) + + if len(rows) < target: + urls = [ + build_url(request, offset=offset, length=min(PAGE_SIZE, target - offset)) + for offset in range(len(rows), target, PAGE_SIZE) + ] + pages = await amake_requests(urls, response_callback=response_callback) + for page in pages: + rows.extend(page.get("response", {}).get("data", [])) + + return {"rows": rows[:target], "total": total, "date_format": date_format} + + +async def empty_result_message( + request: dict, + amake_request, + response_callback, +) -> str: + """Explain an empty result by checking each filter against the live vocabulary. + + Parameters + ---------- + request : dict + The prepared request description, including 'facets', 'facet_params', + and 'coverage'. + amake_request : Callable + Async HTTP helper, injected for testability. + response_callback : Callable + Response callback converting an aiohttp response to JSON. + + Returns + ------- + str + A human-readable explanation of the empty result. + """ + from openbb_us_eia.utils.catalog import format_choice_list + + facet_params = request.get("facet_params") or {} + facets = request.get("facets") or {} + date_hint = "" + if request.get("start") or request.get("end"): + coverage = request.get("coverage") or (None, None) + requested = f"{request.get('start') or '...'} to {request.get('end') or '...'}" + date_hint = f"\nRequested period: {requested}." + if coverage[0] or coverage[1]: + date_hint += f" The dataset covers {coverage[0]} to {coverage[1]}." + + if not facets: + return f"The request returned no data.{date_hint}" + + invalid_lines: list[str] = [] + valid_lines: list[str] = [] + for facet_id, values in facets.items(): + name = facet_params.get(facet_id, facet_id) + try: + response = await amake_request( + f"{API_BASE}/{request['path']}/facet/{facet_id}" + f"?api_key={request['api_key']}", + response_callback=response_callback, + ) + entries = response.get("response", {}).get("facets", []) + except Exception: # noqa: BLE001 + valid_lines.append(f" {name}: {', '.join(values)}") + continue + vocabulary = { + str(entry.get("id")): str(entry.get("name") or entry.get("id")) + for entry in entries + } + invalid = [value for value in values if value not in vocabulary] + if invalid: + invalid_lines.append( + f" {name}: {', '.join(invalid)} is not valid for this dataset." + f" Valid {name} choices:\n" + format_choice_list(vocabulary, name) + ) + else: + labeled = ", ".join(f"{value} ({vocabulary[value]})" for value in values) + valid_lines.append(f" {name}: {labeled}") + + if invalid_lines: + return "\n".join( + [ + "The request returned no data because of invalid filter value(s):", + *invalid_lines, + ] + ) + return "\n".join( + [ + "The request returned no data. Each filter value is valid for this" + " dataset, but the combination does not match any series:", + *valid_lines, + "Remove or change one of the filters." + date_hint, + ] + ) + + +def transform_rows( + spec: dict[str, Any], + rows: list[dict], + date_format: str, +) -> list[dict]: + """Normalize raw API rows for one dataset. + + Parameters + ---------- + spec : dict[str, Any] + Dataset specification from the catalog. + rows : list[dict] + Raw rows from the API response. + date_format : str + The EIA period format of the rows. + + Returns + ------- + list[dict] + Normalized rows. + """ + from openbb_us_eia.utils.catalog import parse_period + + facet_renames: dict[str, str] = {} + for canonical, facet in spec["facets"].items(): + facet_id = facet["id"] + facet_renames[facet_id] = canonical + base = re.sub(r"(?i)id$", "", facet_id) + for companion in ( + *FACET_NAME_COLUMNS.get(facet_id, ()), + f"{facet_id}Description", + f"{facet_id}-name", + f"{facet_id}-description", + f"{base}Description", + f"{base}Name", + f"{base}-name", + ): + facet_renames[companion] = f"{canonical}_name" + + column_renames: dict[str, str] = {} + numeric_columns: set[str] = set() + dropped_columns: set[str] = set() + for snake_name, detail in spec["data_columns"].items(): + column_renames[detail["id"]] = snake_name + dropped_columns.add(f"{detail['id']}-units") + if detail.get("numeric", True): + numeric_columns.add(snake_name) + + out: list[dict] = [] + for row in rows: + record: dict[str, Any] = {"date": parse_period(str(row["period"]), date_format)} + for key, value in row.items(): + if key == "period" or key in dropped_columns: + continue + name = facet_renames.get(key) or column_renames.get(key) or _snake(key) + record[name] = to_float(value) if name in numeric_columns else value + out.append(record) + return out + + +def to_float(value: Any) -> float | None: + """Cast a measurement to float; withheld or flag values become null.""" + if value is None or isinstance(value, (int, float)): + return value + try: + return float(value) + except (TypeError, ValueError): + return None + + +def maybe_float(value: Any) -> Any: + """Cast a string to float when possible, passing other values through.""" + if not isinstance(value, str): + return value + try: + return float(value) + except ValueError: + return value diff --git a/openbb_platform/providers/eia/openbb_us_eia/utils/catalog.py b/openbb_platform/providers/eia/openbb_us_eia/utils/catalog.py new file mode 100644 index 00000000000..c7f2d2753c6 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/utils/catalog.py @@ -0,0 +1,595 @@ +"""Runtime access to the generated EIA dataset catalog.""" + +import json +import lzma +import re +from datetime import ( + date as dateType, + datetime, + timedelta, + timezone, +) +from functools import lru_cache +from pathlib import Path +from typing import Any + +from openbb_core.app.model.abstract.error import OpenBBError + +ASSET_PATH = Path(__file__).parent.parent / "assets" / "eia_catalog.json.xz" + +_CAMEL_RE = re.compile(r"(?<=[a-z0-9])(?=[A-Z])") + +_SLUG_DROP_TOKENS = {"inc", "llc", "ltd"} + + +def snake_case(name: str) -> str: + """Convert an API identifier to snake_case.""" + return _CAMEL_RE.sub("_", name.replace("-", "_")).lower() + + +def label_slug( + label: str, + max_length: int = 60, + keep_parenthetical: bool = False, +) -> str: + """Build a human-readable snake_case parameter value from a display label. + + Parameters + ---------- + label : str + The display label, e.g. 'Battery storage' or 'Spot Price FOB'. + max_length : int + Maximum slug length; longer slugs are cut at a word boundary. + keep_parenthetical : bool + Keep parenthetical text as words instead of dropping it. Used to + disambiguate labels like 'Columbia (WI)' and 'Columbia (SC)'. + + Returns + ------- + str + The slug, e.g. 'battery_storage' or 'spot_price_fob'. + """ + text = label.lower().replace("&", " and ") + text = text.replace("u.s.", " us ").replace("f.o.b.", " fob ") + if keep_parenthetical: + text = text.replace("(", " ").replace(")", " ") + else: + text = re.sub(r"\(.*?\)", " ", text) + text = re.sub(r"^table \d+\W*", "", text) + text = re.sub(r"[^0-9a-z]+", "_", text).strip("_") + tokens = [t for t in text.split("_") if t and t not in _SLUG_DROP_TOKENS] + slug = "_".join(tokens) + if not slug: + return "value" + if len(slug) > max_length: + slug = slug[:max_length].rsplit("_", 1)[0] or slug[:max_length] + return slug + + +def attach_params(choices: list[dict[str, str]]) -> list[dict[str, str]]: + """Attach a readable ``param`` slug to each choice of one facet vocabulary. + + Parameters + ---------- + choices : list[dict[str, str]] + Choice records with 'value' and 'label' keys, deduplicated by value. + + Returns + ------- + list[dict[str, str]] + The records with a 'param' slug per choice. + """ + labels = [choice.get("label") or choice["value"] for choice in choices] + slugs = [label_slug(label) for label in labels] + + by_slug: dict[str, set[str]] = {} + for slug, label in zip(slugs, labels): + by_slug.setdefault(slug, set()).add(label) + retry = {slug for slug, slug_labels in by_slug.items() if len(slug_labels) > 1} + for index, slug in enumerate(slugs): + if slug in retry: + slugs[index] = label_slug( + labels[index], max_length=250, keep_parenthetical=True + ) + + assigned: dict[str, str] = {} + out: list[dict[str, str]] = [] + for index, choice in enumerate(choices): + slug, label = slugs[index], labels[index] + if slug in assigned and assigned[slug] != label: + code = re.sub(r"[^0-9a-z]+", "_", choice["value"].lower()).strip("_") + candidate = f"{slug}_{code}" if code else f"{slug}_{index}" + slug = candidate if candidate not in assigned else f"{slug}_{index}" + assigned[slug] = label + out.append({**choice, "param": slug}) + return out + + +STANDARD_FIELDS = { + "dataset", + "release", + "frequency", + "data_type", + "start_date", + "end_date", + "sort", + "limit", +} + +DATASET_GROUPS = ( + "coal", + "petroleum", + "natural_gas", + "electricity", + "electricity_grid", + "state_electricity_profiles", + "densified_biomass", + "nuclear_outages", +) + + +def pascal_case(name: str) -> str: + """Convert a snake_case identifier to PascalCase.""" + return "".join(part.capitalize() for part in name.split("_")) + + +def model_name(group: str, dataset: str) -> str: + """Build the provider-interface model name for one dataset.""" + return f"Eia{pascal_case(group)}{pascal_case(dataset)}" + + +def dataset_summary(spec: dict[str, Any]) -> str: + """Build the one-line command summary for a dataset.""" + name = ( + spec["name"] + .replace("U.S.", "US") + .replace("F.O.B.", "FOB") + .replace("No. ", "No ") + .replace("\\", "/") + .rstrip(".") + ) + description = spec.get("description") or "" + return f"{name}." + (f" {description}" if description else "") + + +@lru_cache(maxsize=1) +def load_catalog() -> dict[str, Any]: + """Load the packaged EIA dataset catalog. + + Returns + ------- + dict[str, Any] + The full catalog document keyed by group name. + """ + return json.loads(lzma.decompress(ASSET_PATH.read_bytes()).decode("utf-8"))[ + "groups" + ] + + +def get_group(group: str) -> dict[str, Any]: + """Get one catalog group. + + Parameters + ---------- + group : str + Catalog group name, e.g. 'coal'. + + Returns + ------- + dict[str, Any] + The group document with 'datasets' and 'choices' keys. + """ + catalog = load_catalog() + if group not in catalog: + raise OpenBBError( + ValueError(f"Unknown EIA group '{group}'. Choices: {', '.join(catalog)}") + ) + return catalog[group] + + +def get_dataset(group: str, dataset: str) -> dict[str, Any]: + """Get one dataset specification. + + Parameters + ---------- + group : str + Catalog group name. + dataset : str + Dataset slug within the group. + + Returns + ------- + dict[str, Any] + The dataset specification. + """ + datasets = get_group(group)["datasets"] + if dataset not in datasets: + raise OpenBBError( + ValueError( + f"Unknown dataset '{dataset}' for EIA group '{group}'." + f" Choices: {', '.join(datasets)}" + ) + ) + return datasets[dataset] + + +def dataset_choices(group: str) -> list[str]: + """List the dataset slugs of a group.""" + return list(get_group(group)["datasets"]) + + +def facet_choices(group: str, facet: str) -> list[dict[str, str]]: + """Embedded value choices for one canonical facet of a group. + + Parameters + ---------- + group : str + Catalog group name. + facet : str + Canonical facet parameter name. + + Returns + ------- + list[dict[str, str]] + Choices as {'value': ..., 'label': ...} records; empty when the facet's + value set is too large to embed. + """ + return get_group(group)["choices"].get(facet, []) + + +def facet_schema(group: str, facet: str) -> dict[str, Any]: + """Build the ``__json_schema_extra__`` entry for a multi-value facet field. + + Parameters + ---------- + group : str + Catalog group name. + facet : str + Canonical facet parameter name. + + Returns + ------- + dict[str, Any] + Schema extra with ``multiple_items_allowed`` and embedded choices when + the facet's value set is small enough. + """ + schema: dict[str, Any] = {"multiple_items_allowed": True} + choices = facet_choices(group, facet) + if choices and len(choices) <= SCHEMA_CHOICES_LIMIT: + schema["choices"] = [ + choice.get("param") or choice["value"] for choice in choices + ] + return schema + + +def facet_description(group: str, facet: str, multiple: bool = True) -> str: + """Build a query field description for one canonical facet. + + Parameters + ---------- + group : str + Catalog group name. + facet : str + Canonical facet parameter name. + multiple : bool + Whether the field accepts a comma-separated list of codes. + + Returns + ------- + str + Description text listing the datasets the facet applies to. + """ + datasets = get_group(group)["datasets"] + applies = [slug for slug, spec in datasets.items() if facet in spec["facets"]] + labels = { + spec["facets"][facet]["description"] + for spec in datasets.values() + if facet in spec["facets"] + } + label = sorted(labels)[0] if labels else facet + parts = [f"{label} filter."] + if multiple: + parts.append("Accepts a comma-separated list of codes.") + choices = facet_choices(group, facet) + if choices: + parts.append(f"Choices: {choices_text(choices)}.") + else: + parts.append("Use the `facet_options` endpoint for the list of valid codes.") + if len(applies) < len(datasets): + parts.append(f"Applies to datasets: {', '.join(applies)}.") + return " ".join(parts) + + +def resolve_frequency(spec: dict[str, Any], frequency: str | None) -> tuple[str, dict]: + """Resolve and validate the frequency for a dataset. + + Parameters + ---------- + spec : dict[str, Any] + Dataset specification. + frequency : str | None + Requested frequency id; None selects the dataset default. + + Returns + ------- + tuple[str, dict] + The frequency id and its specification (format, path). + """ + frequencies = spec["frequencies"] + if frequency is None: + frequency = spec.get("default_frequency") or next(iter(frequencies)) + if frequency not in frequencies: + raise OpenBBError( + ValueError( + f"Frequency '{frequency}' is not available for '{spec['path']}'." + f" Choices: {', '.join(frequencies)}" + ) + ) + return frequency, frequencies[frequency] + + +def resolve_data_columns(spec: dict[str, Any], data_type: str | None) -> list[str]: + """Resolve the API data column ids to request for a dataset. + + Parameters + ---------- + spec : dict[str, Any] + Dataset specification. + data_type : str | None + Comma-separated data column names; None selects all columns. + + Returns + ------- + list[str] + API data column ids. + """ + columns = spec["data_columns"] + if not data_type: + return [detail["id"] for detail in columns.values()] + requested = [snake_case(item.strip()) for item in data_type.split(",")] + invalid = [item for item in requested if item and item not in columns] + if invalid: + raise OpenBBError( + ValueError( + f"Invalid data_type value(s) {', '.join(invalid)} for '{spec['path']}'." + f" Choices: {', '.join(columns)}" + ) + ) + return [columns[item]["id"] for item in requested if item] + + +SCHEMA_CHOICES_LIMIT = 100 + + +def choices_text(choices: list[dict[str, str]], limit: int = 50) -> str: + """Render facet or column choices as an inline readable list. + + Parameters + ---------- + choices : list[dict[str, str]] + Choice records with 'value', 'label', and optional 'param' keys. + limit : int + Maximum number of choices to render. + + Returns + ------- + str + Semicolon-separated readable values, capped at ``limit``. + """ + parts = [choice.get("param") or choice["value"] for choice in choices[:limit]] + text = "; ".join(parts) + if len(choices) > limit: + text += ( + f"; plus {len(choices) - limit} more -" + " use the `facet_options` endpoint for the full list" + ) + return text + + +def format_choice_list( + vocabulary: dict[str, str], + name: str, + limit: int = 50, +) -> str: + """Render a facet vocabulary as a readable choice list. + + Parameters + ---------- + vocabulary : dict[str, str] + Facet value codes mapped to their labels. + name : str + The filter parameter name, used in the overflow hint. + limit : int + Maximum number of choices to render. + + Returns + ------- + str + One indented ``code = label`` line per choice. + """ + shown = sorted(vocabulary.items(), key=lambda item: item[1])[:limit] + lines = [f" {value} = {label}" for value, label in shown] + if len(vocabulary) > limit: + lines.append( + f" ... {len(vocabulary) - limit} more - use the `facet_options`" + f" endpoint for the full '{name}' list." + ) + return "\n".join(lines) + + +def resolve_facets( + spec: dict[str, Any], + frequency: str, + values: dict[str, str | None], + choices: dict[str, list[dict[str, str]]] | None = None, +) -> dict[str, list[str]]: + """Map canonical facet parameters onto API facet ids for a dataset. + + Parameters + ---------- + spec : dict[str, Any] + Dataset specification. + frequency : str + Resolved frequency id, used for frequency-restricted facets. + values : dict[str, str | None] + Canonical facet parameter values as comma-separated strings. + choices : dict[str, list[dict[str, str]]] | None + The group's embedded facet choices. When present for a facet, values + are validated against the vocabulary (case-insensitively, correcting + the casing) and invalid values raise with the valid choices listed. + + Returns + ------- + dict[str, list[str]] + API facet id to list of filter values. + """ + facets = spec["facets"] + query: dict[str, list[str]] = {} + for canonical, raw in values.items(): + if raw is None or raw == "": + continue + if canonical not in facets: + applicable = ", ".join(facets) if facets else "none" + raise OpenBBError( + ValueError( + f"The '{canonical}' filter does not apply to '{spec['path']}'." + f" Applicable filters: {applicable}" + ) + ) + restricted = facets[canonical].get("frequencies") + if restricted and frequency not in restricted: + raise OpenBBError( + ValueError( + f"The '{canonical}' filter only applies to" + f" frequency: {', '.join(restricted)}" + ) + ) + items = [item.strip() for item in str(raw).split(",") if item.strip()] + embedded = facets[canonical].get("choices") or (choices or {}).get(canonical) + if embedded: + lookup: dict[str, list[str]] = {} + for entry in embedded: + lookup.setdefault(entry["value"].lower(), []).append(entry["value"]) + if entry.get("param"): + lookup.setdefault(entry["param"].lower(), []).append(entry["value"]) + corrected: list[str] = [] + invalid: list[str] = [] + for item in items: + matches = lookup.get(item.lower()) + if matches is None: + invalid.append(item) + else: + corrected.extend(code for code in matches if code not in corrected) + if invalid: + valid = sorted( + {entry.get("param") or entry["value"] for entry in embedded} + ) + shown = ", ".join(valid[:50]) + if len(valid) > 50: + shown += ( + f", plus {len(valid) - 50} more -" + " use the `facet_options` endpoint for the full list" + ) + raise OpenBBError( + ValueError( + f"Invalid {canonical} value(s): {', '.join(invalid)}." + f" Valid choices: {shown}" + ) + ) + items = corrected + query[facets[canonical]["id"]] = items + _apply_fixed_facets(facets, frequency, query, choices) + return query + + +def _apply_fixed_facets( + facets: dict[str, Any], + frequency: str, + query: dict[str, list[str]], + choices: dict[str, list[dict[str, str]]] | None, +) -> None: + """Filter on facets that have exactly one choice, which are never parameters. + + A facet with a single possible value is not a real filter, so the generated + models do not expose it. The request must still carry it. + """ + for canonical, detail in facets.items(): + if detail["id"] in query or not detail.get("filterable", True): + continue + restricted = detail.get("frequencies") + if restricted and frequency not in restricted: + continue + fixed = detail.get("choices") or (choices or {}).get(canonical) or [] + if len(fixed) == 1: + query[detail["id"]] = [fixed[0]["value"]] + + +def format_period(value: dateType, fmt: str, end: bool = False) -> str: + """Format a date as an EIA period string. + + Parameters + ---------- + value : datetime.date + The date to convert. + fmt : str + EIA period format, e.g. 'YYYY-"Q"Q' or 'YYYY-MM-DD"T"HH24'. + end : bool + Unused placeholder kept for signature stability; period boundaries are + inclusive on both ends in the EIA API. + + Returns + ------- + str + The period string, truncated to the dataset's granularity. + """ + _ = end + if fmt == "YYYY": + return f"{value.year:04d}" + if fmt == "YYYY-MM": + return f"{value.year:04d}-{value.month:02d}" + if fmt == 'YYYY-"Q"Q': + return f"{value.year:04d}-Q{(value.month - 1) // 3 + 1}" + if fmt == "YYYY-MM-DD": + return value.strftime("%Y-%m-%d") + if fmt.startswith('YYYY-MM-DD"T"HH24'): + hour = value.hour if isinstance(value, datetime) else 0 + return f"{value.strftime('%Y-%m-%d')}T{hour:02d}" + raise OpenBBError(ValueError(f"Unsupported EIA period format: {fmt}")) + + +def parse_period(value: str, fmt: str) -> dateType | datetime: + """Parse an EIA period string into a date or datetime. + + Parameters + ---------- + value : str + The period string returned by the API. + fmt : str + EIA period format for the requested frequency. + + Returns + ------- + datetime.date | datetime.datetime + Period start as a date, or a datetime for hourly frequencies. + """ + if fmt == "YYYY": + return dateType(int(value), 1, 1) + if fmt == "YYYY-MM": + year, month = value.split("-") + return dateType(int(year), int(month), 1) + if fmt == 'YYYY-"Q"Q': + year, quarter = value.split("-Q") + return dateType(int(year), (int(quarter) - 1) * 3 + 1, 1) + if fmt == "YYYY-MM-DD": + return datetime.strptime(value, "%Y-%m-%d").date() + if fmt.startswith('YYYY-MM-DD"T"HH24'): + base = datetime.strptime(value[:13], "%Y-%m-%dT%H") + offset = value[13:] + if not offset: + return base + digits = offset[1:].replace(":", "") + delta = timedelta(hours=int(digits[:2] or 0), minutes=int(digits[2:4] or 0)) + return base.replace( + tzinfo=timezone(-delta if offset[0] == "-" else delta), + ) + raise OpenBBError(ValueError(f"Unsupported EIA period format: {fmt}")) diff --git a/openbb_platform/providers/eia/openbb_us_eia/utils/constants.py b/openbb_platform/providers/eia/openbb_us_eia/utils/constants.py index 9fcf1b4f671..d7f7e4d3f51 100644 --- a/openbb_platform/providers/eia/openbb_us_eia/utils/constants.py +++ b/openbb_platform/providers/eia/openbb_us_eia/utils/constants.py @@ -1,8 +1,6 @@ -"""OpenBB EIA Provider Module Constants.""" +"""OpenBB EIA provider constants.""" -# pylint: disable=too-many-lines - -from typing import Literal +from typing import Literal, get_args WpsrCategoryType = Literal[ "balance_sheet", @@ -19,21 +17,7 @@ WpsrCategoryType = Literal[ "spot_prices_diesel_jet_fuel_propane", "retail_prices", ] -WpsrCategoryChoices = [ - "balance_sheet", - "inputs_and_production", - "refiner_blender_net_production", - "crude_petroleum_stocks", - "gasoline_fuel_stocks", - "total_gasoline_by_sub_padd", - "distillate_fuel_oil_stocks", - "imports", - "imports_by_country", - "weekly_estimates", - "spot_prices_crude_gas_heating", - "spot_prices_diesel_jet_fuel_propane", - "retail_prices", -] +WpsrCategoryChoices = list(get_args(WpsrCategoryType)) WpsrTableType = Literal[ "all", "conventional_gas", @@ -75,47 +59,7 @@ WpsrTableType = Literal[ "ulta_low_sulfur_distillate_reclassification_avg", "weekly", ] -WpsrTableChoices = [ - "all", - "conventional_gas", - "crude", - "crude_production", - "crude_production_avg", - "diesel", - "ethanol_plant_production", - "ethanol_plant_production_avg", - "exports", - "exports_avg", - "heating_oil", - "imports", - "imports_avg", - "imports_by_country", - "imports_by_country_avg", - "inputs_and_utilization", - "inputs_and_utilization_avg", - "jet_fuel", - "monthly", - "net_imports_inc_spr_avg", - "net_imports_incl_spr", - "net_production", - "net_production_avg", - "net_production_by_product", - "net_production_by_production_avg", - "product_by_region", - "product_by_region_avg", - "product_supplied", - "product_supplied_avg", - "propane", - "rbob", - "refiner_blender_net_production", - "refiner_blender_net_production_avg", - "stocks", - "supply", - "supply_avg", - "ulta_low_sulfur_distillate_reclassification", - "ulta_low_sulfur_distillate_reclassification_avg", - "weekly", -] +WpsrTableChoices = list(get_args(WpsrTableType)) WpsrFileMap = { "balance_sheet": "https://ir.eia.gov/wpsr/psw01.xls", "inputs_and_production": "https://ir.eia.gov/wpsr/psw02.xls", diff --git a/openbb_platform/providers/eia/openbb_us_eia/utils/generate_catalog.py b/openbb_platform/providers/eia/openbb_us_eia/utils/generate_catalog.py new file mode 100644 index 00000000000..eca4eb5b636 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/utils/generate_catalog.py @@ -0,0 +1,1264 @@ +"""Generate the EIA dataset catalog asset and the checked-in model modules from the APIv2 metadata tree.""" + +import argparse +import json +import lzma +import os +import re +import subprocess +import sys +import threading +import time +from concurrent.futures import ThreadPoolExecutor, as_completed +from pathlib import Path +from typing import Any + + +def _catalog_helpers(): + """Load ``utils/catalog.py`` directly, without importing the package ``__init__``.""" + import importlib.util + + module = globals().get("_CATALOG_HELPERS") + if module is None: + spec = importlib.util.spec_from_file_location( + "_eia_catalog_helpers", Path(__file__).parent / "catalog.py" + ) + if spec is None or spec.loader is None: + raise ImportError("Unable to load openbb_us_eia/utils/catalog.py") + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + globals()["_CATALOG_HELPERS"] = module + return module + + +def attach_params(choices: list[dict]) -> list[dict]: + """Attach param slugs via the runtime catalog helper.""" + return _catalog_helpers().attach_params(choices) + + +API_BASE = "https://api.eia.gov/v2" +PACKAGE_ROOT = Path(__file__).parent.parent +ASSET_PATH = PACKAGE_ROOT / "assets" / "eia_catalog.json.xz" + +CHOICES_LIMIT = 1000 + +FACET_CANONICAL: dict[str, dict[str, str]] = { + "coal": { + "censusRegionId": "census_region", + "coalRankId": "coal_rank", + "coalSupplier": "coal_supplier", + "coalType": "coal_rank", + "contractType": "contract_type", + "countryId": "country", + "customsDistrictId": "customs_district", + "exportImportType": "export_import_type", + "location": "state_region", + "marketTypeId": "market_type", + "mineBasinId": "mine_basin", + "mineCountyId": "mine_county", + "mineMSHAId": "mine", + "mineStateId": "mine_state", + "mineStatusId": "mine_status", + "mineTypeId": "mine_type", + "mississippiRegionId": "mississippi_region", + "plant": "plant", + "plantId": "plant", + "plantStateId": "plant_state", + "rank": "coal_rank", + "regionId": "mine_region", + "sector": "sector", + "stateId": "state_region", + "stateRegionId": "state_region", + "supplyRegionId": "supply_region", + "transportationMode": "transportation_mode", + }, + "petroleum": { + "duoarea": "region", + "product": "product", + "process": "process", + "series": "series", + }, + "natural_gas": { + "duoarea": "region", + "product": "product", + "process": "process", + "series": "series", + }, + "electricity": { + "balancing_authority_code": "balancing_authority", + "energy_source_code": "energy_source", + "entityid": "entity", + "fuel2002": "fuel", + "fuelType": "fuel_type", + "fueltypeid": "fuel", + "generatorid": "generator", + "location": "state", + "plantCode": "plant", + "plantid": "plant", + "primeMover": "prime_mover", + "prime_mover_code": "prime_mover", + "sector": "sector", + "sectorid": "sector", + "state": "state", + "stateid": "state", + "status": "status", + "technology": "technology", + "unit": "unit", + }, + "electricity_grid": { + "fromba": "from_ba", + "fueltype": "fuel_type", + "parent": "parent", + "respondent": "respondent", + "subba": "subregion", + "timezone": "timezone", + "toba": "to_ba", + "type": "series_type", + }, + "state_electricity_profiles": { + "energysourceid": "energy_source", + "fuelid": "fuel", + "producertypeid": "producer_type", + "sector": "sector", + "state": "state", + "stateID": "state", + "stateId": "state", + "stateid": "state", + "technology": "technology", + "timePeriod": "time_period", + }, + "crude_oil_imports": { + "destinationId": "destination", + "destinationType": "destination_type", + "gradeId": "grade", + "originId": "origin", + "originType": "origin_type", + }, + "international": { + "activityId": "activity", + "countryRegionId": "country", + "countryRegionTypeId": "country_type", + "dataFlagId": "data_flag", + "productId": "product", + "unit": "unit", + }, + "seds": { + "seriesId": "series", + "stateId": "state", + }, + "total_energy": { + "msn": "msn", + }, + "densified_biomass": { + "fuelTypeId": "fuel_type", + "region": "region", + "respondent": "respondent", + "stateId": "state", + "status": "status", + }, + "nuclear_outages": { + "facility": "facility", + "generator": "generator", + }, + "aeo": { + "history": "history", + "regionId": "region", + "scenario": "scenario", + "seriesId": "series", + "tableId": "table", + }, + "ieo": { + "history": "history", + "regionId": "region", + "scenario": "scenario", + "seriesId": "series", + "tableId": "table", + }, +} + +LITERAL_FACETS: dict[str, set[str]] = { + "coal": { + "census_region", + "contract_type", + "export_import_type", + "market_type", + "mine_basin", + "mine_region", + "mine_status", + "mine_type", + "mississippi_region", + "supply_region", + "transportation_mode", + }, + "electricity": {"status"}, + "electricity_grid": {"series_type", "timezone"}, + "state_electricity_profiles": {"fuel", "producer_type", "time_period"}, + "crude_oil_imports": {"destination_type", "grade", "origin_type"}, + "international": {"activity", "country_type", "unit"}, + "densified_biomass": {"fuel_type", "region", "status"}, + "nuclear_outages": {"generator"}, + "aeo": {"history"}, + "ieo": {"history"}, +} + +NON_FILTER_FACETS: set[tuple[str, str]] = { + ("international", "data_flag"), +} + +PETROLEUM_DUPLICATE_PATHS = { + "petroleum/move/imc1", + "petroleum/move/imc2", + "petroleum/move/imc3", + "petroleum/move/ipct", + "petroleum/move/land1", + "petroleum/move/land2", + "petroleum/move/land3", +} + +GRID_DATASETS: dict[str, dict[str, str]] = { + "demand": { + "hourly": "electricity/rto/region-data", + "daily": "electricity/rto/daily-region-data", + }, + "generation_by_fuel": { + "hourly": "electricity/rto/fuel-type-data", + "daily": "electricity/rto/daily-fuel-type-data", + }, + "interchange": { + "hourly": "electricity/rto/interchange-data", + "daily": "electricity/rto/daily-interchange-data", + }, + "demand_by_subregion": { + "hourly": "electricity/rto/region-sub-ba-data", + "daily": "electricity/rto/daily-region-sub-ba-data", + }, +} + +ELECTRICITY_DATASETS = { + "electricity/electric-power-operational-data", + "electricity/facility-fuel", + "electricity/operating-generator-capacity", + "electricity/retail-sales", +} + +STRING_DATA_COLUMNS = { + "county", + "operating_company", + "operating_company_address", + "operating_year_month", + "planned_derate_year_month", + "planned_retirement_year_month", + "planned_uprate_year_month", + "prime_source", + "refuse_flag", +} + +SLUG_REPLACEMENTS = [ + ("f.o.b.", "fob"), + ("u.s.", "us"), + ("no. 2", "no2"), + ("no. 4", "no4"), +] + +SLUG_MAX_LENGTH = 60 + +SLUG_OVERRIDES: dict[str, str] = { + "natural-gas/enr/adng": "associated_dissolved_proved_reserves", + "natural-gas/enr/nang": "nonassociated_proved_reserves", + "natural-gas/enr/ngpl": "plant_liquids_in_proved_reserves", + "natural-gas/pri/rescom": "residential_and_commercial_prices_selected_states", + "natural-gas/stor/lng": "lng_storage_additions_and_withdrawals", + "petroleum/crd/cplc": "crude_plus_lease_condensate_proved_reserves", + "petroleum/move/netr": "net_receipts_between_pad_districts", + "petroleum/move/ptb": "movements_between_pad_districts", + "petroleum/move/rail": "movements_by_rail_between_pad_districts", + "petroleum/move/wimpc": "weekly_crude_imports_by_top_10_origins", + "petroleum/pnp/feedng": "natural_gas_feedstock_for_hydrogen", + "petroleum/pri/dfp2": "crude_first_purchase_prices_selected_streams", + "petroleum/stoc/ts": "stocks_of_selected_products", + "electricity/state-electricity-profiles/emissions-by-state-by-fuel": ( + "emissions_by_state_by_fuel" + ), +} + + +_CAMEL_RE = re.compile(r"(?<=[a-z0-9])(?=[A-Z])") + + +def snake_case(name: str) -> str: + """Convert an API identifier to snake_case.""" + return _CAMEL_RE.sub("_", name.replace("-", "_")).lower() + + +def slugify(name: str) -> str: + """Build a snake_case dataset slug from a display name.""" + text = name.lower() + text = re.sub(r"\(.*?\)", "", text) + text = text.split(" - deprecated", 1)[0] + text = text.split(" - discontinued", 1)[0] + for old, new in SLUG_REPLACEMENTS: + text = text.replace(old, new) + text = re.sub(r"[^0-9a-z]+", "_", text) + return re.sub(r"_+", "_", text).strip("_") + + +def fetch_tree(api_key: str) -> dict[str, Any]: + """Crawl the EIA APIv2 metadata tree. + + Parameters + ---------- + api_key : str + EIA Open Data API key. + + Returns + ------- + dict[str, Any] + Mapping with ``root``, ``nodes`` and ``facet_values`` keys matching the + structure consumed by ``build_catalog``. + """ + import requests # noqa: PLC0415 + + session = requests.Session() + lock = threading.Lock() + count = {"n": 0} + + def get(url: str) -> dict: + for attempt in range(6): + try: + response = session.get(url, params={"api_key": api_key}, timeout=30) + except requests.RequestException: + time.sleep(2**attempt) + continue + if response.status_code == 200: + with lock: + count["n"] += 1 + return response.json().get("response", {}) + if response.status_code in (409, 429, 500, 502, 503, 504): + time.sleep(2**attempt) + continue + raise RuntimeError(f"HTTP {response.status_code} for {url}") + raise RuntimeError(f"Retries exhausted for {url}") + + root = get(API_BASE) + nodes: dict[str, dict] = {} + to_visit = [route["id"] for route in root.get("routes", [])] + + while to_visit: + with ThreadPoolExecutor(max_workers=8) as pool: + futures = { + pool.submit(get, f"{API_BASE}/{path}"): path for path in to_visit + } + next_visit: list[str] = [] + for future in as_completed(futures): + path = futures[future] + node = future.result() + nodes[path] = node + for child in node.get("routes", []) or []: + next_visit.append(f"{path}/{child['id']}") + to_visit = next_visit + + facet_values: dict[str, dict[str, dict]] = {} + jobs = [ + (path, facet["id"]) + for path, node in nodes.items() + if not node.get("routes") + for facet in node.get("facets", []) or [] + ] + with ThreadPoolExecutor(max_workers=8) as pool: + futures = { + pool.submit(get, f"{API_BASE}/{path}/facet/{facet_id}"): (path, facet_id) + for path, facet_id in jobs + } + for future in as_completed(futures): + path, facet_id = futures[future] + try: + result = future.result() + except RuntimeError as exc: + sys.stderr.write(f"facet fetch failed for {path}/{facet_id}: {exc}\n") + continue + facet_values.setdefault(path, {})[facet_id] = { + "total": result.get("totalFacets", 0), + "values": result.get("facets", []) or [], + } + + return {"root": root, "nodes": nodes, "facet_values": facet_values} + + +def _child_meta(tree: dict[str, Any]) -> dict[str, dict]: + """Map each node path to the name/description its parent advertises for it.""" + meta: dict[str, dict] = {} + for route in tree["root"].get("routes", []): + meta[route["id"]] = route + for path, node in tree["nodes"].items(): + for child in node.get("routes", []) or []: + meta[f"{path}/{child['id']}"] = child + return meta + + +def _frequency_spec(node: dict, path: str) -> dict[str, dict]: + """Build the frequency specification for one API route node.""" + return { + freq["id"]: { + "format": freq.get("format", ""), + "description": freq.get("description", ""), + "path": path, + } + for freq in node.get("frequency", []) or [] + } + + +def _data_columns(node: dict) -> dict[str, dict]: + """Build the data column specification for one API route node.""" + columns: dict[str, dict] = {} + for data_id, spec in (node.get("data") or {}).items(): + detail = spec if isinstance(spec, dict) else {} + snake = snake_case(data_id) + columns[snake] = { + "id": data_id, + "alias": detail.get("alias"), + "units": detail.get("units"), + "numeric": snake not in STRING_DATA_COLUMNS, + } + return columns + + +def _is_placeholder(value_id: str, label: str) -> bool: + """Detect placeholder vocabulary values the API cannot filter on.""" + return ( + value_id.strip().upper() == "(NA)" or label.strip().lower() == "not applicable" + ) + + +def _facet_spec( + group: str, + node: dict, + path: str, + facet_values: dict[str, dict[str, dict]], +) -> dict[str, dict]: + """Map one node's facets onto canonical parameter names.""" + canonical_map = FACET_CANONICAL[group] + spec: dict[str, dict] = {} + for facet in node.get("facets", []) or []: + facet_id = facet["id"] + if facet_id not in canonical_map: + raise KeyError( + f"Unmapped facet id '{facet_id}' for group '{group}' at {path}" + ) + canonical = canonical_map[facet_id] + totals = facet_values.get(path, {}).get(facet_id, {}) + entry: dict[str, Any] = { + "id": facet_id, + "description": facet.get("description") or facet.get("name") or facet_id, + "n_values": totals.get("total", 0), + } + if (group, canonical) in NON_FILTER_FACETS: + entry["filterable"] = False + values = totals.get("values", []) or [] + if values and len(values) <= CHOICES_LIMIT: + deduped: dict[str, dict] = {} + for value in values: + code = str(value.get("id")) + label = str(value.get("name") or value.get("alias") or value.get("id")) + if _is_placeholder(code, label): + continue + deduped.setdefault(code, {"value": code, "label": label}) + entry["choices"] = attach_params( + sorted(deduped.values(), key=lambda choice: choice["label"]) + ) + spec[canonical] = entry + return spec + + +def _merge_choices( + accumulator: dict[str, dict[str, str]], + group: str, + node: dict, + path: str, + facet_values: dict[str, dict[str, dict]], +) -> None: + """Accumulate facet value choices for one node into the group union.""" + canonical_map = FACET_CANONICAL[group] + for facet in node.get("facets", []) or []: + canonical = canonical_map[facet["id"]] + entry = facet_values.get(path, {}).get(facet["id"], {}) + union = accumulator.setdefault(canonical, {}) + for value in entry.get("values", []): + value_id = str(value.get("id")) + label = str(value.get("name") or value.get("alias") or value_id) + if _is_placeholder(value_id, label): + continue + union.setdefault(value_id, label) + + +def _dataset_entry( + group: str, + path: str, + tree: dict[str, Any], + child_meta: dict[str, dict], +) -> dict[str, Any]: + """Build one dataset specification from an API route node.""" + node = tree["nodes"][path] + meta = child_meta.get(path, {}) + name = node.get("name") or meta.get("name") or path + description = node.get("description") or meta.get("description") or "" + category_path = path.rsplit("/", 1)[0] + category = None + if "/" in path: + category = (child_meta.get(category_path) or {}).get("name") + return { + "path": path, + "name": re.sub(r"\s+", " ", str(name)).strip(), + "description": re.sub(r"\s+", " ", str(description)).strip(), + "category": category, + "category_slug": slugify(category) if category else None, + "frequencies": _frequency_spec(node, path), + "default_frequency": node.get("defaultFrequency"), + "start_period": node.get("startPeriod"), + "end_period": node.get("endPeriod"), + "data_columns": _data_columns(node), + "facets": _facet_spec(group, node, path, tree["facet_values"]), + } + + +def _leaves_under(tree: dict[str, Any], prefix: str) -> list[str]: + """List leaf route paths under a prefix, sorted.""" + return sorted( + path + for path, node in tree["nodes"].items() + if (path == prefix or path.startswith(prefix + "/")) and not node.get("routes") + ) + + +def _named_group( + group: str, + tree: dict[str, Any], + child_meta: dict[str, dict], + paths: list[str], + slug_overrides: dict[str, str] | None = None, +) -> dict[str, Any]: + """Build a catalog group whose dataset slugs derive from display names.""" + datasets: dict[str, dict] = {} + choices: dict[str, dict[str, str]] = {} + for path in paths: + entry = _dataset_entry(group, path, tree, child_meta) + slug = ( + (slug_overrides or {}).get(path) + or SLUG_OVERRIDES.get(path) + or slugify(entry["name"]) + ) + if len(slug) > SLUG_MAX_LENGTH: + raise ValueError( + f"Slug '{slug}' for {path} exceeds {SLUG_MAX_LENGTH} chars;" + " add a SLUG_OVERRIDES entry." + ) + if slug in datasets: + raise ValueError(f"Duplicate dataset slug '{slug}' for {path} in '{group}'") + datasets[slug] = entry + _merge_choices(choices, group, tree["nodes"][path], path, tree["facet_values"]) + return {"datasets": dict(sorted(datasets.items())), "choices": choices} + + +def _grid_group(tree: dict[str, Any], child_meta: dict[str, dict]) -> dict[str, Any]: + """Build the electricity grid group, merging hourly and daily route pairs.""" + datasets: dict[str, dict] = {} + choices: dict[str, dict[str, str]] = {} + for slug, paths in GRID_DATASETS.items(): + hourly = _dataset_entry("electricity_grid", paths["hourly"], tree, child_meta) + daily = _dataset_entry("electricity_grid", paths["daily"], tree, child_meta) + entry = hourly + entry["frequencies"].update(daily["frequencies"]) + for canonical, facet in daily["facets"].items(): + if canonical not in entry["facets"]: + facet["frequencies"] = sorted(daily["frequencies"]) + entry["facets"][canonical] = facet + entry["start_period"] = min( + filter(None, [hourly["start_period"], daily["start_period"]]), default=None + ) + entry["end_period"] = max( + filter(None, [hourly["end_period"], daily["end_period"]]), default=None + ) + datasets[slug] = entry + for path in paths.values(): + _merge_choices( + choices, + "electricity_grid", + tree["nodes"][path], + path, + tree["facet_values"], + ) + return {"datasets": dict(sorted(datasets.items())), "choices": choices} + + +def build_catalog(tree: dict[str, Any]) -> dict[str, Any]: + """Assemble the full catalog from a crawled metadata tree. + + Parameters + ---------- + tree : dict[str, Any] + Crawl output with ``root``, ``nodes`` and ``facet_values``. + + Returns + ------- + dict[str, Any] + The catalog document written to ``assets/eia_catalog.json.xz``. + """ + child_meta = _child_meta(tree) + groups: dict[str, dict] = {} + + groups["coal"] = _named_group("coal", tree, child_meta, _leaves_under(tree, "coal")) + groups["petroleum"] = _named_group( + "petroleum", + tree, + child_meta, + [ + path + for path in _leaves_under(tree, "petroleum") + if path not in PETROLEUM_DUPLICATE_PATHS + ], + ) + groups["natural_gas"] = _named_group( + "natural_gas", tree, child_meta, _leaves_under(tree, "natural-gas") + ) + groups["electricity"] = _named_group( + "electricity", tree, child_meta, sorted(ELECTRICITY_DATASETS) + ) + groups["electricity_grid"] = _grid_group(tree, child_meta) + groups["state_electricity_profiles"] = _named_group( + "state_electricity_profiles", + tree, + child_meta, + _leaves_under(tree, "electricity/state-electricity-profiles"), + ) + groups["crude_oil_imports"] = _named_group( + "crude_oil_imports", + tree, + child_meta, + ["crude-oil-imports"], + slug_overrides={"crude-oil-imports": "crude_oil_imports"}, + ) + groups["international"] = _named_group( + "international", + tree, + child_meta, + ["international"], + slug_overrides={"international": "international"}, + ) + groups["seds"] = _named_group( + "seds", tree, child_meta, ["seds"], slug_overrides={"seds": "seds"} + ) + groups["total_energy"] = _named_group( + "total_energy", + tree, + child_meta, + ["total-energy"], + slug_overrides={"total-energy": "total_energy"}, + ) + groups["densified_biomass"] = _named_group( + "densified_biomass", tree, child_meta, _leaves_under(tree, "densified-biomass") + ) + groups["nuclear_outages"] = _named_group( + "nuclear_outages", tree, child_meta, _leaves_under(tree, "nuclear-outages") + ) + groups["aeo"] = _named_group( + "aeo", + tree, + child_meta, + _leaves_under(tree, "aeo"), + slug_overrides={ + path: path.split("/", 1)[1] for path in _leaves_under(tree, "aeo") + }, + ) + groups["ieo"] = _named_group( + "ieo", + tree, + child_meta, + _leaves_under(tree, "ieo"), + slug_overrides={ + path: path.split("/", 1)[1] for path in _leaves_under(tree, "ieo") + }, + ) + + for group in groups.values(): + group["choices"] = { + canonical: attach_params( + [ + {"value": value, "label": label} + for value, label in sorted(values.items(), key=lambda kv: kv[1]) + ] + ) + for canonical, values in sorted(group["choices"].items()) + if len(values) <= CHOICES_LIMIT + } + + return {"groups": groups} + + +MODELS_ROOT = PACKAGE_ROOT / "models" + +CHOICE_TYPE_LIMIT = 100 + +SCHEMA_CHOICES_LIMIT = 100 + +FLAT_GROUPS = ( + "crude_oil_imports", + "international", + "seds", + "total_energy", +) + +RELEASE_GROUPS = ("aeo", "ieo") + +EXTRA_DATA_FIELDS: dict[str, dict[str, str]] = { + "petroleum": {"units": "Unit of the value."}, + "natural_gas": {"units": "Unit of the value."}, + "aeo": {"unit": "Unit of the value."}, + "ieo": {"unit": "Unit of the value."}, + "seds": {"unit": "Unit of the value."}, + "total_energy": {"unit": "Unit of the value."}, + "international": {}, +} + + +def _pascal(name: str) -> str: + """Convert a snake_case name to PascalCase.""" + return "".join(part.capitalize() for part in name.split("_")) + + +def _base_name(group: str, dataset: str) -> str: + """Build the model class base name for one dataset.""" + if group in FLAT_GROUPS or group in RELEASE_GROUPS: + return f"Eia{_pascal(group)}" + return f"Eia{_pascal(group)}{_pascal(dataset)}" + + +def _literal_annotation(values: list[str]) -> str: + """Render a ``Literal[...] | None`` annotation source string.""" + unique = list(dict.fromkeys(values)) + body = ", ".join(json.dumps(value) for value in unique) + return f"Literal[{body}] | None" + + +def _field(name: str, annotation: str, description: str) -> str: + """Render one optional pydantic field definition.""" + return ( + f" {name}: {annotation} = Field(\n" + f" default=None,\n" + f" description={json.dumps(description)},\n" + f" )\n" + ) + + +def _dataset_summary(spec: dict) -> str: + """Build the one-line summary for a dataset, safe for CLI rendering.""" + name = ( + spec["name"] + .replace("U.S.", "US") + .replace("F.O.B.", "FOB") + .replace("No. ", "No ") + .replace("\\", "/") + .rstrip(".") + ) + description = spec.get("description") or "" + return f"{name}." + (f" {description}" if description else "") + + +def _data_type_description(spec: dict) -> str: + """Spell out every data column with its alias and units.""" + parts = [] + for column, detail in spec["data_columns"].items(): + label = detail.get("alias") or column.replace("_", " ") + entry = ( + column + if label.lower() == column.replace("_", " ") + else f"{column} = {label}" + ) + if detail.get("units"): + entry += f" ({detail['units']})" + parts.append(entry) + return ( + "Data column(s) to return, comma-separated." + " The default returns every column." + f" Choices: {'; '.join(parts)}." + ) + + +def _is_filter(facet: dict) -> bool: + """Return True when a facet is a real filter, not a single fixed value.""" + if facet.get("filterable") is False: + return False + return len(facet.get("choices") or []) != 1 + + +def _facet_query_field(group: str, canonical: str, facet: dict) -> str: + """Render one facet filter field for a query params class.""" + choices = facet.get("choices") or [] + single_select = canonical in LITERAL_FACETS.get(group, set()) + if choices and single_select and len(choices) <= CHOICE_TYPE_LIMIT: + annotation = _literal_annotation( + [choice.get("param") or choice["value"] for choice in choices] + ) + description = f"{facet['description']} filter." + else: + annotation = "str | None" + description = ( + f"{facet['description']} filter. Accepts a comma-separated list of values." + ) + if not choices: + description += " Use the `facet_options` endpoint for the valid values." + elif len(choices) > SCHEMA_CHOICES_LIMIT: + description += ( + f" There are {len(choices)} valid values -" + " use the `facet_options` endpoint to list them." + ) + restricted = facet.get("frequencies") + if restricted: + description += f" Only applies to frequency: {', '.join(restricted)}." + return _field(canonical, annotation, description) + + +def _schema_extra_source(spec: dict, dataset_field: str | None = None) -> str: + """Render the ``__json_schema_extra__`` literal for a query params class.""" + lines = [" __json_schema_extra__ = {"] + if len(spec["data_columns"]) > 1: + data_choices = json.dumps(list(spec["data_columns"])) + lines.append( + f' "data_type": {{"multiple_items_allowed": True,' + f' "choices": {data_choices}}},' + ) + for canonical, facet in spec["facets"].items(): + if not _is_filter(facet): + continue + choices = facet.get("choices") or [] + entry = '{"multiple_items_allowed": True' + if choices and len(choices) <= SCHEMA_CHOICES_LIMIT: + params = list( + dict.fromkeys( + choice.get("param") or choice["value"] for choice in choices + ) + ) + entry += f', "choices": {json.dumps(params)}' + entry += "}" + lines.append(f' "{canonical}": {entry},') + _ = dataset_field + lines.append(" }") + return "\n".join(lines) + "\n" + + +def _query_params_source( + group: str, + dataset: str, + spec: dict, + release_datasets: list[str] | None = None, +) -> str: + """Render the query params class for one dataset.""" + base = _base_name(group, dataset) + summary = _dataset_summary(spec) + lines = [ + f"class {base}QueryParams(EiaApiQueryParams):", + f' """{summary}', + "", + f" Source: https://www.eia.gov/opendata/browser/{spec['path']}", + ' """', + "", + f' __group__ = "{group}"', + ] + releases = list(release_datasets or []) + if release_datasets is None: + lines.append(f' __dataset__ = "{dataset}"') + elif len(releases) == 1: + lines.append(f' __dataset__ = "{releases[0]}"') + lines.append(_schema_extra_source(spec).rstrip("\n")) + lines.append("") + body: list[str] = [] + if len(releases) > 1: + annotation = _literal_annotation(releases).removesuffix(" | None") + default = json.dumps(sorted(releases)[-1]) + body.append( + f" release: {annotation} = Field(\n" + f" default={default},\n" + f' description="The {spec["category"] or group} release."\n' + ' " Facet values vary by release;' + ' use the `facet_options` endpoint to list them.",\n' + " )\n" + ) + frequencies = list(spec["frequencies"]) + if len(frequencies) > 1: + default_frequency = spec.get("default_frequency") or frequencies[0] + body.append( + _field( + "frequency", + _literal_annotation(frequencies), + f"The data frequency. The default is '{default_frequency}'.", + ) + ) + if len(spec["data_columns"]) > 1: + body.append(_field("data_type", "str | None", _data_type_description(spec))) + for canonical, facet in spec["facets"].items(): + if not _is_filter(facet): + continue + body.append(_facet_query_field(group, canonical, facet)) + lines.append("".join(body).rstrip("\n")) + return "\n".join(lines) + "\n" + + +def _data_source(group: str, dataset: str, spec: dict) -> str: + """Render the data class for one dataset.""" + base = _base_name(group, dataset) + lines = [ + f"class {base}Data(EiaApiData):", + f' """{_dataset_summary(spec)}"""', + "", + ] + body: list[str] = [] + for canonical, facet in spec["facets"].items(): + body.append(_field(canonical, "str | None", f"{facet['description']} code.")) + body.append( + _field(f"{canonical}_name", "str | None", f"{facet['description']} name.") + ) + for column, detail in spec["data_columns"].items(): + if any(part.startswith(f" {column}:") for part in body): + raise ValueError( + f"Data column '{column}' collides with a facet field" + f" in '{spec['path']}'." + ) + label = detail.get("alias") or column.replace("_", " ").capitalize() + description = label + (f" ({detail['units']})" if detail.get("units") else "") + annotation = "float | None" if detail.get("numeric", True) else "str | None" + if detail.get("numeric", True): + description += ". Withheld or unavailable values return as null." + body.append(_field(column, annotation, description)) + for extra_name, extra_description in EXTRA_DATA_FIELDS.get(group, {}).items(): + body.append(_field(extra_name, "str | None", extra_description)) + lines.append("".join(body).rstrip("\n")) + return "\n".join(lines) + "\n" + + +def _fetcher_source(group: str, dataset: str, spec: dict) -> str: + """Render the fetcher class for one dataset.""" + base = _base_name(group, dataset) + summary = _dataset_summary(spec).split(". ")[0].rstrip(".") + return f'''class {base}Fetcher(Fetcher[{base}QueryParams, list[{base}Data]]): + """{summary} fetcher.""" + + @staticmethod + def transform_query(params: dict[str, Any]) -> {base}QueryParams: + """Transform the query parameters.""" + return transform_dataset_query({base}QueryParams, params) + + @staticmethod + async def aextract_data( + query: {base}QueryParams, + credentials: dict[str, str] | None, + **kwargs: Any, + ) -> dict: + """Extract the data from the EIA API.""" + return await extract_dataset_data(query, credentials) + + @staticmethod + def transform_data( + query: {base}QueryParams, + data: dict, + **kwargs: Any, + ) -> list[{base}Data]: + """Transform the data.""" + return transform_dataset_data({base}Data, query, data) +''' + + +def render_dataset_module( + group: str, + dataset: str, + spec: dict, + release_datasets: list[str] | None = None, +) -> str: + """Render one complete dataset model module. + + Parameters + ---------- + group : str + Catalog group name. + dataset : str + Dataset slug; for release groups, the spec's release used as template. + spec : dict + Dataset specification. + release_datasets : list[str] | None + Release keys when rendering an aeo/ieo-style release module. + + Returns + ------- + str + The module source code. + """ + header = ( + f'"""{_dataset_summary(spec).split(". ")[0].rstrip(".")} model."""\n\n' + "from typing import Any, Literal\n\n" + "from openbb_core.provider.abstract.fetcher import Fetcher\n" + "from pydantic import Field\n\n" + "from openbb_us_eia.utils.api_query import (\n" + " EiaApiData,\n" + " EiaApiQueryParams,\n" + " extract_dataset_data,\n" + " transform_dataset_data,\n" + " transform_dataset_query,\n" + ")\n\n\n" + ) + return ( + header + + _query_params_source(group, dataset, spec, release_datasets) + + "\n\n" + + _data_source(group, dataset, spec) + + "\n\n" + + _fetcher_source(group, dataset, spec) + ) + + +def render_registry(catalog: dict[str, Any]) -> str: + """Render the generated fetcher registry module.""" + imports: list[str] = [] + entries: list[str] = [] + for group in DATASET_GROUPS_EMIT: + datasets = catalog["groups"][group]["datasets"] + if group in RELEASE_GROUPS: + base = _base_name(group, "") + imports.append(f"from openbb_us_eia.models.{group} import {base}Fetcher") + entries.append(f' "{base}": {base}Fetcher,') + continue + if group in FLAT_GROUPS: + base = _base_name(group, group) + imports.append(f"from openbb_us_eia.models.{group} import {base}Fetcher") + entries.append(f' "{base}": {base}Fetcher,') + continue + for dataset in datasets: + base = _base_name(group, dataset) + imports.append( + f"from openbb_us_eia.models.{group}.{dataset} import {base}Fetcher" + ) + entries.append(f' "{base}": {base}Fetcher,') + imports.sort() + entries.sort() + return ( + '"""Registry of EIA dataset fetchers."""\n\n' + + "\n".join(imports) + + "\n\nDATASET_FETCHERS = {\n" + + "\n".join(entries) + + "\n}\n" + ) + + +def _release_template(group: str, group_doc: dict) -> dict: + """Build the spec describing a release-keyed report as a whole.""" + datasets = group_doc["datasets"] + latest = datasets[sorted(datasets)[-1]] + template = dict(latest) + template["name"] = latest.get("category") or group.upper() + template["description"] = ( + "Long-term energy projections by release year and scenario." + " Select the report vintage with the `release` parameter." + ) + template["path"] = group + template["start_period"] = min( + filter(None, (spec.get("start_period") for spec in datasets.values())), + default=None, + ) + template["end_period"] = max( + filter(None, (spec.get("end_period") for spec in datasets.values())), + default=None, + ) + facets: dict = {} + for canonical, detail in latest["facets"].items(): + entry = dict(detail) + union = group_doc["choices"].get(canonical) + if union: + entry["choices"] = union + entry["n_values"] = len(union) + else: + entry.pop("choices", None) + facets[canonical] = entry + template["facets"] = facets + return template + + +DATASET_GROUPS_EMIT = ( + "coal", + "petroleum", + "natural_gas", + "electricity", + "electricity_grid", + "state_electricity_profiles", + "densified_biomass", + "nuclear_outages", + "crude_oil_imports", + "international", + "seds", + "total_energy", + "aeo", + "ieo", +) + +MULTI_DATASET_GROUPS = tuple( + group + for group in DATASET_GROUPS_EMIT + if group not in FLAT_GROUPS and group not in RELEASE_GROUPS +) + + +def write_models(catalog: dict[str, Any]) -> int: + """Write every generated model module and the registry. + + Parameters + ---------- + catalog : dict[str, Any] + The catalog document. + + Returns + ------- + int + Number of model modules written. + """ + import shutil + + written = 0 + for group in MULTI_DATASET_GROUPS: + group_dir = MODELS_ROOT / group + shutil.rmtree(group_dir, ignore_errors=True) + group_dir.mkdir(parents=True) + title = group.replace("_", " ").title() + (group_dir / "__init__.py").write_text( + f'"""EIA {title} models."""\n', encoding="utf-8" + ) + for dataset, spec in catalog["groups"][group]["datasets"].items(): + module = render_dataset_module(group, dataset, spec) + (group_dir / f"{dataset}.py").write_text(module, encoding="utf-8") + written += 1 + for group in FLAT_GROUPS: + datasets = catalog["groups"][group]["datasets"] + slug, spec = next(iter(datasets.items())) + module = render_dataset_module(group, slug, spec) + (MODELS_ROOT / f"{group}.py").write_text(module, encoding="utf-8") + written += 1 + for group in RELEASE_GROUPS: + datasets = catalog["groups"][group]["datasets"] + releases = list(datasets) + template = _release_template(group, catalog["groups"][group]) + module = render_dataset_module( + group, group, template, release_datasets=releases + ) + (MODELS_ROOT / f"{group}.py").write_text(module, encoding="utf-8") + written += 1 + (MODELS_ROOT / "registry.py").write_text(render_registry(catalog), encoding="utf-8") + lint_generated(MODELS_ROOT) + return written + + +def lint_generated(target: Path) -> None: + """Run ruff lint fixes and formatting on the generated modules. + + Parameters + ---------- + target : Path + Directory holding the generated modules. + + Raises + ------ + RuntimeError + If ruff reports unfixable findings or fails to format. + """ + for argv in ( + [sys.executable, "-m", "ruff", "check", "--fix", str(target)], + [sys.executable, "-m", "ruff", "format", str(target)], + ): + completed = subprocess.run(argv, check=False) # noqa: S603 + if completed.returncode != 0: + raise RuntimeError( + f"ruff {argv[3]} failed for the generated modules in {target}" + ) + + +def main() -> int: + """Run the catalog generator.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--tree", + type=Path, + default=None, + help="Path to a saved crawl JSON. When omitted, the EIA API is crawled live.", + ) + parser.add_argument( + "--api-key", + default=None, + help="EIA API key for a live crawl. Defaults to the EIA_API_KEY" + " environment variable, then the OpenBB 'eia_api_key' credential.", + ) + parser.add_argument( + "--asset-only", + action="store_true", + help="Write only the catalog asset, leaving the generated model source" + " untouched. Used by the package build hook.", + ) + args = parser.parse_args() + + if args.tree: + tree = json.loads(args.tree.read_text(encoding="utf-8")) + else: + api_key = args.api_key or os.environ.get("EIA_API_KEY") + if not api_key: + from openbb_core.app.service.user_service import ( + UserService, # noqa: PLC0415 + ) + + credentials = UserService().default_user_settings.credentials.model_dump() + api_key = credentials.get("eia_api_key") + api_key = ( + api_key.get_secret_value() + if hasattr(api_key, "get_secret_value") + else api_key + ) + if not api_key: + sys.stderr.write("An EIA API key is required for a live crawl.\n") + return 1 + tree = fetch_tree(api_key) + + catalog = build_catalog(tree) + ASSET_PATH.parent.mkdir(parents=True, exist_ok=True) + payload = json.dumps( + catalog, ensure_ascii=False, separators=(",", ":"), sort_keys=True + ) + ASSET_PATH.write_bytes(lzma.compress(payload.encode("utf-8"), preset=9)) + n_datasets = sum(len(group["datasets"]) for group in catalog["groups"].values()) + + if args.asset_only: + sys.stdout.write( + f"Wrote {ASSET_PATH} ({ASSET_PATH.stat().st_size / 1024:.0f} KiB)" + f" covering {n_datasets} datasets.\n" + ) + return 0 + + written = write_models(catalog) + completed = subprocess.run( # noqa: S603 + [ + sys.executable, + "-m", + "ty", + "check", + "--python", + sys.executable, + "--ignore", + "unresolved-import", + str(MODELS_ROOT), + ], + cwd=MODELS_ROOT.parent.parent, + check=False, + ) + if completed.returncode != 0: + sys.stderr.write("ty check failed for the generated modules.\n") + return completed.returncode + sys.stdout.write( + f"Wrote {ASSET_PATH} ({ASSET_PATH.stat().st_size / 1024:.0f} KiB)," + f" {written} model modules, and the registry" + f" covering {n_datasets} datasets.\n" + ) + return 0 + + +if __name__ == "__main__": # pragma: no cover + sys.exit(main()) diff --git a/openbb_platform/providers/eia/openbb_us_eia/utils/helpers.py b/openbb_platform/providers/eia/openbb_us_eia/utils/helpers.py index e29c1d83c3b..ad043a8a49f 100644 --- a/openbb_platform/providers/eia/openbb_us_eia/utils/helpers.py +++ b/openbb_platform/providers/eia/openbb_us_eia/utils/helpers.py @@ -1,4 +1,4 @@ -"""OpenBB EIA Provider Module Helpers.""" +"""OpenBB EIA provider helpers.""" from typing import TYPE_CHECKING @@ -8,36 +8,106 @@ from openbb_core.app.model.abstract.error import OpenBBError if TYPE_CHECKING: from pandas import ExcelFile +API_BASE = "https://api.eia.gov/v2" -async def response_callback(response, _): - """Response callback to read the response.""" + +async def response_callback(response, _) -> dict: + """Read an EIA API response, surfacing authentication errors. + + Parameters + ---------- + response : aiohttp.ClientResponse + The response to read. + + Returns + ------- + dict + The decoded JSON body. + """ if response.status == 403: res = await response.json() code = res.get("error", {}).get("code", "") msg = res.get("error", {}).get("message", "An invalid api_key was supplied.") raise OpenBBError(f"{code} -> {msg}") - return await response.json() + result = await response.json() + if isinstance(result, dict) and "error" in result and "response" not in result: + error = result["error"] + detail = error.get("message", error) if isinstance(error, dict) else error + raise OpenBBError(f"EIA API error -> {detail}") + return result + + +def build_data_url(request: dict, offset: int, length: int) -> str: + """Render one page of an EIA data request as a URL. + + Parameters + ---------- + request : dict + Request description with 'path', 'api_key', 'frequency', 'data_columns', + 'facets', 'start', 'end', and 'sort' keys. + offset : int + Row offset of the page. + length : int + Number of rows to request. + + Returns + ------- + str + The request URL. + """ + from urllib.parse import urlencode + + pairs: list[tuple[str, str]] = [("api_key", request["api_key"])] + if request.get("frequency"): + pairs.append(("frequency", request["frequency"])) + for position, column in enumerate(request.get("data_columns") or []): + pairs.append((f"data[{position}]", column)) + for facet_id, values in (request.get("facets") or {}).items(): + pairs.extend((f"facets[{facet_id}][]", value) for value in values) + if request.get("start"): + pairs.append(("start", request["start"])) + if request.get("end"): + pairs.append(("end", request["end"])) + pairs.extend( + [ + ("sort[0][column]", "period"), + ("sort[0][direction]", request.get("sort", "desc")), + ("offset", str(offset)), + ("length", str(length)), + ] + ) + return f"{API_BASE}/{request['path']}/data/?{urlencode(pairs)}" @alru_cache(maxsize=14) async def download_excel_file(url: str, use_cache: bool = True) -> "ExcelFile": - """Download the excel file from the URL. Set use_cache to False to invalidate the ALRU cache.""" - # pylint: disable=import-outside-toplevel - from io import BytesIO # noqa + """Download an Excel file, caching it for the session. + + Parameters + ---------- + url : str + The file URL. + use_cache : bool + Set False to invalidate the cached copy and download again. + + Returns + ------- + pandas.ExcelFile + The downloaded workbook. + """ + from io import BytesIO + from openbb_core.provider.utils.helpers import amake_request from pandas import ExcelFile - async def callback(response, _): - """Read the response and return the ExcelFile object.""" - res = await response.read() - file = ExcelFile(BytesIO(res)) - return file + async def callback(response, _) -> "ExcelFile": + return ExcelFile(BytesIO(await response.read())) - # Clear the cache to download the file again. if use_cache is False: - download_excel_file.cache_invalidate(url) + download_excel_file.cache_invalidate(url, True) + download_excel_file.cache_invalidate(url, False) try: - return await amake_request(url, response_callback=callback) - except Exception as e: # pylint: disable=broad-except + return await amake_request(url, response_callback=callback) # ty: ignore[invalid-return-type,invalid-argument-type] + except Exception as e: raise OpenBBError(f"Error downloading the file from the EIA site -> {e}") from e diff --git a/openbb_platform/providers/eia/openbb_us_eia/utils/rss.py b/openbb_platform/providers/eia/openbb_us_eia/utils/rss.py new file mode 100644 index 00000000000..5b33bbf6451 --- /dev/null +++ b/openbb_platform/providers/eia/openbb_us_eia/utils/rss.py @@ -0,0 +1,363 @@ +"""EIA RSS feed registry, item building, and HTML-widget rendering.""" + +from datetime import datetime, timezone +from pathlib import Path +from time import struct_time +from typing import TYPE_CHECKING +from urllib.parse import urljoin, urlsplit, urlunsplit + +if TYPE_CHECKING: + from aiohttp import ClientSession + +EIA_SITE = "https://www.eia.gov/" +_TEMPLATE = Path(__file__).parents[1] / "assets" / "rss_feed.html" + +EIA_RSS_FEEDS: dict[str, dict[str, str]] = { + "today_in_energy": { + "label": "Today in Energy", + "description": "Short, timely articles with graphics on energy facts," + " issues, and trends.", + "url": "https://www.eia.gov/rss/todayinenergy.xml", + "base": "https://www.eia.gov/todayinenergy/", + "viewer": "page", + }, + "whats_new": { + "label": "What's New", + "description": "Notification of new EIA products as they are released.", + "url": "https://www.eia.gov/about/new/WNtest3.php", + "base": EIA_SITE, + "viewer": "page", + }, + "press_releases": { + "label": "Press Releases", + "description": "Press releases from the Energy Information Administration.", + "url": "https://www.eia.gov/rss/press_rss.xml", + "base": EIA_SITE, + "viewer": "page", + }, + "congressional_testimony": { + "label": "Congressional Testimony", + "description": "Scheduled testimonies and information EIA presented to" + " Congress.", + "url": "https://www.eia.gov/rss/testimony.xml", + "base": EIA_SITE, + "viewer": "pdf", + }, + "presentations": { + "label": "Presentations", + "description": "Presentations and speeches given by EIA at various venues.", + "url": "https://www.eia.gov/rss/presentations.xml", + "base": EIA_SITE, + "viewer": "pdf", + }, + "gasoline_diesel": { + "label": "Gasoline & Diesel Fuel Update", + "description": "Retail gasoline and on-highway diesel fuel prices," + " nationally and by region.", + "url": "https://www.eia.gov/petroleum/gasdiesel/includes/gas_diesel_rss.xml", + "base": "https://www.eia.gov/petroleum/gasdiesel/", + "viewer": "table", + }, + "heating_oil_propane": { + "label": "Heating Oil & Propane Update", + "description": "Heating oil and propane retail prices and supply," + " nationally and by region (October-March).", + "url": "https://www.eia.gov/petroleum/heatingoilpropane/includes/hopu_rss.xml", + "base": "https://www.eia.gov/petroleum/heatingoilpropane/", + "viewer": "table", + }, +} + +FEED_TIMEOUT_SEC = 10.0 + + +def feed_choices() -> list[dict[str, str]]: + """Return ``[{label, value}]`` for every EIA RSS feed (tab options).""" + return [ + {"label": feed["label"], "value": key} for key, feed in EIA_RSS_FEEDS.items() + ] + + +def strip_html(text: str) -> str: + """Strip HTML tags and collapse whitespace.""" + if not text: + return "" + from html.parser import HTMLParser + + parts: list[str] = [] + + class _Stripper(HTMLParser): + def handle_data(self, data: str) -> None: + parts.append(data) + + stripper = _Stripper() + stripper.feed(text) + return " ".join("".join(parts).split()) + + +_EXCERPT_TAGS = {"strong", "em", "b", "i", "sub", "sup"} +_VOID_TAGS = {"script", "style"} + + +def article_text(html: str, limit: int = 20000) -> str: + """Extract an article page's readable text, dropping script/style contents. + + ``strip_html`` keeps every data node, which on a full page pulls inline + JavaScript and CSS into the result; this mutes ``_VOID_TAGS`` so the output + is the prose an agent can actually read. + """ + if not html: + return "" + from html.parser import HTMLParser + + class _Text(HTMLParser): + def __init__(self) -> None: + super().__init__(convert_charrefs=True) + self.parts: list[str] = [] + self.muted: list[str] = [] + + def handle_starttag(self, tag: str, attrs: list) -> None: + if tag in _VOID_TAGS: + self.muted.append(tag) + + def handle_endtag(self, tag: str) -> None: + if tag in _VOID_TAGS and tag in self.muted: + self.muted.remove(tag) + + def handle_data(self, data: str) -> None: + if not self.muted: + self.parts.append(data) + + parser = _Text() + parser.feed(html) + return " ".join("".join(parser.parts).split())[:limit] + + +def clean_excerpt(summary: str, limit: int = 320) -> str: + """Decode a feed summary to sanitized inline HTML, truncated to ``limit`` chars.""" + from html import escape, unescape + from html.parser import HTMLParser + + class _Excerpt(HTMLParser): + def __init__(self) -> None: + super().__init__(convert_charrefs=True) + self.parts: list[str] = [] + self.count = 0 + self.open: list[str] = [] + self.muted: list[str] = [] + self.done = False + + def handle_starttag(self, tag: str, attrs: list) -> None: + if tag in _VOID_TAGS: + self.muted.append(tag) + return + if self.done or tag not in _EXCERPT_TAGS: + return + self.parts.append(f"<{tag}>") + self.open.append(tag) + + def handle_endtag(self, tag: str) -> None: + if tag in _VOID_TAGS: + if tag in self.muted: + self.muted.remove(tag) + return + if self.done or tag not in self.open: + return + while self.open: + current = self.open.pop() + self.parts.append(f"</{current}>") + if current == tag: + break + + def handle_data(self, data: str) -> None: + if self.done or self.muted: + return + remaining = limit - self.count + if remaining <= 0: + self.done = True + return + text = data + if len(text) > remaining: + text = text[:remaining].rsplit(" ", 1)[0].rstrip(",.;:") + "…" + self.done = True + self.parts.append(escape(text)) + self.count += len(text) + + def result(self) -> str: + for tag in reversed(self.open): + self.parts.append(f"</{tag}>") + return "".join(self.parts) + + parser = _Excerpt() + parser.feed(unescape(summary or "")) + return parser.result() + + +def struct_time_to_iso(value: "struct_time | None") -> str: + """Convert a feedparser ``struct_time`` to an ISO 8601 string.""" + if value is None: + return datetime.now(timezone.utc).isoformat() + return datetime(*value[:6], tzinfo=timezone.utc).isoformat() + + +async def fetch_feed(session: "ClientSession", url: str, retries: int = 3): + """Fetch and parse an RSS feed, retrying transient failures.""" + import asyncio + + import aiohttp + import feedparser + + for attempt in range(retries): + try: + response = await session.get( + url, + headers={ + "Accept": "application/rss+xml, application/xml;q=0.9, */*;q=0.8" + }, + timeout=aiohttp.ClientTimeout(total=FEED_TIMEOUT_SEC), + ) + async with response: + response.raise_for_status() + payload = await response.read() + return feedparser.parse(payload) + except (aiohttp.ClientError, TimeoutError): + if attempt + 1 < retries: + await asyncio.sleep(0.4 * (attempt + 1)) + return feedparser.parse(b"") + + +def _youtube_embed(url: str) -> str | None: + """Return a YouTube embed URL for a watch/short link, else ``None``.""" + import re + + match = re.search(r"(?:youtu\.be/|youtube\.com/(?:watch\?v=|embed/))([\w-]+)", url) + return f"https://www.youtube.com/embed/{match.group(1)}" if match else None + + +def render_price_table(description: str) -> str: + """Render a fuel-price feed item's ``<br/>`` table as HTML sections.""" + import re + + text = re.sub(r"(?i)<br\s*/?>", "\n", description or "") + text = strip_html(text) if "<" in text else text + row_re = re.compile(r"^([\d.,]+)\s*\.{2,}\s*(.+)$") + parts: list[str] = [] + open_table = False + for raw in text.split("\n"): + line = " ".join(raw.split()) + if not line or line.lower().startswith("summary excerpt"): + continue + match = row_re.match(line) + if match: + if not open_table: + parts.append('<table class="price">') + open_table = True + value, label = match.group(1), _escape(match.group(2)) + parts.append(f"<tr><td>{label}</td><td class=v>{value}</td></tr>") + else: + if open_table: + parts.append("</table>") + open_table = False + parts.append(f"<h4>{_escape(line)}</h4>") + if open_table: + parts.append("</table>") + return "".join(parts) + + +def _escape(text: str) -> str: + """Escape text for safe inclusion in HTML.""" + from html import escape + + return escape(text or "") + + +def build_feed(feed_key: str, parsed, limit: int, proxy_base: str = "") -> dict: + """Normalize a parsed feed into the widget's data payload.""" + spec = EIA_RSS_FEEDS[feed_key] + base = spec["base"] + viewer = spec["viewer"] + feed_title = (parsed.feed.get("title") if parsed.feed else "") or spec["label"] + entries = sorted( + parsed.entries, + key=lambda e: e.get("published_parsed") or e.get("updated_parsed") or (0,) * 9, + reverse=True, + )[:limit] + + items: list[dict] = [] + for entry in entries: + summary = entry.get("summary") or entry.get("description") or "" + link = urljoin(base, (entry.get("link") or "").strip()) + item: dict = { + "title": (entry.get("title") or "(untitled)").strip(), + "date": struct_time_to_iso( + entry.get("published_parsed") or entry.get("updated_parsed") + ), + "author": (entry.get("author") or feed_title).strip(), + "url": link, + "excerpt": clean_excerpt(summary), + "viewer": viewer, + "src": link, + "meta": [], + "body_html": "", + } + if viewer == "pdf": + _fill_presentation(item, entry, base) + elif viewer == "table": + item["body_html"] = render_price_table(summary) + src_parts = urlsplit(item["src"]) + src_host = (src_parts.hostname or "").lower() + if ( + item["viewer"] in ("page", "pdf") + and proxy_base + and (src_host == "eia.gov" or src_host.endswith(".eia.gov")) + ): + tail = urlunsplit( + ("", "", src_parts.path, src_parts.query, src_parts.fragment) + ).lstrip("/") + item["src"] = f"{proxy_base}/{tail}" + items.append(item) + + return { + "feed": feed_key, + "label": spec["label"], + "description": spec["description"], + "items": items, + } + + +def _fill_presentation(item: dict, entry: dict, base: str) -> None: + """Populate a testimony/presentation item's PDF source and metadata.""" + pdf = str(entry.get("eia_pdf") or "").strip() + ppt = str(entry.get("eia_ppt") or "").strip() + item["ppt_url"] = urljoin(base, ppt) if ppt else "" + if pdf: + item["src"] = urljoin(base, pdf) + elif (embed := _youtube_embed(item["url"])) is not None: + item["src"] = embed + item["viewer"] = "embed" + else: + item["viewer"] = "page" + for key, label in ( + ("eia_subject", "Subject"), + ("eia_presentedby", "Presented by"), + ("eia_presentedto", "Presented to"), + ("eia_location", "Location"), + ): + value = strip_html(str(entry.get(key) or "")).strip() + if value: + item["meta"].append({"label": label, "value": value}) + + +def render_rss_html(data: dict, theme: str) -> str: + """Render the widget HTML for a built feed payload and theme.""" + import json + + payload = {**data, "theme": "light" if theme == "light" else "dark"} + blob = ( + json.dumps(payload) + .replace("<", "\\u003c") + .replace(">", "\\u003e") + .replace("&", "\\u0026") + ) + template = _TEMPLATE.read_text(encoding="utf-8") + return template.replace("__EIA_RSS_DATA__", blob) diff --git a/openbb_platform/providers/eia/openbb_us_eia/utils/total_energy_map.json b/openbb_platform/providers/eia/openbb_us_eia/utils/total_energy_map.json deleted file mode 100644 index b649b3932e6..00000000000 --- a/openbb_platform/providers/eia/openbb_us_eia/utils/total_energy_map.json +++ /dev/null @@ -1,982 +0,0 @@ -{ - "ARICBUS": "Asphalt and Road Oil Consumed by the Industrial Sector in Trillion Btu", - "ARTCBUS": "Asphalt and Road Oil Product Supplied in Trillion Btu", - "AVTCPUS": "Aviation Gasoline Product Supplied in Thousand Barrels per Day", - "B1IMPUS": "Renewable Diesel Fuel Imports in Thousand Barrels", - "B1LCBUS": "Renewable Diesel Fuel Losses and Co-products in Trillion Btu", - "BDACBUS": "Biodiesel Consumed by the Transportation Sector in Trillion Btu", - "BDNIPUS": "Biodiesel Net Imports in Thousand Barrels", - "BDTCMUS": "Biodiesel Consumption in Million Gallons", - "BFTCBUS": "Biofuels Consumption in Trillion Btu", - "BMACEUS": "Biomass Transportation Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "BOPRBUS": "Other Biofuels Production in Trillion Btu", - "BTL9SUS": "Battery Storage Electric Power Sector Generating Units, Usage Factor in Percent", - "CLACBUS": "Coal Consumed by the Transportation Sector in Trillion Btu", - "CLCCBUS": "Coal Consumed by the Commercial Sector in Trillion Btu", - "CLEIBUS": "Coal Consumed by the Electric Power Sector in Trillion Btu", - "CLERDUS": "Average Cost of Coal Receipts at Electric Generating Plants in Dollars per Million Btu, Including Taxes", - "CLICBUS": "Coal Consumed by the Industrial Sector in Trillion Btu", - "CLIMBUS": "Coal Imports in Trillion Btu", - "CLOCPUS": "Coal Consumed by the Other Industrial Sector, Total in Thousand Short Tons", - "CLPRBUS": "Coal Production in Trillion Btu", - "COFMUCL": "Average Free on Board Cost of Crude Oil Imports From Colombia in Dollars per Barrel", - "COFMUNT": "Average Free on Board Cost of Crude Oil Imports From All Non-OPEC Countries in Dollars per Barrel", - "COIMUOP": "Average Landed Cost of Crude Oil Imports From All OPEC Countries in Dollars per Barrel", - "COIMUSA": "Average Landed Cost of Crude Oil Imports From Saudi Arabia in Dollars per Barrel", - "COIMUUS": "Average Landed Cost of Crude Oil Imports in Dollars per Barrel", - "CONIBUS": "Crude Oil Net Imports in Quadrillion Btu", - "CPUCIUS": "Consumer Price Index (Urban) in Index 1982-1984 = 100", - "CYCASUS": "Natural Gas Combined Cycle Plants Generating Units, Capacity Factor in Percent", - "CYI9SUS": "Natural Gas Combined Cycle Plants Industrial Sector Generating Units, Capacity Factor in Percent", - "D2RCAUS": "Average Cost of Residential Heating Oil in Real (1982-1984) Dollars per Million Btu", - "DFCCEUS": "Distillate Fuel Oil Commercial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "DFICBUS": "Distillate Fuel Oil Consumed by the Industrial Sector in Trillion Btu", - "DFIMPUS": "Distillate Fuel Oil Imports in Thousand Barrels per Day", - "DFROPUS": "Distillate Fuel Oil Refinery and Blender Net Production in Thousand Barrels per Day", - "ELC5PUS": "Electricity Net Generation Total (including from sources not shown), Commercial Sector in Million Kilowatthours", - "ELGBPUS": "Total Electric, Net Summer Capacity in Million Kilowatts", - "ELI9PUS": "Total Industrial Sector, Net Summer Capacity in Million Kilowatts", - "ELIMBUS": "Electricity Imports in Trillion Btu", - "ELNIBUS": "Electric Power Sector Electricity Net Imports in Trillion Btu", - "ELUNPUS": "Transmission and Distribution Losses and Unaccounted for in Million Kilowatthours", - "ENPRPUS": "Fuel Ethanol Production in Thousand Barrels", - "ESACUUS": "Average Price of Electricity to Ultimate Customers, Transportation in Cents per Kilowatthour, Including Taxes", - "ESCCEUS": "Commercial Share of Electric Power Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "ESRCBUS": "Electricity Sales to Ultimate Customers in the Residential Sector in Trillion Btu", - "ESRCOUS": "Average Cost of Residential Electricity in Real (1982-1984) Cents per Kilowatthour", - "ESRCPUS": "Electricity Sales to Ultimate Customers, Residential in Million Kilowatthours", - "ESTCPUS": "Electricity Sales to Ultimate Customers, Total in Million Kilowatthours", - "EV2CNUS": "Number of level 2 charging ports in Number", - "EVCHPUS": "Total number of locations in Number", - "EVPPPUS": "Number of locations with public and private ports in Number", - "FFL9PUS": "Fossil Fuels Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "HLACEUS": "HGL Transportation Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "HLEXPUS": "Total Hydrocarbon Gas Liquids Exports in Thousand Barrels per Day", - "HLRCBUS": "Propane Consumed by the Residential Sector in Trillion Btu", - "HLRCEUS": "HGL Residential Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "JFACEUS": "Jet Fuel Transportation Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "JFPSPUS": "Jet Fuel Stocks, End of Period in Million Barrels", - "JKTCUUS": "Average Refiner Price of Kerosene-Type Jet Fuel to End Users in Dollars per Gallon Excluding Taxes", - "KSICEUS": "Kerosene Industrial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "KSTCPUS": "Kerosene Product Supplied in Thousand Barrels per Day", - "LNEXPCH": "Natural Gas Exports to China in Billion Cubic Feet", - "LNEXPIH": "Natural Gas Exports to India in Billion Cubic Feet", - "LNEXPSP": "Natural Gas Exports to Spain in Billion Cubic Feet", - "LNIMPOM": "Natural Gas Imports from Oman in Billion Cubic Feet", - "LUACEUS": "Lubricants Transportation Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "MGICPUS": "Motor Gasoline Consumed by the Industrial Sector in Thousand Barrels per Day", - "MGWHUUS": "Average Refiner Price of Finished Motor Gasoline for Resale in Dollars per Gallon Excluding Taxes", - "NGAJPUS": "Natural Gas Balancing Item in Billion Cubic Feet", - "NGCCSUS": "Percentage of Commercial Sector Consumption for Which Price Data Are Available in Percent", - "NGEGPUS": "Electricity Net Generation From Natural Gas, Electric Power Sector in Million Kilowatthours", - "NGETPUS": "Electricity Net Generation From Natural Gas, All Sectors in Million Kilowatthours", - "NGI5PUS": "Electricity Net Generation From Natural Gas, Industrial Sector in Million Kilowatthours", - "NGL1PUS": "Natural Gas Consumption for Electricity Generation, Electric Power Sector in Billion Cubic Feet", - "NGL9PUS": "Natural Gas Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "NGNFPUS": "Natural Gas Non-Combustion Consumption in Billion Cubic Feet", - "NGUSPUS": "Natural Gas in Underground Storage, End of Period, Total in Billion Cubic Feet", - "NGWCPUS": "Change in Working Gas From Same Period Previous Year, Volume in Billion Cubic Feet", - "NNTCEUS": "Natural Gas, Excluding Supplemental Gaseous Fuels, CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "NUL9SUS": "Nuclear Electric Power Sector Generating Units, Capacity Factor in Percent", - "OGNRPON": "Crude Oil and Natural Gas Rotary Rigs in Operation, Onshore in Number of Rigs", - "OGWSPUS": "Active Well Service Rig Count in Number of Rigs", - "OLECPUS": "Other Petroleum Liquids Consumption for Electricity Generation and Useful Thermal Output, All Sectors in Thousand Barrels", - "OMNIVUS": "Non-Energy Balance in Million Dollars", - "OPACBUS": "Other Products Consumed by the Transportation Sector in Trillion Btu", - "OTECBUS": "Other Consumption for Electricity Generation and Useful Thermal Output, All Sectors in Trillion Btu", - "OTI3BUS": "Other Consumption for Electricity Generation and Useful Thermal Output, Industrial Sector in Trillion Btu", - "OTNFPUS": "Other Petroleum Non-Combusiton Consumption in Thousand Barrels per Day", - "PAC5PUS": "Electricity Net Generation From Petroleum, Commercial Sector in Million Kilowatthours", - "PACCPUS": "Total Petroleum Consumed by the Commercial Sector in Thousand Barrels per Day", - "PAEGPUS": "Electricity Net Generation From Petroleum, Electric Power Sector in Million Kilowatthours", - "PAEIEUS": "Petroleum Electric Power Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "PAEKPUS": "Total Petroleum Stocks, Electric Power Sector, End of Period in Thousand Barrels", - "PAEXVUS": "Petroleum Exports in Million Dollars", - "PAI5PUS": "Electricity Net Generation From Petroleum, Industrial Sector in Million Kilowatthours", - "PAIMPCN": "Petroleum Imports From Canada in Thousand Barrels per Day", - "PAIMPNT": "Petroleum Imports From Total Non-OPEC Countries in Thousand Barrels per Day", - "PAIMPUA": "Petroleum Imports from United Arab Emirates in Thousand Barrels per Day", - "PAL9SUS": "Petroleum Electric Power Sector Generating Units, Capacity Factor in Percent", - "PASCPUS": "Petroleum Stock Change in Thousand Barrels per Day", - "PCEIEUS": "Petroleum Coke Electric Power Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "PCERDUS": "Average Cost of Petroleum Coke Receipts at Electric Generating Plants in Dollars per Million Btu, Including Taxes", - "PMEXBUS": "Total Petroleum, Excluding Biofuels, Exports in Trillion Btu", - "PMICEUS": "Petroleum, Excluding Biofuels, Industrial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "PMTCEUS": "Petroleum, Excluding Biofuels, CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "PQTCPUS": "Propane Product Supplied in Thousand Barrels per Day", - "PRTCUUS": "Average Refiner Price of Propane (Consumer Grade) to End Users in Dollars per Gallon Excluding Taxes", - "PZPSPUS": "Propane/Propylene Stocks in Million Barrels", - "PZTCBUS": "Propane/Propylene Product Supplied in Trillion Btu", - "RAIMUUS": "Average Refiner Acquisition Cost of Crude Oil, Imported in Dollars per Barrel", - "REC9PUS": "Renewable Energy Commercial Sector, Net Summer Capacity in Million Kilowatts", - "RERCBUS": "Total Renewable Energy Consumed by the Residential Sector in Trillion Btu", - "RFACBUS": "Residual Fuel Oil Consumed by the Transportation Sector in Trillion Btu", - "RFCCBUS": "Residual Fuel Oil Consumed by the Commercial Sector in Trillion Btu", - "RFCCEUS": "Residual Fuel Oil Commercial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "RFCCPUS": "Residual Fuel Oil Consumed by the Commercial Sector in Thousand Barrels per Day", - "RFL1PUS": "Residual Fuel Oil Consumption for Electricity Generation, Electric Power Sector in Thousand Barrels", - "RQEXBUS": "Petroleum Products, Excluding Biofuels, Exports in Trillion Btu", - "SOC7PUS": "Small-Scale Solar Photovoltaic Generation: Commercial Sector in Million Kilowatthours", - "SOETPUS": "Electricity Net Generation From Solar, All Sectors in Million Kilowatthours", - "TEAJBUS": "Primary Energy Stock Change and Other in Trillion Btu", - "TECCEUS": "Total Energy Commercial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "TEICEUS": "Total Industrial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "TNCCBUS": "End-Use Energy Consumed by the Commercial Sector in Trillion Btu", - "WDC9PUS": "Wood Commercial Sector, Net Summer Capacity in Million Kilowatts", - "WDEPBUS": "Wood Consumption for Electricity Generation, All Sectors in Trillion Btu", - "WDETPUS": "Electricity Net Generation From Wood, All Sectors in Million Kilowatthours", - "WSGBPUS": "Waste, Net Summer Capacity in Million Kilowatts", - "WYEGBUS": "Wind Energy Consumed by the Electric Power Sector in Trillion Btu", - "WYEGPUS": "Electricity Net Generation From Wind, Electric Power Sector in Million Kilowatthours", - "WYICBUS": "Wind Energy Consumed by the Industrial Sector in Trillion Btu", - "ZWHDPUS": "Heating Degree-Days, United States in Number", - "AVACBUS": "Aviation Gasoline Consumed by the Transportation Sector in Trillion Btu", - "AVTCEUS": "Aviation Gasoline CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "B1PRMUS": "Renewable Diesel Fuel Production in Million Gallons", - "B1TCBUS": "Renewable Diesel Fuel Consumption in Trillion Btu", - "BDEXPUS": "Biodiesel Exports in Thousand Barrels", - "BDFDBUS": "Biodiesel Feedstock in Trillion Btu", - "BFPRBUS": "Biofuels Production in Trillion Btu", - "BMEXBUS": "Biomass Exports in Quadrillion Btu", - "BMICEUS": "Biomass Industrial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "BMNIBUS": "Biomass Net Imports in Quadrillion Btu", - "BMRCBUS": "Biomass Energy Consumed by the Residential Sector in Trillion Btu", - "BOIMPUS": "Other Biofuels Imports in Thousand Barrels", - "BTL9PUS": "Battery Storage Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "CKTCEUS": "Coal, Including Coal Coke Net Imports, CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "CLACPUS": "Coal Consumed by the Transportation Sector in Thousand Short Tons", - "CLC9PUS": "Coal Commercial Sector, Net Summer Capacity in Million Kilowatts", - "CLEPPUS": "Coal Consumption for Electricity Generation, All Sectors in Thousand Short Tons", - "CLGBPUS": "Coal, Net Summer Capacity in Million Kilowatts", - "CLI9SUS": "Coal Industrial Sector Generating Units, Capacity Factor in Percent", - "CLICEUS": "Coal Industrial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "CLIMPUS": "Coal Imports in Thousand Short Tons", - "CLLUPUS": "Coal Losses and Unaccounted for in Thousand Short Tons", - "CLNFBUS": "Coal Non-Combustion Consumption in Quadrillion Btu", - "CLNIPUS": "Coal Net Imports in Thousand Short Tons", - "CLPSPUS": "Coal Stocks, Total, End of Period in Thousand Short Tons", - "CLRCPUS": "Coal Consumed by the Residential Sector in Thousand Short Tons", - "CLSCPUS": "Coal Stock Change in Thousand Short Tons", - "CLSJPUS": "Coal Stocks, End-Use Sectors Total, End of Period in Thousand Short Tons", - "CLSOPUS": "Coal Stocks, Industrial Sector, Other, End of Period in Thousand Short Tons", - "COFMUUS": "Average Free on Board Cost of Crude Oil Imports in Dollars per Barrel", - "COIMBUS": "Crude Oil Imports in Trillion Btu", - "COIMPUS": "Crude Oil Imports, Total in Thousand Barrels per Day", - "COIMUAQ": "Average Landed Cost of Crude Oil Imports From Angola in Dollars per Barrel", - "COSQPUS": "Crude Oil Stocks, Strategic Petroleum Reserve, End of Period in Million Barrels", - "DFPSPUS": "Distillate Fuel Oil Stocks, End of Period in Million Barrels", - "DFRCEUS": "Distillate Fuel Oil Residential Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "DFRCPUS": "Distillate Fuel Oil Consumed by the Residential Sector in Thousand Barrels per Day", - "DKEPPUS": "Distillate Fuel Oil Consumption for Electricity Generation, All Sectors in Thousand Barrels", - "ELL9PUS": "Total Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "ELNIPUS": "Electricity Net Imports in Million Kilowatthours", - "ELTCPUS": "Electricity End Use, Total in Million Kilowatthours", - "ESTCBUS": "Electricity Sales to Ultimate Customers in the End-Use Sectors in Trillion Btu", - "EV0CNUS": "Number of legacy charging ports in Number", - "EV1CNUS": "Number of level 1 charging ports in Number", - "EVCHNUS": "Total number of ports in Number", - "EVNOPUS": "Number of locations with non-networked ports only in Number", - "EVPVPUS": "Number of locations with private ports only in Number", - "GEFFBUS": "Geothermal Energy Consumption, Fossil Fuel Equivalent in Trillion Btu", - "GEGBPUS": "Geothermal, Net Summer Capacity in Million Kilowatts", - "GEI9PUS": "Geothermal Industrial Sector, Net Summer Capacity in Million Kilowatts", - "HLACBUS": "Propane Consumed by the Transportation Sector in Trillion Btu", - "HLICEUS": "HGL Industrial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "HPC9SUS": "Hydroelectric Pumped Storage Commercial Sector Generating Units, Usage Factor in Percent", - "HPETPUS": "Electricity Net Generation From Hydroelectric Pumped Storage, All Sectors in Million Kilowatthours", - "HPL9PUS": "Hydroelectric Pumped Storage Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "HVCASUS": "Hydroelectric Generating Units, Capacity Factor in Percent", - "JFACPUS": "Jet Fuel Consumed by the Transportation Sector in Thousand Barrels per Day", - "JFROPUS": "Jet Fuel Refinery and Blender Net Production in Thousand Barrels per Day", - "KSCCBUS": "Kerosene Consumed by the Commercial Sector in Trillion Btu", - "KSTCEUS": "Kerosene CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "LNIMPAG": "Natural Gas Imports from Algeria in Billion Cubic Feet", - "LNIMPOT": "Natural Gas Imports from Other Countries in Billion Cubic Feet", - "LNIMPYE": "Natural Gas Imports from Yemen in Billion Cubic Feet", - "LUTCPUS": "Lubricants Product Supplied in Thousand Barrels per Day", - "MGUCUUS": "All Grades of Gasoline, U.S. City Average Retail Price in Dollars per Gallon Including Taxes", - "MMCCEUS": "Motor Gasoline, Excluding Ethanol, Commercial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "MMICEUS": "Motor Gasoline, Excluding Ethanol, Industrial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "NGEISUS": "Percentage of Electric Power Sector Consumption for Which Price Data Are Available in Percent", - "NGEXBUS": "Natural Gas Exports in Trillion Btu", - "NGEXPUS": "Total Natural Gas Exports in Billion Cubic Feet", - "NGIMPCN": "Natural Gas Imports from Canada in Billion Cubic Feet", - "NGNFBUS": "Natural Gas Non-Combustion Consumption in Quadrillion Btu", - "NGPRBUS": "Natural Gas (Dry) Production in Trillion Btu", - "NGRCPUS": "Natural Gas Consumed by the Residential Sector in Billion Cubic Feet", - "NGSFPUS": "Supplemental Gaseous Fuels in Billion Cubic Feet", - "NLPRBUS": "Natural Gas Plant Liquids Production in Trillion Btu", - "NNRCEUS": "Natural Gas, Excluding Supplemental Gaseous Fuels, Residential Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "NUI9SUS": "Nuclear Industrial Sector Generating Units, Capacity Factor in Percent", - "NYCASUS": "Natural Gas Conventional Steam Plants Generating Units, Capacity Factor in Percent", - "OGPFPUS": "Crude Oil Wells, Total Footage Drilled in Thousand Feet", - "OJECBUS": "Other Gases Consumption for Electricity Generation and Useful Thermal Output, All Sectors in Trillion Btu", - "OLRIPUS": "Other Liquids Refinery and Blender Net Inputs in Thousand Barrels per Day", - "PAC9SUS": "Petroleum Commercial Sector Generating Units, Capacity Factor in Percent", - "PACASUS": "Petroleum Generating Units, Capacity Factor in Percent", - "PAEXPMX": "Petroleum Exports to Mexico in Thousand Barrels per Day", - "PAI1PUS": "Petroleum Consumption for Electricity Generation, Industrial Sector in Thousand Barrels", - "PAIMPBZ": "Petroleum Imports From Brazil in Thousand Barrels per Day", - "PAIMPEN": "Petroleum Imports from Ecuador in Thousand Barrels per Day", - "PANIPUS": "Petroleum Net Imports in Thousand Barrels per Day", - "PATCBUS": "Total Petroleum Products Supplied in Trillion Btu", - "PATWPUS": "Wells Drilled, Crude Oil in Number", - "PCEIMUS": "Petroleum Coke Consumption for Electricity Generation and Useful Thermal Output, Electric Power Sector in Thousand Short Tons", - "PCICBUS": "Petroleum Coke Consumed by the Industrial Sector in Trillion Btu", - "PCNFBUS": "Petroleum Coke Non-Combustion Consumption in Quadrillion Btu", - "PCTCBUS": "Petroleum Coke Product Supplied in Trillion Btu", - "PCTCEUS": "Petroleum Coke CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "PFNFPUS": "Petrochemical Feedstocks Non-Combustion Consumption in Thousand Barrels per Day", - "PTEIPUS": "Total Petroleum Consumption for Electricity Generation and Useful Thermal Output, Electric Power Sector in Thousand Barrels", - "PZICPUS": "Propane/Propylene Consumed by the Industrial Sector in Thousand Barrels per Day", - "RADMUUS": "Average Refiner Acquisition Cost of Crude Oil, Domestic in Dollars per Barrel", - "RBTCUUS": "Average Refiner Price of Residual Fuel Oil, Sulfur Content Less Than or Equal to 1 Percent, Sales to End Users in Dollars per Gallon Excluding Taxes", - "RECCBUS": "Total Renewable Energy Consumed by the Commercial Sector in Trillion Btu", - "RRRTUUS": "Regular Motor Gasoline, Reformulated Gasoline Areas, Average Retail Price in Dollars per Gallon Including Taxes", - "SHI9SUS": "Solar Thermal Industrial Sector Generating Units, Capacity Factor in Percent", - "SOCCBUS": "Solar Energy Consumed by the Commercial Sector in Trillion Btu", - "SOEGBUS": "Utility-Scale Solar Energy Consumption for Electricity: Electric Power Sector in Trillion Btu", - "TEIMBUS": "Total Primary Energy Imports in Trillion Btu", - "TEIMVUS": "Energy Imports in Million Dollars", - "TEPRBUS": "Total Primary Energy Production in Trillion Btu", - "TESSBUS": "Total Energy Consumed by the End-Use-Sectors in Trillion Btu", - "WDEGPUS": "Electricity Net Generation From Wood, Electric Power Sector in Million Kilowatthours", - "WDL9PUS": "Wood Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "WDRCBUS": "Wood Energy Consumed by the Residential Sector in Trillion Btu", - "WSC5PUS": "Electricity Net Generation From Waste, Commercial Sector in Million Kilowatthours", - "WSEIBUS": "Waste Consumption for Electricity Generation and Useful Thermal Output, Electric Power Sector in Trillion Btu", - "WSTCEUS": "Biomass Waste CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "WYCASUS": "Wind Generating Units, Capacity Factor in Percent", - "WYETPUS": "Electricity Net Generation From Wind, All Sectors in Million Kilowatthours", - "WYFFBUS": "Wind Energy Consumption, Fossil Fuel Equivalent in Trillion Btu", - "WYI9SUS": "Wind Industrial Sector Generating Units, Capacity Factor in Percent", - "ZWCDPC2": "Cooling Degree-Days, Middle Atlantic in Number", - "ZWCDPC4": "Cooling Degree-Days, West North Central in Number", - "ZWHDPC8": "Heating Degree-Days, Mountain in Number", - "ARICPUS": "Asphalt and Road Oil Consumed by the Industrial Sector in Thousand Barrels per Day", - "ARNFPUS": "Asphalt & Road Oil Non-Combustion Consumption in Thousand Barrels per Day", - "ARTCPUS": "Asphalt and Road Oil Product Supplied in Thousand Barrels per Day", - "BDSCPUS": "Biodiesel Stock Change in Thousand Barrels", - "BDTCPUS": "Biodiesel Consumption in Thousand Barrels", - "BFLCBUS": "Biomass Losses and Co-products in the Industrial Sector in Trillion Btu", - "BMC9SUS": "Biomass Commercial Sector Generating Units, Capacity Factor in Percent", - "BML9SUS": "Biomass Electric Power Sector Generating Units, Capacity Factor in Percent", - "BMTCEUS": "Biomass CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "BOLCBUS": "Other Biofuels Losses and Co-products in Trillion Btu", - "BOTCBUS": "Other Biofuels Consumption in Trillion Btu", - "CLC9SUS": "Coal Commercial Sector Generating Units, Capacity Factor in Percent", - "CLCASUS": "Coal Generating Units, Capacity Factor in Percent", - "CLEIEUS": "Coal Electric Power Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "CLL1PUS": "Coal Consumption for Electricity Generation, Electric Power Sector in Thousand Short Tons", - "CLL9PUS": "Coal Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "CLSDPUS": "Coal Stocks, Producers and Distributors, End of Period in Thousand Short Tons", - "COIMUUK": "Average Landed Cost of Crude Oil Imports From United Kingdom in Dollars per Barrel", - "CYC9SUS": "Natural Gas Combined Cycle Plants Commercial Sector Generating Units, Capacity Factor in Percent", - "DFACPUS": "Distillate Fuel Oil Consumed by the Transportation Sector in Thousand Barrels per Day", - "DFEXPUS": "Distillate Fuel Oil Exports in Thousand Barrels per Day", - "DFONUUS": "On-Highway Diesel Fuel Average Price in Dollars per Gallon Including Taxes", - "DFTCBUS": "Distillate Fuel Oil Product Supplied in Trillion Btu", - "DSWHUUS": "Average Refiner Price of No. 2 Diesel Fuel for Resale in Dollars per Gallon Excluding Taxes", - "ELEGPUS": "Electricity Net Generation Total (including from sources not shown), Electric Power Sector in Million Kilowatthours", - "EMFDBUS": "Fuel Ethanol, Excluding Denaturant, Feedstock in Trillion Btu", - "ENTCBUS": "Fuel Ethanol Consumption in Trillion Btu", - "ESACBUS": "Electricity Sales to Ultimate Customers in the Transportation Sector in Trillion Btu", - "ESCMUUS": "Average Price of Electricity to Ultimate Customers, Commercial in Cents per Kilowatthour, Including Taxes", - "EVDCNUS": "Number of DC fast charging ports in Number", - "FFGBPUS": "Fossil Fuels, Net Summer Capacity in Million Kilowatts", - "GEI9SUS": "Geothermal Industrial Sector Generating Units, Capacity Factor in Percent", - "HLICBUS": "Total Hydrocarbon Gas Liquids Consumed by the Industrial Sector in Trillion Btu", - "HLROPUS": "Total Hydrocarbon Gas Liquids Refinery and Blender Net Production in Thousand Barrels per Day", - "HPI9SUS": "Hydroelectric Pumped Storage Industrial Sector Generating Units, Usage Factor in Percent", - "HVCCBUS": "Conventional Hydroelectric Power Consumed by the Commercial Sector in Trillion Btu", - "HVI9PUS": "Conventional Hydroelectric Power Industrial Sector, Net Summer Capacity in Million Kilowatts", - "KSICBUS": "Kerosene Consumed by the Industrial Sector in Trillion Btu", - "KSRCBUS": "Kerosene Consumed by the Residential Sector in Trillion Btu", - "KSRCPUS": "Kerosene Consumed by the Residential Sector in Thousand Barrels per Day", - "LNIMPQA": "Natural Gas Imports from Qatar in Billion Cubic Feet", - "LNIMPUA": "Natural Gas Imports from United Arab Emirates in Billion Cubic Feet", - "LUICEUS": "Lubricants Industrial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "LUTCEUS": "Lubricants CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "MGICBUS": "Motor Gasoline Consumed by the Industrial Sector in Trillion Btu", - "MGIMPUS": "Finished Motor Gasoline Imports in Thousand Barrels per Day", - "MMTCEUS": "Motor Gasoline, Excluding Ethanol, CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "NGC5PUS": "Electricity Net Generation From Natural Gas, Commercial Sector in Million Kilowatthours", - "NGC9PUS": "Natural Gas Commercial Sector, Net Summer Capacity in Million Kilowatts", - "NGEIUUS": "Average Natural Gas Price, Electric Power Sector in Dollars per Thousand Cubic Feet", - "NGEPPUS": "Natural Gas Consumption for Electricity Generation, All Sectors in Billion Cubic Feet", - "NGIMBUS": "Natural Gas Imports in Trillion Btu", - "NGINSUS": "Percentage of Industrial Sector Consumption for Which Price Data Are Available in Percent", - "NGMPPUS": "Natural Gas Marketed Production (Wet) in Billion Cubic Feet", - "NGPRPUS": "Natural Gas Production (Dry) in Billion Cubic Feet", - "NGRCAUS": "Average Cost of Residential Natural Gas in Real (1982-1984) Dollars per Million Btu", - "NGRCSUS": "Percentage of Residential Sector Consumption for Which Price Data Are Available in Percent", - "NGRCUUS": "Average Natural Gas Price, Delivered to Consumers, Residential in Dollars per Thousand Cubic Feet", - "NNICBUS": "Natural Gas Consumed by the Industrial Sector (Excluding Supplemental Gaseous Fuels) in Trillion Btu", - "NNRCBUS": "Natural Gas Consumed by the Residential Sector (Excluding Supplemental Gaseous Fuels) in Trillion Btu", - "NUC9SUS": "Nuclear Commercial Sector Generating Units, Capacity Factor in Percent", - "NXWSPUS": "Natural Gas Storage Activity, Withdrawals in Billion Cubic Feet", - "OGDRPUS": "Crude Oil and Natural Gas Rotary Rigs in Operation, Directional Trajectory in Number of Rigs", - "OGHRPUS": "Crude Oil and Natural Gas Rotary Rigs in Operation, Horizontal Trajectory in Number of Rigs", - "OGTFPUS": "Crude Oil, Natural Gas, and Dry Wells, Total Footage Drilled in Thousand Feet", - "OJEGPUS": "Electricity Net Generation From Other Gases, Electric Power Sector in Million Kilowatthours", - "OPEXPUS": "Other Petroleum Products Exports in Thousand Barrels per Day", - "OTI1BUS": "Other Consumption for Electricity Generation, Industrial Sector in Trillion Btu", - "OTNFBUS": "Other Petroleum Non-Combustion Consumption in Quadrillion Btu", - "PACCBUS": "Total Petroleum Consumed by the Commercial Sector in Trillion Btu", - "PAEXPCH": "Petroleum Exports to China in Thousand Barrels per Day", - "PAEXPIH": "Petroleum Exports to India in Thousand Barrels per Day", - "PAGBPUS": "Petroleum, Net Summer Capacity in Million Kilowatts", - "PAGLPUS": "Petroleum Processing Gain in Thousand Barrels per Day", - "PAICBUS": "Total Petroleum Consumed by the Industrial Sector in Trillion Btu", - "PAIMPAG": "Petroleum Imports From Algeria in Thousand Barrels per Day", - "PAIMPNO": "Petroleum Imports From Norway in Thousand Barrels per Day", - "PAIMPSA": "Petroleum Imports From Saudi Arabia in Thousand Barrels per Day", - "PANFBUS": "Total Petroleum Non-Combustion Consumption in Quadrillion Btu", - "PANQSUS": "Petroleum Net Imports as Share of Products Supplied in Percent", - "PCCCBUS": "Petroleum Coke Consumed by the Commercial Sector in Trillion Btu", - "PCNFPUS": "Petroleum Coke Non-Combustion Consumption in Thousand Barrels per Day", - "PCTCPUS": "Petroleum Coke Product Supplied in Thousand Barrels per Day", - "PFNFBUS": "Petrochemical Feedstocks Non-Combustion Consumption in Quadrillion Btu", - "PMACBUS": "Petroleum Consumed by the Transportation Sector (Excluding Biofuels) in Trillion Btu", - "PMICBUS": "Petroleum Consumed by the Industrial Sector (Excluding Biofuels) in Trillion Btu", - "PQTCBUS": "Propane Product Supplied in Trillion Btu", - "RFECPUS": "Residual Fuel Oil Consumption for Electricity Generation and Useful Thermal Output, All Sectors in Thousand Barrels", - "RFEIBUS": "Residual Fuel Oil Consumed by the Electric Power Sector in Trillion Btu", - "RFICPUS": "Residual Fuel Oil Consumed by the Industrial Sector in Thousand Barrels per Day", - "SODTBUS": "Small-Scale Solar Energy Consumption: Total in Trillion Btu", - "SOI5BUS": "Utility-Scale Solar Energy Consumption for Electricity: Industrial Sector in Trillion Btu", - "SOI5PUS": "Utility-Scale Solar Electricity Net Generation: Industrial Sector in Million Kilowatthours", - "SOI7PUS": "Small-Scale Solar Photovoltaic Generation: Industrial Sector in Million Kilowatthours", - "SOICBUS": "Solar Energy Consumed by the Industrial Sector in Trillion Btu", - "SOR7BUS": "Small-Scale Solar Energy Consumption for Electricity: Residential Sector in Trillion Btu", - "SPC9SUS": "Solar Photovoltaic Commercial Sector Generating Units, Capacity Factor in Percent", - "TEEXBUS": "Total Primary Energy Exports in Trillion Btu", - "TENFBUS": "Total Fossil Fuels Non-Combustion Consumption in Quadrillion Btu", - "TETXBUS": "Total Primary Energy Consumed by the End-Use Sectors in Trillion Btu", - "TMIMVUS": "Total Merchandise Imports in Million Dollars", - "TNACBUS": "End-Use Energy Consumed by the Transportation Sector in Trillion Btu", - "TNICBUS": "End-Use Energy Consumed by the Industrial Sector in Trillion Btu", - "TXICBUS": "Total Primary Energy Consumed by the Industrial Sector in Trillion Btu", - "VTTWPUS": "Crude Oil, Natural Gas, and Dry Wells Drilled, Vertical Trajectory in Number", - "WCDOPUS": "Waste Coal Supplied in Thousand Short Tons", - "WDI5PUS": "Electricity Net Generation From Wood, Industrial Sector in Million Kilowatthours", - "WDICBUS": "Wood Energy Consumed by the Industrial Sector in Trillion Btu", - "WDL1BUS": "Wood Consumption for Electricity Generation, Electric Power Sector in Trillion Btu", - "WSTCBUS": "Waste Energy Consumption in Trillion Btu", - "WYI9PUS": "Wind Industrial Sector, Net Summer Capacity in Million Kilowatts", - "ZWCDPC3": "Cooling Degree-Days, East North Central in Number", - "ZWHDPC3": "Heating Degree-Days, East North Central in Number", - "ZWHDPC7": "Heating Degree-Days, West South Central in Number", - "B1PSPUS": "Renewable Diesel Fuel Stocks in Thousand Barrels", - "BDIMPUS": "Biodiesel Imports in Thousand Barrels", - "BDLCBUS": "Biodiesel Losses and Co-products in Trillion Btu", - "BDPRMUS": "Biodiesel Production in Million Gallons", - "BDTCEUS": "Biodiesel CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "BMCCBUS": "Total Biomass Energy Consumed by the Commercial Sector in Trillion Btu", - "BOACBUS": "Other Biofuels Consumed by the Transportation Sector in Trillion Btu", - "BOTCPUS": "Other Biofuels Consumption in Thousand Barrels", - "BTC9SUS": "Battery Storage Commercial Sector Generating Units, Usage Factor in Percent", - "BTCASUS": "Battery Storage Generating Units, Usage Factor in Percent", - "BTI9PUS": "Battery Storage Industrial Sector, Net Summer Capacity in Million Kilowatts", - "CLACEUS": "Coal Transportation Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "CLEXBUS": "Coal Exports in Trillion Btu", - "CLI4PUS": "Coal Consumed by the Other Industrial Sector, Non-CHP in Thousand Short Tons", - "CLI5PUS": "Electricity Net Generation From Coal, Industrial Sector in Million Kilowatthours", - "CLNIBUS": "Coal Net Imports in Quadrillion Btu", - "CLPRPUS": "Coal Production in Thousand Short Tons", - "CLRCEUS": "Coal Residential Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "CLSIPUS": "Coal Stocks, Industrial Sector, Total, End of Period in Thousand Short Tons", - "CLSKPUS": "Coal Stocks, Industrial Sector, Coke Plants, End of Period in Thousand Short Tons", - "COPSPUS": "Crude Oil Stocks, Total, End of Period in Million Barrels", - "COQIPUS": "Crude Oil Imports, Strategic Petroleum Reserve in Thousand Barrels per Day", - "DFACBUS": "Distillate Fuel Oil Consumed by the Transportation Sector in Trillion Btu", - "DFCCPUS": "Distillate Fuel Oil Consumed by the Commercial Sector in Thousand Barrels per Day", - "DFRCBUS": "Distillate Fuel Oil Consumed by the Residential Sector in Trillion Btu", - "DKECPUS": "Distillate Fuel Oil Consumption for Electricity Generation and Useful Thermal Output, All Sectors in Thousand Barrels", - "DKEIBUS": "Distillate Fuel Oil Consumed by the Electric Power Sector in Trillion Btu", - "DKL1PUS": "Distillate Fuel Oil Consumption for Electricity Generation, Electric Power Sector in Thousand Barrels", - "ELEXBUS": "Electricity Exports in Trillion Btu", - "EMTCBUS": "Fuel Ethanol, Excluding Denaturant, Consumption in Trillion Btu", - "ENDNPUS": "Fuel Ethanol Denaturant in Thousand Barrels", - "ENNIPUS": "Fuel Ethanol Net Imports in Thousand Barrels", - "ENPRBUS": "Fuel Ethanol Production in Trillion Btu", - "ESACEUS": "Transportation Share of Electric Power Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "ESCCPUS": "Electricity Sales to Ultimate Customers, Commercial in Million Kilowatthours", - "ESICUUS": "Average Price of Electricity to Ultimate Customers, Industrial in Cents per Kilowatthour, Including Taxes", - "ESRCUUS": "Average Price of Electricity to Ultimate Customers, Residential in Cents per Kilowatthour, Including Taxes", - "EV2CRUS": "Number of level 2 charging ports per location in Number", - "EVNNPUS": "Number of locations with networked and non-networked ports in Number", - "EVNTPUS": "Number of locations with networked ports only in Number", - "FFERDUS": "Average Cost of Fossil Fuel Receipts at Electric Generating Plants in Dollars per Million Btu, Including Taxes", - "FFPRBUS": "Total Fossil Fuels Production in Trillion Btu", - "GEC9SUS": "Geothermal Commercial Sector Generating Units, Capacity Factor in Percent", - "GEEGPUS": "Electricity Net Generation From Geothermal, Electric Power Sector in Million Kilowatthours", - "HLCCBUS": "Propane Consumed by the Commercial Sector in Trillion Btu", - "HLIMPUS": "Total Hydrocarbon Gas Liquids Imports in Thousand Barrels per Day", - "HLNFPUS": "Hydrocarbon Gas Liquids Non-Combustion Consumption in Thousand Barrels per Day", - "HLTCPUS": "Total Hydrocarbon Gas Liquids Product Supplied in Thousand Barrels per Day", - "HPC9PUS": "Hydroelectric Pumped Storage Commercial Sector, Net Summer Capacity in Million Kilowatts", - "HPGBPUS": "Hydroelectric Pumped Storage, Net Summer Capacity in Million Kilowatts", - "HPI9PUS": "Hydroelectric Pumped Storage Industrial Sector, Net Summer Capacity in Million Kilowatts", - "HVC9SUS": "Hydroelectric Commercial Sector Generating Units, Capacity Factor in Percent", - "HVI9SUS": "Hydroelectric Industrial Sector Generating Units, Capacity Factor in Percent", - "HVTCBUS": "Hydroelectric Power Consumption/Production in Trillion Btu", - "JFEXPUS": "Jet Fuel Exports in Thousand Barrels per Day", - "KSICPUS": "Kerosene Consumed by the Industrial Sector in Thousand Barrels per Day", - "KSWHUUS": "Average Refiner Price of Kerosene for Resale in Dollars per Gallon Excluding Taxes", - "LNEXPBZ": "Natural Gas Exports to Brazil in Billion Cubic Feet", - "LNIMPAU": "Natural Gas Imports from Australia in Billion Cubic Feet", - "LOICBUS": "Electrical System Energy Losses Proportioned to the Industrial Sector in Trillion Btu", - "MGACBUS": "Motor Gasoline Consumed by the Transportation Sector in Trillion Btu", - "MGCCPUS": "Motor Gasoline Consumed by the Commercial Sector in Thousand Barrels per Day", - "NGACEUS": "Natural Gas Transportation Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "NGACPUS": "Natural Gas Consumed by the Transportation Sector, Total in Billion Cubic Feet", - "NGC1PUS": "Natural Gas Consumption for Electricity Generation, Commercial Sector in Billion Cubic Feet", - "NGC3PUS": "Natural Gas Consumption for Electricity Generation and Useful Thermal Output, Commercial Sector in Billion Cubic Feet", - "NGI9PUS": "Natural Gas Industrial Sector, Net Summer Capacity in Million Kilowatts", - "NGICPUS": "Natural Gas Consumed by the Industrial Sector, Total in Billion Cubic Feet", - "NGNWPUS": "Natural Gas Net Storage Withdrawals in Billion Cubic Feet", - "NLPRPUS": "Natural Gas Liquids Production in Thousand Barrels per Day", - "NNCCBUS": "Natural Gas Consumed by the Commercial Sector (Excluding Supplemental Gaseous Fuels) in Trillion Btu", - "NTCASUS": "Natural Gas Gas Turbine Plants Generating Units, Capacity Factor in Percent", - "NTI9SUS": "Natural Gas Gas Turbine Plants Industrial Sector Generating Units, Capacity Factor in Percent", - "NUL9PUS": "Nuclear Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "OGNRPOF": "Crude Oil and Natural Gas Rotary Rigs in Operation, Offshore in Number of Rigs", - "OJETPUS": "Electricity Net Generation From Other Gases, All Sectors in Million Kilowatthours", - "OJL1BUS": "Other Gases Consumption for Electricity Generation, Electric Power Sector in Trillion Btu", - "OTEIBUS": "Other Consumption for Electricity Generation and Useful Thermal Output, Electric Power Sector in Trillion Btu", - "PAACPUS": "Total Petroleum Consumed by the Transportation Sector in Thousand Barrels per Day", - "PAC9PUS": "Petroleum Commercial Sector, Net Summer Capacity in Million Kilowatts", - "PAEIBUS": "Total Petroleum Consumed by the Electric Power Sector in Trillion Btu", - "PAEXPSK": "Petroleum Exports to South Korea in Thousand Barrels per Day", - "PAI3PUS": "Petroleum Consumption for Electricity Generation and Useful Thermal Output, Industrial Sector in Thousand Barrels", - "PAIMPMX": "Petroleum Imports From Mexico in Thousand Barrels per Day", - "PAIMPNL": "Petroleum Imports From Netherlands in Thousand Barrels per Day", - "PAIMVUS": "Petroleum Imports in Million Dollars", - "PAL9PUS": "Petroleum Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "PAPRPAK": "Crude Oil Production, Alaska in Thousand Barrels per Day", - "PAPSPUS": "Petroleum Stocks, United States, End of Period in Million Barrels", - "PAROPUS": "Total Petroleum Refinery and Blender Net Production in Thousand Barrels per Day", - "PCL1MUS": "Petroleum Coke Consumption for Electricity Generation, Electric Power Sector in Thousand Short Tons", - "PYICPUS": "Propylene Consumed by the Industrial Sector in Thousand Barrels per Day", - "PYTCPUS": "Propylene Product Supplied in Thousand Barrels per Day", - "REGBPUS": "Renewable Energy, Net Summer Capacity in Million Kilowatts", - "REICBUS": "Total Renewable Energy Consumed by the Industrial Sector in Trillion Btu", - "RFACEUS": "Residual Fuel Oil Transportation Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "RFEXPUS": "Residual Fuel Oil Exports in Thousand Barrels per Day", - "RFIMPUS": "Residual Fuel Oil Imports in Thousand Barrels per Day", - "RFTCBUS": "Residual Fuel Oil Product Supplied in Trillion Btu", - "ROTCUUS": "Average Refiner Price of Residual Fuel Oil, Sulfur Content Greater Than 1 Percent, Sales to End Users in Dollars per Gallon Excluding Taxes", - "ROWHUUS": "Average Refiner Price of Residual Fuel Oil, Sulfur Content Greater Than 1 Percent, Sales for Resale in Dollars per Gallon Excluding Taxes", - "RQNIBUS": "Petroleum Products, Excluding Biofuels, Net Imports in Quadrillion Btu", - "SNNFBUS": "Special Naphthas Non-Combustion Consumption in Quadrillion Btu", - "SOC5PUS": "Utility-Scale Solar Electricity Net Generation: Commercial Sector in Million Kilowatthours", - "SORCBUS": "Solar Energy Consumed by the Residential Sector in Trillion Btu", - "SOT5BUS": "Utility-Scale Solar Energy Consumption: Total in Trillion Btu", - "SOT5PUS": "Utility-Scale Solar Electricity Net Generation: Total in Million Kilowatthours", - "SOT7BUS": "Small-Scale Solar Energy Consumption for Electricity: Total in Trillion Btu", - "SPCASUS": "Solar Photovoltaic Generating Units, Capacity Factor in Percent", - "TEACBUS": "Total Energy Consumed by the Transportation Sector in Trillion Btu", - "TENIVUS": "Energy Balance in Million Dollars", - "TERCEUS": "Total Energy Residential Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "TETCBUS": "Primary Energy Consumption Total in Trillion Btu", - "WDEIBUS": "Wood Consumption for Electricity Generation and Useful Thermal Output, Electric Power Sector in Trillion Btu", - "WDI3BUS": "Wood Consumption for Electricity Generation and Useful Thermal Output, Industrial Sector in Trillion Btu", - "WDPRBUS": "Wood Energy Production in Trillion Btu", - "WDTCEUS": "Wood CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "WSECBUS": "Waste Consumption for Electricity Generation and Useful Thermal Output, All Sectors in Trillion Btu", - "WSEGPUS": "Electricity Net Generation From Waste, Electric Power Sector in Million Kilowatthours", - "WSI3BUS": "Waste Consumption for Electricity Generation and Useful Thermal Output, Industrial Sector in Trillion Btu", - "WSI5PUS": "Electricity Net Generation From Waste, Industrial Sector in Million Kilowatthours", - "WSI9PUS": "Waste Industrial Sector, Net Summer Capacity in Million Kilowatts", - "WSL1BUS": "Waste Consumption for Electricity Generation, Electric Power Sector in Trillion Btu", - "WYCCBUS": "Wind Energy Consumed by the Commercial Sector in Trillion Btu", - "WYGBPUS": "Wind, Net Summer Capacity in Million Kilowatts", - "ZWCDPC1": "Cooling Degree-Days, New England in Number", - "ZWHDPC1": "Heating Degree-Days, New England in Number", - "ARNFBUS": "Asphalt & Road Oil Non-Combustion Consumption in Quadrillion Btu", - "BDPRBUS": "Biodiesel Production in Trillion Btu", - "BDPSPUS": "Biodiesel Stocks, End of Period in Thousand Barrels", - "BFIMBUS": "Biomass Imports in Trillion Btu", - "BMTCBUS": "Total Biomass Energy Consumption in Trillion Btu", - "BOTCMUS": "Other Biofuels Consumption in Million Gallons", - "CCIMBUS": "Coal Coke Imports in Trillion Btu", - "CCNIBUS": "Coal Coke Net Imports in Quadrillion Btu", - "CLC3PUS": "Coal Consumption for Electricity Generation and Useful Thermal Output, Commercial Sector in Thousand Short Tons", - "CLC4PUS": "Coal Consumed by the Commercial Sector, Other in Thousand Short Tons", - "CLCCPUS": "Coal Consumed by the Commercial Sector, Total in Thousand Short Tons", - "CLECPUS": "Coal Consumption for Electricity Generation and Useful Thermal Output, All Sectors in Thousand Short Tons", - "CLETPUS": "Electricity Net Generation From Coal, All Sectors in Million Kilowatthours", - "CLEXPUS": "Coal Exports in Thousand Short Tons", - "CLI9PUS": "Coal Industrial Sector, Net Summer Capacity in Million Kilowatts", - "CLSHPUS": "Coal Stocks, Residential and Commercial Sectors, End of Period in Thousand Short Tons", - "CODPUUS": "Average Crude Oil Domestic First Purchase Price in Dollars per Barrel", - "COFMUNI": "Average Free on Board Cost of Crude Oil Imports From Nigeria in Dollars per Barrel", - "COFMUSA": "Average Free on Board Cost of Crude Oil Imports From Saudi Arabia in Dollars per Barrel", - "COIMUMX": "Average Landed Cost of Crude Oil Imports From Mexico in Dollars per Barrel", - "COIMUVE": "Average Landed Cost of Crude Oil Imports From Venezuela in Dollars per Barrel", - "D2WHUUS": "Average Refiner Price of No. 2 Fuel Oil for Resale in Dollars per Gallon Excluding Taxes", - "DFCCBUS": "Distillate Fuel Oil Consumed by the Commercial Sector in Trillion Btu", - "DFICEUS": "Distillate Fuel Oil Industrial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "DFTCPUS": "Distillate Fuel Oil Product Supplied in Thousand Barrels per Day", - "DMTCEUS": "Distillate Fuel Oil, Excluding Biodiesel, CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "ELEXPUS": "Electricity Exports in Million Kilowatthours", - "ESCCBUS": "Electricity Sales to Ultimate Customers in the Commercial Sector in Trillion Btu", - "ESICBUS": "Electricity Sales to Ultimate Customers in the Industrial Sector in Trillion Btu", - "ESTCUUS": "Average Price of Electricity to Ultimate Customers, Total in Cents per Kilowatthour, Including Taxes", - "FFACBUS": "Total Fossil Fuels Consumed by the Transportation Sector in Trillion Btu", - "FFICBUS": "Total Fossil Fuels Consumed by the Industrial Sector in Trillion Btu", - "GEL9SUS": "Geothermal Electric Power Sector Generating Units, Capacity Factor in Percent", - "HLCCPUS": "Propane Consumed by the Commercial Sector in Thousand Barrels per Day", - "HLTCBUS": "Total Hydrocarbon Gas Liquids Product Supplied in Trillion Btu", - "HPEGPUS": "Electricity Net Generation From Hydroelectric Pumped Storage, Electric Power Sector in Million Kilowatthours", - "HPL9SUS": "Hydroelectric Pumped Storage Electric Power Sector Generating Units, Usage Factor in Percent", - "HVC9PUS": "Conventional Hydroelectric Power Commercial Sector, Net Summer Capacity in Million Kilowatts", - "JFACBUS": "Jet Fuel Consumed by the Transportation Sector in Trillion Btu", - "JFTCEUS": "Jet Fuel CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "JFTCPUS": "Jet Fuel Product Supplied in Thousand Barrels per Day", - "KSRCEUS": "Kerosene Residential Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "KSTCUUS": "Average Refiner Price of Kerosene to End Users in Dollars per Gallon Excluding Taxes", - "LNEXPUK": "Natural Gas Exports to United Kingdom in Billion Cubic Feet", - "LNIMPEY": "Natural Gas Imports from Egypt in Billion Cubic Feet", - "LNIMPNO": "Natural Gas Imports from Norway in Billion Cubic Feet", - "LNIMPTD": "Natural Gas Imports from Trinidad and Tobago in Billion Cubic Feet", - "LUACPUS": "Lubricants Consumed by the Transportation Sector in Thousand Barrels per Day", - "MGCCBUS": "Motor Gasoline Consumed by the Commercial Sector in Trillion Btu", - "MGROPUS": "Finished Motor Gasoline Refinery and Blender Net Production in Thousand Barrels per Day", - "MGTCAUS": "Average Cost of Motor Gasoline in Real (1982-1984) Dollars per Million Btu", - "NGACBUS": "Natural Gas Consumed by the Transportation Sector (Excluding Supplemental Gaseous Fuels) in Trillion Btu", - "NGCCPUS": "Natural Gas Consumed by the Commercial Sector in Billion Cubic Feet", - "NGELPUS": "NGPL Production in Billion Cubic Feet", - "NGGBPUS": "Natural Gas, Net Summer Capacity in Million Kilowatts", - "NGI4PUS": "Natural Gas Consumed by the Other Industrial Sector, Non-CHP in Billion Cubic Feet", - "NGIMPUS": "Natural Gas Imports in Billion Cubic Feet", - "NGNIBUS": "Natural Gas Net Imports in Quadrillion Btu", - "NGPZPUS": "Natural Gas Consumed by the Transportation Sector, Pipelines and Distribution in Billion Cubic Feet", - "NGVHUUS": "Average Natural Gas Transportation Sector Price in Dollars per Thousand Cubic Feet", - "NGWPUUS": "Average Natural Gas Price, Wellhead in Dollars per Thousand Cubic Feet", - "NNCCEUS": "Natural Gas, Excluding Supplemental Gaseous Fuels, Commercial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "NUC9PUS": "Nuclear Commercial Sector, Net Summer Capacity in Million Kilowatts", - "NUEGPUS": "Electricity Net Generation From Nuclear Electric Power, Electric Power Sector in Million Kilowatthours", - "NUETBUS": "Nuclear Electric Power Consumption/Production in Trillion Btu", - "NUETSUS": "Nuclear Share of Electricity Net Generation in Percent", - "NXSCPUS": "Natural Gas Storage Activity, Net in Billion Cubic Feet", - "NYL9SUS": "Natural Gas Conventional Steam Plants Electric Power Sector Generating Units, Capacity Factor in Percent", - "OGGFPUS": "Natural Gas Wells, Total Footage Drilled in Thousand Feet", - "OGNRPUS": "Crude Oil and Natural Gas Rotary Rigs in Operation, Total in Number of Rigs", - "OGTWPUS": "Crude Oil, Natural Gas, and Dry Wells Drilled, Total in Number", - "OGVFPUS": "Crude Oil, Natural Gas, and Dry Wells, Vertical Trajectory, Total Footage Drilled in Thousand Feet", - "OLEIPUS": "Other Petroleum Liquids Consumption for Electricity Generation and Useful Thermal Output, Electric Power Sector in Thousand Barrels", - "OLL1PUS": "Other Petroleum Liquids Consumption for Electricity Generation, Electric Power Sector in Thousand Barrels", - "OPACPUS": "Other Products Consumed by the Transportation Sector in Thousand Barrels per Day", - "OPIMPUS": "Other Petroleum Products Imports in Thousand Barrels per Day", - "OTL1BUS": "Other Consumption for Electricity Generation, Electric Power Sector in Trillion Btu", - "PAACBUS": "Total Petroleum Consumed by the Transportation Sector in Trillion Btu", - "PAC1PUS": "Petroleum Consumption for Electricity Generation, Commercial Sector in Thousand Barrels", - "PAEIZUS": "Total Petroleum Consumed by the Electric Power Sector in Thousand Barrels per Day", - "PAEXPSN": "Petroleum Exports to Singapore in Thousand Barrels per Day", - "PAI9PUS": "Petroleum Industrial Sector, Net Summer Capacity in Million Kilowatts", - "PAIMPKU": "Petroleum Imports From Kuwait in Thousand Barrels per Day", - "PAIMPOP": "Petroleum Imports From Total OPEC in Thousand Barrels per Day", - "PAIMPVI": "Petroleum Imports From U.S. Virgin Islands in Thousand Barrels per Day", - "PAIMSPG": "Petroleum Imports From Persian Gulf as Share of Total Imports in Percent", - "PAIQSPG": "Petroleum Imports From Persian Gulf as Share of Products Supplied in Percent", - "PAIQSUS": "Petroleum Imports as Share of Products Supplied in Percent", - "PANFPUS": "Total Petroleum Non-Combustion Consumption in Thousand Barrels per Day", - "PANRPUS": "Crude Oil Rotary Rigs in Operation, Total in Number of Rigs", - "PCEIZUS": "Petroleum Coke Consumed by the Electric Power Sector in Thousand Barrels per Day", - "PCEKMUS": "Petroleum Coke Stocks, Electric Power Sector, End of Period in Thousand Short Tons", - "PMCCEUS": "Petroleum, Excluding Biofuels, Commercial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "PMIMBUS": "Total Petroleum, Excluding Biofuels, Imports in Trillion Btu", - "PMTCBUS": "Petroleum Consumption (Excluding Biofuels) in Trillion Btu", - "PNPRPUS": "Total Petroleum Field Production in Thousand Barrels per Day", - "PQIMPUS": "Propane Imports in Thousand Barrels per Day", - "PUUCUUS": "Unleaded Premium Gasoline, U.S. City Average Retail Price in Dollars per Gallon Including Taxes", - "PYICBUS": "Propylene Consumed by the Industrial Sector in Trillion Btu", - "PYROPUS": "Propylene Refinery and Blender Net Production in Thousand Barrels per Day", - "RACPUUS": "Average Refiner Acquisition Cost of Crude Oil, Composite in Dollars per Barrel", - "REL9PUS": "Renewable Energy Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "RFEKPUS": "Residual Fuel Oil Stocks, Electric Power Sector, End of Period in Thousand Barrels", - "RFICEUS": "Residual Fuel Oil Industrial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "RFTCUUS": "Average Refiner Price of Residual Fuel Oil, Sales to End Users in Dollars per Gallon Excluding Taxes", - "SHC9SUS": "Solar Thermal Commercial Sector Generating Units, Capacity Factor in Percent", - "SHL9SUS": "Solar Thermal Electric Power Sector Generating Units, Capacity Factor in Percent", - "SOT7PUS": "Small-Scale Solar Photovoltaic Generation: Total (All Sectors) in Million Kilowatthours", - "SPI9SUS": "Solar Photovoltaic Industrial Sector Generating Units, Capacity Factor in Percent", - "SPL9SUS": "Solar Photovoltaic Electric Power Sector Generating Units, Capacity Factor in Percent", - "TEEXVUS": "Energy Exports in Million Dollars", - "TEICBUS": "Total Energy Consumed by the Industrial Sector in Trillion Btu", - "TETCEUS": "Total Energy CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "TMEXVUS": "Total Merchandise Exports in Million Dollars", - "TMNIVUS": "Total Merchandise Balance in Million Dollars", - "TXEIBUS": "Total Primary Energy Consumed by the Electric Power Sector in Trillion Btu", - "WDECBUS": "Wood Consumption for Electricity Generation and Useful Thermal Output, All Sectors in Trillion Btu", - "WSC9PUS": "Waste Commercial Sector, Net Summer Capacity in Million Kilowatts", - "ZWCDPC6": "Cooling Degree-Days, East South Central in Number", - "AVTCBUS": "Aviation Gasoline Product Supplied in Trillion Btu", - "AVTCUUS": "Average Refiner Price of Finished Aviation Gasoline to End Users in Dollars per Gallon Excluding Taxes", - "B1PRBUS": "Renewable Diesel Fuel Production in Trillion Btu", - "B1TCMUS": "Renewable Diesel Fuel Consumption in Million Gallons", - "B1TCPUS": "Renewable Diesel Fuel Consumption in Thousand Barrels", - "BDTCBUS": "Biodiesel Consumption in Trillion Btu", - "BMCCEUS": "Biomass Commercial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "BMI9SUS": "Biomass Industrial Sector Generating Units, Capacity Factor in Percent", - "BMPRBUS": "Total Biomass Energy Production in Trillion Btu", - "BTC9PUS": "Battery Storage Commercial Sector, Net Summer Capacity in Million Kilowatts", - "CCEXBUS": "Coal Coke Exports in Trillion Btu", - "CCNIEUS": "Coal Coke Net Imports CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "CLC5PUS": "Electricity Net Generation From Coal, Commercial Sector in Million Kilowatthours", - "CLEIPUS": "Coal Consumption for Electricity Generation and Useful Thermal Output, Electric Power Sector in Thousand Short Tons", - "CLEKPUS": "Coal Stocks, Electric Power Sector, End of Period in Thousand Short Tons", - "CLI1PUS": "Coal Consumption for Electricity Generation, Industrial Sector in Thousand Short Tons", - "CLI3PUS": "Coal Consumption for Electricity Generation and Useful Thermal Output, Industrial Sector in Thousand Short Tons", - "CLICPUS": "Coal Consumed by the Industrial Sector, Total in Thousand Short Tons", - "CLL9SUS": "Coal Electric Power Sector Generating Units, Capacity Factor in Percent", - "CLRCBUS": "Coal Consumed by the Residential Sector in Trillion Btu", - "COFMUPG": "Average Free on Board Cost of Crude Oil Imports From Persian Gulf Nations in Dollars per Barrel", - "COIMUNT": "Average Landed Cost of Crude Oil Imports From All Non-OPEC Countries in Dollars per Barrel", - "CYL9SUS": "Natural Gas Combined Cycle Plants Electric Power Sector Generating Units, Capacity Factor in Percent", - "DFICPUS": "Distillate Fuel Oil Consumed by the Industrial Sector in Thousand Barrels per Day", - "DHTWPUS": "Wells Drilled, Dry in Number", - "DKEIEUS": "Distillate Fuel, Including Kerosene-Type Jet Fuel, Oil Electric Power Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "ELDUPUS": "Electricity Direct Use in Million Kilowatthours", - "EMLCBUS": "Fuel Ethanol, Excluding Denaturant, Losses and Co-products in Trillion Btu", - "EMTCEUS": "Fuel Ethanol, Excluding Denaturant, CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "ENTCPUS": "Fuel Ethanol Consumption in Thousand Barrels", - "ESICEUS": "Industrial Share of Electric Power Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "ESRCEUS": "Residential Share of Electric Power Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "ESVHPUS": "Electric Vehicle Use in Million Kilowatthours", - "FFEIBUS": "Total Fossil Fuels Consumed by the Electric Power Sector in Trillion Btu", - "FFRCBUS": "Total Fossil Fuels Consumed by the Residential Sector in Trillion Btu", - "GEICBUS": "Geothermal Energy Consumed by the Industrial Sector in Trillion Btu", - "HLCCEUS": "HGL Commercial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "HLTCEUS": "Hydrocarbon Gas Liquids CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "HRTWPUS": "Crude Oil, Natural Gas, and Dry Wells Drilled, Horizontal and Directional Trajectory in Number", - "HVGBPUS": "Conventional Hydroelectric Power, Net Summer Capacity in Million Kilowatts", - "HVL9PUS": "Conventional Hydroelectric Power Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "JFTCBUS": "Jet Fuel Product Supplied in Trillion Btu", - "KSCCEUS": "Kerosene Commercial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "LNEXPOT": "Natural Gas Exports to Other Countries in Billion Cubic Feet", - "LUNFPUS": "Lubricants Non-Combustion Consumption in Thousand Barrels per Day", - "MGACPUS": "Motor Gasoline Consumed by the Transportation Sector in Thousand Barrels per Day", - "MGTCBUS": "Motor Gasoline Product Supplied in Trillion Btu", - "NGGWPUS": "Natural Gas Gross Withdrawals in Billion Cubic Feet", - "NGINPUS": "Natural Gas Consumed by the Other Industrial Sector, Total in Billion Cubic Feet", - "NGINUUS": "Average Natural Gas Price, Delivered to Consumers, Industrial in Dollars per Thousand Cubic Feet", - "NGTWPUS": "Wells Drilled, Natural Gas in Number", - "NGWCCUS": "Change in Working Gas From Same Period Previous Year, Percent in Percent", - "NLRIPUS": "Natural Gas Liquids Refinery and Blender Net Inputs in Thousand Barrels per Day", - "NNEIBUS": "Natural Gas Consumed by the Electric Power Sector (Excluding Supplemental Gaseous Fuels) in Trillion Btu", - "NUCASUS": "Nuclear Generating Units, Capacity Factor in Percent", - "NUEGBUS": "Nuclear Electric Power Consumed by the Electric Power Sector in Trillion Btu", - "NUGBPUS": "Nuclear Generating Units, Net Summer Capacity, End of Period in Million Kilowatts", - "NUI9PUS": "Nuclear Industrial Sector, Net Summer Capacity in Million Kilowatts", - "NYI9SUS": "Natural Gas Conventional Steam Plants Industrial Sector Generating Units, Capacity Factor in Percent", - "OJI1BUS": "Other Gases Consumption for Electricity Generation, Industrial Sector in Trillion Btu", - "OJI5PUS": "Electricity Net Generation From Other Gases, Industrial Sector in Million Kilowatthours", - "OPICPUS": "Other Petroleum Products Consumed by the Industrial Sector in Thousand Barrels per Day", - "OPPSPUS": "Other Products Stocks in Million Barrels", - "OPTCEUS": "Other Petroleum Products CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "OPTCPUS": "Other Products Supplied in Thousand Barrels per Day", - "PAAJPUS": "Petroleum Adjustments in Thousand Barrels per Day", - "PAERDUS": "Average Cost of Total Petroleum Receipts at Electric Generating Plants in Dollars per Million Btu, Including Taxes", - "PAEXPJA": "Petroleum Exports to Japan in Thousand Barrels per Day", - "PAEXPOT": "Petroleum Exports to Other Countries in Thousand Barrels per Day", - "PAI9SUS": "Petroleum Industrial Sector Generating Units, Capacity Factor in Percent", - "PAIMPIQ": "Petroleum Imports From Iraq in Thousand Barrels per Day", - "PAIMPRU": "Petroleum Imports From Russia in Thousand Barrels per Day", - "PANIVUS": "Petroleum Balance in Million Dollars", - "PAPRBUS": "Crude Oil Production in Trillion Btu", - "PAPRP48": "Crude Oil Production, 48 States in Thousand Barrels per Day", - "PAPRPUS": "Crude Oil Production, Total in Thousand Barrels per Day", - "PARCBUS": "Total Petroleum Consumed by the Residential Sector in Trillion Btu", - "PARCEUS": "Petroleum Residential Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "PCCCPUS": "Petroleum Coke Consumed by the Commercial Sector in Thousand Barrels per Day", - "PCEIBUS": "Petroleum Coke Consumed by the Electric Power Sector in Trillion Btu", - "PCICPUS": "Petroleum Coke Consumed by the Industrial Sector in Thousand Barrels per Day", - "PMNIBUS": "Total Petroleum, Excluding Biofuels, Net Imports in Quadrillion Btu", - "PQICPUS": "Propane Consumed by the Industrial Sector in Thousand Barrels per Day", - "PQROPUS": "Propane Refinery and Blender Net Production in Thousand Barrels per Day", - "PRWHUUS": "Average Refiner Price of Propane (Consumer Grade) for Resale in Dollars per Gallon Excluding Taxes", - "PZIMPUS": "Propane/Propylene Imports in Thousand Barrels per Day", - "PZTCPUS": "Propane/Propylene Product Supplied in Thousand Barrels per Day", - "REEIBUS": "Total Renewable Energy Consumed by the Electric Power Sector in Trillion Btu", - "REPRBUS": "Total Renewable Energy Production in Trillion Btu", - "RETCBUS": "Total Renewable Energy Consumption in Trillion Btu", - "RFEIPUS": "Residual Fuel Oil Consumption for Electricity Generation and Useful Thermal Output, Electric Power Sector in Thousand Barrels", - "RFEIZUS": "Residual Fuel Oil Consumed by the Electric Power Sector in Thousand Barrels per Day", - "RFROPUS": "Residual Fuel Oil Refinery and Blender Net Production in Thousand Barrels per Day", - "RLUCUUS": "Leaded Regular Gasoline, U.S. City Average Retail Price in Dollars per Gallon Including Taxes", - "RMRTUUS": "Regular Motor Gasoline, All Areas, Average Retail Price in Dollars per Gallon Including Taxes", - "RUUCUUS": "Unleaded Regular Gasoline, U.S. City Average Retail Price in Dollars per Gallon Including Taxes", - "SNNFPUS": "Special Naphthas Non-Combustion Consumption in Thousand Barrels per Day", - "SOGBPUS": "Solar, Net Summer Capacity in Million Kilowatts", - "SOR7PUS": "Small-Scale Solar Photovoltaic Generation: Residential Sector in Million Kilowatthours", - "SOTCBUS": "Solar/PV Energy Consumption/Production in Trillion Btu", - "SOTEPUS": "Solar Electricity Net Generation in Million Kilowatthours", - "TECCBUS": "Total Energy Consumed by the Commercial Sector in Trillion Btu", - "TERCBUS": "Total Energy Consumed by the Residential Sector in Trillion Btu", - "TXEIEUS": "Total Energy Electric Power Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "WDCCBUS": "Wood Energy Consumed by the Commercial Sector in Trillion Btu", - "WSC1BUS": "Waste Consumption for Electricity Generation, Commercial Sector in Trillion Btu", - "WSEPBUS": "Waste Consumption for Electricity Generation, All Sectors in Trillion Btu", - "WSETPUS": "Electricity Net Generation From Waste, All Sectors in Million Kilowatthours", - "WSICBUS": "Waste Energy Consumed by the Industrial Sector in Trillion Btu", - "ZWCDPC7": "Cooling Degree-Days, West South Central in Number", - "ZWCDPC9": "Cooling Degree-Days, Pacific in Number", - "ZWHDPC2": "Heating Degree-Days, Middle Atlantic in Number", - "ZWHDPC6": "Heating Degree-Days, East South Central in Number", - "AVWHUUS": "Average Refiner Price of Finished Aviation Gasoline for Resale in Dollars per Gallon Excluding Taxes", - "B1ACBUS": "Renewable Diesel Fuel Consumed by the Transportation Sector in Trillion Btu", - "B1FDBUS": "Renewable Diesel Fuel Feedstock in Trillion Btu", - "BDPRPUS": "Biodiesel Production in Thousand Barrels", - "BMCASUS": "Biomass Generating Units, Capacity Factor in Percent", - "BMEIEUS": "Biomass Electric Power Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "BOPRMUS": "Other Biofuels Production in Million Gallons", - "BOSCPUS": "Other Biofuels Stock Change in Thousand Barrels", - "BTGBPUS": "Battery Storage, Net Summer Capacity in Million Kilowatts", - "BTI9SUS": "Battery Storage Industrial Sector Generating Units, Usage Factor in Percent", - "CLC1PUS": "Coal Consumption for Electricity Generation, Commercial Sector in Thousand Short Tons", - "CLCCEUS": "Coal Commercial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "CLEGPUS": "Electricity Net Generation From Coal, Electric Power Sector in Million Kilowatthours", - "CLNFPUS": "Coal Non-Combustion Consumption in Thousand Short Tons", - "CLTCPUS": "Coal Consumption, Total in Thousand Short Tons", - "COEXPUS": "Crude Oil Exports in Thousand Barrels per Day", - "COFMUAQ": "Average Free on Board Cost of Crude Oil Imports From Angola in Dollars per Barrel", - "COFMUOP": "Average Free on Board Cost of Crude Oil Imports From All OPEC Countries in Dollars per Barrel", - "COFMUUK": "Average Free on Board Cost of Crude Oil Imports From United Kingdom in Dollars per Barrel", - "COIMUCN": "Average Landed Cost of Crude Oil Imports From Canada in Dollars per Barrel", - "COIMUPG": "Average Landed Cost of Crude Oil Imports From Persian Gulf Nations in Dollars per Barrel", - "CORIPUS": "Crude Oil Refinery and Blender Net Input in Thousand Barrels per Day", - "COSXPUS": "Crude Oil Stocks, Non-Strategic Petroleum Reserve, End of Period in Million Barrels", - "D2TCUUS": "Average Refiner Price of No. 2 Fuel Oil to End Users in Dollars per Gallon Excluding Taxes", - "DFEKPUS": "Distillate Fuel Oil Stocks, Electric Power Sector, End of Period in Thousand Barrels", - "DKERDUS": "Average Cost of Distillate Fuel Receipts at Electric Generating Plants in Dollars per Million Btu, Including Taxes", - "DMACEUS": "Distillate Fuel Oil, Excluding Biodiesel, Transportation Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "ELIMPUS": "Electricity Imports in Million Kilowatthours", - "EMACBUS": "Fuel Ethanol, Excluding Denaturant, Consumed by the Transportation Sector in Trillion Btu", - "ENPSPUS": "Fuel Ethanol Stocks, End of Period in Thousand Barrels", - "ESOTUUS": "Average Price of Electricity to Ultimate Customers, Other in Cents per Kilowatthour, Including Taxes", - "EVDCRUS": "Number of DC fast charging ports per location in Number", - "EVPUPUS": "Number of locations with public ports only in Number", - "FFCCBUS": "Total Fossil Fuels Consumed by the Commercial Sector in Trillion Btu", - "FFTCBUS": "Total Fossil Fuels Consumption in Trillion Btu", - "GECASUS": "Geothermal Generating Units, Capacity Factor in Percent", - "GECCBUS": "Geothermal Energy Consumed by the Commercial Sector in Trillion Btu", - "GERCBUS": "Geothermal Energy Consumed by the Residential Sector in Trillion Btu", - "HLNFBUS": "Hydrocarbon Gas Liquids Non-Combustion Consumption in Quadrillion Btu", - "HLRCPUS": "Propane Consumed by the Residential Sector in Thousand Barrels per Day", - "HVEGBUS": "Conventional Hydroelectric Power Consumed by the Electric Power Sector in Trillion Btu", - "HVEGPUS": "Electricity Net Generation From Conventional Hydroelectric Power, Electric Power Sector in Million Kilowatthours", - "HVFFBUS": "Conventional Hydro Energy Consumption, Fossil Fuel Equivalent in Trillion Btu", - "HVICBUS": "Conventional Hydroelectric Power Consumed by the Industrial Sector in Trillion Btu", - "HVL9SUS": "Hydroelectric Electric Power Sector Generating Units, Capacity Factor in Percent", - "JFIMPUS": "Jet Fuel Imports in Thousand Barrels per Day", - "JKWHUUS": "Average Refiner Price of Kerosene-Type Jet Fuel for Resale in Dollars per Gallon Excluding Taxes", - "KSTCBUS": "Kerosene Product Supplied in Trillion Btu", - "LNEXPCE": "Natural Gas Exports to Chile in Billion Cubic Feet", - "LNEXPFR": "Natural Gas Exports to France in Billion Cubic Feet", - "LNEXPTU": "Natural Gas Exports to Turkey in Billion Cubic Feet", - "LOACBUS": "Electrical System Energy Losses Proportioned to the Transportation Sector in Trillion Btu", - "LUNFBUS": "Lubricants Non-Combustion Consumption in Quadrillion Btu", - "LUTCBUS": "Lubricants Product Supplied in Trillion Btu", - "MGEXPUS": "Finished Motor Gasoline Exports in Thousand Barrels per Day", - "MGTCOUS": "Average Cost of Motor Gasoline in Real (1982-1984) Dollars per Gallon", - "MGTCUUS": "Average Refiner Price of Finished Motor Gasoline to End Users in Dollars per Gallon Excluding Taxes", - "MTPSPUS": "Motor Gasoline Stocks (Including Blending Components and Gasohol), End of Period in Million Barrels", - "NGCCUUS": "Average Natural Gas Price, Delivered to Consumers, Commercial in Dollars per Thousand Cubic Feet", - "NGCGUUS": "Average Natural Gas Price, Citygate in Dollars per Thousand Cubic Feet", - "NGEXPMX": "Natural Gas Exports to Mexico in Billion Cubic Feet", - "NGI3PUS": "Natural Gas Consumption for Electricity Generation and Useful Thermal Output, Industrial Sector in Billion Cubic Feet", - "NGLPPUS": "Natural Gas Consumed by the Industrial Sector, Lease and Plant Fuel in Billion Cubic Feet", - "NGNIPUS": "Natural Gas Net Imports in Billion Cubic Feet", - "NGRCOUS": "Average Cost of Residential Natural Gas in Real (1982-1984) Dollars per Thousand Cubic Feet", - "NNEIEUS": "Natural Gas Electric Power Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "NUETPUS": "Electricity Net Generation From Nuclear Electric Power, All Sectors in Million Kilowatthours", - "OJEIBUS": "Other Gases Consumption for Electricity Generation and Useful Thermal Output, Electric Power Sector in Trillion Btu", - "OJEPBUS": "Other Gases Consumption for Electricity Generation, All Sectors in Trillion Btu", - "OJI3BUS": "Other Gases Consumption for Electricity Generation and Useful Thermal Output, Industrial Sector in Trillion Btu", - "OLEKPUS": "Other Petroleum Liquids Stocks, Electric Power Sector, End of Period in Thousand Barrels", - "OLEPPUS": "Other Petroleum Liquids Consumption for Electricity Generation, All Sectors in Thousand Barrels", - "OPICEUS": "Other Petroleum Products Industrial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "OPROPUS": "Other Petroleum Products Refinery and Blender Net Production in Thousand Barrels per Day", - "OPTCBUS": "Other Products Supplied in Trillion Btu", - "OTEPBUS": "Other Consumption for Electricity Generation, All Sectors in Trillion Btu", - "PAECPUS": "Total Petroleum Consumption for Electricity Generation and Useful Thermal Output, All Sectors in Thousand Barrels", - "PAETPUS": "Electricity Net Generation From Petroleum, All Sectors in Million Kilowatthours", - "PAEXPBZ": "Petroleum Exports to Brazil in Thousand Barrels per Day", - "PAEXPUK": "Petroleum Exports to United Kingdom in Thousand Barrels per Day", - "PAIMPCL": "Petroleum Imports From Colombia in Thousand Barrels per Day", - "PAIMPOT": "Petroleum Imports From Other Non-OPEC in Thousand Barrels per Day", - "PAIMPPG": "Petroleum Imports From Persian Gulf in Thousand Barrels per Day", - "PAIMPUS": "Total Petroleum Imports in Thousand Barrels per Day", - "PAIMSOP": "Petroleum Imports From OPEC as Share of Total Imports in Percent", - "PAIQSOP": "Petroleum Imports From OPEC as Share of Products Supplied in Percent", - "PAL1PUS": "Total Petroleum Consumption for Electricity Generation, Electric Power Sector in Thousand Barrels", - "PARIPUS": "Total Petroleum Refinery and Blender Net Inputs in Thousand Barrels per Day", - "PCECMUS": "Petroleum Coke Consumption for Electricity Generation and Useful Thermal Output, All Sectors in Thousand Short Tons", - "PCEPMUS": "Petroleum Coke Consumption for Electricity Generation, All Sectors in Thousand Short Tons", - "PMACEUS": "Petroleum, Excluding Biofuels, Transportation Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "PQPSPUS": "Propane Stocks in Million Barrels", - "PYIMPUS": "Propylene Imports in Thousand Barrels per Day", - "PYTCBUS": "Propylene Product Supplied in Trillion Btu", - "PZROPUS": "Propane/Propylene Refinery and Blender Net Production in Thousand Barrels per Day", - "REFFBUS": "Renewable Energy Consumption, Fossil Fuel Equivalent in Trillion Btu", - "REI9PUS": "Renewable Energy Industrial Sector, Net Summer Capacity in Million Kilowatts", - "REPFBUS": "Renewable Energy Production, Fossil Fuel Equivalent in Trillion Btu", - "RFEIEUS": "Residual Fuel Oil Electric Power Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "RFERDUS": "Average Cost of Residual Fuel Receipts at Electric Generating Plants in Dollars per Million Btu, Including Taxes", - "RFICBUS": "Residual Fuel Oil Consumed by the Industrial Sector in Trillion Btu", - "RYPRPUS": "Biofuels Plant Net Production in Thousand Barrels per Day", - "SHCASUS": "Solar Thermal Generating Units, Capacity Factor in Percent", - "SOC9PUS": "Solar Commercial Sector, Net Summer Capacity in Million Kilowatts", - "SOFFBUS": "Solar Energy Consumption, Fossil Fuel Equivalent in Trillion Btu", - "SOI7BUS": "Small-Scale Solar Energy Consumption for Electricity: Industrial Sector in Trillion Btu", - "SOI9PUS": "Solar Industrial Sector, Net Summer Capacity in Million Kilowatts", - "SOL9PUS": "Solar Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "SOT8BUS": "Small-Scale Solar Energy Consumption for Heat: Total in Trillion Btu", - "TENFSUS": "Total Fossil Fuels Non-Combustion Consumption Percent of Total Energy Consumption in Percent", - "TENIBUS": "Total Primary Energy Net Imports in Trillion Btu", - "TFPRBUS": "Total Energy Production, Fossil Fuel Equivalent in Trillion Btu", - "TFTCBUS": "Total Energy Consumption, Fossil Fuel Equivalent in Trillion Btu", - "TXACBUS": "Total Primary Energy Consumed by the Transportation Sector in Trillion Btu", - "TXCCBUS": "Total Primary Energy Consumed by the Commercial Sector in Trillion Btu", - "WDI9PUS": "Wood Industrial Sector, Net Summer Capacity in Million Kilowatts", - "WDTCBUS": "Wood Energy Consumption in Trillion Btu", - "WSC3BUS": "Waste Consumption for Electricity Generation and Useful Thermal Output, Commercial Sector in Trillion Btu", - "WYC9PUS": "Wind Commercial Sector, Net Summer Capacity in Million Kilowatts", - "WYL9PUS": "Wind Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "WYL9SUS": "Wind Electric Power Sector Generating Units, Capacity Factor in Percent", - "ZWCDPC5": "Cooling Degree-Days, South Atlantic in Number", - "ZWCDPC8": "Cooling Degree-Days, Mountain in Number", - "ZWCDPUS": "Cooling Degree-Days, United States in Number", - "ZWHDPC4": "Heating Degree-Days, West North Central in Number", - "ZWHDPC9": "Heating Degree-Days, Pacific in Number", - "AVACEUS": "Aviation Gasoline Transportation Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "AVACPUS": "Aviation Gasoline Consumed by the Transportation Sector in Thousand Barrels per Day", - "B1PRPUS": "Renewable Diesel Fuel Production in Thousand Barrels", - "B1SCPUS": "Renewable Diesel Fuel Stock Change in Thousand Barrels", - "BMACBUS": "Total Biomass Energy Consumed by the Transportation Sector in Trillion Btu", - "BMEIBUS": "Total Biomass Energy Consumed by the Electric Power Sector in Trillion Btu", - "BMICBUS": "Total Biomass Energy Consumed by the Industrial Sector in Trillion Btu", - "BMRCEUS": "Biomass Residential Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "BOFDBUS": "Other Biofuels Feedstock in Trillion Btu", - "BOPRPUS": "Other Biofuels Production in Thousand Barrels", - "BOPSPUS": "Other Biofuels Stocks in Thousand Barrels", - "CLKCPUS": "Coal Consumed by the Industrial Sector, Coke Plants in Thousand Short Tons", - "CLTCBUS": "Coal Consumption in Trillion Btu", - "COEXBUS": "Crude Oil Exports in Trillion Btu", - "COFMUMX": "Average Free on Board Cost of Crude Oil Imports From Mexico in Dollars per Barrel", - "COFMUVE": "Average Free on Board Cost of Crude Oil Imports From Venezuela in Dollars per Barrel", - "COIMUCL": "Average Landed Cost of Crude Oil Imports From Colombia in Dollars per Barrel", - "COIMUNI": "Average Landed Cost of Crude Oil Imports From Nigeria in Dollars per Barrel", - "D2RCOUS": "Average Cost of Residential Heating Oil in Real (1982-1984) Dollars per Gallon", - "DKEIPUS": "Distillate Fuel Oil Consumption for Electricity Generation and Useful Thermal Output, Electric Power Sector in Thousand Barrels", - "DKEIZUS": "Distillate Fuel Oil Consumed by the Electric Power Sector in Thousand Barrels per Day", - "DSTCUUS": "Average Refiner Price of No. 2 Diesel Fuel to End Users in Dollars per Gallon Excluding Taxes", - "ELC9PUS": "Total Commercial Sector, Net Summer Capacity in Million Kilowatts", - "ELETPUS": "Electricity Net Generation Total (including from sources not shown), All Sectors in Million Kilowatthours", - "ELI5PUS": "Electricity Net Generation Total (including from sources not shown), Industrial Sector in Million Kilowatthours", - "EMCCBUS": "Fuel Ethanol, Excluding Denaturant, Consumed by the Commercial Sector in Trillion Btu", - "EMICBUS": "Fuel Ethanol, Excluding Denaturant, Consumed by the Industrial Sector in Trillion Btu", - "ENPRMUS": "Fuel Ethanol Production in Million Gallons", - "ENSCPUS": "Fuel Ethanol Stock Change in Thousand Barrels", - "ENTCMUS": "Fuel Ethanol Consumption in Million Gallons", - "ESACPUS": "Electricity Sales to Ultimate Customers, Transportation in Million Kilowatthours", - "ESICPUS": "Electricity Sales to Ultimate Customers, Industrial in Million Kilowatthours", - "ESRCAUS": "Average Cost of Residential Electricity in Real (1982-1984) Dollars per Million Btu", - "FFC9PUS": "Fossil Fuels Commercial Sector, Net Summer Capacity in Million Kilowatts", - "FFI9PUS": "Fossil Fuels Industrial Sector, Net Summer Capacity in Million Kilowatts", - "GEC9PUS": "Geothermal Commercial Sector, Net Summer Capacity in Million Kilowatts", - "GEEGBUS": "Geothermal Energy Consumed by the Electric Power Sector in Trillion Btu", - "GEEIEUS": "Geothermal Energy Electric Power Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "GEETPUS": "Electricity Net Generation From Geothermal, All Sectors in Million Kilowatthours", - "GEL9PUS": "Geothermal Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "GETCBUS": "Geothermal Energy Consumption/Production in Trillion Btu", - "HLACPUS": "Propane Consumed by the Transportation Sector in Thousand Barrels per Day", - "HLICPUS": "Total Hydrocarbon Gas Liquids Consumed by the Industrial Sector in Thousand Barrels per Day", - "HLPSPUS": "Total Hydrocarbon Gas Liquids Stocks in Million Barrels", - "HPCASUS": "Hydroelectric Pumped Storage Generating Units, Usage Factor in Percent", - "HVETPUS": "Electricity Net Generation From Conventional Hydroelectric Power, All Sectors in Million Kilowatthours", - "HVI5PUS": "Electricity Net Generation From Hydroelectric Power, Industrial Sector in Million Kilowatthours", - "KSCCPUS": "Kerosene Consumed by the Commercial Sector in Thousand Barrels per Day", - "LNEXPJA": "Natural Gas Exports to Japan in Billion Cubic Feet", - "LNEXPSK": "Natural Gas Exports to South Korea in Billion Cubic Feet", - "LNIMPNI": "Natural Gas Imports from Nigeria in Billion Cubic Feet", - "LOCCBUS": "Electrical System Energy Losses Proportioned to the Commercial Sector in Trillion Btu", - "LORCBUS": "Electricity System Energy Losses Proportioned to the Residential Sector in Trillion Btu", - "LOTCBUS": "Total Electrical Energy System Losses Proportioned to the End-Use Sectors in Trillion Btu", - "LUACBUS": "Lubricants Consumed by the Transportation Sector in Trillion Btu", - "LUICBUS": "Lubricants Consumed by the Industrial Sector in Trillion Btu", - "LUICPUS": "Lubricants Consumed by the Industrial Sector in Thousand Barrels per Day", - "MGTCPUS": "Motor Gasoline Product Supplied in Thousand Barrels per Day", - "MMACEUS": "Motor Gasoline, Excluding Ethanol, Transportation Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "NGBGPUS": "Natural Gas in Underground Storage, End of Period, Base Gas in Billion Cubic Feet", - "NGECPUS": "Natural Gas Consumption for Electricity Generation and Useful Thermal Output, All Sectors in Billion Cubic Feet", - "NGEIPUS": "Natural Gas Consumption for Electricity Generation and Useful Thermal Output, Electric Power Sector in Billion Cubic Feet", - "NGERDUS": "Average Cost of Natural Gas Receipts at Electric Generating Plants in Dollars per Million Btu, Including Taxes", - "NGEXPCN": "Natural Gas Exports to Canada in Billion Cubic Feet", - "NGI1PUS": "Natural Gas Consumption for Electricity Generation, Industrial Sector in Billion Cubic Feet", - "NGIMPMX": "Natural Gas Imports from Mexico in Billion Cubic Feet", - "NGNRPUS": "Natural Gas Rotary Rigs in Operation, Total in Number of Rigs", - "NGTCPUS": "Natural Gas Consumption, Total in Billion Cubic Feet", - "NGVHPUS": "Natural Gas Consumed by the Transportation Sector, Vehicle Fuel in Billion Cubic Feet", - "NGWGPUS": "Natural Gas in Underground Storage, End of Period, Working Gas in Billion Cubic Feet", - "NNICEUS": "Natural Gas Industrial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "NNTCBUS": "Natural Gas Consumption (Excluding Supplemental Gaseous Fuels) in Trillion Btu", - "NTC9SUS": "Natural Gas Gas Turbine Plants Commercial Sector Generating Units, Capacity Factor in Percent", - "NTL9SUS": "Natural Gas Gas Turbine Plants Electric Power Sector Generating Units, Capacity Factor in Percent", - "NUOUPUS": "Nuclear Generating Units, Total Operable Units, End of Period in Number", - "NWEIEUS": "Non-Biomass Waste Electric Power Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "NXSIPUS": "Natural Gas Storage Activity, Injections in Billion Cubic Feet", - "NYC9SUS": "Natural Gas Conventional Steam Plants Commercial Sector Generating Units, Capacity Factor in Percent", - "OGDFPUS": "Dry Wells, Total Footage Drilled in Thousand Feet", - "OGHFPUS": "Crude Oil, Natural Gas, and Dry Wells, Horizontal and Directional Trajectory, Total Footage Drilled in Thousand Feet", - "OGVTPUS": "Crude Oil and Natural Gas Rotary Rigs in Operation, Vertical Trajectory in Number of Rigs", - "OPICBUS": "Other Petroleum Products Consumed by the Industrial Sector in Trillion Btu", - "PAC3PUS": "Petroleum Consumption for Electricity Generation and Useful Thermal Output, Commercial Sector in Thousand Barrels", - "PAEPPUS": "Total Petroleum Consumption for Electricity Generation, All Sectors in Thousand Barrels", - "PAEXPCN": "Petroleum Exports to Canada in Thousand Barrels per Day", - "PAEXPNL": "Petroleum Exports to Netherlands in Thousand Barrels per Day", - "PAEXPUS": "Total Petroleum Exports in Thousand Barrels per Day", - "PAICPUS": "Total Petroleum Consumed by the Industrial Sector in Thousand Barrels per Day", - "PAIMPLY": "Petroleum Imports From Libya in Thousand Barrels per Day", - "PAIMPNI": "Petroleum Imports From Nigeria in Thousand Barrels per Day", - "PAIMPOO": "Petroleum Imports From Other OPEC in Thousand Barrels per Day", - "PAIMPUK": "Petroleum Imports From United Kingdom in Thousand Barrels per Day", - "PAIMPVE": "Petroleum Imports From Venezuela in Thousand Barrels per Day", - "PARCPUS": "Total Petroleum Consumed by the Residential Sector in Thousand Barrels per Day", - "PATCPUS": "Petroleum Products Supplied/Consumption, United States in Thousand Barrels per Day", - "PCCCEUS": "Petroleum Coke Commercial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "PCICEUS": "Petroleum Coke Industrial Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "PMCCBUS": "Petroleum Consumed by the Commercial Sector (Excluding Biofuels) in Trillion Btu", - "PQICBUS": "Propane Consumed by the Industrial Sector in Trillion Btu", - "PYPSPUS": "Propylene Stocks in Million Barrels", - "PZEXPUS": "Propane Exports in Thousand Barrels per Day", - "PZICBUS": "Propane/Propylene Consumed by the Industrial Sector in Trillion Btu", - "RBWHUUS": "Average Refiner Price of Residual Fuel Oil, Sulfur Content Less Than or Equal to 1 Percent, Sales for Resale in Dollars per Gallon Excluding Taxes", - "RCRTUUS": "Regular Motor Gasoline, Conventional Gasoline Areas, Average Retail Price in Dollars per Gallon Including Taxes", - "REACBUS": "Total Biomass Energy Consumed by the Transportation Sector in Trillion Btu", - "RFACPUS": "Residual Fuel Oil Consumed by the Transportation Sector in Thousand Barrels per Day", - "RFEPPUS": "Residual Fuel Oil Consumption for Electricity Generation, All Sectors in Thousand Barrels", - "RFPSPUS": "Residual Fuel Oil Stocks, End of Period in Million Barrels", - "RFTCEUS": "Residual Fuel Oil CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "RFTCPUS": "Residual Fuel Oil Product Supplied in Thousand Barrels per Day", - "RFWHUUS": "Average Refiner Price of Residual Fuel Oil, Sales for Resale in Dollars per Gallon Excluding Taxes", - "RQIMBUS": "Petroleum Products, Excluding Biofuels, Imports in Trillion Btu", - "SOC5BUS": "Utility-Scale Solar Energy Consumption for Electricity: Commercial Sector in Trillion Btu", - "SOC7BUS": "Small-Scale Solar Energy Consumption for Electricity: Commercial Sector in Trillion Btu", - "SOEGPUS": "Utility-Scale Solar Electricity Net Generation: Electric Power Sector in Million Kilowatthours", - "TEACEUS": "Total Energy Transportation Sector CO2 Emissions in Million Metric Tons of Carbon Dioxide", - "TNRCBUS": "End-Use Energy Consumed by the Residential Sector in Trillion Btu", - "TNTCBUS": "End-Use Energy Consumed by the End-Use Sectors in Trillion Btu", - "TXRCBUS": "Total Primary Energy Consumed by the Residential Sector in Trillion Btu", - "WDGBPUS": "Wood, Net Summer Capacity in Million Kilowatts", - "WDI1BUS": "Wood Consumption for Electricity Generation, Industrial Sector in Trillion Btu", - "WSCCBUS": "Waste Energy Consumed by the Commercial Sector in Trillion Btu", - "WSI1BUS": "Waste Consumption for Electricity Generation, Industrial Sector in Trillion Btu", - "WSL9PUS": "Waste Electric Power Sector, Net Summer Capacity in Million Kilowatts", - "WYC9SUS": "Wind Commercial Sector Generating Units, Capacity Factor in Percent", - "WYTCBUS": "Wind Energy Consumption/Production in Trillion Btu", - "ZWHDPC5": "Heating Degree-Days, South Atlantic in Number" -} diff --git a/openbb_platform/providers/eia/poetry.lock b/openbb_platform/providers/eia/poetry.lock deleted file mode 100644 index 9b02ef24d72..00000000000 --- a/openbb_platform/providers/eia/poetry.lock +++ /dev/null @@ -1,2018 +0,0 @@ -# This file is automatically @generated by Poetry 2.4.1 and should not be changed by hand. - -[[package]] -name = "aiohappyeyeballs" -version = "2.6.2" -description = "Happy Eyeballs for asyncio" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "aiohappyeyeballs-2.6.2-py3-none-any.whl", hash = "sha256:4708045e2d7a6c6bdf8aafa8ed39649eaf926a4543b54560659129e3365953c4"}, - {file = "aiohappyeyeballs-2.6.2.tar.gz", hash = "sha256:e202810ee718bd01fc6ef49e8ea53d023d5cb6b581076d7925aa499fa55dbe64"}, -] - -[[package]] -name = "aiohttp" -version = "3.13.5" -description = "Async http client/server framework (asyncio)" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "aiohttp-3.13.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b"}, - {file = "aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5"}, - {file = "aiohttp-3.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670"}, - {file = "aiohttp-3.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274"}, - {file = "aiohttp-3.13.5-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a"}, - {file = "aiohttp-3.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d"}, - {file = "aiohttp-3.13.5-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796"}, - {file = "aiohttp-3.13.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95"}, - {file = "aiohttp-3.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5"}, - {file = "aiohttp-3.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a"}, - {file = "aiohttp-3.13.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73"}, - {file = "aiohttp-3.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297"}, - {file = "aiohttp-3.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074"}, - {file = "aiohttp-3.13.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e"}, - {file = "aiohttp-3.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7"}, - {file = "aiohttp-3.13.5-cp310-cp310-win32.whl", hash = "sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9"}, - {file = "aiohttp-3.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76"}, - {file = "aiohttp-3.13.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6"}, - {file = "aiohttp-3.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d"}, - {file = "aiohttp-3.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c"}, - {file = "aiohttp-3.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb"}, - {file = "aiohttp-3.13.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6"}, - {file = "aiohttp-3.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13"}, - {file = "aiohttp-3.13.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174"}, - {file = "aiohttp-3.13.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc"}, - {file = "aiohttp-3.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6"}, - {file = "aiohttp-3.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49"}, - {file = "aiohttp-3.13.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8"}, - {file = "aiohttp-3.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d"}, - {file = "aiohttp-3.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c"}, - {file = "aiohttp-3.13.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac"}, - {file = "aiohttp-3.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3"}, - {file = "aiohttp-3.13.5-cp311-cp311-win32.whl", hash = "sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06"}, - {file = "aiohttp-3.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8"}, - {file = "aiohttp-3.13.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9"}, - {file = "aiohttp-3.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416"}, - {file = "aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2"}, - {file = "aiohttp-3.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4"}, - {file = "aiohttp-3.13.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9"}, - {file = "aiohttp-3.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5"}, - {file = "aiohttp-3.13.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e"}, - {file = "aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1"}, - {file = "aiohttp-3.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286"}, - {file = "aiohttp-3.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9"}, - {file = "aiohttp-3.13.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88"}, - {file = "aiohttp-3.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3"}, - {file = "aiohttp-3.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b"}, - {file = "aiohttp-3.13.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe"}, - {file = "aiohttp-3.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14"}, - {file = "aiohttp-3.13.5-cp312-cp312-win32.whl", hash = "sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3"}, - {file = "aiohttp-3.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1"}, - {file = "aiohttp-3.13.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61"}, - {file = "aiohttp-3.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832"}, - {file = "aiohttp-3.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9"}, - {file = "aiohttp-3.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090"}, - {file = "aiohttp-3.13.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b"}, - {file = "aiohttp-3.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a"}, - {file = "aiohttp-3.13.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8"}, - {file = "aiohttp-3.13.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665"}, - {file = "aiohttp-3.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540"}, - {file = "aiohttp-3.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb"}, - {file = "aiohttp-3.13.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46"}, - {file = "aiohttp-3.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8"}, - {file = "aiohttp-3.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d"}, - {file = "aiohttp-3.13.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6"}, - {file = "aiohttp-3.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c"}, - {file = "aiohttp-3.13.5-cp313-cp313-win32.whl", hash = "sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc"}, - {file = "aiohttp-3.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83"}, - {file = "aiohttp-3.13.5-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c"}, - {file = "aiohttp-3.13.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be"}, - {file = "aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25"}, - {file = "aiohttp-3.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56"}, - {file = "aiohttp-3.13.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2"}, - {file = "aiohttp-3.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a"}, - {file = "aiohttp-3.13.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be"}, - {file = "aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b"}, - {file = "aiohttp-3.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94"}, - {file = "aiohttp-3.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d"}, - {file = "aiohttp-3.13.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7"}, - {file = "aiohttp-3.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772"}, - {file = "aiohttp-3.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5"}, - {file = "aiohttp-3.13.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1"}, - {file = "aiohttp-3.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b"}, - {file = "aiohttp-3.13.5-cp314-cp314-win32.whl", hash = "sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3"}, - {file = "aiohttp-3.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162"}, - {file = "aiohttp-3.13.5-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a"}, - {file = "aiohttp-3.13.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254"}, - {file = "aiohttp-3.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36"}, - {file = "aiohttp-3.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f"}, - {file = "aiohttp-3.13.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800"}, - {file = "aiohttp-3.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf"}, - {file = "aiohttp-3.13.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b"}, - {file = "aiohttp-3.13.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a"}, - {file = "aiohttp-3.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8"}, - {file = "aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be"}, - {file = "aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b"}, - {file = "aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6"}, - {file = "aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037"}, - {file = "aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500"}, - {file = "aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9"}, - {file = "aiohttp-3.13.5-cp314-cp314t-win32.whl", hash = "sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8"}, - {file = "aiohttp-3.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9"}, - {file = "aiohttp-3.13.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:347542f0ea3f95b2a955ee6656461fa1c776e401ac50ebce055a6c38454a0adf"}, - {file = "aiohttp-3.13.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:178c7b5e62b454c2bc790786e6058c3cc968613b4419251b478c153a4aec32b1"}, - {file = "aiohttp-3.13.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af545c2cffdb0967a96b6249e6f5f7b0d92cdfd267f9d5238d5b9ca63e8edb10"}, - {file = "aiohttp-3.13.5-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:206b7b3ef96e4ce211754f0cd003feb28b7d81f0ad26b8d077a5d5161436067f"}, - {file = "aiohttp-3.13.5-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ee5e86776273de1795947d17bddd6bb19e0365fd2af4289c0d2c5454b6b1d36b"}, - {file = "aiohttp-3.13.5-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:95d14ca7abefde230f7639ec136ade282655431fd5db03c343b19dda72dd1643"}, - {file = "aiohttp-3.13.5-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:912d4b6af530ddb1338a66229dac3a25ff11d4448be3ec3d6340583995f56031"}, - {file = "aiohttp-3.13.5-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e999f0c88a458c836d5fb521814e92ed2172c649200336a6df514987c1488258"}, - {file = "aiohttp-3.13.5-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:39380e12bd1f2fdab4285b6e055ad48efbaed5c836433b142ed4f5b9be71036a"}, - {file = "aiohttp-3.13.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9efcc0f11d850cefcafdd9275b9576ad3bfb539bed96807663b32ad99c4d4b88"}, - {file = "aiohttp-3.13.5-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:147b4f501d0292077f29d5268c16bb7c864a1f054d7001c4c1812c0421ea1ed0"}, - {file = "aiohttp-3.13.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d147004fede1b12f6013a6dbb2a26a986a671a03c6ea740ddc76500e5f1c399f"}, - {file = "aiohttp-3.13.5-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9277145d36a01653863899c665243871434694bcc3431922c3b35c978061bdb8"}, - {file = "aiohttp-3.13.5-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4e704c52438f66fdd89588346183d898bb42167cf88f8b7ff1c0f9fc957c348f"}, - {file = "aiohttp-3.13.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a8a4d3427e8de1312ddf309cc482186466c79895b3a139fed3259fc01dfa9a5b"}, - {file = "aiohttp-3.13.5-cp39-cp39-win32.whl", hash = "sha256:6f497a6876aa4b1a102b04996ce4c1170c7040d83faa9387dd921c16e30d5c83"}, - {file = "aiohttp-3.13.5-cp39-cp39-win_amd64.whl", hash = "sha256:cb979826071c0986a5f08333a36104153478ce6018c58cba7f9caddaf63d5d67"}, - {file = "aiohttp-3.13.5.tar.gz", hash = "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1"}, -] - -[package.dependencies] -aiohappyeyeballs = ">=2.5.0" -aiosignal = ">=1.4.0" -async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""} -attrs = ">=17.3.0" -frozenlist = ">=1.1.1" -multidict = ">=4.5,<7.0" -propcache = ">=0.2.0" -yarl = ">=1.17.0,<2.0" - -[package.extras] -speedups = ["Brotli (>=1.2) ; platform_python_implementation == \"CPython\"", "aiodns (>=3.3.0)", "backports.zstd ; platform_python_implementation == \"CPython\" and python_version < \"3.14\"", "brotlicffi (>=1.2) ; platform_python_implementation != \"CPython\""] - -[[package]] -name = "aiosignal" -version = "1.4.0" -description = "aiosignal: a list of registered asynchronous callbacks" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e"}, - {file = "aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7"}, -] - -[package.dependencies] -frozenlist = ">=1.1.0" -typing-extensions = {version = ">=4.2", markers = "python_version < \"3.13\""} - -[[package]] -name = "annotated-doc" -version = "0.0.4" -description = "Document parameters, class attributes, return types, and variables inline, with Annotated." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320"}, - {file = "annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4"}, -] - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "anyio" -version = "4.13.0" -description = "High-level concurrency and networking framework on top of asyncio or Trio" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708"}, - {file = "anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc"}, -] - -[package.dependencies] -exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} -idna = ">=2.8" -typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} - -[package.extras] -trio = ["trio (>=0.32.0)"] - -[[package]] -name = "async-lru" -version = "2.3.0" -description = "Simple LRU cache for asyncio" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "async_lru-2.3.0-py3-none-any.whl", hash = "sha256:eea27b01841909316f2cc739807acea1c623df2be8c5cfad7583286397bb8315"}, - {file = "async_lru-2.3.0.tar.gz", hash = "sha256:89bdb258a0140d7313cf8f4031d816a042202faa61d0ab310a0a538baa1c24b6"}, -] - -[package.dependencies] -typing_extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} - -[[package]] -name = "async-timeout" -version = "5.0.1" -description = "Timeout context manager for asyncio programs" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.10\"" -files = [ - {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, - {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, -] - -[[package]] -name = "attrs" -version = "26.1.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309"}, - {file = "attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32"}, -] - -[[package]] -name = "certifi" -version = "2026.5.20" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "certifi-2026.5.20-py3-none-any.whl", hash = "sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897"}, - {file = "certifi-2026.5.20.tar.gz", hash = "sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d"}, -] - -[[package]] -name = "charset-normalizer" -version = "3.4.7" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-win32.whl", hash = "sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-win32.whl", hash = "sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux_2_31_armv7l.whl", hash = "sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_riscv64.whl", hash = "sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-win32.whl", hash = "sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-win_amd64.whl", hash = "sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-win32.whl", hash = "sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-win_amd64.whl", hash = "sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-win_arm64.whl", hash = "sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c"}, - {file = "charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d"}, - {file = "charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5"}, -] - -[[package]] -name = "click" -version = "8.4.1" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "click-8.4.1-py3-none-any.whl", hash = "sha256:482be17c6991b8c19c5429a1e995d9b0efdbb63172824c41f99965dc0ade8ec2"}, - {file = "click-8.4.1.tar.gz", hash = "sha256:918b5633eddf6b41c32d4f454bf0de810065c74e3f7dbf8ee5452f8be88d3e96"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main"] -markers = "platform_system == \"Windows\"" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "et-xmlfile" -version = "2.0.0" -description = "An implementation of lxml.xmlfile for the standard library" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa"}, - {file = "et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54"}, -] - -[[package]] -name = "exceptiongroup" -version = "1.3.1" -description = "Backport of PEP 654 (exception groups)" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.10\"" -files = [ - {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, - {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, -] - -[package.dependencies] -typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} - -[package.extras] -test = ["pytest (>=6)"] - -[[package]] -name = "fastapi" -version = "0.128.8" -description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "fastapi-0.128.8-py3-none-any.whl", hash = "sha256:5618f492d0fe973a778f8fec97723f598aa9deee495040a8d51aaf3cf123ecf1"}, - {file = "fastapi-0.128.8.tar.gz", hash = "sha256:3171f9f328c4a218f0a8d2ba8310ac3a55d1ee12c28c949650288aee25966007"}, -] - -[package.dependencies] -annotated-doc = ">=0.0.2" -pydantic = ">=2.7.0" -starlette = ">=0.40.0,<1.0.0" -typing-extensions = ">=4.8.0" -typing-inspection = ">=0.4.2" - -[package.extras] -all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.9.3)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "pyyaml (>=5.3.1)", "ujson (>=5.8.0)", "uvicorn[standard] (>=0.12.0)"] -standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"] -standard-no-fastapi-cloud-cli = ["email-validator (>=2.0.0)", "fastapi-cli[standard-no-fastapi-cloud-cli] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"] - -[[package]] -name = "frozenlist" -version = "1.8.0" -description = "A list-like structure which implements collections.abc.MutableSequence" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "frozenlist-1.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011"}, - {file = "frozenlist-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565"}, - {file = "frozenlist-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad"}, - {file = "frozenlist-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2"}, - {file = "frozenlist-1.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186"}, - {file = "frozenlist-1.8.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e"}, - {file = "frozenlist-1.8.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450"}, - {file = "frozenlist-1.8.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef"}, - {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4"}, - {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff"}, - {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c"}, - {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f"}, - {file = "frozenlist-1.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7"}, - {file = "frozenlist-1.8.0-cp310-cp310-win32.whl", hash = "sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a"}, - {file = "frozenlist-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6"}, - {file = "frozenlist-1.8.0-cp310-cp310-win_arm64.whl", hash = "sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e"}, - {file = "frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84"}, - {file = "frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9"}, - {file = "frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93"}, - {file = "frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f"}, - {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695"}, - {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52"}, - {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581"}, - {file = "frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567"}, - {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b"}, - {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92"}, - {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d"}, - {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd"}, - {file = "frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967"}, - {file = "frozenlist-1.8.0-cp311-cp311-win32.whl", hash = "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25"}, - {file = "frozenlist-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b"}, - {file = "frozenlist-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a"}, - {file = "frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1"}, - {file = "frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b"}, - {file = "frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4"}, - {file = "frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383"}, - {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4"}, - {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8"}, - {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b"}, - {file = "frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52"}, - {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29"}, - {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3"}, - {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143"}, - {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608"}, - {file = "frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa"}, - {file = "frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf"}, - {file = "frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746"}, - {file = "frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd"}, - {file = "frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a"}, - {file = "frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7"}, - {file = "frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40"}, - {file = "frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027"}, - {file = "frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822"}, - {file = "frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121"}, - {file = "frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5"}, - {file = "frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e"}, - {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11"}, - {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1"}, - {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1"}, - {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8"}, - {file = "frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed"}, - {file = "frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496"}, - {file = "frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231"}, - {file = "frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62"}, - {file = "frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94"}, - {file = "frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c"}, - {file = "frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52"}, - {file = "frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51"}, - {file = "frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65"}, - {file = "frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82"}, - {file = "frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714"}, - {file = "frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d"}, - {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506"}, - {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51"}, - {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e"}, - {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0"}, - {file = "frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41"}, - {file = "frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b"}, - {file = "frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888"}, - {file = "frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042"}, - {file = "frozenlist-1.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0"}, - {file = "frozenlist-1.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f"}, - {file = "frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c"}, - {file = "frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2"}, - {file = "frozenlist-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8"}, - {file = "frozenlist-1.8.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686"}, - {file = "frozenlist-1.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e"}, - {file = "frozenlist-1.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a"}, - {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128"}, - {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f"}, - {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7"}, - {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30"}, - {file = "frozenlist-1.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7"}, - {file = "frozenlist-1.8.0-cp314-cp314-win32.whl", hash = "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806"}, - {file = "frozenlist-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0"}, - {file = "frozenlist-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b"}, - {file = "frozenlist-1.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d"}, - {file = "frozenlist-1.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed"}, - {file = "frozenlist-1.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930"}, - {file = "frozenlist-1.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c"}, - {file = "frozenlist-1.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24"}, - {file = "frozenlist-1.8.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37"}, - {file = "frozenlist-1.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a"}, - {file = "frozenlist-1.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2"}, - {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef"}, - {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe"}, - {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8"}, - {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a"}, - {file = "frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e"}, - {file = "frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df"}, - {file = "frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd"}, - {file = "frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79"}, - {file = "frozenlist-1.8.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d8b7138e5cd0647e4523d6685b0eac5d4be9a184ae9634492f25c6eb38c12a47"}, - {file = "frozenlist-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a6483e309ca809f1efd154b4d37dc6d9f61037d6c6a81c2dc7a15cb22c8c5dca"}, - {file = "frozenlist-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1b9290cf81e95e93fdf90548ce9d3c1211cf574b8e3f4b3b7cb0537cf2227068"}, - {file = "frozenlist-1.8.0-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:59a6a5876ca59d1b63af8cd5e7ffffb024c3dc1e9cf9301b21a2e76286505c95"}, - {file = "frozenlist-1.8.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6dc4126390929823e2d2d9dc79ab4046ed74680360fc5f38b585c12c66cdf459"}, - {file = "frozenlist-1.8.0-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:332db6b2563333c5671fecacd085141b5800cb866be16d5e3eb15a2086476675"}, - {file = "frozenlist-1.8.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9ff15928d62a0b80bb875655c39bf517938c7d589554cbd2669be42d97c2cb61"}, - {file = "frozenlist-1.8.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7bf6cdf8e07c8151fba6fe85735441240ec7f619f935a5205953d58009aef8c6"}, - {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:48e6d3f4ec5c7273dfe83ff27c91083c6c9065af655dc2684d2c200c94308bb5"}, - {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:1a7607e17ad33361677adcd1443edf6f5da0ce5e5377b798fba20fae194825f3"}, - {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:5a3a935c3a4e89c733303a2d5a7c257ea44af3a56c8202df486b7f5de40f37e1"}, - {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:940d4a017dbfed9daf46a3b086e1d2167e7012ee297fef9e1c545c4d022f5178"}, - {file = "frozenlist-1.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b9be22a69a014bc47e78072d0ecae716f5eb56c15238acca0f43d6eb8e4a5bda"}, - {file = "frozenlist-1.8.0-cp39-cp39-win32.whl", hash = "sha256:1aa77cb5697069af47472e39612976ed05343ff2e84a3dcf15437b232cbfd087"}, - {file = "frozenlist-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:7398c222d1d405e796970320036b1b563892b65809d9e5261487bb2c7f7b5c6a"}, - {file = "frozenlist-1.8.0-cp39-cp39-win_arm64.whl", hash = "sha256:b4f3b365f31c6cd4af24545ca0a244a53688cad8834e32f56831c4923b50a103"}, - {file = "frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d"}, - {file = "frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad"}, -] - -[[package]] -name = "h11" -version = "0.16.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, - {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, -] - -[[package]] -name = "html5lib" -version = "1.1" -description = "HTML parser based on the WHATWG HTML specification" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main"] -files = [ - {file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"}, - {file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"}, -] - -[package.dependencies] -six = ">=1.9" -webencodings = "*" - -[package.extras] -all = ["chardet (>=2.2)", "genshi", "lxml ; platform_python_implementation == \"CPython\""] -chardet = ["chardet (>=2.2)"] -genshi = ["genshi"] -lxml = ["lxml ; platform_python_implementation == \"CPython\""] - -[[package]] -name = "idna" -version = "3.17" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "idna-3.17-py3-none-any.whl", hash = "sha256:466e48829084efe2548012b855df21540b96f2e20e51bd124c851536556a592c"}, - {file = "idna-3.17.tar.gz", hash = "sha256:5eb0cb53bc467c12eadcf6de83163ad8527cec9416f44b9b61b19caedad2b87f"}, -] - -[package.extras] -all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] - -[[package]] -name = "importlib-metadata" -version = "9.0.0" -description = "Read metadata from Python packages" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "importlib_metadata-9.0.0-py3-none-any.whl", hash = "sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7"}, - {file = "importlib_metadata-9.0.0.tar.gz", hash = "sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc"}, -] - -[package.dependencies] -zipp = ">=3.20" - -[package.extras] -check = ["pytest-checkdocs (>=2.14)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=3.4)"] -perf = ["ipython"] -test = ["packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] -type = ["pytest-mypy (>=1.0.1) ; platform_python_implementation != \"PyPy\""] - -[[package]] -name = "multidict" -version = "6.7.1" -description = "multidict implementation" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "multidict-6.7.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c93c3db7ea657dd4637d57e74ab73de31bccefe144d3d4ce370052035bc85fb5"}, - {file = "multidict-6.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8"}, - {file = "multidict-6.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdea2e7b2456cfb6694fb113066fd0ec7ea4d67e3a35e1f4cbeea0b448bf5872"}, - {file = "multidict-6.7.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17207077e29342fdc2c9a82e4b306f1127bf1ea91f8b71e02d4798a70bb99991"}, - {file = "multidict-6.7.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4f49cb5661344764e4c7c7973e92a47a59b8fc19b6523649ec9dc4960e58a03"}, - {file = "multidict-6.7.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a9fc4caa29e2e6ae408d1c450ac8bf19892c5fca83ee634ecd88a53332c59981"}, - {file = "multidict-6.7.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c5f0c21549ab432b57dcc82130f388d84ad8179824cc3f223d5e7cfbfd4143f6"}, - {file = "multidict-6.7.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7dfb78d966b2c906ae1d28ccf6e6712a3cd04407ee5088cd276fe8cb42186190"}, - {file = "multidict-6.7.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b0d9b91d1aa44db9c1f1ecd0d9d2ae610b2f4f856448664e01a3b35899f3f92"}, - {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dd96c01a9dcd4889dcfcf9eb5544ca0c77603f239e3ffab0524ec17aea9a93ee"}, - {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:067343c68cd6612d375710f895337b3a98a033c94f14b9a99eff902f205424e2"}, - {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5884a04f4ff56c6120f6ccf703bdeb8b5079d808ba604d4d53aec0d55dc33568"}, - {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8affcf1c98b82bc901702eb73b6947a1bfa170823c153fe8a47b5f5f02e48e40"}, - {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0d17522c37d03e85c8098ec8431636309b2682cf12e58f4dbc76121fb50e4962"}, - {file = "multidict-6.7.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24c0cf81544ca5e17cfcb6e482e7a82cd475925242b308b890c9452a074d4505"}, - {file = "multidict-6.7.1-cp310-cp310-win32.whl", hash = "sha256:d82dd730a95e6643802f4454b8fdecdf08667881a9c5670db85bc5a56693f122"}, - {file = "multidict-6.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:cf37cbe5ced48d417ba045aca1b21bafca67489452debcde94778a576666a1df"}, - {file = "multidict-6.7.1-cp310-cp310-win_arm64.whl", hash = "sha256:59bc83d3f66b41dac1e7460aac1d196edc70c9ba3094965c467715a70ecb46db"}, - {file = "multidict-6.7.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d"}, - {file = "multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e"}, - {file = "multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855"}, - {file = "multidict-6.7.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3"}, - {file = "multidict-6.7.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e"}, - {file = "multidict-6.7.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a"}, - {file = "multidict-6.7.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8"}, - {file = "multidict-6.7.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0"}, - {file = "multidict-6.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144"}, - {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49"}, - {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71"}, - {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3"}, - {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c"}, - {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0"}, - {file = "multidict-6.7.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa"}, - {file = "multidict-6.7.1-cp311-cp311-win32.whl", hash = "sha256:d62b7f64ffde3b99d06b707a280db04fb3855b55f5a06df387236051d0668f4a"}, - {file = "multidict-6.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:bdbf9f3b332abd0cdb306e7c2113818ab1e922dc84b8f8fd06ec89ed2a19ab8b"}, - {file = "multidict-6.7.1-cp311-cp311-win_arm64.whl", hash = "sha256:b8c990b037d2fff2f4e33d3f21b9b531c5745b33a49a7d6dbe7a177266af44f6"}, - {file = "multidict-6.7.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a90f75c956e32891a4eda3639ce6dd86e87105271f43d43442a3aedf3cddf172"}, - {file = "multidict-6.7.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fccb473e87eaa1382689053e4a4618e7ba7b9b9b8d6adf2027ee474597128cd"}, - {file = "multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7"}, - {file = "multidict-6.7.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb2a55f408c3043e42b40cc8eecd575afa27b7e0b956dfb190de0f8499a57a53"}, - {file = "multidict-6.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb0ce7b2a32d09892b3dd6cc44877a0d02a33241fafca5f25c8b6b62374f8b75"}, - {file = "multidict-6.7.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c3a32d23520ee37bf327d1e1a656fec76a2edd5c038bf43eddfa0572ec49c60b"}, - {file = "multidict-6.7.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9c90fed18bffc0189ba814749fdcc102b536e83a9f738a9003e569acd540a733"}, - {file = "multidict-6.7.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:da62917e6076f512daccfbbde27f46fed1c98fee202f0559adec8ee0de67f71a"}, - {file = "multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961"}, - {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3758692429e4e32f1ba0df23219cd0b4fc0a52f476726fff9337d1a57676a582"}, - {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:398c1478926eca669f2fd6a5856b6de9c0acf23a2cb59a14c0ba5844fa38077e"}, - {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c102791b1c4f3ab36ce4101154549105a53dc828f016356b3e3bcae2e3a039d3"}, - {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a088b62bd733e2ad12c50dad01b7d0166c30287c166e137433d3b410add807a6"}, - {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3d51ff4785d58d3f6c91bdbffcb5e1f7ddfda557727043aa20d20ec4f65e324a"}, - {file = "multidict-6.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc5907494fccf3e7d3f94f95c91d6336b092b5fc83811720fae5e2765890dfba"}, - {file = "multidict-6.7.1-cp312-cp312-win32.whl", hash = "sha256:28ca5ce2fd9716631133d0e9a9b9a745ad7f60bac2bccafb56aa380fc0b6c511"}, - {file = "multidict-6.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19"}, - {file = "multidict-6.7.1-cp312-cp312-win_arm64.whl", hash = "sha256:ba0a9fb644d0c1a2194cf7ffb043bd852cea63a57f66fbd33959f7dae18517bf"}, - {file = "multidict-6.7.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2b41f5fed0ed563624f1c17630cb9941cf2309d4df00e494b551b5f3e3d67a23"}, - {file = "multidict-6.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84e61e3af5463c19b67ced91f6c634effb89ef8bfc5ca0267f954451ed4bb6a2"}, - {file = "multidict-6.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:935434b9853c7c112eee7ac891bc4cb86455aa631269ae35442cb316790c1445"}, - {file = "multidict-6.7.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:432feb25a1cb67fe82a9680b4d65fb542e4635cb3166cd9c01560651ad60f177"}, - {file = "multidict-6.7.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e82d14e3c948952a1a85503817e038cba5905a3352de76b9a465075d072fba23"}, - {file = "multidict-6.7.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4cfb48c6ea66c83bcaaf7e4dfa7ec1b6bbcf751b7db85a328902796dfde4c060"}, - {file = "multidict-6.7.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1d540e51b7e8e170174555edecddbd5538105443754539193e3e1061864d444d"}, - {file = "multidict-6.7.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:273d23f4b40f3dce4d6c8a821c741a86dec62cded82e1175ba3d99be128147ed"}, - {file = "multidict-6.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d624335fd4fa1c08a53f8b4be7676ebde19cd092b3895c421045ca87895b429"}, - {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:12fad252f8b267cc75b66e8fc51b3079604e8d43a75428ffe193cd9e2195dfd6"}, - {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:03ede2a6ffbe8ef936b92cb4529f27f42be7f56afcdab5ab739cd5f27fb1cbf9"}, - {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:90efbcf47dbe33dcf643a1e400d67d59abeac5db07dc3f27d6bdeae497a2198c"}, - {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c4b9bfc148f5a91be9244d6264c53035c8a0dcd2f51f1c3c6e30e30ebaa1c84"}, - {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:401c5a650f3add2472d1d288c26deebc540f99e2fb83e9525007a74cd2116f1d"}, - {file = "multidict-6.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:97891f3b1b3ffbded884e2916cacf3c6fc87b66bb0dde46f7357404750559f33"}, - {file = "multidict-6.7.1-cp313-cp313-win32.whl", hash = "sha256:e1c5988359516095535c4301af38d8a8838534158f649c05dd1050222321bcb3"}, - {file = "multidict-6.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:960c83bf01a95b12b08fd54324a4eb1d5b52c88932b5cba5d6e712bb3ed12eb5"}, - {file = "multidict-6.7.1-cp313-cp313-win_arm64.whl", hash = "sha256:563fe25c678aaba333d5399408f5ec3c383ca5b663e7f774dd179a520b8144df"}, - {file = "multidict-6.7.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:c76c4bec1538375dad9d452d246ca5368ad6e1c9039dadcf007ae59c70619ea1"}, - {file = "multidict-6.7.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:57b46b24b5d5ebcc978da4ec23a819a9402b4228b8a90d9c656422b4bdd8a963"}, - {file = "multidict-6.7.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e954b24433c768ce78ab7929e84ccf3422e46deb45a4dc9f93438f8217fa2d34"}, - {file = "multidict-6.7.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3bd231490fa7217cc832528e1cd8752a96f0125ddd2b5749390f7c3ec8721b65"}, - {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:253282d70d67885a15c8a7716f3a73edf2d635793ceda8173b9ecc21f2fb8292"}, - {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b4c48648d7649c9335cf1927a8b87fa692de3dcb15faa676c6a6f1f1aabda43"}, - {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:98bc624954ec4d2c7cb074b8eefc2b5d0ce7d482e410df446414355d158fe4ca"}, - {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1b99af4d9eec0b49927b4402bcbb58dea89d3e0db8806a4086117019939ad3dd"}, - {file = "multidict-6.7.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aac4f16b472d5b7dc6f66a0d49dd57b0e0902090be16594dc9ebfd3d17c47e7"}, - {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:21f830fe223215dffd51f538e78c172ed7c7f60c9b96a2bf05c4848ad49921c3"}, - {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f5dd81c45b05518b9aa4da4aa74e1c93d715efa234fd3e8a179df611cc85e5f4"}, - {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:eb304767bca2bb92fb9c5bd33cedc95baee5bb5f6c88e63706533a1c06ad08c8"}, - {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c9035dde0f916702850ef66460bc4239d89d08df4d02023a5926e7446724212c"}, - {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:af959b9beeb66c822380f222f0e0a1889331597e81f1ded7f374f3ecb0fd6c52"}, - {file = "multidict-6.7.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:41f2952231456154ee479651491e94118229844dd7226541788be783be2b5108"}, - {file = "multidict-6.7.1-cp313-cp313t-win32.whl", hash = "sha256:df9f19c28adcb40b6aae30bbaa1478c389efd50c28d541d76760199fc1037c32"}, - {file = "multidict-6.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d54ecf9f301853f2c5e802da559604b3e95bb7a3b01a9c295c6ee591b9882de8"}, - {file = "multidict-6.7.1-cp313-cp313t-win_arm64.whl", hash = "sha256:5a37ca18e360377cfda1d62f5f382ff41f2b8c4ccb329ed974cc2e1643440118"}, - {file = "multidict-6.7.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee"}, - {file = "multidict-6.7.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2"}, - {file = "multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1"}, - {file = "multidict-6.7.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d"}, - {file = "multidict-6.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31"}, - {file = "multidict-6.7.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048"}, - {file = "multidict-6.7.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362"}, - {file = "multidict-6.7.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37"}, - {file = "multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709"}, - {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0"}, - {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb"}, - {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd"}, - {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601"}, - {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1"}, - {file = "multidict-6.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b"}, - {file = "multidict-6.7.1-cp314-cp314-win32.whl", hash = "sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d"}, - {file = "multidict-6.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f"}, - {file = "multidict-6.7.1-cp314-cp314-win_arm64.whl", hash = "sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5"}, - {file = "multidict-6.7.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581"}, - {file = "multidict-6.7.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a"}, - {file = "multidict-6.7.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c"}, - {file = "multidict-6.7.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262"}, - {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59"}, - {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889"}, - {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4"}, - {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d"}, - {file = "multidict-6.7.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609"}, - {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489"}, - {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c"}, - {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e"}, - {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c"}, - {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9"}, - {file = "multidict-6.7.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2"}, - {file = "multidict-6.7.1-cp314-cp314t-win32.whl", hash = "sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7"}, - {file = "multidict-6.7.1-cp314-cp314t-win_amd64.whl", hash = "sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5"}, - {file = "multidict-6.7.1-cp314-cp314t-win_arm64.whl", hash = "sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2"}, - {file = "multidict-6.7.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:65573858d27cdeaca41893185677dc82395159aa28875a8867af66532d413a8f"}, - {file = "multidict-6.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c524c6fb8fc342793708ab111c4dbc90ff9abd568de220432500e47e990c0358"}, - {file = "multidict-6.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:aa23b001d968faef416ff70dc0f1ab045517b9b42a90edd3e9bcdb06479e31d5"}, - {file = "multidict-6.7.1-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6704fa2b7453b2fb121740555fa1ee20cd98c4d011120caf4d2b8d4e7c76eec0"}, - {file = "multidict-6.7.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:121a34e5bfa410cdf2c8c49716de160de3b1dbcd86b49656f5681e4543bcd1a8"}, - {file = "multidict-6.7.1-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:026d264228bcd637d4e060844e39cdc60f86c479e463d49075dedc21b18fbbe0"}, - {file = "multidict-6.7.1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0e697826df7eb63418ee190fd06ce9f1803593bb4b9517d08c60d9b9a7f69d8f"}, - {file = "multidict-6.7.1-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb08271280173720e9fea9ede98e5231defcbad90f1624bea26f32ec8a956e2f"}, - {file = "multidict-6.7.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6b3228e1d80af737b72925ce5fb4daf5a335e49cd7ab77ed7b9fdfbf58c526e"}, - {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3943debf0fbb57bdde5901695c11094a9a36723e5c03875f87718ee15ca2f4d2"}, - {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:98c5787b0a0d9a41d9311eae44c3b76e6753def8d8870ab501320efe75a6a5f8"}, - {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:08ccb2a6dc72009093ebe7f3f073e5ec5964cba9a706fa94b1a1484039b87941"}, - {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb351f72c26dc9abe338ca7294661aa22969ad8ffe7ef7d5541d19f368dc854a"}, - {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ac1c665bad8b5d762f5f85ebe4d94130c26965f11de70c708c75671297c776de"}, - {file = "multidict-6.7.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fa6609d0364f4f6f58351b4659a1f3e0e898ba2a8c5cac04cb2c7bc556b0bc5"}, - {file = "multidict-6.7.1-cp39-cp39-win32.whl", hash = "sha256:6f77ce314a29263e67adadc7e7c1bc699fcb3a305059ab973d038f87caa42ed0"}, - {file = "multidict-6.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:f537b55778cd3cbee430abe3131255d3a78202e0f9ea7ffc6ada893a4bcaeea4"}, - {file = "multidict-6.7.1-cp39-cp39-win_arm64.whl", hash = "sha256:749aa54f578f2e5f439538706a475aa844bfa8ef75854b1401e6e528e4937cf9"}, - {file = "multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56"}, - {file = "multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d"}, -] - -[package.dependencies] -typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""} - -[[package]] -name = "numpy" -version = "2.2.6" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.10" -groups = ["main"] -markers = "python_version == \"3.10\"" -files = [ - {file = "numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb"}, - {file = "numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90"}, - {file = "numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163"}, - {file = "numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf"}, - {file = "numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83"}, - {file = "numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915"}, - {file = "numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680"}, - {file = "numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289"}, - {file = "numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d"}, - {file = "numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3"}, - {file = "numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f9f1adb22318e121c5c69a09142811a201ef17ab257a1e66ca3025065b7f53ae"}, - {file = "numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c820a93b0255bc360f53eca31a0e676fd1101f673dda8da93454a12e23fc5f7a"}, - {file = "numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3d70692235e759f260c3d837193090014aebdf026dfd167834bcba43e30c2a42"}, - {file = "numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:481b49095335f8eed42e39e8041327c05b0f6f4780488f61286ed3c01368d491"}, - {file = "numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b64d8d4d17135e00c8e346e0a738deb17e754230d7e0810ac5012750bbd85a5a"}, - {file = "numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba10f8411898fc418a521833e014a77d3ca01c15b0c6cdcce6a0d2897e6dbbdf"}, - {file = "numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd48227a919f1bafbdda0583705e547892342c26fb127219d60a5c36882609d1"}, - {file = "numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9551a499bf125c1d4f9e250377c1ee2eddd02e01eac6644c080162c0c51778ab"}, - {file = "numpy-2.2.6-cp311-cp311-win32.whl", hash = "sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47"}, - {file = "numpy-2.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:e8213002e427c69c45a52bbd94163084025f533a55a59d6f9c5b820774ef3303"}, - {file = "numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff"}, - {file = "numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c"}, - {file = "numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3"}, - {file = "numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282"}, - {file = "numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87"}, - {file = "numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249"}, - {file = "numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49"}, - {file = "numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de"}, - {file = "numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4"}, - {file = "numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2"}, - {file = "numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84"}, - {file = "numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b"}, - {file = "numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d"}, - {file = "numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566"}, - {file = "numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f"}, - {file = "numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f"}, - {file = "numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868"}, - {file = "numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d"}, - {file = "numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd"}, - {file = "numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c"}, - {file = "numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6"}, - {file = "numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda"}, - {file = "numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40"}, - {file = "numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8"}, - {file = "numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f"}, - {file = "numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa"}, - {file = "numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571"}, - {file = "numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1"}, - {file = "numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff"}, - {file = "numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06"}, - {file = "numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d"}, - {file = "numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db"}, - {file = "numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543"}, - {file = "numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00"}, - {file = "numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd"}, -] - -[[package]] -name = "numpy" -version = "2.4.6" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.11" -groups = ["main"] -markers = "python_version >= \"3.11\"" -files = [ - {file = "numpy-2.4.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4"}, - {file = "numpy-2.4.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:110f8b71aacb688ec69062bb7f6938a0f8acb01b7c1c4beb453c65b6d234584d"}, - {file = "numpy-2.4.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:4cfe66903cc32a9921a6733d96b19bb6abf310397581bbad89c228f5abaf0ee8"}, - {file = "numpy-2.4.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8155154c7c691289fe18f510b5d4657c68c67989f293f0535a91360392ff6538"}, - {file = "numpy-2.4.6-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ab0a9c4ffb1a6d95ef519fe4247dba8eb6b18ad93999f76b7f657039acabd47"}, - {file = "numpy-2.4.6-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89cd468399cfd2504718f0ba50e410dca55a170b61a02ad92bb18c8a65186e93"}, - {file = "numpy-2.4.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2d37ab77531417474168eb79d6d80b14f821a966818505d03013d0833edb7a8"}, - {file = "numpy-2.4.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f407cb6b8e9d6d8c626bc73c945db1706035af8fd632295547bf1c9e46d092d6"}, - {file = "numpy-2.4.6-cp311-cp311-win32.whl", hash = "sha256:ddea102b48f9e339f3948bf22040944184627a30fdf7f858667673b9c5f033c8"}, - {file = "numpy-2.4.6-cp311-cp311-win_amd64.whl", hash = "sha256:1e254a00cdf42b1e4d5b3d68d33af63268d41340d8885df2ab6470f2e1500147"}, - {file = "numpy-2.4.6-cp311-cp311-win_arm64.whl", hash = "sha256:ed9749eef4cbd126da3dc1d6bcb3a57f5eb7ac6a6484146bdbf743f552dfc577"}, - {file = "numpy-2.4.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:001fbb8e08d942dd57599e781f2472269ee7f2755fae407b4f67b2f0b17da3f1"}, - {file = "numpy-2.4.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ebfb099f8dcf083deef3ac1ca4c1503f387cf76296fcb3816b66f5ecb5f54fdb"}, - {file = "numpy-2.4.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3213d622a0283a39a93d188f3cf72b26862df52fbb4ca3697f51705016523d41"}, - {file = "numpy-2.4.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:357cc07a6d7b0b182ff02249616a03742827ebb1277546b5c7cd7f7620a45698"}, - {file = "numpy-2.4.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f9fb9157b4ce2971008323afe46053787b526ef624fea915b261468a8421a0f"}, - {file = "numpy-2.4.6-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90f9849678c75fe7afa2d348ac842c168b0a4d3d61919687216dfc547976d853"}, - {file = "numpy-2.4.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c1a2af6c6ef86344a6b0db6b97834208bf598db514f2b155042439b62605601a"}, - {file = "numpy-2.4.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5805d5a22fd19c8ccff10a9561f9df94436b0545619ea579db2d3c35294bce2"}, - {file = "numpy-2.4.6-cp312-cp312-win32.whl", hash = "sha256:e3eeb0aabd6bd5ce64faae67e9935203a6991b4bc2a485a767fbafb2c5125f45"}, - {file = "numpy-2.4.6-cp312-cp312-win_amd64.whl", hash = "sha256:d8e8286dd7cea7895157318d1b91cdacac64c479f3cbc8dce548331728484751"}, - {file = "numpy-2.4.6-cp312-cp312-win_arm64.whl", hash = "sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8"}, - {file = "numpy-2.4.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:511dbaf848decaaaf4b4ca48032619fb3138710c4bf7da7617765edad1ef96b0"}, - {file = "numpy-2.4.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bf162abab1c1a736333192707cef898e735a5ca00f38f27eeedf44b39d9e85eb"}, - {file = "numpy-2.4.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:043191bfa8eab18c776647b62723ac9dddece59743b13f49b2016094129c2b3f"}, - {file = "numpy-2.4.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:6180d8b35af935aed8ece3a85e0a43f87393ae0ac87c8d2c8bd2c993f7270ef3"}, - {file = "numpy-2.4.6-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72fbe16c6fac95aedf5937fa873445cec2110be35d8a4e9433d7501fd98dae6b"}, - {file = "numpy-2.4.6-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7830bab239b79cda9c08c2da014761cafb48da6150e1da17ac06283f43b6089"}, - {file = "numpy-2.4.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ef4aea96ce4d3b074422cb4f2f64e216bf9e213004bb58ecfdf50ea02ea8eb9a"}, - {file = "numpy-2.4.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dfa20cc6ca228e6b155b11da03825975ce66aea520985dbbddf0f2a5a495c605"}, - {file = "numpy-2.4.6-cp313-cp313-win32.whl", hash = "sha256:56b39e5e0622a09a25bf5baf62f4bcf0cb8a41ae6e2819cf49bbc5a74c083f91"}, - {file = "numpy-2.4.6-cp313-cp313-win_amd64.whl", hash = "sha256:c4fc99836233ea196540b17ab0983aff60ed07941751930f5f4d05bc3b3b7359"}, - {file = "numpy-2.4.6-cp313-cp313-win_arm64.whl", hash = "sha256:a7c711e21628b52034bb5ab8d1bce291f752fcc5e92accc615778acee1ff4778"}, - {file = "numpy-2.4.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:112b06a867b235ef466ed3508ddf0238050df9c727cafb5301ac385b899189a1"}, - {file = "numpy-2.4.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:eaf7fa2de5c0be8ae6ff8e9bea2ccd725e980541244521d8d4b5f3354a27babe"}, - {file = "numpy-2.4.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:7265a2f3d436e54ef9f2b52b5c937e6be778781bd97a590319d7348f1c1ca997"}, - {file = "numpy-2.4.6-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20"}, - {file = "numpy-2.4.6-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ede83e07a75dd06bc501566c1eca2afc0d61677c1472ac9ad93fdee6e638a48d"}, - {file = "numpy-2.4.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:68bb27509ac1b9a3443094260f6326150663b06abe40b73a2f81160623da5b67"}, - {file = "numpy-2.4.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a0df0043bdb289bde1f62da130d20df23d58b45429f752bc7a8fc5325a225ecd"}, - {file = "numpy-2.4.6-cp313-cp313t-win32.whl", hash = "sha256:29a287e0cf63ff528da061de6b9f64a4618da591ca1046aafc54062e40ca7eab"}, - {file = "numpy-2.4.6-cp313-cp313t-win_amd64.whl", hash = "sha256:25c692919ac5a01f170a3bfcd62d745b24fd095c353d50812637d6fcab442e75"}, - {file = "numpy-2.4.6-cp313-cp313t-win_arm64.whl", hash = "sha256:1e978ec1e8bd0e0e4de6bb75de9d30cbb74db6b6a2bb727618613703ca0167dd"}, - {file = "numpy-2.4.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06ca2f61ec4385a07a6977c55ba998a4466c123642b4a32694d3128fce18c079"}, - {file = "numpy-2.4.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7"}, - {file = "numpy-2.4.6-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:d581b735e177fdcdce6fed8e7e8880a3fb6ee4e3653a3ac6af01c6f4c03effc5"}, - {file = "numpy-2.4.6-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:0a041d3d761dc3c35cc56ce0351506a02bcbc25f7b169f652435141a17db9096"}, - {file = "numpy-2.4.6-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40fdc1ae7125e518ea98e53e69a4ebc27e1fd50510c47b7ea130cf21e5e1d42b"}, - {file = "numpy-2.4.6-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8"}, - {file = "numpy-2.4.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:33111801a01c12a8a1e3721f0a9232f8cfc8ae2c6b7098167e6f623c6073f402"}, - {file = "numpy-2.4.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae506e6902902557576a26ff33eda8695e7ecb3cb36c3b573a0765dee114ebdb"}, - {file = "numpy-2.4.6-cp314-cp314-win32.whl", hash = "sha256:aaf159caa35993cb1f56fb9b8e4610d35758e7ca005412eb1daa856a78c9c4b1"}, - {file = "numpy-2.4.6-cp314-cp314-win_amd64.whl", hash = "sha256:b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261"}, - {file = "numpy-2.4.6-cp314-cp314-win_arm64.whl", hash = "sha256:6f41ae150c4e32db4f3310cdaf64b1593a03dbabe29eec77fc9b50fe64061df6"}, - {file = "numpy-2.4.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ece3d2cfe132e7d51f44a832b303895e6f2d499c5e74dfbdb06ee246147a304a"}, - {file = "numpy-2.4.6-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:e3e5193ef5a3dc73bceee50f7fdc2c90dbb76c42df8d8fae3d1067a583df579e"}, - {file = "numpy-2.4.6-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:17f9ade344e7d9b464a084d69bcf18fc691cb1db67c62ed80820bf4926d78f0e"}, - {file = "numpy-2.4.6-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cd5ffd25db4e7ba6a375693b3fc0fc1791ec636c17db3720da19bde7180ec43"}, - {file = "numpy-2.4.6-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d92c3819208a60205a12a245c91ad70cb0a85336659b19b834205573ac8456e"}, - {file = "numpy-2.4.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e85b752a1e912b70eaad4fafbd4d1238007ab221de2009b9a2f5ae7461239895"}, - {file = "numpy-2.4.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:29cb7f67d10b479ff07c17d33e39f78c07f71c40ef30d63c153d340e96cd3fb4"}, - {file = "numpy-2.4.6-cp314-cp314t-win32.whl", hash = "sha256:260a5d70215b61ab4fadf5c7baacd64821842975eea312125ed3c39a6391b063"}, - {file = "numpy-2.4.6-cp314-cp314t-win_amd64.whl", hash = "sha256:81a1cca95ed5bb92aa8b10dd2cdc9a0d3853a50fad926c28b5d7e8ea54389627"}, - {file = "numpy-2.4.6-cp314-cp314t-win_arm64.whl", hash = "sha256:0c9136e14ed34a9e343a31c533d78a9813a69a3148332bce5e9821cb2f996e66"}, - {file = "numpy-2.4.6-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:55cced7c52e981362f708ad635198e97a752dfba412cc03c23bbf3bd8d5cd662"}, - {file = "numpy-2.4.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d6da64deb6b8ed903e7560180a92f2d804ee1ba5eeb849ac2748b8c1aba1f6d7"}, - {file = "numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:68a5124b13fa6cc2086764a20005d30bc0548146f7f5322f02fce212ca14317f"}, - {file = "numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:948424b06129ce883307e8cff868c31396d8dc7630a59c61d70d98dbe70f222c"}, - {file = "numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbbdb29840ca3d91ee0fece42fc29278886d908280bfec0a5846c6f901a3eb0"}, - {file = "numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8ad03c0965fb3c692200e74d458ca28c1dbb4ce96f9a479a8aa041ad5fabca02"}, - {file = "numpy-2.4.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:2803abfebfc990042cd494d8ce2d5f82e9d847af6d35ec486923aa19dbad5e73"}, - {file = "numpy-2.4.6.tar.gz", hash = "sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda"}, -] - -[[package]] -name = "openbb-core" -version = "1.6.10" -description = "OpenBB package with core functionality." -optional = false -python-versions = "<4,>=3.10" -groups = ["main"] -files = [ - {file = "openbb_core-1.6.10-py3-none-any.whl", hash = "sha256:45b036ee816f2d5b1f25124f0a76f437c8a6304aa3b7d09b4c954339c6f0c447"}, - {file = "openbb_core-1.6.10.tar.gz", hash = "sha256:37e5aabc0a03fdac4f05f460127bfcb81c249afc6d6033997c246a97be70d0fe"}, -] - -[package.dependencies] -aiohttp = ">=3.13.3" -fastapi = ">=0.128.0,<0.129.0" -html5lib = ">=1.1,<2.0" -importlib-metadata = ">=6.8.0" -pandas = ">=1.5.3" -pydantic = ">=2.12.3,<3.0.0" -pyjwt = ">=2.12.0,<3.0.0" -python-dotenv = ">=1.0.0,<2.0.0" -python-multipart = ">=0.0.27,<0.0.28" -requests = ">=2.33.0,<3.0.0" -ruff = ">=0.15,<0.16" -uuid7 = ">=0.1.0,<0.2.0" -uvicorn = ">=0.40.0,<0.41.0" -websockets = ">=15.0" - -[[package]] -name = "openpyxl" -version = "3.1.5" -description = "A Python library to read/write Excel 2010 xlsx/xlsm files" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2"}, - {file = "openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050"}, -] - -[package.dependencies] -et-xmlfile = "*" - -[[package]] -name = "pandas" -version = "2.3.3" -description = "Powerful data structures for data analysis, time series, and statistics" -optional = false -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version == \"3.10\"" -files = [ - {file = "pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c"}, - {file = "pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a"}, - {file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1"}, - {file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838"}, - {file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250"}, - {file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4"}, - {file = "pandas-2.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826"}, - {file = "pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523"}, - {file = "pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45"}, - {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66"}, - {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b"}, - {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791"}, - {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151"}, - {file = "pandas-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c"}, - {file = "pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53"}, - {file = "pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35"}, - {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908"}, - {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89"}, - {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98"}, - {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084"}, - {file = "pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b"}, - {file = "pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713"}, - {file = "pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8"}, - {file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d"}, - {file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac"}, - {file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c"}, - {file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493"}, - {file = "pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee"}, - {file = "pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5"}, - {file = "pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21"}, - {file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78"}, - {file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110"}, - {file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86"}, - {file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc"}, - {file = "pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0"}, - {file = "pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593"}, - {file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c"}, - {file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b"}, - {file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6"}, - {file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3"}, - {file = "pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5"}, - {file = "pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec"}, - {file = "pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7"}, - {file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450"}, - {file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5"}, - {file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788"}, - {file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87"}, - {file = "pandas-2.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c503ba5216814e295f40711470446bc3fd00f0faea8a086cbc688808e26f92a2"}, - {file = "pandas-2.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a637c5cdfa04b6d6e2ecedcb81fc52ffb0fd78ce2ebccc9ea964df9f658de8c8"}, - {file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:854d00d556406bffe66a4c0802f334c9ad5a96b4f1f868adf036a21b11ef13ff"}, - {file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf1f8a81d04ca90e32a0aceb819d34dbd378a98bf923b6398b9a3ec0bf44de29"}, - {file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:23ebd657a4d38268c7dfbdf089fbc31ea709d82e4923c5ffd4fbd5747133ce73"}, - {file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5554c929ccc317d41a5e3d1234f3be588248e61f08a74dd17c9eabb535777dc9"}, - {file = "pandas-2.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:d3e28b3e83862ccf4d85ff19cf8c20b2ae7e503881711ff2d534dc8f761131aa"}, - {file = "pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b"}, -] - -[package.dependencies] -numpy = {version = ">=1.22.4", markers = "python_version < \"3.11\""} -python-dateutil = ">=2.8.2" -pytz = ">=2020.1" -tzdata = ">=2022.7" - -[package.extras] -all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] -aws = ["s3fs (>=2022.11.0)"] -clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] -compression = ["zstandard (>=0.19.0)"] -computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] -consortium-standard = ["dataframe-api-compat (>=0.1.7)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] -feather = ["pyarrow (>=10.0.1)"] -fss = ["fsspec (>=2022.11.0)"] -gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] -hdf5 = ["tables (>=3.8.0)"] -html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] -mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] -output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] -parquet = ["pyarrow (>=10.0.1)"] -performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] -plot = ["matplotlib (>=3.6.3)"] -postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] -pyarrow = ["pyarrow (>=10.0.1)"] -spss = ["pyreadstat (>=1.2.0)"] -sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] -test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] -xml = ["lxml (>=4.9.2)"] - -[[package]] -name = "pandas" -version = "3.0.3" -description = "Powerful data structures for data analysis, time series, and statistics" -optional = false -python-versions = ">=3.11" -groups = ["main"] -markers = "python_version >= \"3.11\"" -files = [ - {file = "pandas-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:455f6f8139d4282188f526868dbc3c828470e88a3d9d59a891bd46a455f21b98"}, - {file = "pandas-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4e15135e2ee5df1063313e2425ceef8ac0f4ae775893815b0923651b806a5639"}, - {file = "pandas-3.0.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:05f1f1752b8533ea03f7f39a9c15b1a058d067bb48f4748948e7a8691e0510f2"}, - {file = "pandas-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a1e45c80cceb3b4a21bc5939d52e8cbd8d9b7305309219d59e9754d9ce09e27"}, - {file = "pandas-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:14da8316da4d0c5a77618425996bfb1248ca87fc2c1486e6fde4652bd18b5824"}, - {file = "pandas-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a55066a0505dae0ba2b50a46637db34b46f9094c65c5d4800794ef6335010938"}, - {file = "pandas-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6674ab18ad8c57802867264b00e15e7bb904700cdd9046e3b2fa1fce237439ea"}, - {file = "pandas-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:5cc09a68b3120e0f54870dede8287a7bb1fa463907e4fcec1ea77cab6179bf7a"}, - {file = "pandas-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fed2ff7fd9779120e388e285fc029bd5cf9490cdd2e4166a9ee22c0e49a9ab09"}, - {file = "pandas-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b168fc218fd80a6cbdbdbc1a97ddc7889ed057d7eb45f50d866ceab5f39904c4"}, - {file = "pandas-3.0.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0383c72c75cdcca61a9e116e611143902dbfd08bff356829c2f6d1cf40a9ca8c"}, - {file = "pandas-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6dc0b3fd2169c9157deed50b4d519553a3655c8c6a96027136d654592be973a9"}, - {file = "pandas-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e65d5407dc0b394f509699650e4a2ec01c0514f21850f453fa60f3be79a5dbf"}, - {file = "pandas-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f8894dc474d648fe7b6ff0ca9b0bd73950d19952bc1a6534540762c5d79d305c"}, - {file = "pandas-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:c7be265b62cef88e253a941e4698604973736dcfe242fdb5198f0f7bc473cdcc"}, - {file = "pandas-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:557409bc4178e70ee8d9ddb494798e51ebf6ea59330f6be22c51bab2a7db6c49"}, - {file = "pandas-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:67b3b64c11910cfa29f4e94a14d3bff9ee693b6fc76055e7cad549cee0aec5fa"}, - {file = "pandas-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:39436b377d56d2a2e52d0395bdbee171f01068e99af5250509aceeb929f765c7"}, - {file = "pandas-3.0.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4be06d68f9ddcfc645b87534911da79a8fbffc7573c80e0edcf42a5020624d8"}, - {file = "pandas-3.0.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a4eeb6830daf35a71cc09649bd823e2b542dac246cdee9614c6e4bd65028cd6a"}, - {file = "pandas-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1928e07221f82db493cd4af1e23c1bfca524a19a4699887975bff68f49a72bfb"}, - {file = "pandas-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51b1fe551acb77dac643c6fda86084d8d446c10fe64b06a9cc29c4cc8540e7f2"}, - {file = "pandas-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:a82d532a3351d435432cd913edbccaf8b8e01d4dd0e5ced5a8d2e8ecd94c7e44"}, - {file = "pandas-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:275c14e0fce14a2ec20eee474aecd305478ea3c1e6f6a9d8fe219a165542717e"}, - {file = "pandas-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:46997386d528eb40376ecd6b033cf4a8a1e5282580f68f43de875b78cba2199d"}, - {file = "pandas-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:261e308dfb22448384b7580cf719d2f998fe2966c92893c3e77d14008af1f066"}, - {file = "pandas-3.0.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dd1a5d1def6a46002e964510bdc67c368aa0951df5d1d9f8365336f5a1f490cd"}, - {file = "pandas-3.0.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d72828c20c6d6e83e1e22a6a3b47b326b71664112fa9705dcbccfd7a39b62085"}, - {file = "pandas-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d26cbe1fcfc12e8fd900e2454163e466b2d3af84f7c75481df7683ffc073d870"}, - {file = "pandas-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3e91cec1879ada0624fc3dc9953c5cbd60208e59c0db28f540c5d6d47502422f"}, - {file = "pandas-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:08d789b41f87e0905880e293cedf6197ce71fe67cc081358b1e148a491b9bd13"}, - {file = "pandas-3.0.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:3650109c0f22879df8bd6179ab9ee3d7f1d1d4e7e0094a3f0032d9f51e2e64ac"}, - {file = "pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:bab900348131a7db1f69a7309ef141fd5680f1487094193bcbbb61791573bf8f"}, - {file = "pandas-3.0.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba7e08b9ac1d54569cd1e256e3668975ed624d6826f7b68df0342b012007bddb"}, - {file = "pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d71c63ae4ebdbf70209742096f1fc46a83a0613c99d4b23766cced9ff8cd62a"}, - {file = "pandas-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e3a2ec42c98ffa2565a67e08e218d06d72576d758d90facb7c00805194d8f360"}, - {file = "pandas-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:335f62418ed562cfc3c49e9e196375c28b729dcef8543abf4f9438e381bf3c76"}, - {file = "pandas-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:3c20a521bbb85902f79f7270c80a59e1b5452d96d170c034f207181870f97ac5"}, - {file = "pandas-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:a2d2dff8a04f3917b55ab3910c32990f8ddf7eceba114947838cefa976a68977"}, - {file = "pandas-3.0.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:0d589105b3c14645af1738ff279b2995102d8f7a03b0a66dc8d95550eb513e04"}, - {file = "pandas-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:13fc1e853d9e04743d11ba75a985ccbc2a317fe07d8af61e445a6fd24dacd6a6"}, - {file = "pandas-3.0.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:819959dab7bbd0049c15623fbac4e29a191b9528160a61fb1032242d8ced2d9c"}, - {file = "pandas-3.0.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:60ae316d3fd75d1858d450d0db0103ea2be3e7d4a95ec2f064f7e2ae63f7b028"}, - {file = "pandas-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd3a518890b400d32f9023722dc9a9a5c969f00b415419a3c06c043f09bb5d7d"}, - {file = "pandas-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9c39be2d709d01fa972a0cabc522389fceca4f3969332ba25a7d6c5802cf976a"}, - {file = "pandas-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4db8c527972a821cf5286b40ccc57642a39bc62e62022b42f99f8a67fca8c3a1"}, - {file = "pandas-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b2c95f8bfc1ee412bf482605d7bfd30c12d1d26bd59fdd91efeef1d4718decb1"}, - {file = "pandas-3.0.3.tar.gz", hash = "sha256:696a4a00a2a2a35d4e5deb3fc946641b96c944f02230e4f76137fe35d806c4fc"}, -] - -[package.dependencies] -numpy = [ - {version = ">=1.26.0", markers = "python_version < \"3.14\""}, - {version = ">=2.3.3", markers = "python_version >= \"3.14\""}, -] -python-dateutil = ">=2.8.2" -tzdata = {version = "*", markers = "sys_platform == \"win32\" or sys_platform == \"emscripten\""} - -[package.extras] -all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "adbc-driver-sqlite (>=1.2.0)", "beautifulsoup4 (>=4.12.3)", "bottleneck (>=1.4.2)", "fastparquet (>=2024.11.0)", "fsspec (>=2024.10.0)", "gcsfs (>=2024.10.0)", "html5lib (>=1.1)", "hypothesis (>=6.116.0)", "jinja2 (>=3.1.5)", "lxml (>=5.3.0)", "matplotlib (>=3.9.3)", "numba (>=0.60.0)", "numexpr (>=2.10.2)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.5)", "psycopg2 (>=2.9.10)", "pyarrow (>=13.0.0)", "pyiceberg (>=0.8.1)", "pymysql (>=1.1.1)", "pyreadstat (>=1.2.8)", "pytest (>=8.3.4)", "pytest-xdist (>=3.6.1)", "python-calamine (>=0.3.0)", "pytz (>=2020.1)", "pyxlsb (>=1.0.10)", "qtpy (>=2.4.2)", "s3fs (>=2024.10.0)", "scipy (>=1.14.1)", "tables (>=3.10.1)", "tabulate (>=0.9.0)", "xarray (>=2024.10.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.2.0)", "zstandard (>=0.23.0)"] -aws = ["s3fs (>=2024.10.0)"] -clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.4.2)"] -compression = ["zstandard (>=0.23.0)"] -computation = ["scipy (>=1.14.1)", "xarray (>=2024.10.0)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.5)", "python-calamine (>=0.3.0)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.2.0)"] -feather = ["pyarrow (>=13.0.0)"] -fss = ["fsspec (>=2024.10.0)"] -gcp = ["gcsfs (>=2024.10.0)"] -hdf5 = ["tables (>=3.10.1)"] -html = ["beautifulsoup4 (>=4.12.3)", "html5lib (>=1.1)", "lxml (>=5.3.0)"] -iceberg = ["pyiceberg (>=0.8.1)"] -mysql = ["SQLAlchemy (>=2.0.36)", "pymysql (>=1.1.1)"] -output-formatting = ["jinja2 (>=3.1.5)", "tabulate (>=0.9.0)"] -parquet = ["pyarrow (>=13.0.0)"] -performance = ["bottleneck (>=1.4.2)", "numba (>=0.60.0)", "numexpr (>=2.10.2)"] -plot = ["matplotlib (>=3.9.3)"] -postgresql = ["SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "psycopg2 (>=2.9.10)"] -pyarrow = ["pyarrow (>=13.0.0)"] -spss = ["pyreadstat (>=1.2.8)"] -sql-other = ["SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "adbc-driver-sqlite (>=1.2.0)"] -test = ["hypothesis (>=6.116.0)", "pytest (>=8.3.4)", "pytest-xdist (>=3.6.1)"] -timezone = ["pytz (>=2020.1)"] -xml = ["lxml (>=5.3.0)"] - -[[package]] -name = "propcache" -version = "0.5.2" -description = "Accelerated property cache" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "propcache-0.5.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a81be28596d6559f6131ef33e10200de6e17643b3c74ce03f9eb103be6ae8b"}, - {file = "propcache-0.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29cbaac5ea0212663e6845e04b5e188d5a6ae6dd919810ac835bf1d3b42c3f4c"}, - {file = "propcache-0.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6bf3be92233808fcd338eba0fb4d0b59ec5772af4f4ecfcec450d1bfc0f8b5eb"}, - {file = "propcache-0.5.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2f8ea531c794b9d6274acd4e8d2c2ebcac590a4361d27482edd3010b79f1325e"}, - {file = "propcache-0.5.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:decfca4c79dd53ebab484b00cc4b6717d8c369f86e74aa4ca395a64ac651495e"}, - {file = "propcache-0.5.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4621064bbf28fa77ff64dd5d94367c04684c67d3a5bf1dff25f0cd0d98a38f3b"}, - {file = "propcache-0.5.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b96db7141a592cbc968daf1feea83a118e6ab378af4abbc72b248c895414c22d"}, - {file = "propcache-0.5.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1ca071adabaab6e9219924bbe00af821f1ee7de113a9eca1cdc292de3d120f4d"}, - {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e4294d04a94dcab1b3bccd8b66d962dcad411a1d19414b2a41d1445f1de32ad0"}, - {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a0e399a2eccb91ed18721f86aa85757727400b6865c89e88934781deb9c8498b"}, - {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:823581fd5cb08b12a48bfa11fe962a7916766b6170c17b028fbdf762b85eb9bf"}, - {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:949c91d1a990cf3b2e8188dfcfb25005e0b834a06c63fa4ef9f360878ce21ecf"}, - {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:cc1177027eda740fdb152706bd215a3f124e3eea15afc39f2cb9fe351b50619e"}, - {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b05d643f944a8c3c4bd86d65ffd87bf3264b617f87791940302bc474d2ff5274"}, - {file = "propcache-0.5.2-cp310-cp310-win32.whl", hash = "sha256:8114f28879e0904748e831c3a7774261bd9e75f49be089f389a76f959dcd13fe"}, - {file = "propcache-0.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:5fcb98e7598b1ee0addab320d90f65b530297a867dbfe9de52ea838077e16e3d"}, - {file = "propcache-0.5.2-cp310-cp310-win_arm64.whl", hash = "sha256:04dc2390d9edbbaef7461f33322555976ffddf0b650a038649d026358714e6c5"}, - {file = "propcache-0.5.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:74b70780220e2dd89175ca24b81b68b67c83db499ae611e7f2313cb329801c78"}, - {file = "propcache-0.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4840ab0ae0216d952f4b53dc6d0b992bfc2bedbfe360bdd9b548bc184c08959"}, - {file = "propcache-0.5.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c6844ba6364fb12f403928a82cfd295ab103a2b315c77c747b2dbe4a41894ea7"}, - {file = "propcache-0.5.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2293949b855ce597f2826452d17c2d545fb5622379c4ea6fdf525e9b8e8a2511"}, - {file = "propcache-0.5.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0fd59b5af35f74da48d905dcbad55449ba13be91823cb05a9bd590bbf5b61660"}, - {file = "propcache-0.5.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29f9309a2e42b0d273be006fdb4be2d6c39a47f6f57d8fb1cf9f81481df81b66"}, - {file = "propcache-0.5.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5aaa2b923c1944ac8febd6609cb373540a5563e7cbcb0fd770f75dace2eb817b"}, - {file = "propcache-0.5.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66ea454f095ddf5b6b14f56c064c0941c4788be11e18d2464cf643bf7203ff67"}, - {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:95f1e3f4760d404b13c9976c0229b2b49a3c8e2c62a9ce92efdd2b11ada75e3f"}, - {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:85341b12b9d55bad0bded24cac341bb34289469e03a11f3f583ea1cc1db0326c"}, - {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:26a4dca084132874e639895c3135dfad5eb20bae209f62d1aeb31b03e601c3c0"}, - {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3b199b9b2b3d6a7edf3183ba8a9a137a22b97f7df525feb5ae1eccf026d2a9c6"}, - {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e59bc9e66329185b93dab73f210f1a37f81cb40f321501db8017c9aea15dba27"}, - {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:552ffadf6ad409844bc5919c42a0a83d88314cedddaea0e41e80a8b8fffe881f"}, - {file = "propcache-0.5.2-cp311-cp311-win32.whl", hash = "sha256:cd416c1de191973c52ff1a12a57446bfc7642797b282d7caf2162d7d1b8aa9a0"}, - {file = "propcache-0.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:44e488ef40dbb452700b2b1f8188934121f6648f52c295055662d2191959ff82"}, - {file = "propcache-0.5.2-cp311-cp311-win_arm64.whl", hash = "sha256:54adaa85a22078d1e306304a40984dc5be99d599bf3dc0a24dc98f7daeab89ab"}, - {file = "propcache-0.5.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:806719138ecd720339a12410fb9614ac9b2b2d3a5fdf8235d56981c36f4039ba"}, - {file = "propcache-0.5.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:db2b80ea58eab4f86b2beec3cc8b39e8ff9276ac20e96b7cce43c8ae84cd6b5a"}, - {file = "propcache-0.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e5cbfac9f61484f7e9f3597775500cd3ebe8274e9b050c38f9525c77c97520bf"}, - {file = "propcache-0.5.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbc581d2814337da56222fab8dc5f161cd798a434e49bac27930aaef798e144"}, - {file = "propcache-0.5.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:857187f381f88c8e2fa2fe56ab94879d011b883d5a2ee5a1b60a8cd2a06846d9"}, - {file = "propcache-0.5.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:178b4a2cdaac1818e2bf1c5a99b94383fa73ea5382e032a48dec07dc5668dc42"}, - {file = "propcache-0.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f328175a2cde1f0ff2c4ed8ce968b9dcfb55f3a7153f39e2957ed994da13476"}, - {file = "propcache-0.5.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5671d09a36b06d0fd4a3da0fccbcae360e9b1570924171a15e9e0997f0249fba"}, - {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80168e2ebe4d3ec6599d10ad8f520304ae1cad9b6c5a95372aef1b66b7bfb53a"}, - {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:45f11346f884bc47444f6e6647131055844134c3175b629f84952e2b5cd62b64"}, - {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8e778ebd44ef4f66ed60a0416b06b489687db264a9c0b3620362f26489492913"}, - {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:c0cb9ed24c8964e172768d455a38254c2dd8a552905729ce006cad3d3dda59b1"}, - {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1d1ad32d9d4355e2be65574fd0bfd3677e7066b009cd5b9b2dee8aa6a6393b33"}, - {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c80f4ba3e8f00189165999a742ee526ebeccedf6c3f7beb0c7df821e9772435a"}, - {file = "propcache-0.5.2-cp312-cp312-win32.whl", hash = "sha256:8c7972d8f193740d9175f0998ab38717e6cd322d5935c5b0fef8c0d323fd9031"}, - {file = "propcache-0.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:d9ee8826a7d47863a08ac44e1a5f611a462eefc3a194b492da242128bec75b42"}, - {file = "propcache-0.5.2-cp312-cp312-win_arm64.whl", hash = "sha256:2800a4a8ead6b28cccd1ec54b59346f0def7922ee1c7598e8499c733cfbb7c84"}, - {file = "propcache-0.5.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:099aaf4b4d1a02265b92a977edf00b5c4f63b3b17ac6de39b0d637c9cac0188a"}, - {file = "propcache-0.5.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:68ce1c44c7a813a7f71ea04315a8c7b330b63db99d059a797a4651bb6f69f117"}, - {file = "propcache-0.5.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fc299c129490f55f254cd90be0deca4764e36e9a7c08b4aa588479a3bbed3098"}, - {file = "propcache-0.5.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a6ae2198be502c10f09b2516e7b5d019816924bc3183a43ce792a7bd6625e6f4"}, - {file = "propcache-0.5.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6041d31504dc1779d700e1edcfb08eea334b357620b06681a4eabb57a74e574e"}, - {file = "propcache-0.5.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7eabc04151c78a9f4d5bbb5f1faf571e4defeb4b585e0fe95b60ff2dbe4d3d7"}, - {file = "propcache-0.5.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4db0ba63d693afd40d249bd93f842b5f144f8fcbb83de05660373bcf30517b1d"}, - {file = "propcache-0.5.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1dbcf7675229b35d31abb6547d8ebc8c27a830ac3f9a794edff6254873ec7c0a"}, - {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d310c013aad2c72f1c3f2f8dd3279d460a858c551f97aeb8c63e4693cca7b4d2"}, - {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:06187263ddad280d05b4d8a8b3bb7d164cbebd469236544a42e6d9b28ac6a4fa"}, - {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3115559b8effafd63b142ea5ed53d63a16ea6469cbc63dce4ee194b42db5d853"}, - {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c60462af8e6dc30c35407c7237ea908d777b22862bbee27bc4699c0d8bcdc45a"}, - {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:40314bca9ac559716fe374094fc81c11dcc34b64fd6c585360f5775690505704"}, - {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cfa21e036ce1e1db2be04ba3b85d2df1bb1702fa01932d984c5464c665228ff4"}, - {file = "propcache-0.5.2-cp313-cp313-win32.whl", hash = "sha256:f156a3529f38063b6dbaf356e15602a7f95f8055b1295a438433a6386f10463d"}, - {file = "propcache-0.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:dfed59d0a5aeb01e242e66ff0300bc4a265a7c05f612d30016f0b60b1017d757"}, - {file = "propcache-0.5.2-cp313-cp313-win_arm64.whl", hash = "sha256:ba338430e87ceb9c8f0cf754de38a9860560261e56c00376debd628698a7364f"}, - {file = "propcache-0.5.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a592f5f3da71c8691c788c13cb6734b6d17663d2e1cb8caddf0673d01ef8847d"}, - {file = "propcache-0.5.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6a997d0489e9668a384fcfd5061b857aa5361de73191cac204d04b889cfbbafa"}, - {file = "propcache-0.5.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:10734b5484ea113152ee25a91dccedf81631791805d2c9ccb054958e51842c94"}, - {file = "propcache-0.5.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cafca7e56c12bb02ae16d283742bef25a61122e9dab2b5b3f2ccbe589ce32164"}, - {file = "propcache-0.5.2-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f064f8d2b59177878b7615df1735cd8fe3462ed6be8c7b217d17a276489c2b7f"}, - {file = "propcache-0.5.2-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f78abfa8dfc32376fd1aacf597b2f2fbbe0ea751419aee718af5d4f82537ef8c"}, - {file = "propcache-0.5.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7467da8a9822bf1a55336f877340c5bcbd3c482afc43a99771169f74a26dedc"}, - {file = "propcache-0.5.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a6ddc6ac9e25de626c1f129c1b467d7ecd33ce2237d3fd0c4e429feef0a7ee1f"}, - {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2f22cbbac9e26a8e864c0985ff1268d5d939d53d9d9411a9824279097e03a2cb"}, - {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:fc76378c62a0f04d0cd82fbb1a2cd2d7e28fcb40d5873f28a6c44e388aaa2751"}, - {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:acd2c8edba48e31e58a363b8cf4e5c7db3b04b3f9e371f601df30d9b0d244836"}, - {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:452b5065457eb9991ec5eb38ff41d6cd4c991c9ac7c531c4d5849ae473a9a13f"}, - {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:3430bb2bfe1331885c427745a751e774ee679fd4344f80b97bf879815fe8fa55"}, - {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cef6cea3922890dd6c9654971001fa797b526c16ab5e1e46c05fd6f877be7568"}, - {file = "propcache-0.5.2-cp313-cp313t-win32.whl", hash = "sha256:72d61e16dd78228b58c5d47be830ff3da7e5f139abdf0aef9d86cde1c5cf2191"}, - {file = "propcache-0.5.2-cp313-cp313t-win_amd64.whl", hash = "sha256:0958834041a0166d343b8d2cedcd8bcbaeb4fdbe0cf08320c5379f143c3be6e7"}, - {file = "propcache-0.5.2-cp313-cp313t-win_arm64.whl", hash = "sha256:6de8bd93ddde9b992cf2b2e0d796d501a19026b5b9fd87356d7d0779531a8d96"}, - {file = "propcache-0.5.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:46088abff4cba581dea21ae0467a480526cb25aa5f3c269e909f800328bc3999"}, - {file = "propcache-0.5.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fc88b26f08d634f7bc819a7852e5214f5802641ab8d9fd5326892292eee1993e"}, - {file = "propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97797ebb098e670a2f92dd66f32897e30d7615b14e7f59711de23e30a9072539"}, - {file = "propcache-0.5.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba57fffe4ac99c5d30076161b5866336d97600769bad35cc68f7774b15298a4e"}, - {file = "propcache-0.5.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:583c19759d9eec1e5b69e2fbef36a7d9c326041be9746cb822d335c8cedc2979"}, - {file = "propcache-0.5.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d0326e2e5e1f3163fa306c834e48e8d490e5fae607a097a40c0648109b47ba80"}, - {file = "propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e00820e192c8dbebcafb383ebbf99030895f09905e7a0eb2e0340a0bcc2bc825"}, - {file = "propcache-0.5.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c66afea89b1e43725731d2004732a046fe6fe955d51f952c3e95a7314a284a39"}, - {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc37dec6c6cdad0b57881a5658fd14fbf53e333b1a86cf86559f190e1d9ec4"}, - {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:5570dbcc97571c15f68068e529c92715a12f8d54030e272d264b377e22bd17a5"}, - {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f814362777a9f841adddb200ecdf8f5cb1e5a3c4b7a86378edbd6ccb26edd702"}, - {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:196913dea116aeb5a2ba95af4ddcb7ea85559ae07d8eee8751688310d09168c3"}, - {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:6e7b8719005dd1175be4ab1cd25e9b98659a5e0347331506ec6760d2773a7fb5"}, - {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:51f96d685ab16e88cab128cd37a52c5da540809c8b879fa047731bfcb4ad35a4"}, - {file = "propcache-0.5.2-cp314-cp314-win32.whl", hash = "sha256:cc6fc3cc62e8501d3ed62894425040d2728ecddb1ed072737a5c70bd537aa9f0"}, - {file = "propcache-0.5.2-cp314-cp314-win_amd64.whl", hash = "sha256:81e3a30b0bb60caa22033dd0f8a3618d1d67356212514f62c57db75cb0ef410c"}, - {file = "propcache-0.5.2-cp314-cp314-win_arm64.whl", hash = "sha256:0d2c9bf8528f135dbb805ce027567e09164f7efa51a2be07458a2c0420f292d0"}, - {file = "propcache-0.5.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:4bc8ff1feffc6a61c7002ffe84634c41b822e104990ae009f44a0834430070bb"}, - {file = "propcache-0.5.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:79aa3ff0a9b566633b642fa9caf7e21ed1c13d6feca718187873f199e1514078"}, - {file = "propcache-0.5.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1b31822f4474c4036bae62de9402710051d431a606d6a0f907fec79935a071aa"}, - {file = "propcache-0.5.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fef48778b5a2a756523fdb781326b028ca75e32858b04f2cdd19f394564917"}, - {file = "propcache-0.5.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8b73ab70f1a3351fbc71f663b3e645af6dd0329100c353081cf69c37433fc6fe"}, - {file = "propcache-0.5.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5538d2c13d93e4698af7e092b57bc7298fd35d1d58e656ae18f23ee0d0378e03"}, - {file = "propcache-0.5.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd645f03898405cabe694fb8bc35241e3a9c332ec85627584fe3de201452b335"}, - {file = "propcache-0.5.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a473b3440261e0c60706e732b2ed2f517857344fc21bf48fdfe211e2d98eb285"}, - {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7afa37062e6650640e932e4cc9297d81f9f42d9944029cc386b8247dea4da837"}, - {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:8a90efd5777e996e42d568db9ac740b944d691e565cbfd31b2f7832f9184b2b8"}, - {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:f19bb891234d72535764d703bfed1153cc34f4214d5bd7150aee1eec9e8f4366"}, - {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:32775082acd2d807ee3db715c7770d38767b817870acfa08c29e057f3c4d5b56"}, - {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9282fb1a3bccd038da9f768b927b24a0c753e466c086b7c4f3c6982851eefb2d"}, - {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cc49723e2f60d6b32a0f0b08a3fd6d13203c07f1cd9566cfce0f12a917c967a2"}, - {file = "propcache-0.5.2-cp314-cp314t-win32.whl", hash = "sha256:2d7aa89ebca5acc98cba9d1472d976e394782f587bad6661003602a619fd1821"}, - {file = "propcache-0.5.2-cp314-cp314t-win_amd64.whl", hash = "sha256:d447bb0b3054be5818458fbb171208b1d9ff11eba14e18ca18b90cbb45767370"}, - {file = "propcache-0.5.2-cp314-cp314t-win_arm64.whl", hash = "sha256:fe67a3d11cd9b4efabfa45c3d00ffba2b26811442a73a581a94b67c2b5faccf6"}, - {file = "propcache-0.5.2-py3-none-any.whl", hash = "sha256:be1ddfcbb376e3de5d2e2db1d58d6d67463e6b4f9f040c000de8e300295465fe"}, - {file = "propcache-0.5.2.tar.gz", hash = "sha256:01c4fc7480cd0598bb4b57022df55b9ca296da7fc5a8760bd8451a7e63a7d427"}, -] - -[[package]] -name = "pydantic" -version = "2.13.4" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba"}, - {file = "pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.46.4" -typing-extensions = ">=4.14.1" -typing-inspection = ">=0.4.2" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.46.4" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4"}, - {file = "pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5"}, - {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63e0198ca18aad131c089b9204c23079c3afa95487e561f4c522d519e55aba"}, - {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f47286a97f0bc9b8859519809077b91b2cefe4ae47fcbf5e466a009c1c5d742b"}, - {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:905a0ed8ea6f2d61c1738835f99b699348d7857379083e5fc497fa0c967a407c"}, - {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea793e075b70290d89d8142074262885d3f7da19634845135751bd6344f73b50"}, - {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395aebd9183f9d112f569aeb5b2214d1a10a33bec8456447f7fbdfa51d38d4cd"}, - {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b078afbc25f3a1436c7a1d2cd3e322497ee99615ba97c563566fdf46aff1ee01"}, - {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f747929cf940cddb5b3668a390056ddd5ba2e5010615ea2dcf4f9c4f3ab8791d"}, - {file = "pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:daa27d92c36f24388fe3ad306b174781c747627f134452e4f128ea00ce1fe8c4"}, - {file = "pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:19e51f073cd3df251856a8a4189fbdf1de4012c3ebacfb1884f94f1eb406079f"}, - {file = "pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1747f85cee84c26985853c6f3d9bd3e75da5212912443fa111c113b9c246f39"}, - {file = "pydantic_core-2.46.4-cp310-cp310-win32.whl", hash = "sha256:2f84c03c8607173d16b5a854ec68a2f9079ae03237a54fb506d13af47e1d018d"}, - {file = "pydantic_core-2.46.4-cp310-cp310-win_amd64.whl", hash = "sha256:8358a950c8909158e3df31538a7e4edc2d7265a7c54b47f0864d9e5bae9dcebf"}, - {file = "pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594"}, - {file = "pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c"}, - {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826"}, - {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04"}, - {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e"}, - {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3"}, - {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4"}, - {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398"}, - {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3"}, - {file = "pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848"}, - {file = "pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3"}, - {file = "pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109"}, - {file = "pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda"}, - {file = "pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33"}, - {file = "pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d"}, - {file = "pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2"}, - {file = "pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f"}, - {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7"}, - {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7"}, - {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712"}, - {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4"}, - {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce"}, - {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987"}, - {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b"}, - {file = "pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458"}, - {file = "pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b"}, - {file = "pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c"}, - {file = "pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894"}, - {file = "pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89"}, - {file = "pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a"}, - {file = "pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008"}, - {file = "pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4"}, - {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76"}, - {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3"}, - {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76"}, - {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4"}, - {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a"}, - {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262"}, - {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e"}, - {file = "pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd"}, - {file = "pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be"}, - {file = "pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d"}, - {file = "pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb"}, - {file = "pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292"}, - {file = "pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d"}, - {file = "pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb"}, - {file = "pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462"}, - {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9"}, - {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4"}, - {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914"}, - {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28"}, - {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b"}, - {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c"}, - {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb"}, - {file = "pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898"}, - {file = "pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e"}, - {file = "pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519"}, - {file = "pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4"}, - {file = "pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac"}, - {file = "pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5"}, - {file = "pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596"}, - {file = "pydantic_core-2.46.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:fd8b3d9fd264be37976686c7f65cd52a83f5e84f4bfd2adf9c1d469676bbb6ae"}, - {file = "pydantic_core-2.46.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9f444c499b3eefd3a92e348059471ea0c3a6e303d9c1cec09fa748fd9f895201"}, - {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3447661d99f75a3683a4cf5c87da72f2161964611864dbbeac7fbb118bb4bfc0"}, - {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b9bab013d1c7a79d3501ff86d0bc9c31bf587db4551677b96bec07df78c6b15"}, - {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d995260fdf4e1db774581b4900e0f832abe3c7c84996726bbc161b19c8f29e76"}, - {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f13a646d65d09fbf1bc6b3a9635d30095c8e7e5cc419ff35ecc563c5fd04cd49"}, - {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432c179df7874eeb73307aad2df0755e1ae0efa61ff0ea89b93e194411ae3928"}, - {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:e68b7a074f65a2fd746c52a7ce6142ab7006074ac269ace0c25cd8ba171f8066"}, - {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4a05d69cba51d852c5c3e92758653245a50c0b646ced0cf05bd793ed592839d6"}, - {file = "pydantic_core-2.46.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:228ee9bae8bef5b1e97ec58302f80357c37199e0d0a99174e138d28e6957b9d9"}, - {file = "pydantic_core-2.46.4-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:10e17cbb10a330363733efc4d7c4d0dd827ac0909b8f6a6542298fed1ea62f29"}, - {file = "pydantic_core-2.46.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:91a06d2e259ecfbd8c901d70c3c507900458498142b3026a296b7de4d1322cc9"}, - {file = "pydantic_core-2.46.4-cp39-cp39-win32.whl", hash = "sha256:d80ee3d731373b24cebbc10d689ca4ee1875caf0d5703a245db18efd4dd37fc1"}, - {file = "pydantic_core-2.46.4-cp39-cp39-win_amd64.whl", hash = "sha256:3be77f45df024d789a672ae34f8b06fb346c4f9f46ea714956660ea4862e89ac"}, - {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c"}, - {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b"}, - {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b"}, - {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea"}, - {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7"}, - {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df"}, - {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526"}, - {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc"}, - {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983"}, - {file = "pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1"}, -] - -[package.dependencies] -typing-extensions = ">=4.14.1" - -[[package]] -name = "pyjwt" -version = "2.13.0" -description = "JSON Web Token implementation in Python" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728"}, - {file = "pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423"}, -] - -[package.dependencies] -typing_extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} - -[package.extras] -crypto = ["cryptography (>=3.4.0)"] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "python-dotenv" -version = "1.2.2" -description = "Read key-value pairs from a .env file and set them as environment variables" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a"}, - {file = "python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3"}, -] - -[package.extras] -cli = ["click (>=5.0)"] - -[[package]] -name = "python-multipart" -version = "0.0.27" -description = "A streaming multipart parser for Python" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "python_multipart-0.0.27-py3-none-any.whl", hash = "sha256:6fccfad17a27334bd0193681b369f476eda3409f17381a2d65aa7df3f7275645"}, - {file = "python_multipart-0.0.27.tar.gz", hash = "sha256:9870a6a8c5a20a5bf4f07c017bd1489006ff8836cff097b6933355ee2b49b602"}, -] - -[[package]] -name = "pytz" -version = "2026.2" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -groups = ["main"] -markers = "python_version == \"3.10\"" -files = [ - {file = "pytz-2026.2-py2.py3-none-any.whl", hash = "sha256:04156e608bee23d3792fd45c94ae47fae1036688e75032eea2e3bf0323d1f126"}, - {file = "pytz-2026.2.tar.gz", hash = "sha256:0e60b47b29f21574376f218fe21abc009894a2321ea16c6754f3cad6eb7cdd6a"}, -] - -[[package]] -name = "requests" -version = "2.34.2" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0"}, - {file = "requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed"}, -] - -[package.dependencies] -certifi = ">=2023.5.7" -charset_normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.26,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<8)"] - -[[package]] -name = "ruff" -version = "0.15.15" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "ruff-0.15.15-py3-none-linux_armv6l.whl", hash = "sha256:cf93e5388f412e1b108b1f8b34a6e036b70fe8aff89393befad96fe48670311b"}, - {file = "ruff-0.15.15-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ac5a646d1f6a7dadd5d50842dae2c1f9862ac887ef5d1b1375e02def791fde6e"}, - {file = "ruff-0.15.15-py3-none-macosx_11_0_arm64.whl", hash = "sha256:77d955a431430c66f72dd94e379ad38a16daea3d25094872ac4edf9e797be530"}, - {file = "ruff-0.15.15-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7614ee79c69788cf6cedd568069ade9cecc22a1ad20494efe8d0c9ebb4b622d4"}, - {file = "ruff-0.15.15-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3cdb1679e06a1f6b47bc384714ae96f6e2fb65ca441eb78c43d2ca554176ce1f"}, - {file = "ruff-0.15.15-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2728b93d7b23a603ea2c0ac6eb73d760bd38ec9de35f35fb41e18f7a3fee7622"}, - {file = "ruff-0.15.15-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be582fcc0db438902c7792b08d6ddf6c9b9e21addaa10092c2c741cfb09e5a45"}, - {file = "ruff-0.15.15-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7aa77465b8ecaf1a27bea098d696f7fed5e1eccbd10b321b682d6de586ae5627"}, - {file = "ruff-0.15.15-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48decfa11d740de4889de623be1463308346312f2409a56e24aa280c86162dc4"}, - {file = "ruff-0.15.15-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a5015088452ca0081387063649ec67f06d3d1d6b8b936a1f836b5e9657ecd48c"}, - {file = "ruff-0.15.15-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f5294aab6356c81600fcdea3a62bb1b924dfd5e91767c12318d3f68f86af57cd"}, - {file = "ruff-0.15.15-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:db5bd4d802415cca656dc1616070b725952d6ae95eb5d4831e49fbd94a38f75f"}, - {file = "ruff-0.15.15-py3-none-musllinux_1_2_i686.whl", hash = "sha256:587a6278ed42059191c1a466e490bd7930fb50bd2e255398bc29616c895a61cb"}, - {file = "ruff-0.15.15-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:df0c1c084f5f4be9812f61518a45c440d3c30d69ce4bf6c5270e66d38338f02a"}, - {file = "ruff-0.15.15-py3-none-win32.whl", hash = "sha256:29428ea79694afbe756d45fd59b36f22b6b020dc0443cf7de0173046236964b9"}, - {file = "ruff-0.15.15-py3-none-win_amd64.whl", hash = "sha256:8df0323902e15e24bc4bf246da830573d3cf3352bd0b9a164eab335d111ff4a4"}, - {file = "ruff-0.15.15-py3-none-win_arm64.whl", hash = "sha256:3c8ceca6792f38196b8f589bc92eccd03eef286602da92e5dc05cc42ef6441b7"}, - {file = "ruff-0.15.15.tar.gz", hash = "sha256:b8dff018130b46d8e5bf0f926ef6b60cf871d6d5ae45fc9334e09632daa741d6"}, -] - -[[package]] -name = "six" -version = "1.17.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] -files = [ - {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, - {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, -] - -[[package]] -name = "starlette" -version = "0.52.1" -description = "The little ASGI library that shines." -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "starlette-0.52.1-py3-none-any.whl", hash = "sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74"}, - {file = "starlette-0.52.1.tar.gz", hash = "sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933"}, -] - -[package.dependencies] -anyio = ">=3.6.2,<5" -typing-extensions = {version = ">=4.10.0", markers = "python_version < \"3.13\""} - -[package.extras] -full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"] - -[[package]] -name = "typing-extensions" -version = "4.15.0" -description = "Backported and Experimental Type Hints for Python 3.9+" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, - {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, -] - -[[package]] -name = "typing-inspection" -version = "0.4.2" -description = "Runtime typing introspection tools" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, - {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, -] - -[package.dependencies] -typing-extensions = ">=4.12.0" - -[[package]] -name = "tzdata" -version = "2026.2" -description = "Provider of IANA time zone data" -optional = false -python-versions = ">=2" -groups = ["main"] -markers = "sys_platform == \"win32\" or sys_platform == \"emscripten\" or python_version == \"3.10\"" -files = [ - {file = "tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7"}, - {file = "tzdata-2026.2.tar.gz", hash = "sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10"}, -] - -[[package]] -name = "urllib3" -version = "2.7.0" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897"}, - {file = "urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c"}, -] - -[package.extras] -brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] - -[[package]] -name = "uuid7" -version = "0.1.0" -description = "UUID version 7, generating time-sorted UUIDs with 200ns time resolution and 48 bits of randomness" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "uuid7-0.1.0-py2.py3-none-any.whl", hash = "sha256:5e259bb63c8cb4aded5927ff41b444a80d0c7124e8a0ced7cf44efa1f5cccf61"}, - {file = "uuid7-0.1.0.tar.gz", hash = "sha256:8c57aa32ee7456d3cc68c95c4530bc571646defac01895cfc73545449894a63c"}, -] - -[[package]] -name = "uvicorn" -version = "0.40.0" -description = "The lightning-fast ASGI server." -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "uvicorn-0.40.0-py3-none-any.whl", hash = "sha256:c6c8f55bc8bf13eb6fa9ff87ad62308bbbc33d0b67f84293151efe87e0d5f2ee"}, - {file = "uvicorn-0.40.0.tar.gz", hash = "sha256:839676675e87e73694518b5574fd0f24c9d97b46bea16df7b8c05ea1a51071ea"}, -] - -[package.dependencies] -click = ">=7.0" -h11 = ">=0.8" -typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} - -[package.extras] -standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchfiles (>=0.13)", "websockets (>=10.4)"] - -[[package]] -name = "webencodings" -version = "0.5.1" -description = "Character encoding aliases for legacy web content" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, - {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, -] - -[[package]] -name = "websockets" -version = "16.0" -description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a"}, - {file = "websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0"}, - {file = "websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957"}, - {file = "websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72"}, - {file = "websockets-16.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde"}, - {file = "websockets-16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3"}, - {file = "websockets-16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3"}, - {file = "websockets-16.0-cp310-cp310-win32.whl", hash = "sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9"}, - {file = "websockets-16.0-cp310-cp310-win_amd64.whl", hash = "sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35"}, - {file = "websockets-16.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8"}, - {file = "websockets-16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad"}, - {file = "websockets-16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d"}, - {file = "websockets-16.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe"}, - {file = "websockets-16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b"}, - {file = "websockets-16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5"}, - {file = "websockets-16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64"}, - {file = "websockets-16.0-cp311-cp311-win32.whl", hash = "sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6"}, - {file = "websockets-16.0-cp311-cp311-win_amd64.whl", hash = "sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac"}, - {file = "websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00"}, - {file = "websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79"}, - {file = "websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39"}, - {file = "websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c"}, - {file = "websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f"}, - {file = "websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1"}, - {file = "websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2"}, - {file = "websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89"}, - {file = "websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea"}, - {file = "websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9"}, - {file = "websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230"}, - {file = "websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c"}, - {file = "websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5"}, - {file = "websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82"}, - {file = "websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8"}, - {file = "websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f"}, - {file = "websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a"}, - {file = "websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156"}, - {file = "websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0"}, - {file = "websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904"}, - {file = "websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4"}, - {file = "websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e"}, - {file = "websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4"}, - {file = "websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1"}, - {file = "websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3"}, - {file = "websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8"}, - {file = "websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d"}, - {file = "websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244"}, - {file = "websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e"}, - {file = "websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641"}, - {file = "websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8"}, - {file = "websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e"}, - {file = "websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944"}, - {file = "websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206"}, - {file = "websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6"}, - {file = "websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd"}, - {file = "websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d"}, - {file = "websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03"}, - {file = "websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da"}, - {file = "websockets-16.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c"}, - {file = "websockets-16.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767"}, - {file = "websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec"}, - {file = "websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5"}, -] - -[[package]] -name = "xlrd" -version = "2.0.2" -description = "Library for developers to extract data from Microsoft Excel (tm) .xls spreadsheet files" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -groups = ["main"] -files = [ - {file = "xlrd-2.0.2-py2.py3-none-any.whl", hash = "sha256:ea762c3d29f4cca48d82df517b6d89fbce4db3107f9d78713e48cd321d5c9aa9"}, - {file = "xlrd-2.0.2.tar.gz", hash = "sha256:08b5e25de58f21ce71dc7db3b3b8106c1fa776f3024c54e45b45b374e89234c9"}, -] - -[package.extras] -build = ["twine", "wheel"] -docs = ["sphinx"] -test = ["pytest", "pytest-cov"] - -[[package]] -name = "yarl" -version = "1.24.2" -description = "Yet another URL library" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "yarl-1.24.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5249a113065c2b7a958bc699759e359cd61cfc81e3069662208f48f191b7ed12"}, - {file = "yarl-1.24.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f4425fa244fbf530b006d0c5f79ce920114cfff5b4f5f6056e669f8e160fdc0"}, - {file = "yarl-1.24.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15c0b5e49d3c44e2a0b93e6a49476c5edad0a7686b92c395765a7ea775572a75"}, - {file = "yarl-1.24.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:246d32a53a947c8f0189f5d699cbd4c7036de45d9359e13ba238d1239678c727"}, - {file = "yarl-1.24.2-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:64480fb3e4d4ed9ed71c48a91a477384fc342a50ca30071d2f8a88d51d9c9413"}, - {file = "yarl-1.24.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:349de4701dc3760b6e876628423a8f147ef4f5599d10aba1e10702075d424ed9"}, - {file = "yarl-1.24.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d162677af8d5d3d6ebab8394b021f4d041ac107a4b705873148a77a49dc9e1b2"}, - {file = "yarl-1.24.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f5f5c6ec23a9043f2d139cc072f53dd23168d202a334b9b2fda8de4c3e890d90"}, - {file = "yarl-1.24.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:60de6742447fbbf697f16f070b8a443f1b5fe6ca3826fbef9fe70ecd5328e643"}, - {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:acf93187c3710e422368eb768aee98db551ec7c85adc250207a95c16548ab7ac"}, - {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:f4b0352fd41fd34b6651934606268816afd6914d09626f9bcbbf018edb0afb3f"}, - {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:6b208bb939099b4b297438da4e9b25357f0b1c791888669b963e45b203ea9f36"}, - {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4b85b8825e631295ff4bc8943f7471d54c533a9360bbe15ebb38e018b555bb8a"}, - {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e26acf20c26cb4fefc631fdb75aca2a6b8fa8b7b5d7f204fb6a8f1e63c706f53"}, - {file = "yarl-1.24.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:819ca24f8eafcfb683c1bd5f44f2f488cea1274eb8944731ffd2e1f10f619342"}, - {file = "yarl-1.24.2-cp310-cp310-win_amd64.whl", hash = "sha256:5cb0f995a901c36be096ccbf4c673591c2faabbe96279598ffaec8c030f85bf4"}, - {file = "yarl-1.24.2-cp310-cp310-win_arm64.whl", hash = "sha256:f408eace7e22a68b467a0562e0d27d322f91fe3eaaa6f466b962c6cfaea9fa39"}, - {file = "yarl-1.24.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:36348bebb147b83818b9d7e673ea4debc75970afc6ffdc7e3975ad05ce5a58c1"}, - {file = "yarl-1.24.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a97e42c8a2233f2f279ecadd9e4a037bcb5d813b78435e8eedd4db5a9e9708c"}, - {file = "yarl-1.24.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8d027d56f1035e339d1001ac33eceab5b2ec8e42e449787bb75e289fb9a5cd1d"}, - {file = "yarl-1.24.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a6377060e7927187a42b7eb202090cbe2b34933a4eeaf90e3bd9e33432e5cae"}, - {file = "yarl-1.24.2-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:17076578bce0049a5ce57d14ad1bded391b68a3b213e9b81b0097b090244999a"}, - {file = "yarl-1.24.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:50713f1d4d6be6375bb178bb43d140ee1acb8abe589cd723320b7925a275be1e"}, - {file = "yarl-1.24.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:34263e2fa8fb5bb63a0d97706cda38edbad62fddb58c7f12d6acbc092812aa50"}, - {file = "yarl-1.24.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49016d82f032b1bd1e10b01078a7d29ae71bf468eeae0ea22df8bab691e60003"}, - {file = "yarl-1.24.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3f6d2c216318f8f32038ca3f72501ba08536f0fd18a36e858836b121b2deed9f"}, - {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:08d3a33218e0c64393e7610284e770409a9c31c429b078bcb24096ed0a783b8f"}, - {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5d699376c4ca3cba49bbfae3a05b5b70ded572937171ce1e0b8d87118e2ba294"}, - {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a1cab588b4fa14bea2e55ebea27478adfb05372f47573738e1acc4a36c0b05d2"}, - {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:ec87ccc31bd21db7ad009d8572c127c1000f268517618a4cc09adba3c2a7f21c"}, - {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d1dd47a22843b212baa8d74f37796815d43bd046b42a0f41e9da433386c3136b"}, - {file = "yarl-1.24.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7b54b9c67c2b06bd7b9a77253d242124b9c95d2c02def5a1144001ee547dd9d5"}, - {file = "yarl-1.24.2-cp311-cp311-win_amd64.whl", hash = "sha256:f8fdbcff8b2c7c9284e60c196f693588598ddcee31e11c18e14949ce44519d45"}, - {file = "yarl-1.24.2-cp311-cp311-win_arm64.whl", hash = "sha256:b32c37a7a337e90822c45797bf3d79d60875cfcccd3ecc80e9f453d87026c122"}, - {file = "yarl-1.24.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b975866c184564c827e0877380f0dae57dcca7e52782128381b72feff6dfceb8"}, - {file = "yarl-1.24.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3b075301a2836a0e297b1b658cb6d6135df535d62efefdd60366bd589c2c82f2"}, - {file = "yarl-1.24.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ae44649b00947634ab0dab2a374a638f52923a6e67083f2c156cd5cbd1a881d"}, - {file = "yarl-1.24.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:507cc19f0b45454e2d6dcd62ff7d062b9f77a2812404e62dbdaec05b50faa035"}, - {file = "yarl-1.24.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c4c17bad5a530912d2111825d3f05e89bab2dd376aaa8cbc77e449e6db63e576"}, - {file = "yarl-1.24.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f5f0cbb112838a4a293985b6ed73948a547dadcc1ba6d2089938e7abdedceef8"}, - {file = "yarl-1.24.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ec8356b8a6afcf81fc7aeeef13b1ff7a49dec00f313394bbb9e83830d32ccd7"}, - {file = "yarl-1.24.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e7ebcdef69dec6c6451e616f32b622a6d4a2e92b445c992f7c8e5274a6bbc4c"}, - {file = "yarl-1.24.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:47a55d6cf6db2f401017a9e96e5288844e5051911fb4e0c8311a3980f5e59a7d"}, - {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3065657c80a2321225e804048597ad55658a7e76b32d6f5ee4074d04c50401db"}, - {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cb84b80d88e19ede158619b80813968713d8d008b0e2497a576e6a0557d50712"}, - {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:990de4f680b1c217e77ff0d6aa0029f9eb79889c11fb3e9a3942c7eba29c1996"}, - {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:abb8ec0323b80161e3802da3150ef660b41d0e9be2048b76a363d93eee992c2b"}, - {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e7977781f83638a4c73e0f88425563d70173e0dfd90ac006a45c65036293ee3c"}, - {file = "yarl-1.24.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e30dd55825dc554ec5b66a94953b8eda8745926514c5089dfcacecb9c99b5bd1"}, - {file = "yarl-1.24.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dafe10c12ddd4d120d528c4b5599c953bd7b12845347d507b95451195bb6cad"}, - {file = "yarl-1.24.2-cp312-cp312-win_arm64.whl", hash = "sha256:044a09d8401fcf8681977faef6d286b8ade1e2d2e9dceda175d1cfa5ca496f30"}, - {file = "yarl-1.24.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:491ac9141decf49ee8030199e1ee251cdff0e131f25678817ff6aa5f837a3536"}, - {file = "yarl-1.24.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e89418f65eda18f99030386305bd44d7d504e328a7945db1ead514fbe03a0607"}, - {file = "yarl-1.24.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cdfcce633b4a4bb8281913c57fcafd4b5933fbc19111a5e3930bbd299d6102f1"}, - {file = "yarl-1.24.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:863297ddede92ee49024e9a9b11ecb59f310ca85b60d8537f56bed9bbb5b1986"}, - {file = "yarl-1.24.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:374423f70754a2c96942ede36a29d37dc6b0cb8f92f8d009ddf3ed78d3da5488"}, - {file = "yarl-1.24.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:33a29b5d00ccbf3219bb3e351d7875739c19481e030779f48cc46a7a71681a9b"}, - {file = "yarl-1.24.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a9532c57211730c515341af11fef6e9b61d157487272a096d0c04da445642592"}, - {file = "yarl-1.24.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:91e72cf093fd833483a97ee648e0c053c7c629f51ff4a0e7edd84f806b0c5617"}, - {file = "yarl-1.24.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b3177bc0a768ef3bacceb4f272632990b7bea352f1b2f1eee9d6d6ff16516f92"}, - {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e196952aacaf3b232e265ff02980b64d483dc0972bd49bcb061171ff22ac203a"}, - {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:204e7a61ce99919c0de1bf904ab5d7aa188a129ea8f690a8f76cfb6e2844dc44"}, - {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b156914620f0b9d78dc1adb3751141daee561cfec796088abb89ed49d220f1a"}, - {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:8372a2b976cf70654b2be6619ab6068acabb35f724c0fda7b277fbf53d66a5cf"}, - {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f9a1e9b622ca284143aab5d885848686dcd85453bb1ca9abcdb7503e64dc0056"}, - {file = "yarl-1.24.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:810e19b685c8c3c5862f6a38160a1f4e4c0916c9390024ec347b6157a45a0992"}, - {file = "yarl-1.24.2-cp313-cp313-win_amd64.whl", hash = "sha256:7d37fb7c38f2b6edab0f845c4f85148d4c44204f52bc127021bd2bc9fdbf1656"}, - {file = "yarl-1.24.2-cp313-cp313-win_arm64.whl", hash = "sha256:1e831894be7c2954240e49791fa4b50c05a0dc881de2552cfe3ffd8631c7f461"}, - {file = "yarl-1.24.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:f9312b3c02d9b3d23840f67952913c9c8721d7f1b7db305289faefa878f364c2"}, - {file = "yarl-1.24.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a4f4d6cd615823bfc7fb7e9b5987c3f41666371d870d51058f77e2680fbe9630"}, - {file = "yarl-1.24.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0c3063e5c0a8e8e62fae6c2596fa01da1561e4cd1da6fec5789f5cf99a8aefd8"}, - {file = "yarl-1.24.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fecd17873a096036c1c87ab3486f1aef7f269ada7f23f7f856f93b1cc7744f14"}, - {file = "yarl-1.24.2-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a46d1ab4ba4d32e6dc80daf8a28ce0bd83d08df52fbc32f3e288663427734535"}, - {file = "yarl-1.24.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73e68edf6dfd5f73f9ca127d84e2a6f9213c65bdffb736bda19524c0564fcd14"}, - {file = "yarl-1.24.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a296ca617f2d25fbceafb962b88750d627e5984e75732c712154d058ae8d79a3"}, - {file = "yarl-1.24.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51b2cf5ec89a8b8470177641ed62a3ba22d74e1e898e06ad53aa77972487208"}, - {file = "yarl-1.24.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:310fc687f7b2044ec54e372c8cbe923bb88f5c37bded0d3079e5791c2fc3cf50"}, - {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:297a2fe352ecf858b30a98f87948746ec16f001d279f84aebdbd3bd965e2f1bd"}, - {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2a263e76b97bc42bdcd7c5f4953dec1f7cd62a1112fa7f869e57255229390d67"}, - {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:822519b64cf0b474f1a0aaef1dc621438ea46bb77c94df97a5b4d213a7d8a8b1"}, - {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:b6067060d9dc594899ba83e6db6c48c68d1e494a6dab158156ed86977ca7bcb1"}, - {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:0063adad533e57171b79db3943b229d40dfafeeee579767f96541f106bac5f1b"}, - {file = "yarl-1.24.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ee8e3fb34513e8dc082b586ef4910c98335d43a6fab688cd44d4851bacfce3e8"}, - {file = "yarl-1.24.2-cp314-cp314-win_amd64.whl", hash = "sha256:afb00d7fd8e0f285ca29a44cc50df2d622ff2f7a6d933fa641577b5f9d5f3db0"}, - {file = "yarl-1.24.2-cp314-cp314-win_arm64.whl", hash = "sha256:68cf6eacd6028ef1142bc4b48376b81566385ca6f9e7dde3b0fa91be08ffcb57"}, - {file = "yarl-1.24.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:221ce1dd921ac4f603957f17d7c18c5cc0797fbb52f156941f92e04605d1d67b"}, - {file = "yarl-1.24.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5f3224db28173a00d7afacdee07045cc4673dfab2b15492c7ae10deddbece761"}, - {file = "yarl-1.24.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c557165320d6244ebe3a02431b2a201a20080e02f41f0cfa0ccc47a183765da8"}, - {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:904065e6e85b1fa54d0d87438bd58c14c0bad97aad654ad1077fd9d87e8478ed"}, - {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8cec2a38d70edc10e0e856ceda886af5327a017ccbde8e1de1bd44d300357543"}, - {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e7484b9361ed222ee1ca5b4337aa4cbdcc4618ce5aff57d9ef1582fd95893fc0"}, - {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:84f9670b89f34db07f81e53aee83e0b938a3412329d51c8f922488be7fcc4024"}, - {file = "yarl-1.24.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:abb2759733d63a28b4956500a5dd57140f26486c92b2caedfb964ab7d9b79dbf"}, - {file = "yarl-1.24.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:081c2bf54efe03774d0311172bc04fedf9ca01e644d4cd8c805688e527209bdc"}, - {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:86746bef442aa479107fe28132e1277237f9c24c2f00b0b0cf22b3ee0904f2bb"}, - {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:2d07d21d0bc4b17558e8de0b02fbfdf1e347d3bb3699edd00bb92e7c57925420"}, - {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:4fb1ac3fc5fecd8ae7453ea237e4d22b49befa70266dfe1629924245c21a0c7f"}, - {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:4da31a5512ed1729ca8d8aacde3f7faeb8843cde3165d6bcf7f88f74f17bb8aa"}, - {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:533ded4dceb5f1f3da7906244f4e82cf46cfd40d84c69a1faf5ac506aa65ecbe"}, - {file = "yarl-1.24.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7b3a85525f6e7eeabcfdd372862b21ee1915db1b498a04e8bf0e389b607ff0bd"}, - {file = "yarl-1.24.2-cp314-cp314t-win_amd64.whl", hash = "sha256:a7624b1ca46ca5d7b864ef0d2f8efe3091454085ee1855b4e992314529972215"}, - {file = "yarl-1.24.2-cp314-cp314t-win_arm64.whl", hash = "sha256:e434a45ce2e7a947f951fc5a8944c8cc080b7e59f9c50ae80fd39107cf88126d"}, - {file = "yarl-1.24.2-py3-none-any.whl", hash = "sha256:2783d9226db8797636cd6896e4de81feed252d1db72265686c9558d97a4d94b9"}, - {file = "yarl-1.24.2.tar.gz", hash = "sha256:9ac374123c6fd7abf64d1fec93962b0bd4ee2c19751755a762a72dd96c0378f8"}, -] - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" -propcache = ">=0.2.1" - -[[package]] -name = "zipp" -version = "4.1.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "zipp-4.1.0-py3-none-any.whl", hash = "sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f"}, - {file = "zipp-4.1.0.tar.gz", hash = "sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602"}, -] - -[package.extras] -check = ["pytest-checkdocs (>=2.14)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=3.4)"] -test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more_itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] -type = ["pytest-mypy (>=1.0.1) ; platform_python_implementation != \"PyPy\""] - -[metadata] -lock-version = "2.1" -python-versions = ">=3.10,<4" -content-hash = "0816f255be5a9e42dc7adfb37304116632d9f701f13ec6e5119d2bcbe29aeaf9" diff --git a/openbb_platform/providers/eia/pyproject.toml b/openbb_platform/providers/eia/pyproject.toml index ec8b49837f0..1120551d2c5 100644 --- a/openbb_platform/providers/eia/pyproject.toml +++ b/openbb_platform/providers/eia/pyproject.toml @@ -1,22 +1,113 @@ -[tool.poetry] +[project] name = "openbb-us-eia" -version = "1.3.1" -description = "The U.S. Energy Information Administration is committed to its free and open data by making it available through an Application Programming Interface (API) and its open data tools. See https://www.eia.gov/opendata/ for more information." -authors = ["OpenBB Team <hello@openbb.co>"] -license = "AGPL-3.0-only" +version = "2.0.0" +description = "U.S. Energy Information Administration (EIA) provider extension for OpenBB Platform." +authors = [{ name = "OpenBB Team", email = "hello@openbb.co" }] +license = { text = "AGPL-3.0-only" } readme = "README.md" -packages = [{ include = "openbb_us_eia" }] +requires-python = ">=3.10,<4" +dependencies = [ + "openbb-core[pandas]>=2.0.0", + "async-lru>=2", + "curl-cffi>=0.7", + "fastmcp>=2.0", + "feedparser>=6.0", + "openpyxl>=3.1.5", + "xlrd>=2.0.1", +] -[tool.poetry.dependencies] -python = ">=3.10,<4" -openbb-core = "^1.6.10" -async-lru = "^2.0.4" -openpyxl = "^3.1.5" -xlrd = "^2.0.1" +[project.scripts] +generate-eia-catalog = "openbb_us_eia.utils.generate_catalog:main" + +[project.entry-points."openbb_provider_extension"] +us_eia = "openbb_us_eia:eia_provider" + +[project.entry-points."openbb_core_extension"] +eia = "openbb_us_eia.eia_router:router" + +[project.urls] +Homepage = "https://openbb.co" +Repository = "https://github.com/OpenBB-finance/OpenBB" + +[dependency-groups] +dev = ["openbb-devtools>=2.0.0", "openbb-platform-api>=2.0.0"] [build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" +requires = ["hatchling>=1.25", "requests>=2.31"] +build-backend = "hatchling.build" -[tool.poetry.plugins."openbb_provider_extension"] -us_eia = "openbb_us_eia:eia_provider" +[tool.hatch.build.targets.wheel] +packages = ["openbb_us_eia"] + +[tool.hatch.build.targets.sdist] +include = [ + "openbb_us_eia", + "openbb_us_eia/assets/eia_catalog.json.xz", + "hatch_build.py", + "README.md", + "pyproject.toml", +] + +[tool.hatch.build.hooks.custom] +path = "hatch_build.py" + +[tool.uv.sources] +openbb-core = { path = "../../core", editable = true } +openbb-devtools = { path = "../../extensions/devtools", editable = true } +openbb-platform-api = { path = "../../extensions/platform_api", editable = true } + +[tool.ruff] +line-length = 88 +target-version = "py310" +fix = true + +[tool.ruff.lint] +select = ["D", "E", "W", "F", "S", "UP", "I", "PLC", "PLE", "PLR", "PLW", "SIM", "T20"] +ignore = [ + "PLR2004", "PLR0913", "PLR0915", "PLC0415", + "E402", "E501", + "D202", "D203", "D205", "D206", "D210", "D212", "D213", "D214", + "D215", "D300", "D400", "D404", "D405", "D406", "D407", "D408", + "D409", "D410", "D411", "D413", "D415", "D416", "D417", +] + +[tool.ruff.lint.per-file-ignores] +"openbb_us_eia/eia_router.py" = ["ARG001", "PLR0912"] +"openbb_us_eia/models/*.py" = ["ARG002", "PLR0912"] +"openbb_us_eia/utils/generate_catalog.py" = ["S310", "PLR0912", "PLR0914"] +"tests/**" = ["S101", "S108", "D", "SIM105", "SIM117"] +"integration/**" = ["S101", "S108", "D", "SIM105", "SIM117", "PLC0415", "ARG001"] +"**/__init__.py" = ["F401"] + +[tool.ruff.lint.isort] +combine-as-imports = true +force-wrap-aliases = true +known-first-party = ["openbb_us_eia"] + +[tool.ruff.lint.pydocstyle] +convention = "numpy" + +[tool.ty] +[tool.ty.environment] +python-version = "3.10" + +[tool.ty.src] +include = ["openbb_us_eia"] +exclude = ["tests", "integration"] + +[tool.ty.rules] +unresolved-import = "ignore" + +[tool.pytest.ini_options] +testpaths = ["tests"] +addopts = "-q --strict-markers" +markers = [ + "record_http: VCR-backed HTTP cassette tests", + "integration: live integration tests against the EIA API", +] +filterwarnings = [ + "error", + "ignore::DeprecationWarning:openbb_core.provider.utils.client", + "ignore::async_lru.AlruCacheLoopResetWarning", + "ignore::pytest.PytestUnraisableExceptionWarning", +] diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_aeo_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_aeo_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..2701d1b9b34 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_aeo_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/aeo/2026/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2025&facets%5Bhistory%5D%5B%5D=PROJECTION&facets%5BregionId%5D%5B%5D=1-0&facets%5BregionId%5D%5B%5D=5-0&facets%5Bscenario%5D%5B%5D=altelec&facets%5BseriesId%5D%5B%5D=NA_NA_NA_NA_NA_NA_NA_NA&facets%5BtableId%5D%5B%5D=73&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2025 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2025","history":"PROJECTION","scenario":"altelec","scenarioDescription":"Alternative + Electricity","tableId":"73","tableName":"Table 73. Hydrogen Market Projections","seriesId":"NA_NA_NA_NA_NA_NA_NA_NA","seriesName":null,"regionId":"1-0","regionName":"United + States","value":"804.467834","unit":null}],"description":"Annual Energy Outlook + 2026"},"request":{"command":"\/v2\/aeo\/2026\/data\/","params":{"frequency":"annual","data":["value"],"facets":{"history":["PROJECTION"],"scenario":["altelec"],"tableId":["73"],"seriesId":["NA_NA_NA_NA_NA_NA_NA_NA"],"regionId":["5-0","1-0"]},"start":"2025","end":"2025","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:13 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:13 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '822' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_aggregate_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_aggregate_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..b563b9b2e87 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_aggregate_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,66 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/coal/aggregate-production/data/?api_key=MOCK_API_KEY&data%5B0%5D=average-employees&data%5B1%5D=labor-hours&data%5B2%5D=number-of-mines&data%5B3%5D=production&data%5B4%5D=productivity&end=2001&facets%5BcoalRankId%5D%5B%5D=SUB&facets%5BmineTypeId%5D%5B%5D=ALL&facets%5BstateRegionId%5D%5B%5D=AK&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2001 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2001","stateRegionId":"AK","stateRegionDescription":"Alaska","coalRankId":"SUB","coalRankDescription":"Subbituminous","mineTypeId":"ALL","mineTypeDescription":"All","average-employees":null,"labor-hours":null,"number-of-mines":"1","production":"1514241","productivity":null,"average-employees-units":"number + of employees","labor-hours-units":"hours","number-of-mines-units":"number + of mines","production-units":"short tons","productivity-units":"short tons + per labor hour"}],"description":"Coal state aggregated data by mine type, + includes production, \r\n productivity, labor hours, employees, and + coal rank. Source: EIA Form 7A and MSHA Form \r\n 7000-2. Interactive + browser: https:\/\/www.eia.gov\/coal\/data\/browser\/"},"request":{"command":"\/v2\/coal\/aggregate-production\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["average-employees","labor-hours","number-of-mines","production","productivity"],"facets":{"stateRegionId":["AK"],"coalRankId":["SUB"],"mineTypeId":["ALL"]},"start":"2001","end":"2001","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:14 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:14 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1296' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_by_mine_by_plant_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_by_mine_by_plant_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..8cba70d76d5 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_by_mine_by_plant_fetcher_urllib3_v2.yaml @@ -0,0 +1,66 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/coal/shipments/by-mine-by-plant/data/?api_key=MOCK_API_KEY&data%5B0%5D=ash-content&data%5B1%5D=heat-content&data%5B2%5D=price&data%5B3%5D=quantity&data%5B4%5D=sulfur-content&end=2008&facets%5BcoalSupplier%5D%5B%5D=TWENTY+MILE&facets%5BcoalType%5D%5B%5D=All&facets%5BmineMSHAId%5D%5B%5D=100114&facets%5BmineStateId%5D%5B%5D=AL&facets%5BplantId%5D%5B%5D=4143&facets%5BplantStateId%5D%5B%5D=WI&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2008 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2008","mineStateId":"AL","mineStateDescription":"Alabama","mineMSHAId":"100114","mineName":"CORDOVA + LOADING","coalSupplier":"TWENTY MILE","plantStateId":"WI","plantStateDescription":"Wisconsin","plantId":"4143","plantName":"Genoa","coalType":"All","ash-content":"10.9","heat-content":"11445","price":"84.69","quantity":"37000","sulfur-content":".56","ash-content-units":"percent + by weight","heat-content-units":"Btu per pound","price-units":"average dollars + per ton","quantity-units":"tons","sulfur-content-units":"percent by weight"}],"description":"Coal + shipments from mine- to plant-level data, including price, quantity, quality, + and rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive browser: https:\/\/www.eia.gov\/coal\/data\/browser\/"},"request":{"command":"\/v2\/coal\/shipments\/by-mine-by-plant\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["ash-content","heat-content","price","quantity","sulfur-content"],"facets":{"mineStateId":["AL"],"mineMSHAId":["100114"],"coalSupplier":["TWENTY + MILE"],"plantStateId":["WI"],"plantId":["4143"],"coalType":["All"]},"start":"2008","end":"2008","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:14 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:14 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1374' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_consumption_and_quality_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_consumption_and_quality_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..f19cd5412e2 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_consumption_and_quality_fetcher_urllib3_v2.yaml @@ -0,0 +1,68 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/coal/consumption-and-quality/data/?api_key=MOCK_API_KEY&data%5B0%5D=ash-content&data%5B1%5D=consumption&data%5B2%5D=heat-content&data%5B3%5D=price&data%5B4%5D=receipts&data%5B5%5D=stocks&data%5B6%5D=sulfur-content&end=2000&facets%5Blocation%5D%5B%5D=AK&facets%5Bsector%5D%5B%5D=10&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2000 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2000","location":"AK","stateDescription":"Alaska","sector":"10","sectorDescription":"Other + Industrial","ash-content":null,"consumption":null,"heat-content":null,"price":null,"receipts":null,"stocks":null,"sulfur-content":null,"ash-content-units":"average + ash percent by weight","consumption-units":"short tons","heat-content-units":"average + sulfur percent by weight","price-units":"dollars per short ton","receipts-units":"short + tons","stocks-units":"short tons","sulfur-content-units":"average sulfur percent + by weight"}],"description":"Coal consumption and quality data by state and + sector, \n including price, reciepts, heat content, sulfur content, + ash content, and stocks. \n Source: EIA Form 7A and MSHA Form 7000-2. Interactive + browser: https:\/\/www.eia.gov\/coal\/data\/browser\/"},"request":{"command":"\/v2\/coal\/consumption-and-quality\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["ash-content","consumption","heat-content","price","receipts","stocks","sulfur-content"],"facets":{"location":["AK"],"sector":["10"]},"start":"2000","end":"2000","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:14 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:14 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1349' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_exports_imports_quantity_price_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_exports_imports_quantity_price_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..c5ddc92d694 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_exports_imports_quantity_price_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/coal/exports-imports-quantity-price/data/?api_key=MOCK_API_KEY&data%5B0%5D=price&data%5B1%5D=quantity&end=2000&facets%5BcoalRankId%5D%5B%5D=COK&facets%5BcountryId%5D%5B%5D=MX&facets%5BcustomsDistrictId%5D%5B%5D=BA_MD&facets%5BexportImportType%5D%5B%5D=Exports&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2000 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2000","exportImportType":"Exports","coalRankId":"COK","coalRankDescription":"Coke","countryId":"MX","countryDescription":"Mexico","customsDistrictId":"BA_MD","customsDistrictDescription":"Baltimore, + MD","price":"50","quantity":"22344","price-units":"dollars per short ton","quantity-units":"short + tons"}],"description":"Coal import\/export data, including price, quantity, + country, \r\n rank, and customs district. Source: EIA Form 7A and + MSHA Form 7000-2. Interactive \r\n browser: https:\/\/www.eia.gov\/coal\/data\/browser\/"},"request":{"command":"\/v2\/coal\/exports-imports-quantity-price\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["price","quantity"],"facets":{"exportImportType":["Exports"],"coalRankId":["COK"],"countryId":["MX"],"customsDistrictId":["BA_MD"]},"start":"2000","end":"2000","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:15 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:15 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1086' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_market_sales_price_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_market_sales_price_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..f8080a9fef4 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_market_sales_price_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/coal/market-sales-price/data/?api_key=MOCK_API_KEY&data%5B0%5D=price&data%5B1%5D=sales&end=2001&facets%5BmarketTypeId%5D%5B%5D=OM&facets%5BstateRegionId%5D%5B%5D=AK&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2001 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2001","stateRegionId":"AK","stateRegionDescription":"Alaska","marketTypeId":"OM","marketTypeDescription":"Open + Market","price":"w","sales":"w","price-units":"dollars per short ton","sales-units":"short + tons"}],"description":"Coal market sales prices and amounts by mine types + for \r\n regions and states (unless withheld for pricing protections). Source: + EIA Form \r\n 7A and MSHA Form 7000-2. Interactive browser: https:\/\/www.eia.gov\/coal\/data\/browser\/"},"request":{"command":"\/v2\/coal\/market-sales-price\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["price","sales"],"facets":{"stateRegionId":["AK"],"marketTypeId":["OM"]},"start":"2001","end":"2001","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:15 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:15 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '951' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_mine_aggregates_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_mine_aggregates_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..035d1448cf5 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_mine_aggregates_fetcher_urllib3_v2.yaml @@ -0,0 +1,66 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/coal/shipments/mine-aggregates/data/?api_key=MOCK_API_KEY&data%5B0%5D=ash-content&data%5B1%5D=heat-content&data%5B2%5D=price&data%5B3%5D=quantity&data%5B4%5D=sulfur-content&end=2008&facets%5BcoalRankId%5D%5B%5D=BIT&facets%5BmineMSHAId%5D%5B%5D=100114&facets%5BmineStateId%5D%5B%5D=AL&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2008 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2008","mineStateId":"AL","mineStateDescription":"Alabama","mineMSHAId":"100114","mineName":"CORDOVA + LOADING","coalRankId":"BIT","coalRankDescription":"Bituminous","ash-content":"11.55","heat-content":"11943","price":"w","quantity":"80853","sulfur-content":".79","ash-content-units":"percent + by weight","heat-content-units":"Btu per pound","price-units":"average dollars + per ton","quantity-units":"tons","sulfur-content-units":"percent by weight"}],"description":"Coal + shipments aggregated at mine-level data, \r\n including price, quantity, + quality, and rank. Source: EIA Form 7A and \r\n MSHA Form 7000-2. Interactive + browser: https:\/\/www.eia.gov\/coal\/data\/browser\/"},"request":{"command":"\/v2\/coal\/shipments\/mine-aggregates\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["ash-content","heat-content","price","quantity","sulfur-content"],"facets":{"mineStateId":["AL"],"mineMSHAId":["100114"],"coalRankId":["BIT"]},"start":"2008","end":"2008","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:16 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:16 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1238' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_mine_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_mine_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..91d60906fda --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_mine_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,70 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/coal/mine-production/data/?api_key=MOCK_API_KEY&data%5B0%5D=average-employees&data%5B1%5D=labor-hours&data%5B2%5D=latitude&data%5B3%5D=longitude&data%5B4%5D=operating-company&data%5B5%5D=operating-company-address&data%5B6%5D=production&data%5B7%5D=refuse-flag&end=2001&facets%5BcensusRegionId%5D%5B%5D=ESC&facets%5BcoalRankId%5D%5B%5D=PRP&facets%5BmineCountyId%5D%5B%5D=73&facets%5BmineMSHAId%5D%5B%5D=100329&facets%5BmineStatusId%5D%5B%5D=ACT&facets%5BmineTypeId%5D%5B%5D=SUR&facets%5BmississippiRegionId%5D%5B%5D=EMR&facets%5BregionId%5D%5B%5D=STH&facets%5BstateId%5D%5B%5D=AL&facets%5BsupplyRegionId%5D%5B%5D=APS&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2001 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2001","mineMSHAId":"100329","mineName":"Concord + Mine","stateId":"AL","stateDescription":"Alabama","regionId":"STH","regionDescription":"South","supplyRegionId":"APS","supplyRegionDescription":"Appalachia + Southern","censusRegionId":"ESC","censusRegionDescription":"East South Central","mississippiRegionId":"EMR","mississippiRegionDescription":"East + of Mississippi River","mineCountyId":"73","mineCountyName":"Jefferson","coalRankId":"PRP","coalRankDescription":"Preparation + Plant","mineTypeId":"SUR","mineTypeDescription":"Surface","mineStatusId":"ACT","mineStatusDescription":"Active","average-employees":"0","labor-hours":"0","latitude":"33.453888","longitude":"-87.037222","operating-company":"U + S Steel Mining Company Llc","operating-company-address":"8800 Oak Grove Mine + Road, Adger, AL 35006","production":"0","refuse-flag":null,"average-employees-units":"number + of employees","labor-hours-units":"hours","production-units":"short tons"}],"description":"Coal + mine-level data, including production, region, state, \r\n county, + rank, status, type, name and description. Source: EIA Form 7A and MSHA \r\n Form + 7000-2. Interactive browser: https:\/\/www.eia.gov\/coal\/data\/browser\/"},"request":{"command":"\/v2\/coal\/mine-production\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["average-employees","labor-hours","latitude","longitude","operating-company","operating-company-address","production","refuse-flag"],"facets":{"mineMSHAId":["100329"],"stateId":["AL"],"regionId":["STH"],"supplyRegionId":["APS"],"censusRegionId":["ESC"],"mississippiRegionId":["EMR"],"mineCountyId":["73"],"coalRankId":["PRP"],"mineTypeId":["SUR"],"mineStatusId":["ACT"]},"start":"2001","end":"2001","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:16 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:16 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1969' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_mine_state_aggregates_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_mine_state_aggregates_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..d0faf91307d --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_mine_state_aggregates_fetcher_urllib3_v2.yaml @@ -0,0 +1,65 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/coal/shipments/mine-state-aggregates/data/?api_key=MOCK_API_KEY&data%5B0%5D=ash-content&data%5B1%5D=heat-content&data%5B2%5D=price&data%5B3%5D=quantity&data%5B4%5D=sulfur-content&end=2008&facets%5BcoalRankId%5D%5B%5D=SUB&facets%5BmineStateId%5D%5B%5D=AK&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2008 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2008","mineStateId":"AK","mineStateDescription":"Alaska","coalRankId":"SUB","coalRankDescription":"Subbituminous","ash-content":"5.83","heat-content":"8699","price":"30.43","quantity":"424758","sulfur-content":".33","ash-content-units":"percent + by weight","heat-content-units":"Btu per pound","price-units":"average dollars + per ton","quantity-units":"tons","sulfur-content-units":"percent by weight"}],"description":"Coal + shipments aggregated at state-level data, including price, \r\n quantity, + quality, and rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive + browser: \r\n https:\/\/www.eia.gov\/coal\/data\/browser\/"},"request":{"command":"\/v2\/coal\/shipments\/mine-state-aggregates\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["ash-content","heat-content","price","quantity","sulfur-content"],"facets":{"mineStateId":["AK"],"coalRankId":["SUB"]},"start":"2008","end":"2008","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:16 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:16 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1175' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_plant_aggregates_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_plant_aggregates_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..f7ce3caabe6 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_plant_aggregates_fetcher_urllib3_v2.yaml @@ -0,0 +1,65 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/coal/shipments/plant-aggregates/data/?api_key=MOCK_API_KEY&data%5B0%5D=ash-content&data%5B1%5D=heat-content&data%5B2%5D=price&data%5B3%5D=quantity&data%5B4%5D=sulfur-content&end=2008&facets%5Blocation%5D%5B%5D=OVR&facets%5Bplant%5D%5B%5D=3&facets%5Brank%5D%5B%5D=BIT&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2008 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2008","location":"OVR","plantStateDescription":"Overseas","plant":"3","plantName":"Barry","rank":"BIT","coalRankDescription":"Bituminous","ash-content":"6.63","heat-content":"11465","price":"90.76","quantity":"3970914","sulfur-content":".54","ash-content-units":"percent + by weight","heat-content-units":"Btu per pound","price-units":"average dollars + per ton","quantity-units":"tons","sulfur-content-units":"percent by weight"}],"description":"Coal + reciepts aggregated to plant-level data, \n including price, quantity, + quality, and rank. Source: EIA Form 7A \n and MSHA Form 7000-2. Interactive + browser: https:\/\/www.eia.gov\/coal\/data\/browser\/"},"request":{"command":"\/v2\/coal\/shipments\/plant-aggregates\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["ash-content","heat-content","price","quantity","sulfur-content"],"facets":{"location":["OVR"],"plant":["3"],"rank":["BIT"]},"start":"2008","end":"2008","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:17 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:17 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1201' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_plant_state_aggregates_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_plant_state_aggregates_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..c35c69b7376 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_plant_state_aggregates_fetcher_urllib3_v2.yaml @@ -0,0 +1,65 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/coal/shipments/plant-state-aggregates/data/?api_key=MOCK_API_KEY&data%5B0%5D=ash-content&data%5B1%5D=heat-content&data%5B2%5D=price&data%5B3%5D=quantity&data%5B4%5D=sulfur-content&end=2008&facets%5BcoalRankId%5D%5B%5D=SUB&facets%5BplantStateId%5D%5B%5D=AK&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2008 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2008","plantStateId":"AK","plantStateDescription":"Alaska","coalRankId":"SUB","coalRankDescription":"Subbituminous","ash-content":"5.83","heat-content":"8699","price":"30.43","quantity":"424758","sulfur-content":".33","ash-content-units":"percent + by weight","heat-content-units":"Btu per pound","price-units":"average dollars + per ton","quantity-units":"tons","sulfur-content-units":"percent by weight"}],"description":"Coal + reciepts aggregated at state-level data, including price, \r\n quantity, + quality, and rank. Source: EIA Form 7A and MSHA Form 7000-2. Interactive + \r\n browser: https:\/\/www.eia.gov\/coal\/data\/browser\/"},"request":{"command":"\/v2\/coal\/shipments\/plant-state-aggregates\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["ash-content","heat-content","price","quantity","sulfur-content"],"facets":{"plantStateId":["AK"],"coalRankId":["SUB"]},"start":"2008","end":"2008","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:17 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:17 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1178' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_price_by_rank_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_price_by_rank_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..255337cce9b --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_price_by_rank_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/coal/price-by-rank/data/?api_key=MOCK_API_KEY&data%5B0%5D=price&end=2001&facets%5BcoalRankId%5D%5B%5D=SUB&facets%5BstateRegionId%5D%5B%5D=AK&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2001 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2001","stateRegionId":"AK","stateRegionDescription":"Alaska","coalRankId":"SUB","coalRankDescription":"Subbituminous","price":"w","price-units":"dollars + per short ton"}],"description":"Coal prices by rank data for region and state. \r\n Source: + EIA Form 7A and MSHA Form 7000-2. Interactive browser: \r\n https:\/\/www.eia.gov\/coal\/data\/browser\/ "},"request":{"command":"\/v2\/coal\/price-by-rank\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["price"],"facets":{"stateRegionId":["AK"],"coalRankId":["SUB"]},"start":"2001","end":"2001","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:18 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:18 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '824' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_receipts_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_receipts_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..6b321565b10 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_receipts_fetcher_urllib3_v2.yaml @@ -0,0 +1,69 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/coal/shipments/receipts/data/?api_key=MOCK_API_KEY&data%5B0%5D=ash-content&data%5B1%5D=heat-content&data%5B2%5D=price&data%5B3%5D=quantity&data%5B4%5D=sulfur-content&end=2008&facets%5BcoalRankId%5D%5B%5D=BIT&facets%5BcoalSupplier%5D%5B%5D=TWENTY+MILE&facets%5BcontractType%5D%5B%5D=Spot-Market+Purchase&facets%5BmineBasinId%5D%5B%5D=APS&facets%5BmineCountyId%5D%5B%5D=127&facets%5BmineMSHAId%5D%5B%5D=100114&facets%5BmineStateId%5D%5B%5D=AL&facets%5BmineTypeId%5D%5B%5D=SUR&facets%5BplantId%5D%5B%5D=4143&facets%5BplantStateId%5D%5B%5D=WI&facets%5BtransportationMode%5D%5B%5D=Rail&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2008 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2008","plantStateId":"WI","plantStateDescription":"Wisconsin","mineStateId":"AL","mineStateDescription":"Alabama","mineTypeId":"SUR","mineTypeDescription":"Surface","mineMSHAId":"100114","mineName":"CORDOVA + LOADING","mineBasinId":"APS","mineBasinDescription":"Appalachia Southern","mineCountyId":"127","mineCountyName":"Walker","contractType":"Spot-Market + Purchase","transportationMode":"Rail","coalSupplier":"TWENTY MILE","coalRankId":"BIT","coalRankDescription":"Bituminous","plantId":"4143","plantName":"Genoa","ash-content":"10.9","heat-content":"11445","price":"84.69","quantity":"37000","sulfur-content":".56","ash-content-units":"percent + by weight","heat-content-units":"Btu per pound","price-units":"average dollars + per ton","quantity-units":"tons","sulfur-content-units":"percent by weight"}],"description":"Coal + shipment detailed by reciepient data, including transportation type, \r\n supplier, + mine, coal basin, county, state, rank, contract type, price, quantity, and + quality. \r\n Source: EIA Form 7A and MSHA Form 7000-2. Interactive + browser: https:\/\/www.eia.gov\/coal\/data\/browser\/"},"request":{"command":"\/v2\/coal\/shipments\/receipts\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["ash-content","heat-content","price","quantity","sulfur-content"],"facets":{"plantStateId":["WI"],"mineStateId":["AL"],"mineTypeId":["SUR"],"mineMSHAId":["100114"],"mineBasinId":["APS"],"mineCountyId":["127"],"contractType":["Spot-Market + Purchase"],"transportationMode":["Rail"],"coalSupplier":["TWENTY MILE"],"coalRankId":["BIT"],"plantId":["4143"]},"start":"2008","end":"2008","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:18 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:18 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1868' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_reserves_capacity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_reserves_capacity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..80ea15ce25c --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_coal_reserves_capacity_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/coal/reserves-capacity/data/?api_key=MOCK_API_KEY&data%5B0%5D=producer-distributor-stocks&data%5B1%5D=productive-capacity&data%5B2%5D=recoverable-reserves&end=2001&facets%5BmineTypeId%5D%5B%5D=SUR&facets%5BstateId%5D%5B%5D=AK&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2001 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2001","stateId":"AK","stateDescription":"Alaska","mineTypeId":"SUR","mineTypeDescription":"Surface","producer-distributor-stocks":null,"productive-capacity":"w","recoverable-reserves":"w","producer-distributor-stocks-units":"short + tons","productive-capacity-units":"short tons","recoverable-reserves-units":"short + tons"}],"description":"Coal capacity data, including productive capacity, + stocks, \r\n and recoverable reserves by state, region and mine type. Source: + EIA Form 7A and \r\n MSHA Form 7000-2. Interactive browser: https:\/\/www.eia.gov\/coal\/data\/browser\/"},"request":{"command":"\/v2\/coal\/reserves-capacity\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["producer-distributor-stocks","productive-capacity","recoverable-reserves"],"facets":{"stateId":["AK"],"mineTypeId":["SUR"]},"start":"2001","end":"2001","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:18 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:18 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1109' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_crude_oil_imports_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_crude_oil_imports_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..64272e5e257 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_crude_oil_imports_fetcher_urllib3_v2.yaml @@ -0,0 +1,65 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/crude-oil-imports/data/?api_key=MOCK_API_KEY&data%5B0%5D=quantity&end=2009-01&facets%5BdestinationId%5D%5B%5D=PP_5&facets%5BdestinationId%5D%5B%5D=RP_5&facets%5BdestinationType%5D%5B%5D=PP&facets%5BgradeId%5D%5B%5D=LSO&facets%5BoriginId%5D%5B%5D=CTY_AE&facets%5BoriginType%5D%5B%5D=CTY&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2009-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2009-01","originId":"CTY_AE","originName":"United + Arab Emirates","originType":"CTY","originTypeName":"Country","destinationId":"PP_5","destinationName":"PADD5 + (West Coast)","destinationType":"PP","destinationTypeName":"Port PADD","gradeId":"LSO","gradeName":"Light + Sour","quantity":"643","quantity-units":"thousand barrels"}],"description":"Crude + oil imports by country to destination, \r\n includes type, grade, quantity. Source: + EIA-814 Interactive data \r\n product: www.eia.gov\/petroleum\/imports\/companylevel\/"},"request":{"command":"\/v2\/crude-oil-imports\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["quantity"],"facets":{"originId":["CTY_AE"],"originType":["CTY"],"destinationId":["RP_5","PP_5"],"destinationType":["PP"],"gradeId":["LSO"]},"start":"2009-01","end":"2009-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:20 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:20 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1077' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_data_browser_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_data_browser_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..91e30e946d8 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_data_browser_fetcher_urllib3_v2.yaml @@ -0,0 +1,129 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/spt?api_key=MOCK_API_KEY + response: + body: + string: '{"response":{"id":"petroleum","description":"EIA petroleum gas survey + data","frequency":[{"id":"monthly","description":"One data point for each + month.","query":"M","format":"YYYY-MM"},{"id":"weekly","description":"One + data point for each week.","query":"W","format":"YYYY-MM-DD"},{"id":"annual","description":"One + data point for each calendar year.","query":"A","format":"YYYY"},{"id":"daily","description":"One + data point for each day.","query":"D","format":"YYYY-MM-DD"}],"facets":[{"id":"duoarea","description":"DuoArea"},{"id":"product","description":"Product"},{"id":"process","description":"Process"},{"id":"series","description":"Series"}],"data":{"value":[]},"startPeriod":"1986-01-03","endPeriod":"2026-07-03","defaultDateFormat":"YYYY-MM-DD","defaultFrequency":"weekly"},"request":{"command":"\/v2\/petroleum\/pri\/spt\/","params":{"api_key":"MOCK_API_KEY"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:12 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:12 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '947' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/spt/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2025-03&facets%5Bproduct%5D%5B%5D=EPCBRENT&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2025-01 + response: + body: + string: '{"response":{"total":"3","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2025-01","duoarea":"ZEU","area-name":"NA","product":"EPCBRENT","product-name":"UK + Brent Crude Oil","process":"PF4","process-name":"Spot Price FOB","series":"RBRTE","series-description":"Europe + Brent Spot Price FOB (Dollars per Barrel)","value":"79.27","units":"$\/BBL"},{"period":"2025-02","duoarea":"ZEU","area-name":"NA","product":"EPCBRENT","product-name":"UK + Brent Crude Oil","process":"PF4","process-name":"Spot Price FOB","series":"RBRTE","series-description":"Europe + Brent Spot Price FOB (Dollars per Barrel)","value":"75.44","units":"$\/BBL"},{"period":"2025-03","duoarea":"ZEU","area-name":"NA","product":"EPCBRENT","product-name":"UK + Brent Crude Oil","process":"PF4","process-name":"Spot Price FOB","series":"RBRTE","series-description":"Europe + Brent Spot Price FOB (Dollars per Barrel)","value":"72.73","units":"$\/BBL"}]},"request":{"command":"\/v2\/petroleum\/pri\/spt\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"product":["EPCBRENT"]},"start":"2025-01","end":"2025-03","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:13 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:13 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1278' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_capacity_by_region_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_capacity_by_region_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..06efb4abc1d --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_capacity_by_region_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/densified-biomass/capacity-by-region/data/?api_key=MOCK_API_KEY&data%5B0%5D=capacity&data%5B1%5D=number-of-facilities&data%5B2%5D=number-of-fte-employees&end=2016-01&facets%5Bregion%5D%5B%5D=EAST&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2016-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2016-01","region":"EAST","capacity":"2141600","number-of-facilities":"33","number-of-fte-employees":"599","capacity-units":"tons","number-of-facilities-units":"number + of facilities","number-of-fte-employees-units":"number of fte employees"}],"description":"Densified + biomass capacity includes number of facilities \r\n and number of employees. Source: + EIA-63C Report: www.eia.gov\/biomass\/"},"request":{"command":"\/v2\/densified-biomass\/capacity-by-region\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["capacity","number-of-facilities","number-of-fte-employees"],"facets":{"region":["EAST"]},"start":"2016-01","end":"2016-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:20 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:20 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '912' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_characteristics_by_region_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_characteristics_by_region_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..d3967ca39b3 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_characteristics_by_region_fetcher_urllib3_v2.yaml @@ -0,0 +1,65 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/densified-biomass/characteristics-by-region/data/?api_key=MOCK_API_KEY&data%5B0%5D=average-ash&data%5B1%5D=average-heat&data%5B2%5D=average-moisture&end=2016-01&facets%5BfuelTypeId%5D%5B%5D=WPPS&facets%5Bregion%5D%5B%5D=EAST&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2016-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2016-01","fuelTypeId":"WPPS","fuelTypeDescription":"Wood + Pellets Premium Standard","region":"EAST","average-ash":"0","average-heat":"0","average-moisture":"0","average-ash-units":"percent + by weight","average-heat-units":"btu\/lb","average-moisture-units":"percent + by weight"}],"description":"Densified biomass characteristics includes \r\n fuel + type, average ash, heat, and moisture content by region. \r\n Source: + EIA-63C Report: www.eia.gov\/biomass\/"},"request":{"command":"\/v2\/densified-biomass\/characteristics-by-region\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["average-ash","average-heat","average-moisture"],"facets":{"fuelTypeId":["WPPS"],"region":["EAST"]},"start":"2016-01","end":"2016-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:20 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:20 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '998' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_export_sales_and_price_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_export_sales_and_price_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..60f042d1c8d --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_export_sales_and_price_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/densified-biomass/export-sales-and-price/data/?api_key=MOCK_API_KEY&data%5B0%5D=average-price&data%5B1%5D=quantity&end=2016-01&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2016-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2016-01","average-price":"151.07","quantity":"318480","average-price-units":"USD + per ton","quantity-units":"tons"}],"description":"Densified biomass export + prices and quantity. \r\n Source: EIA-63C Report: www.eia.gov\/biomass\/"},"request":{"command":"\/v2\/densified-biomass\/export-sales-and-price\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["average-price","quantity"],"start":"2016-01","end":"2016-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:21 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:21 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '692' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_feedstocks_and_costs_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_feedstocks_and_costs_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..5cefc3593e8 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_feedstocks_and_costs_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/densified-biomass/feedstocks-and-cost/data/?api_key=MOCK_API_KEY&data%5B0%5D=cost&data%5B1%5D=quantity&end=2016-01&facets%5BfuelTypeId%5D%5B%5D=OR&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2016-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2016-01","fuelTypeId":"OR","fuelTypeDescription":"Other + Residuals","cost":"31.72","quantity":"746574","cost-units":"USD per ton","quantity-units":"tons"}],"description":"Densified + biomass feedstocks and cost by type. \r\n Source: EIA-63C Report: www.eia.gov\/biomass\/"},"request":{"command":"\/v2\/densified-biomass\/feedstocks-and-cost\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["cost","quantity"],"facets":{"fuelTypeId":["OR"]},"start":"2016-01","end":"2016-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:21 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:21 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '751' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_inventories_by_region_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_inventories_by_region_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..9664e619d51 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_inventories_by_region_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/densified-biomass/inventories-by-region/data/?api_key=MOCK_API_KEY&data%5B0%5D=inventory&end=2016-01&facets%5BfuelTypeId%5D%5B%5D=CBL&facets%5Bregion%5D%5B%5D=EAST&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2016-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2016-01","fuelTypeId":"CBL","fuelTypeDescription":"Compressed + Bricks Log","region":"EAST","inventory":"0"}],"description":"Densified biomass + inventories by region and fuel type. \r\n Source: EIA-63C Report: www.eia.gov\/biomass\/"},"request":{"command":"\/v2\/densified-biomass\/inventories-by-region\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["inventory"],"facets":{"fuelTypeId":["CBL"],"region":["EAST"]},"start":"2016-01","end":"2016-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:21 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:21 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '727' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_production_by_region_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_production_by_region_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..92adc6d29e9 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_production_by_region_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/densified-biomass/production-by-region/data/?api_key=MOCK_API_KEY&data%5B0%5D=production&end=2016-01&facets%5BfuelTypeId%5D%5B%5D=CBL&facets%5Bregion%5D%5B%5D=EAST&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2016-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2016-01","fuelTypeId":"CBL","fuelTypeDescription":"Compressed + Bricks Log","region":"EAST","production":"0","production-units":"tons"}],"description":"Densified + biomass production by region and fuel type. \r\n Source: EIA-63C Report: www.eia.gov\/biomass\/"},"request":{"command":"\/v2\/densified-biomass\/production-by-region\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["production"],"facets":{"fuelTypeId":["CBL"],"region":["EAST"]},"start":"2016-01","end":"2016-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:22 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:22 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '753' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_sales_and_price_by_region_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_sales_and_price_by_region_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..203464aec42 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_sales_and_price_by_region_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/densified-biomass/sales-and-price-by-region/data/?api_key=MOCK_API_KEY&data%5B0%5D=average-price&data%5B1%5D=quantity&end=2016-01&facets%5Bregion%5D%5B%5D=EAST&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2016-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2016-01","region":"EAST","average-price":"184.18","quantity":"39424","average-price-units":"USD + per ton","quantity-units":"tons"}],"description":"Densified biomass sales + and average price by region. \r\n Source: EIA-63C Report: www.eia.gov\/biomass\/"},"request":{"command":"\/v2\/densified-biomass\/sales-and-price-by-region\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["average-price","quantity"],"facets":{"region":["EAST"]},"start":"2016-01","end":"2016-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:22 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:22 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '746' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_wood_pellet_plant_capacity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_wood_pellet_plant_capacity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..2a303772cf9 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_densified_biomass_wood_pellet_plant_capacity_fetcher_urllib3_v2.yaml @@ -0,0 +1,65 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/densified-biomass/wood-pellet-plants/data/?api_key=MOCK_API_KEY&data%5B0%5D=capacity&end=2016&facets%5Bregion%5D%5B%5D=EAST&facets%5Brespondent%5D%5B%5D=Allegheny+Pellet+Corporation&facets%5BstateId%5D%5B%5D=PA&facets%5Bstatus%5D%5B%5D=Currently+Operating&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2016 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2016","region":"EAST","respondent":"Allegheny + Pellet Corporation","stateId":"PA","stateName":"Pennsylvania","status":"Currently + Operating","capacity":"60000","capacity-units":"tons per year"}],"description":"Details + on wood pellet plants includes region, respondent, \r\n capacity, and status. Source: + EIA-63C Report: www.eia.gov\/biomass\/"},"request":{"command":"\/v2\/densified-biomass\/wood-pellet-plants\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["capacity"],"facets":{"region":["EAST"],"respondent":["Allegheny + Pellet Corporation"],"stateId":["PA"],"status":["Currently Operating"]},"start":"2016","end":"2016","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:22 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:22 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '894' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_electric_power_operations_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_electric_power_operations_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..a8aec6134b9 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_electric_power_operations_fetcher_urllib3_v2.yaml @@ -0,0 +1,71 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/electric-power-operational-data/data/?api_key=MOCK_API_KEY&data%5B0%5D=ash-content&data%5B10%5D=receipts-btu&data%5B11%5D=stocks&data%5B12%5D=sulfur-content&data%5B13%5D=total-consumption&data%5B14%5D=total-consumption-btu&data%5B1%5D=consumption-for-eg&data%5B2%5D=consumption-for-eg-btu&data%5B3%5D=consumption-uto&data%5B4%5D=consumption-uto-btu&data%5B5%5D=cost&data%5B6%5D=cost-per-btu&data%5B7%5D=generation&data%5B8%5D=heat-content&data%5B9%5D=receipts&end=2001-01&facets%5Bfueltypeid%5D%5B%5D=ALL&facets%5Blocation%5D%5B%5D=AK&facets%5Bsectorid%5D%5B%5D=1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2001-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2001-01","location":"AK","stateDescription":"Alaska","sectorid":"1","sectorDescription":"Electric + Utility","fueltypeid":"ALL","fuelTypeDescription":"all fuels","ash-content":"0","ash-content-units":"percent","consumption-for-eg":null,"consumption-for-eg-units":"thousand + physical units","consumption-for-eg-btu":"5.308","consumption-for-eg-btu-units":"million + MMBtu","consumption-uto":null,"consumption-uto-units":"thousand physical units","consumption-uto-btu":null,"consumption-uto-btu-units":"million + MMBtu","cost":"2.12","cost-units":"dollars per physical units","cost-per-btu":"2.1211","cost-per-btu-units":"dollars + per million Btu","generation":"493.206","generation-units":"thousand megawatthours","heat-content":"2.63","heat-content-units":"Btu + per physical units","receipts":"2074.494","receipts-units":"thousand physical + units","receipts-btu":"2074.494","receipts-btu-units":"billion Btu","stocks":"29.357","stocks-units":"thousand + physical units","sulfur-content":"0","sulfur-content-units":"percent","total-consumption":null,"total-consumption-units":"thousand + physical units","total-consumption-btu":"5.308","total-consumption-btu-units":"million + MMBtu"}],"description":"Monthly and annual electric power operations by state, + sector, and energy source.\n Source: Form EIA-923"},"request":{"command":"\/v2\/electricity\/electric-power-operational-data\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["ash-content","consumption-for-eg","consumption-for-eg-btu","consumption-uto","consumption-uto-btu","cost","cost-per-btu","generation","heat-content","receipts","receipts-btu","stocks","sulfur-content","total-consumption","total-consumption-btu"],"facets":{"location":["AK"],"sectorid":["1"],"fueltypeid":["ALL"]},"start":"2001-01","end":"2001-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:23 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:23 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '2034' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_electric_power_operations_for_individual_power_plants_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_electric_power_operations_for_individual_power_plants_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..9c5b06a9b66 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_electric_power_operations_for_individual_power_plants_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/facility-fuel/data/?api_key=MOCK_API_KEY&data%5B0%5D=average-heat-content&data%5B1%5D=consumption-for-eg&data%5B2%5D=consumption-for-eg-btu&data%5B3%5D=generation&data%5B4%5D=gross-generation&data%5B5%5D=total-consumption&data%5B6%5D=total-consumption-btu&end=2001-01&facets%5Bfuel2002%5D%5B%5D=ALL&facets%5BfuelType%5D%5B%5D=ALL&facets%5BplantCode%5D%5B%5D=2&facets%5BprimeMover%5D%5B%5D=ALL&facets%5Bstate%5D%5B%5D=AL&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2001-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2001-01","plantCode":"2","plantName":"Bankhead + Dam","fuel2002":"ALL","fuel2002TypeDescription":"Total","fuelType":"ALL","fuelTypeDescription":"Total","state":"AL","stateDescription":"Alabama","primeMover":"ALL","average-heat-content":null,"average-heat-content-units":null,"consumption-for-eg":null,"consumption-for-eg-units":null,"consumption-for-eg-btu":"195479.69","generation":"18918","gross-generation":"19109.09","total-consumption":null,"total-consumption-units":null,"total-consumption-btu":"195479.69","consumption-for-eg-btu-units":"MMBtu","generation-units":"megawatthours","gross-generation-units":"megawatthours","total-consumption-btu-units":"MMBtu"}],"description":"Annual + and monthly electric power operations for individual power plants, by energy + source and prime mover\n Source: Form EIA-923"},"request":{"command":"\/v2\/electricity\/facility-fuel\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["average-heat-content","consumption-for-eg","consumption-for-eg-btu","generation","gross-generation","total-consumption","total-consumption-btu"],"facets":{"plantCode":["2"],"fuel2002":["ALL"],"fuelType":["ALL"],"state":["AL"],"primeMover":["ALL"]},"start":"2001-01","end":"2001-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:23 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:23 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1473' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_electricity_sales_to_ultimate_customers_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_electricity_sales_to_ultimate_customers_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..ff0da61322e --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_electricity_sales_to_ultimate_customers_fetcher_urllib3_v2.yaml @@ -0,0 +1,66 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/retail-sales/data/?api_key=MOCK_API_KEY&data%5B0%5D=customers&data%5B1%5D=price&data%5B2%5D=revenue&data%5B3%5D=sales&end=2001-01&facets%5Bsectorid%5D%5B%5D=ALL&facets%5Bstateid%5D%5B%5D=AK&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2001-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2001-01","stateid":"AK","stateDescription":"Alaska","sectorid":"ALL","sectorName":"all + sectors","customers":null,"price":"9.97","revenue":"51.96404","sales":"521.03566","customers-units":"number + of customers","price-units":"cents per kilowatt-hour","revenue-units":"million + dollars","sales-units":"million kilowatt hours"}],"description":"Electricity + sales to ultimate customer by state and sector (number of customers, average + price, revenue, and megawatthours of sales). \n Sources: Forms EIA-826, + EIA-861, EIA-861M"},"request":{"command":"\/v2\/electricity\/retail-sales\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["customers","price","revenue","sales"],"facets":{"stateid":["AK"],"sectorid":["ALL"]},"start":"2001-01","end":"2001-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:24 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:24 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1017' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_demand_by_subregion_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_demand_by_subregion_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..de1d55fbc68 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_demand_by_subregion_fetcher_urllib3_v2.yaml @@ -0,0 +1,65 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/rto/region-sub-ba-data/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2019-01-02T00&facets%5Bparent%5D%5B%5D=CISO&facets%5Bsubba%5D%5B%5D=PGAE&frequency=hourly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2019-01-02T00 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD\"T\"HH24","frequency":"hourly","data":[{"period":"2019-01-02T00","subba":"PGAE","subba-name":"Pacific + Gas and Electric","parent":"CISO","parent-name":"California Independent System + Operator","value":"9235","value-units":"megawatthours"}],"description":"Hourly + demand by balancing authority subregion. \n Source: Form EIA-930\n Product: + Hourly Electric Grid Monitor"},"request":{"command":"\/v2\/electricity\/rto\/region-sub-ba-data\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"hourly","data":["value"],"facets":{"subba":["PGAE"],"parent":["CISO"]},"start":"2019-01-02T00","end":"2019-01-02T00","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:25 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:25 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '819' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_demand_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_demand_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..3fd7d7a9a1d --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_demand_fetcher_urllib3_v2.yaml @@ -0,0 +1,65 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/rto/region-data/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2019-01-02T00&facets%5Brespondent%5D%5B%5D=AEC&facets%5Btype%5D%5B%5D=D&frequency=hourly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2019-01-02T00 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD\"T\"HH24","frequency":"hourly","data":[{"period":"2019-01-02T00","respondent":"AEC","respondent-name":"PowerSouth + Energy Cooperative","type":"D","type-name":"Demand","value":"486","value-units":"megawatthours"}],"description":"Hourly + demand, day-ahead demand forecast, net generation, and interchange by balancing + authority. \n Source: Form EIA-930\n Product: Hourly Electric Grid + Monitor"},"request":{"command":"\/v2\/electricity\/rto\/region-data\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"hourly","data":["value"],"facets":{"respondent":["AEC"],"type":["D"]},"start":"2019-01-02T00","end":"2019-01-02T00","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:24 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:24 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '835' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_generation_by_fuel_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_generation_by_fuel_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..edf3c658983 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_generation_by_fuel_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/rto/fuel-type-data/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2019-01-02T00&facets%5Bfueltype%5D%5B%5D=COL&facets%5Brespondent%5D%5B%5D=AEC&frequency=hourly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2019-01-02T00 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD\"T\"HH24","frequency":"hourly","data":[{"period":"2019-01-02T00","respondent":"AEC","respondent-name":"PowerSouth + Energy Cooperative","fueltype":"COL","type-name":"Coal","value":"-3","value-units":"megawatthours"}],"description":"Hourly + net generation by balancing authority and energy source. \n Source: Form + EIA-930\n Product: Hourly Electric Grid Monitor"},"request":{"command":"\/v2\/electricity\/rto\/fuel-type-data\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"hourly","data":["value"],"facets":{"respondent":["AEC"],"fueltype":["COL"]},"start":"2019-01-02T00","end":"2019-01-02T00","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:25 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:25 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '813' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_interchange_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_interchange_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..ec4f2c22052 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_grid_interchange_fetcher_urllib3_v2.yaml @@ -0,0 +1,65 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/rto/interchange-data/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2019-01-02T00&facets%5Bfromba%5D%5B%5D=AEC&facets%5Btoba%5D%5B%5D=MISO&frequency=hourly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2019-01-02T00 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD\"T\"HH24","frequency":"hourly","data":[{"period":"2019-01-02T00","fromba":"AEC","fromba-name":"PowerSouth + Energy Cooperative","toba":"MISO","toba-name":"Midcontinent Independent System + Operator, Inc.","value":"112","value-units":"megawatthours"}],"description":"Daily + interchange between neighboring balancing authorities. \n Source: Form + EIA-930\n Product: Hourly Electric Grid Monitor"},"request":{"command":"\/v2\/electricity\/rto\/interchange-data\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"hourly","data":["value"],"facets":{"fromba":["AEC"],"toba":["MISO"]},"start":"2019-01-02T00","end":"2019-01-02T00","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:26 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:26 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '837' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_inventory_of_operable_generators_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_inventory_of_operable_generators_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..410a3294eac --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_electricity_inventory_of_operable_generators_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/operating-generator-capacity/data/?api_key=MOCK_API_KEY&data%5B0%5D=county&data%5B10%5D=planned-uprate-summer-cap-mw&data%5B11%5D=planned-uprate-year-month&data%5B1%5D=latitude&data%5B2%5D=longitude&data%5B3%5D=nameplate-capacity-mw&data%5B4%5D=net-summer-capacity-mw&data%5B5%5D=net-winter-capacity-mw&data%5B6%5D=operating-year-month&data%5B7%5D=planned-derate-summer-cap-mw&data%5B8%5D=planned-derate-year-month&data%5B9%5D=planned-retirement-year-month&end=2008-01&facets%5Benergy_source_code%5D%5B%5D=WAT&facets%5Bgeneratorid%5D%5B%5D=1&facets%5Bplantid%5D%5B%5D=2&facets%5Bprime_mover_code%5D%5B%5D=HY&facets%5Bsector%5D%5B%5D=electric-utility&facets%5Bstateid%5D%5B%5D=AL&facets%5Bstatus%5D%5B%5D=OP&facets%5Btechnology%5D%5B%5D=Conventional+Hydroelectric&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2008-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2008-01","stateid":"AL","stateName":"Alabama","sector":"electric-utility","sectorName":"Electric + Utility","entityid":"195","entityName":"Alabama Power Co","plantid":"2","plantName":"Bankhead + Dam","generatorid":"1","technology":"Conventional Hydroelectric","energy_source_code":"WAT","energy-source-desc":"Water","prime_mover_code":"HY","balancing_authority_code":null,"balancing-authority-name":null,"status":"OP","statusDescription":"Operating","county":"Tuscaloosa","latitude":"33.218889","longitude":"87.579722","nameplate-capacity-mw":"45","net-summer-capacity-mw":"56","net-winter-capacity-mw":"52","operating-year-month":"1963-07","planned-derate-summer-cap-mw":null,"planned-derate-year-month":null,"planned-retirement-year-month":null,"planned-uprate-summer-cap-mw":null,"planned-uprate-year-month":null,"unit":null,"nameplate-capacity-mw-units":"MW","net-summer-capacity-mw-units":"MW","net-winter-capacity-mw-units":"MW","planned-derate-summer-cap-mw-units":"MW","planned-uprate-summer-cap-mw-units":"MW"}],"description":"Inventory + of operable generators in the U.S.\n Source: Forms EIA-860, EIA-860M"},"request":{"command":"\/v2\/electricity\/operating-generator-capacity\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["county","latitude","longitude","nameplate-capacity-mw","net-summer-capacity-mw","net-winter-capacity-mw","operating-year-month","planned-derate-summer-cap-mw","planned-derate-year-month","planned-retirement-year-month","planned-uprate-summer-cap-mw","planned-uprate-year-month"],"facets":{"stateid":["AL"],"sector":["electric-utility"],"plantid":["2"],"generatorid":["1"],"technology":["Conventional + Hydroelectric"],"energy_source_code":["WAT"],"prime_mover_code":["HY"],"status":["OP"]},"start":"2008-01","end":"2008-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:20:03 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:20:03 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '2028' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_ieo_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_ieo_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..fc771e13c62 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_ieo_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/ieo/2023/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2020&facets%5Bhistory%5D%5B%5D=HISTORIC&facets%5BregionId%5D%5B%5D=6-20&facets%5Bscenario%5D%5B%5D=HighMacro&facets%5BseriesId%5D%5B%5D=cnsm_bl_cm_cl_qbtu&facets%5BtableId%5D%5B%5D=95&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2020 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2020","history":"HISTORIC","scenario":"HighMacro","scenarioDescription":"High + economic growth","tableId":"95","tableName":"Buildings delivered energy consumption + by end-use sector and fuel","seriesId":"cnsm_bl_cm_cl_qbtu","seriesName":"Energy + use : Commercial : Coal","regionId":"6-20","regionName":"Middle East","value":"0.0","unit":"quadrillion + Btu"}],"description":"International Energy Outlook 2023"},"request":{"command":"\/v2\/ieo\/2023\/data\/","params":{"frequency":"annual","data":["value"],"facets":{"history":["HISTORIC"],"scenario":["HighMacro"],"tableId":["95"],"seriesId":["cnsm_bl_cm_cl_qbtu"],"regionId":["6-20"]},"start":"2020","end":"2020","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:36 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:36 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '871' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_international_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_international_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..98915f6af9a --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_international_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/international/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5BactivityId%5D%5B%5D=1&facets%5BcountryRegionId%5D%5B%5D=AGO&facets%5BcountryRegionTypeId%5D%5B%5D=c&facets%5BproductId%5D%5B%5D=57&facets%5Bunit%5D%5B%5D=TBPD&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","productId":"57","productName":"Crude + oil including lease condensate","activityId":"1","activityName":"Production","countryRegionId":"AGO","countryRegionName":"Angola","countryRegionTypeId":"c","countryRegionTypeName":"Country","dataFlagId":null,"dataFlagDescription":null,"unitName":"thousand + barrels per day","value":"162","unit":"TBPD"}],"description":"Country level + production, consumption, imports, exports by energy source (petroleum, natural + gas, electricity, renewable, etc.) \r\n Interactive product: https:\/\/www.eia.gov\/international\/data\/world"},"request":{"command":"\/v2\/international\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"productId":["57"],"activityId":["1"],"countryRegionId":["AGO"],"countryRegionTypeId":["c"],"unit":["TBPD"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:37 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:37 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1103' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_associated_dissolved_proved_reserves_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_associated_dissolved_proved_reserves_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..9faff42f882 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_associated_dissolved_proved_reserves_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/adng/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1979&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R41&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=RNGR41NUS_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1979 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1979","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"R41","process-name":"Associated-Dissolved, Proved Reserves","series":"RNGR41NUS_1","series-description":"U.S. + Associated-Dissolved Natural Gas, Wet After Lease Separation, Proved Reserves + (Billion Cubic Feet)","value":"59425","units":"BCF"}]},"request":{"command":"\/v2\/natural-gas\/enr\/adng\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["R41"],"series":["RNGR41NUS_1"]},"start":"1979","end":"1979","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:37 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:37 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '834' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_average_depth_of_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_average_depth_of_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..32bcdf0be36 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_average_depth_of_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/welldep/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1949&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=XWD0&facets%5Bproduct%5D%5B%5D=ERTW0&facets%5Bseries%5D%5B%5D=E_ERTW0_XWD0_NUS_FW&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1949 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1949","duoarea":"NUS","area-name":"U.S.","product":"ERTW0","product-name":"Wells-Total","process":"XWD0","process-name":"Average + Depth of Exploratory and Developmental Wells Drilled","series":"E_ERTW0_XWD0_NUS_FW","series-description":"U.S. + Average Depth of Crude Oil, Natural Gas, and Dry Exploratory and Developmental Wells + Drilled (Feet per Well)","value":"3635","units":"F\/W"}]},"request":{"command":"\/v2\/natural-gas\/enr\/welldep\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["ERTW0"],"process":["XWD0"],"series":["E_ERTW0_XWD0_NUS_FW"]},"start":"1949","end":"1949","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:38 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:38 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '892' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_coalbed_methane_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_coalbed_methane_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..bc37c5b8aea --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_coalbed_methane_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/coalbed/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1989&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R51&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=RNGR51NUS_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1989 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1989","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"R51","process-name":"Coalbed Methane, Proved Reserves","series":"RNGR51NUS_1","series-description":"U.S. + Coalbed Methane Proved Reserves (Billion Cubic Feet)","value":"3676","units":"BCF"}]},"request":{"command":"\/v2\/natural-gas\/enr\/coalbed\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["R51"],"series":["RNGR51NUS_1"]},"start":"1989","end":"1989","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:38 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:38 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '785' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_coalbed_methane_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_coalbed_methane_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..78a658aaea5 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_coalbed_methane_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/prod/coalbed/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1989&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R52&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=RNGR52NUS_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1989 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1989","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"R52","process-name":"Coalbed Methane, Reserves Based Production","series":"RNGR52NUS_1","series-description":"U.S. + Coalbed Methane Production (Billion Cubic Feet)","value":"91","units":"BCF"}]},"request":{"command":"\/v2\/natural-gas\/prod\/coalbed\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["R52"],"series":["RNGR52NUS_1"]},"start":"1989","end":"1989","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:39 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:39 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '789' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_costs_of_crude_oil_and_natural_gas_wells_drilled_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_costs_of_crude_oil_and_natural_gas_wells_drilled_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..7b91459edb7 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_costs_of_crude_oil_and_natural_gas_wells_drilled_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/wellcost/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1960&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=XWPR&facets%5Bproduct%5D%5B%5D=ERTW0&facets%5Bseries%5D%5B%5D=E_ERTW0_XWPR_NUS_DF&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1960 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1960","duoarea":"NUS","area-name":"U.S.","product":"ERTW0","product-name":"Wells-Total","process":"XWPR","process-name":"Real + Cost per Foot","series":"E_ERTW0_XWPR_NUS_DF","series-description":"U.S. Real + Cost per Foot of Crude Oil, Natural Gas, and Dry Wells Drilled (Dollars per + Foot)","value":"61.83","units":"$\/F"}]},"request":{"command":"\/v2\/natural-gas\/enr\/wellcost\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["ERTW0"],"process":["XWPR"],"series":["E_ERTW0_XWPR_NUS_DF"]},"start":"1960","end":"1960","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:39 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:39 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '828' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_crude_oil_and_natural_gas_drilling_activity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_crude_oil_and_natural_gas_drilling_activity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..d411890bdf5 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_crude_oil_and_natural_gas_drilling_activity_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/drill/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=XRS&facets%5Bproduct%5D%5B%5D=ERTS0&facets%5Bseries%5D%5B%5D=E_ERTS0_XRS_NUS_C&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS","area-name":"U.S.","product":"ERTS0","product-name":"Crude + Oil and Natural Gas","process":"XRS","process-name":"Active Well Service Rigs + in operation","series":"E_ERTS0_XRS_NUS_C","series-description":"U.S. Crude + Oil and Natural Gas Active Well Service Rigs in operation (Count)","value":"1549","units":"COUNT"}]},"request":{"command":"\/v2\/natural-gas\/enr\/drill\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["ERTS0"],"process":["XRS"],"series":["E_ERTS0_XRS_NUS_C"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:39 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:39 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '851' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_crude_oil_and_natural_gas_exploratory_and_development_wells_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_crude_oil_and_natural_gas_exploratory_and_development_wells_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..5d6691c85a5 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_crude_oil_and_natural_gas_exploratory_and_development_wells_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/wellend/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=XWC0&facets%5Bproduct%5D%5B%5D=ERTW0&facets%5Bseries%5D%5B%5D=E_ERTW0_XWC0_NUS_C&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS","area-name":"U.S.","product":"ERTW0","product-name":"Wells-Total","process":"XWC0","process-name":"Exploratory + and Developmental Wells Drilled","series":"E_ERTW0_XWC0_NUS_C","series-description":"U.S. + Crude Oil, Natural Gas, and Dry Exploratory and Developmental Wells Drilled + (Count)","value":"2166","units":"COUNT"}]},"request":{"command":"\/v2\/natural-gas\/enr\/wellend\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["ERTW0"],"process":["XWC0"],"series":["E_ERTW0_XWC0_NUS_C"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:40 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:40 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '861' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_crude_oil_plus_lease_condensate_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_crude_oil_plus_lease_condensate_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..69531e7e1a8 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_crude_oil_plus_lease_condensate_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/cplc/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2009&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R01&facets%5Bproduct%5D%5B%5D=EPCCOND&facets%5Bseries%5D%5B%5D=RES_EPCCOND_R01_NUS_MMBBL&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2009 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2009","duoarea":"NUS","area-name":"U.S.","product":"EPCCOND","product-name":"Crude + Oil + Lease Condensate","process":"R01","process-name":"Proved Reserves","series":"RES_EPCCOND_R01_NUS_MMBBL","series-description":"U.S. + Crude Oil + Lease Condensate Proved Reserves (Million Barrels)","value":"22315","units":"MMBBL"}]},"request":{"command":"\/v2\/natural-gas\/enr\/cplc\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPCCOND"],"process":["R01"],"series":["RES_EPCCOND_R01_NUS_MMBBL"]},"start":"2009","end":"2009","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:40 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:40 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '829' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_dry_natural_gas_proved_reserves_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_dry_natural_gas_proved_reserves_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..3da63d22807 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_dry_natural_gas_proved_reserves_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/dry/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1925&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R11&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=RNGR11NUS_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1925 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1925","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"R11","process-name":"Dry, Expected Future Production","series":"RNGR11NUS_1","series-description":"U.S. + Dry Natural Gas Expected Future Production (Billion Cubic Feet)","value":"23000","units":"BCF"}]},"request":{"command":"\/v2\/natural-gas\/enr\/dry\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["R11"],"series":["RNGR11NUS_1"]},"start":"1925","end":"1925","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:41 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:41 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '792' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_federal_offshore_gulf_of_america_proved_reserves_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_federal_offshore_gulf_of_america_proved_reserves_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..26e5a0a42d0 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_federal_offshore_gulf_of_america_proved_reserves_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/deep/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1992&facets%5Bduoarea%5D%5B%5D=R3FM&facets%5Bprocess%5D%5B%5D=R01&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=RCRR01R3FM_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1992 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1992","duoarea":"R3FM","area-name":"NA","product":"EPC0","product-name":"Crude + Oil","process":"R01","process-name":"Proved Reserves","series":"RCRR01R3FM_1","series-description":"Gulf + of America Federal Offshore Crude Oil Proved Reserves (Million Barrels)","value":"1835","units":"MMBBL"}]},"request":{"command":"\/v2\/natural-gas\/enr\/deep\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["R3FM"],"product":["EPC0"],"process":["R01"],"series":["RCRR01R3FM_1"]},"start":"1992","end":"1992","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:41 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:41 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '786' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_footage_drilled_for_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_footage_drilled_for_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..82b4fb0c0cb --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_footage_drilled_for_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/wellfoot/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1949&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=XWFD&facets%5Bproduct%5D%5B%5D=ERTW0&facets%5Bseries%5D%5B%5D=E_ERTW0_XWFD_NUS_MF&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1949 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1949","duoarea":"NUS","area-name":"U.S.","product":"ERTW0","product-name":"Wells-Total","process":"XWFD","process-name":"Footage + Drilled for Developmental Wells","series":"E_ERTW0_XWFD_NUS_MF","series-description":"U.S. + Footage Drilled for Crude Oil, Natural Gas, and Dry Developmental Wells (Thousand + Feet)","value":"100821","units":"MF"}]},"request":{"command":"\/v2\/natural-gas\/enr\/wellfoot\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["ERTW0"],"process":["XWFD"],"series":["E_ERTW0_XWFD_NUS_MF"]},"start":"1949","end":"1949","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:42 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:42 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '849' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_gulf_of_america_federal_offshore_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_gulf_of_america_federal_offshore_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..8e976dd2009 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_gulf_of_america_federal_offshore_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/prod/deep/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1992&facets%5Bduoarea%5D%5B%5D=R3FM&facets%5Bprocess%5D%5B%5D=R10&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=RCRR10R3FM_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1992 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1992","duoarea":"R3FM","area-name":"NA","product":"EPC0","product-name":"Crude + Oil","process":"R10","process-name":"Production from Reserves","series":"RCRR10R3FM_1","series-description":"Gulf + of America Federal Offshore Crude Oil Production (Million Barrels)","value":"267","units":"MMBBL"}]},"request":{"command":"\/v2\/natural-gas\/prod\/deep\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["R3FM"],"product":["EPC0"],"process":["R10"],"series":["RCRR10R3FM_1"]},"start":"1992","end":"1992","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:42 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:42 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '790' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_heat_content_of_natural_gas_consumed_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_heat_content_of_natural_gas_consumed_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..29cc8e4e8a5 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_heat_content_of_natural_gas_consumed_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/cons/heat/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2012-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VGTH&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=NGA_EPG0_VGTH_NUS_BTUCF&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2012-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2012-01","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"VGTH","process-name":"Heat Content Delivered to Consumers","series":"NGA_EPG0_VGTH_NUS_BTUCF","series-description":"U.S. + Heat Content of Natural Gas Deliveries to Consumers (BTU per Cubic Foot)","value":null,"units":"BTU\/CF"}]},"request":{"command":"\/v2\/natural-gas\/cons\/heat\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["VGTH"],"series":["NGA_EPG0_VGTH_NUS_BTUCF"]},"start":"2012-01","end":"2012-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:42 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:42 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '848' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_international_interstate_movements_of_natural_gas_by_state_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_international_interstate_movements_of_natural_gas_by_state_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..5fba915f3b4 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_international_interstate_movements_of_natural_gas_by_state_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/move/ist/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1930&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bduoarea%5D%5B%5D=NUS-Z0R&facets%5Bduoarea%5D%5B%5D=NUS-Z0S&facets%5Bprocess%5D%5B%5D=EEI&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=NA1280_NUS_2&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1930 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1930","duoarea":"NUS-Z00","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"EEI","process-name":"Exports + Intransit","series":"NA1280_NUS_2","series-description":"U.S. + Natural Gas International Deliveries (MMcf)","value":"1798","units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/move\/ist\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS-Z0S","NUS-Z00","NUS-Z0R"],"product":["EPG0"],"process":["EEI"],"series":["NA1280_NUS_2"]},"start":"1930","end":"1930","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:43 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:43 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '791' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_lease_condensate_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_lease_condensate_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..33fefc34ea3 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_lease_condensate_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/lc/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1979&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R56&facets%5Bproduct%5D%5B%5D=EPL0&facets%5Bseries%5D%5B%5D=RL2R56NUS_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1979 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1979","duoarea":"NUS","area-name":"U.S.","product":"EPL0","product-name":"Natural + Gas Liquids and Liquid Refinery Gases","process":"R56","process-name":"Lease + Condensate, Proved Reserves","series":"RL2R56NUS_1","series-description":"U.S. + Natural Gas Liquids Lease Condensate, Proved Reserves (Million Barrels)","value":"1411","units":"MMBBL"}]},"request":{"command":"\/v2\/natural-gas\/enr\/lc\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPL0"],"process":["R56"],"series":["RL2R56NUS_1"]},"start":"1979","end":"1979","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:43 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:43 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '836' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_lease_condensate_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_lease_condensate_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..ce52729fb22 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_lease_condensate_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/prod/lc/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1979&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R57&facets%5Bproduct%5D%5B%5D=EPL0&facets%5Bseries%5D%5B%5D=RL2R57NUS_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1979 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1979","duoarea":"NUS","area-name":"U.S.","product":"EPL0","product-name":"Natural + Gas Liquids and Liquid Refinery Gases","process":"R57","process-name":"Lease + Condensate, Reserves Based Production","series":"RL2R57NUS_1","series-description":"U.S. + Natural Gas Liquids Lease Condensate, Reserves Based Production (Million Barrels)","value":"147","units":"MMBBL"}]},"request":{"command":"\/v2\/natural-gas\/prod\/lc\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPL0"],"process":["R57"],"series":["RL2R57NUS_1"]},"start":"1979","end":"1979","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:43 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:43 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '856' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_lng_storage_additions_and_withdrawals_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_lng_storage_additions_and_withdrawals_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..b324e70561a --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_lng_storage_additions_and_withdrawals_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/stor/lng/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1969&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=SAL&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=NA1350_NUS_2&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1969 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1969","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"SAL","process-name":"LNG Storage Net Withdrawals","series":"NA1350_NUS_2","series-description":"U.S. + Natural Gas LNG Storage Net Withdrawals (MMcf)","value":"-2581","units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/stor\/lng\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["SAL"],"series":["NA1350_NUS_2"]},"start":"1969","end":"1969","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:44 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:44 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '775' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_maximum_us_active_seismic_crew_counts_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_maximum_us_active_seismic_crew_counts_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..d063de04e47 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_maximum_us_active_seismic_crew_counts_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/seis/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2000-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=XS0&facets%5Bproduct%5D%5B%5D=ERTCES&facets%5Bseries%5D%5B%5D=E_ERTCES_XS0_NUS_C&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2000-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2000-01","duoarea":"NUS","area-name":"U.S.","product":"ERTCES","product-name":"Crews + Engaged in Seismic Exploration","process":"XS0","process-name":"Maximum Number + of Active Crews Engaged in Sismic Surveying","series":"E_ERTCES_XS0_NUS_C","series-description":"U.S. + Maximum Number of Active Crews Engaged in Seismic Surveying (Count)","value":"0","units":"COUNT"}]},"request":{"command":"\/v2\/natural-gas\/enr\/seis\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["ERTCES"],"process":["XS0"],"series":["E_ERTCES_XS0_NUS_C"]},"start":"2000-01","end":"2000-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:44 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:44 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '879' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_annual_supply_disposition_by_state_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_annual_supply_disposition_by_state_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..198ac0e613a --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_annual_supply_disposition_by_state_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/sum/snd/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=SAI&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N5050US2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"SAI","process-name":"Underground Storage Injections","series":"N5050US2","series-description":"U.S. + Total Natural Gas Injections into Underground Storage (MMcf)","value":null,"units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/sum\/snd\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["SAI"],"series":["N5050US2"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:44 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:44 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '794' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_consumption_by_end_use_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_consumption_by_end_use_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..8994cc03600 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_consumption_by_end_use_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/cons/sum/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VCS&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N3020US2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"VCS","process-name":"Commercial Consumption","series":"N3020US2","series-description":"Natural + Gas Deliveries to Commercial Consumers (Including Vehicle Fuel through 1996) + in the U.S. (MMcf)","value":"392315","units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/cons\/sum\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["VCS"],"series":["N3020US2"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:45 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:45 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '829' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_delivered_for_the_account_of_others_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_delivered_for_the_account_of_others_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..d6e8815405c --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_delivered_for_the_account_of_others_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/cons/acct/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1982&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VFT&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=NA1562_NUS_2&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1982 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1982","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"VFT","process-name":"Delivered to Industrial Consumers for + the Account of Others","series":"NA1562_NUS_2","series-description":"U.S. + Natural Gas Delivered to Industrial Consumers for the Account of Others (MMcf)","value":"867124","units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/cons\/acct\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["VFT"],"series":["NA1562_NUS_2"]},"start":"1982","end":"1982","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:45 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:45 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '841' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_gross_withdrawals_and_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_gross_withdrawals_and_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..cd343578bcd --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_gross_withdrawals_and_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/prod/sum/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VRN&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N9030US2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"VRN","process-name":"Removed from Natural Gas","series":"N9030US2","series-description":"U.S. + Nonhydrocarbon Gases Removed from Natural Gas (MMcf)","value":null,"units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/prod\/sum\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["VRN"],"series":["N9030US2"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:46 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:46 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '781' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_liquids_proved_reserves_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_liquids_proved_reserves_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..a4906f0eaa1 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_liquids_proved_reserves_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/ngl/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1979&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R01&facets%5Bproduct%5D%5B%5D=EPL0&facets%5Bseries%5D%5B%5D=RL2R01NUS_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1979 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1979","duoarea":"NUS","area-name":"U.S.","product":"EPL0","product-name":"Natural + Gas Liquids and Liquid Refinery Gases","process":"R01","process-name":"Proved + Reserves","series":"RL2R01NUS_1","series-description":"U.S. Natural Gas Plant + Liquids, Proved Reserves (Million Barrels)","value":"6615","units":"MMBBL"}]},"request":{"command":"\/v2\/natural-gas\/enr\/ngl\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPL0"],"process":["R01"],"series":["RL2R01NUS_1"]},"start":"1979","end":"1979","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:47 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:47 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '808' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_plant_liquids_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_plant_liquids_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..e33ec9206b2 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_plant_liquids_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/prod/ngpl/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1979&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R55&facets%5Bproduct%5D%5B%5D=EPL0&facets%5Bseries%5D%5B%5D=RL2R55NUS_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1979 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1979","duoarea":"NUS","area-name":"U.S.","product":"EPL0","product-name":"Natural + Gas Liquids and Liquid Refinery Gases","process":"R55","process-name":"Gas + Plant Liquids, Reserves Based Production","series":"RL2R55NUS_1","series-description":"U.S. + Natural Gas Plant Liquids, Reserves Based Production (Million Barrels)","value":"580","units":"MMBBL"}]},"request":{"command":"\/v2\/natural-gas\/prod\/ngpl\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPL0"],"process":["R55"],"series":["RL2R55NUS_1"]},"start":"1979","end":"1979","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:47 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:47 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '848' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_plant_processing_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_plant_processing_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..e11bb642aa3 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_plant_processing_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/prod/pp/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VG9&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N9060US2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"VG9","process-name":"Extraction Loss","series":"N9060US2","series-description":"U.S. + Natural Gas Plant Liquids Production (Million Cubic Feet)","value":"79000","units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/prod\/pp\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["VG9"],"series":["N9060US2"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:48 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:48 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '779' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_prices_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_prices_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..0dad970737d --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_prices_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/pri/sum/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=PRS&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N3010US3&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"PRS","process-name":"Price Delivered to Residential Consumers","series":"N3010US3","series-description":"U.S. + Price of Natural Gas Delivered to Residential Consumers (Dollars per Thousand + Cubic Feet)","value":null,"units":"$\/MCF"}]},"request":{"command":"\/v2\/natural-gas\/pri\/sum\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00","NUS"],"product":["EPG0"],"process":["PRS"],"series":["N3010US3"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:49 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:49 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '845' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_proved_reserves_wet_after_lease_separation_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_proved_reserves_wet_after_lease_separation_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..297afc53a45 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_proved_reserves_wet_after_lease_separation_fetcher_urllib3_v2.yaml @@ -0,0 +1,65 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/wals/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1979&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R23&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=RNGR23NUS_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1979 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1979","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"R23","process-name":"Wet After Lease Separation, Reserves + Revision Increases","series":"RNGR23NUS_1","series-description":"U.S. Natural + Gas, Wet After Lease Separation Reserves Revision Increases (Billion Cubic + Feet)","value":"17077","units":"BCF"}]},"request":{"command":"\/v2\/natural-gas\/enr\/wals\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["R23"],"series":["RNGR23NUS_1"]},"start":"1979","end":"1979","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:50 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:50 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '842' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_reserves_summary_as_of_dec31_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_reserves_summary_as_of_dec31_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..0e05535f244 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_reserves_summary_as_of_dec31_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/sum/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1925&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R11&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=RNGR11NUS_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1925 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1925","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"R11","process-name":"Dry, Expected Future Production","series":"RNGR11NUS_1","series-description":"U.S. + Dry Natural Gas Expected Future Production (Billion Cubic Feet)","value":"23000","units":"BCF"}]},"request":{"command":"\/v2\/natural-gas\/enr\/sum\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["R11"],"series":["RNGR11NUS_1"]},"start":"1925","end":"1925","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:50 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:50 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '792' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_spot_and_futures_prices_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_spot_and_futures_prices_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..59a67e38aa2 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_spot_and_futures_prices_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/pri/fut/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1993-12-24&facets%5Bduoarea%5D%5B%5D=Y35NY&facets%5Bprocess%5D%5B%5D=PE4&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=RNGC4&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1993-12-24 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"1993-12-24","duoarea":"Y35NY","area-name":"NEW + YORK CITY","product":"EPG0","product-name":"Natural Gas","process":"PE4","process-name":"Future + Contract 4","series":"RNGC4","series-description":"Natural Gas Futures Contract + 4 (Dollars per Million Btu)","value":"1.869","units":"$\/MMBTU"}]},"request":{"command":"\/v2\/natural-gas\/pri\/fut\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["Y35NY"],"product":["EPG0"],"process":["PE4"],"series":["RNGC4"]},"start":"1993-12-24","end":"1993-12-24","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:51 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:51 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '796' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_summary_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_summary_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..2b05037bb81 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_summary_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/sum/lsum/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=PRS&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N3010US3&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"PRS","process-name":"Price Delivered to Residential Consumers","series":"N3010US3","series-description":"U.S. + Price of Natural Gas Delivered to Residential Consumers (Dollars per Thousand + Cubic Feet)","value":null,"units":"$\/MCF"}]},"request":{"command":"\/v2\/natural-gas\/sum\/lsum\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00","NUS"],"product":["EPG0"],"process":["PRS"],"series":["N3010US3"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:51 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:51 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '846' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_wellhead_value_and_marketed_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_wellhead_value_and_marketed_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..e3f4c82c8b0 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_natural_gas_wellhead_value_and_marketed_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/prod/whv/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VGM&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N9050US2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"VGM","process-name":"Marketed Production","series":"N9050US2","series-description":"U.S. + Natural Gas Marketed Production (MMcf)","value":"1948000","units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/prod\/whv\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["VGM"],"series":["N9050US2"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:52 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:52 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '767' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_nonassociated_proved_reserves_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_nonassociated_proved_reserves_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..c0a89098418 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_nonassociated_proved_reserves_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/nang/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1979&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R31&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=RNGR31NUS_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1979 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1979","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"R31","process-name":"Nonassociated, Proved Reserves","series":"RNGR31NUS_1","series-description":"U.S. + Nonassociated Natural Gas, Wet After Lease Separation, Proved Reserves (Billion + Cubic Feet)","value":"148910","units":"BCF"}]},"request":{"command":"\/v2\/natural-gas\/enr\/nang\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["R31"],"series":["RNGR31NUS_1"]},"start":"1979","end":"1979","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:52 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:52 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '821' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_number_of_gas_producing_oil_wells_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_number_of_gas_producing_oil_wells_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..b06e312bad7 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_number_of_gas_producing_oil_wells_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/prod/oilwells/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2011&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=XDC&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=NGM_EPG0_XDC_NUS_COUNT&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2011 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2011","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"XDC","process-name":"Number of Oil Wells","series":"NGM_EPG0_XDC_NUS_COUNT","series-description":"U.S. + Natural Gas Number of Oil Wells (Count)","value":"181241","units":"COUNT"}]},"request":{"command":"\/v2\/natural-gas\/prod\/oilwells\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["XDC"],"series":["NGM_EPG0_XDC_NUS_COUNT"]},"start":"2011","end":"2011","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:53 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:53 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '787' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_number_of_natural_gas_consumers_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_number_of_natural_gas_consumers_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..f8aff3e2950 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_number_of_natural_gas_consumers_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/cons/num/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1967&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VP5&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=NA1531_NUS_10&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1967 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1967","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"VP5","process-name":"Average Annual Consumption per Commercial + Consumer","series":"NA1531_NUS_10","series-description":"U.S. Natural Gas + Average Annual Consumption per Commercial Consumer (Mcf)","value":"637","units":"MCF"}]},"request":{"command":"\/v2\/natural-gas\/cons\/num\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["VP5"],"series":["NA1531_NUS_10"]},"start":"1967","end":"1967","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:53 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:53 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '819' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_number_of_producing_gas_wells_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_number_of_producing_gas_wells_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..baea7390d6e --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_number_of_producing_gas_wells_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/prod/wells/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1989&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=XDG&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=NA1170_NUS_8&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1989 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1989","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"XDG","process-name":"Number of Gas and Gas Condensate Wells","series":"NA1170_NUS_8","series-description":"U.S. + Natural Gas Number of Gas and Gas Condensate Wells (Count)","value":"262483","units":"COUNT"}]},"request":{"command":"\/v2\/natural-gas\/prod\/wells\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["XDG"],"series":["NA1170_NUS_8"]},"start":"1989","end":"1989","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:54 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:54 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '802' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_offshore_gross_withdrawals_of_natural_gas_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_offshore_gross_withdrawals_of_natural_gas_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..12dbfcfc965 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_offshore_gross_withdrawals_of_natural_gas_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/prod/off/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1997-01&facets%5Bduoarea%5D%5B%5D=R3FM&facets%5Bprocess%5D%5B%5D=FGG&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N9011FX2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1997-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1997-01","duoarea":"R3FM","area-name":"NA","product":"EPG0","product-name":"Natural + Gas","process":"FGG","process-name":"Withdrawals from Gas Wells","series":"N9011FX2","series-description":"Federal + Offshore--Gulf of America Natural Gas Gross Withdrawals from Gas Wells (MMcf)","value":"380694","units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/prod\/off\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R3FM"],"product":["EPG0"],"process":["FGG"],"series":["N9011FX2"]},"start":"1997-01","end":"1997-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:54 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:54 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '815' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_plant_liquids_in_proved_reserves_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_plant_liquids_in_proved_reserves_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..711f19e3c35 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_plant_liquids_in_proved_reserves_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/ngpl/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1979&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R54&facets%5Bproduct%5D%5B%5D=EPL0&facets%5Bseries%5D%5B%5D=RL2R54NUS_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1979 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1979","duoarea":"NUS","area-name":"U.S.","product":"EPL0","product-name":"Natural + Gas Liquids and Liquid Refinery Gases","process":"R54","process-name":"Gas + Plant Liquids, Expected Future Production","series":"RL2R54NUS_1","series-description":"U.S. + Natural Gas Plant Liquids, Expected Future Production (Million Barrels)","value":"5204","units":"MMBBL"}]},"request":{"command":"\/v2\/natural-gas\/enr\/ngpl\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPL0"],"process":["R54"],"series":["RL2R54NUS_1"]},"start":"1979","end":"1979","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:54 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:54 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '850' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_proved_nonproducing_reserves_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_proved_nonproducing_reserves_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..d99f251f8af --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_proved_nonproducing_reserves_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/nprod/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1996&facets%5Bduoarea%5D%5B%5D=R1901F&facets%5Bduoarea%5D%5B%5D=R44F&facets%5Bduoarea%5D%5B%5D=R48&facets%5Bduoarea%5D%5B%5D=R5F&facets%5Bduoarea%5D%5B%5D=RCAC&facets%5Bduoarea%5D%5B%5D=RCAJ&facets%5Bduoarea%5D%5B%5D=RCAL&facets%5Bduoarea%5D%5B%5D=RCASF&facets%5Bduoarea%5D%5B%5D=RLAN&facets%5Bduoarea%5D%5B%5D=RLASF&facets%5Bduoarea%5D%5B%5D=RLASO&facets%5Bduoarea%5D%5B%5D=RNMEAST&facets%5Bduoarea%5D%5B%5D=RNMWEST&facets%5Bduoarea%5D%5B%5D=RTX01&facets%5Bduoarea%5D%5B%5D=RTX02&facets%5Bduoarea%5D%5B%5D=RTX03&facets%5Bduoarea%5D%5B%5D=RTX04&facets%5Bduoarea%5D%5B%5D=RTX05&facets%5Bduoarea%5D%5B%5D=RTX06&facets%5Bduoarea%5D%5B%5D=RTX07B&facets%5Bduoarea%5D%5B%5D=RTX07C&facets%5Bduoarea%5D%5B%5D=RTX08&facets%5Bduoarea%5D%5B%5D=RTX08A&facets%5Bduoarea%5D%5B%5D=RTX09&facets%5Bduoarea%5D%5B%5D=RTX10&facets%5Bduoarea%5D%5B%5D=RTXSF&facets%5Bduoarea%5D%5B%5D=RUSF&facets%5Bprocess%5D%5B%5D=R9910&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=RES_EPG0_R9910_R44F_BCF&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1996 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1996","duoarea":"R44F","area-name":"NA","product":"EPG0","product-name":"Natural + Gas","process":"R9910","process-name":"Associated-Dissolved, Reserves in Nonproducing + Reservoirs","series":"RES_EPG0_R9910_R44F_BCF","series-description":"Gulf + of America Federal Offshore (Western) Associated-Dissolved Natural Gas, Reserves + in Nonproducing Reservoirs, Wet (Bcf)","value":"384","units":"BCF"}]},"request":{"command":"\/v2\/natural-gas\/enr\/nprod\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["RTX01","R44F","RTX07B","RNMWEST","RTX03","RTX05","RTXSF","RTX08A","RTX08","RCAC","RLASO","RTX07C","RCAL","RCASF","RLASF","RTX09","RUSF","R1901F","R5F","RNMEAST","RTX06","R48","RCAJ","RLAN","RTX02","RTX04","RTX10"],"product":["EPG0"],"process":["R9910"],"series":["RES_EPG0_R9910_R44F_BCF"]},"start":"1996","end":"1996","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:55 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:55 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1109' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_residential_and_commercial_prices_selected_states_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_residential_and_commercial_prices_selected_states_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..c01a5c67ae1 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_residential_and_commercial_prices_selected_states_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/pri/rescom/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1989-01&facets%5Bduoarea%5D%5B%5D=SDC&facets%5Bprocess%5D%5B%5D=PRS&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N3010DC3&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1989-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1989-01","duoarea":"SDC","area-name":"USA-DC","product":"EPG0","product-name":"Natural + Gas","process":"PRS","process-name":"Price Delivered to Residential Consumers","series":"N3010DC3","series-description":"District + of Columbia Price of Natural Gas Delivered to Residential Consumers (Dollars + per Thousand Cubic Feet)","value":"7.49","units":"$\/MCF"}]},"request":{"command":"\/v2\/natural-gas\/pri\/rescom\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["SDC"],"product":["EPG0"],"process":["PRS"],"series":["N3010DC3"]},"start":"1989-01","end":"1989-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:55 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:55 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '858' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_shale_gas_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_shale_gas_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..e310b5c2967 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_shale_gas_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/enr/shalegas/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2007&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R5301&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=RES_EPG0_R5301_NUS_BCF&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2007 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2007","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"R5301","process-name":"Shale, Proved Reserves","series":"RES_EPG0_R5301_NUS_BCF","series-description":"U.S. + Shale Proved Reserves (Billion Cubic Feet)","value":"23304","units":"BCF"}]},"request":{"command":"\/v2\/natural-gas\/enr\/shalegas\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["R5301"],"series":["RES_EPG0_R5301_NUS_BCF"]},"start":"2007","end":"2007","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:56 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:56 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '793' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_shale_gas_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_shale_gas_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..6744ed7b6d9 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_shale_gas_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/prod/shalegas/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2007&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R5302&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=RES_EPG0_R5302_NUS_BCF&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2007 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2007","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"R5302","process-name":"Shale, Reserves Based Production","series":"RES_EPG0_R5302_NUS_BCF","series-description":"U.S. + Shale Production (Billion Cubic Feet)","value":"1293","units":"BCF"}]},"request":{"command":"\/v2\/natural-gas\/prod\/shalegas\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["R5302"],"series":["RES_EPG0_R5302_NUS_BCF"]},"start":"2007","end":"2007","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:56 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:56 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '798' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_share_of_total_us_natural_gas_delivered_to_consumers_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_share_of_total_us_natural_gas_delivered_to_consumers_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..0b67ae638b2 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_share_of_total_us_natural_gas_delivered_to_consumers_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/cons/pns/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1993&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VRP&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=NA1500_NUS_4&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1993 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1993","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"VRP","process-name":"% of Total Residential Deliveries","series":"NA1500_NUS_4","series-description":"U.S. + Natural Gas % of Total Residential Deliveries (%)","value":"100","units":"%"}]},"request":{"command":"\/v2\/natural-gas\/cons\/pns\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["VRP"],"series":["NA1500_NUS_4"]},"start":"1993","end":"1993","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:57 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:57 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '779' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_supplemental_gas_supplies_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_supplemental_gas_supplies_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..3a2dd0805e9 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_supplemental_gas_supplies_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/prod/ss/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1980-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=OVI&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N9090US2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1980-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1980-01","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"OVI","process-name":"Input Supplemental Fuels","series":"N9090US2","series-description":"U.S. + Natural Gas Input Supplemental Fuels (MMcf)","value":"17000","units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/prod\/ss\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["OVI"],"series":["N9090US2"]},"start":"1980-01","end":"1980-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:57 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:57 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '774' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_underground_natural_gas_storage_by_all_operators_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_underground_natural_gas_storage_by_all_operators_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..04cbba7770e --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_underground_natural_gas_storage_by_all_operators_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/stor/sum/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=SAB&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N5010US2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"SAB","process-name":"Underground Storage Base Gas","series":"N5010US2","series-description":"U.S. + Total Natural Gas in Underground Storage (Base Gas) (MMcf)","value":null,"units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/stor\/sum\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["SAB"],"series":["N5010US2"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:57 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:57 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '791' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_underground_natural_gas_storage_capacity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_underground_natural_gas_storage_capacity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..b56d2e7162b --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_underground_natural_gas_storage_capacity_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/stor/cap/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1989-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=SAC&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N5290US2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1989-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1989-01","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"SAC","process-name":"Total Underground Storage Capacity","series":"N5290US2","series-description":"U.S. + Total Natural Gas Underground Storage Capacity (MMcf)","value":"8119368","units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/stor\/cap\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["SAC"],"series":["N5290US2"]},"start":"1989-01","end":"1989-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:58 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:58 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '797' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_exports_and_re_exports_by_country_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_exports_and_re_exports_by_country_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..8fe48b11f3a --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_exports_and_re_exports_by_country_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/move/expc/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=EEX&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N9130US2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS-Z00","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"EEX","process-name":"Exports","series":"N9130US2","series-description":"U.S. + Natural Gas Exports (MMcf)","value":"5808","units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/move\/expc\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00"],"product":["EPG0"],"process":["EEX"],"series":["N9130US2"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:58 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:58 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '749' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_exports_and_re_exports_by_point_of_exit_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_exports_and_re_exports_by_point_of_exit_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..e8d37e12aed --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_exports_and_re_exports_by_point_of_exit_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/move/poe2/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS-NJA&facets%5Bduoarea%5D%5B%5D=YCAM-NJA&facets%5Bduoarea%5D%5B%5D=YCCPL-NJA&facets%5Bduoarea%5D%5B%5D=YCPT-NJA&facets%5Bduoarea%5D%5B%5D=YCRP-NJA&facets%5Bduoarea%5D%5B%5D=YELBA-NJA&facets%5Bduoarea%5D%5B%5D=YENA-NJA&facets%5Bduoarea%5D%5B%5D=YFPT-NJA&facets%5Bduoarea%5D%5B%5D=YPLAQ-NJA&facets%5Bduoarea%5D%5B%5D=YSPL-NJA&facets%5Bprocess%5D%5B%5D=PNG&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N9133JA3&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS-NJA","area-name":"JPN","product":"EPG0","product-name":"Natural + Gas","process":"PNG","process-name":"Liquefied Natural Gas Exports Price","series":"N9133JA3","series-description":"Price + of Liquefied U.S. Natural Gas Exports to Japan (Dollars per Thousand Cubic + Feet)","value":null,"units":"$\/MCF"}]},"request":{"command":"\/v2\/natural-gas\/move\/poe2\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-NJA","YCPT-NJA","YSPL-NJA","YCAM-NJA","YCCPL-NJA","YCRP-NJA","YELBA-NJA","YENA-NJA","YFPT-NJA","YPLAQ-NJA"],"product":["EPG0"],"process":["PNG"],"series":["N9133JA3"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:59 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:59 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '933' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_imports_by_country_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_imports_by_country_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..cc13ed091cb --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_imports_by_country_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/move/impc/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=IM0&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N9100US2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS-Z00","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"IM0","process-name":"Imports","series":"N9100US2","series-description":"U.S. + Natural Gas Imports (MMcf)","value":"92694","units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/move\/impc\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00"],"product":["EPG0"],"process":["IM0"],"series":["N9100US2"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 02:59:59 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 02:59:59 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '750' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_imports_by_point_of_entry_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_imports_by_point_of_entry_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..407c5ba3459 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_imports_by_point_of_entry_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/move/poe1/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS-NAG&facets%5Bprocess%5D%5B%5D=IML&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N9103AG2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS-NAG","area-name":"DZA","product":"EPG0","product-name":"Natural + Gas","process":"IML","process-name":"Liquefied Natural Gas Imports","series":"N9103AG2","series-description":"U.S. + Liquefied Natural Gas Imports From Algeria (MMcf)","value":"78","units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/move\/poe1\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-NAG"],"product":["EPG0"],"process":["IML"],"series":["N9103AG2"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:00:00 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:00:00 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '791' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_imports_exports_by_state_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_imports_exports_by_state_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..d3acf3199f2 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_imports_exports_by_state_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/move/state/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=EEX&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N9130US2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS-Z00","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"EEX","process-name":"Exports","series":"N9130US2","series-description":"U.S. + Natural Gas Exports (MMcf)","value":"5808","units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/move\/state\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00"],"product":["EPG0"],"process":["EEX"],"series":["N9130US2"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:00:00 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:00:00 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '750' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_monthly_supply_and_disposition_balance_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_monthly_supply_and_disposition_balance_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..80bffcfc95f --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_natural_gas_monthly_supply_and_disposition_balance_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/sum/sndm/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=IMN&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N9180US1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS-Z00","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"IMN","process-name":"Net Imports","series":"N9180US1","series-description":"U.S. + Natural Gas Net Imports (Bcf)","value":"87","units":"BCF"}]},"request":{"command":"\/v2\/natural-gas\/sum\/sndm\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00","NUS"],"product":["EPG0"],"process":["IMN"],"series":["N9180US1"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:00:01 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:00:01 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '758' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_underground_natural_gas_storage_by_storage_type_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_underground_natural_gas_storage_by_storage_type_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..3b9eeca86ce --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_us_underground_natural_gas_storage_by_storage_type_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/stor/type/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=SAB&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=N5010US2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS","area-name":"U.S.","product":"EPG0","product-name":"Natural + Gas","process":"SAB","process-name":"Underground Storage Base Gas","series":"N5010US2","series-description":"U.S. + Total Natural Gas in Underground Storage (Base Gas) (MMcf)","value":null,"units":"MMCF"}]},"request":{"command":"\/v2\/natural-gas\/stor\/type\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPG0"],"process":["SAB"],"series":["N5010US2"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '3' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:00:04 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:00:04 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '792' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_weekly_working_gas_in_underground_storage_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_weekly_working_gas_in_underground_storage_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..7d07c401ed4 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_natural_gas_weekly_working_gas_in_underground_storage_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/natural-gas/stor/wkly/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2010-01-01&facets%5Bduoarea%5D%5B%5D=R31&facets%5Bduoarea%5D%5B%5D=R32&facets%5Bduoarea%5D%5B%5D=R33&facets%5Bduoarea%5D%5B%5D=R34&facets%5Bduoarea%5D%5B%5D=R35&facets%5Bduoarea%5D%5B%5D=R48&facets%5Bprocess%5D%5B%5D=SNO&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=NW2_EPG0_SNO_R33_BCF&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2010-01-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"2010-01-01","duoarea":"R33","area-name":"NA","product":"EPG0","product-name":"Natural + Gas","process":"SNO","process-name":"Non-Salt Underground Storage - Working + Gas","series":"NW2_EPG0_SNO_R33_BCF","series-description":"Weekly Nonsalt + Region Natural Gas Working Underground Storage (Billion Cubic Feet)","value":"826","units":"BCF"}]},"request":{"command":"\/v2\/natural-gas\/stor\/wkly\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["R31","R34","R33","R32","R35","R48"],"product":["EPG0"],"process":["SNO"],"series":["NW2_EPG0_SNO_R33_BCF"]},"start":"2010-01-01","end":"2010-01-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '5' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:00:09 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:00:09 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '887' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_nuclear_outages_facility_level_nuclear_outages_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_nuclear_outages_facility_level_nuclear_outages_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..0b6c2deafca --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_nuclear_outages_facility_level_nuclear_outages_fetcher_urllib3_v2.yaml @@ -0,0 +1,127 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/nuclear-outages/facility-nuclear-outages/data/?api_key=MOCK_API_KEY&data%5B0%5D=capacity&data%5B1%5D=outage&data%5B2%5D=percentOutage&end=2007-01-01&facets%5Bfacility%5D%5B%5D=46&frequency=daily&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2007-01-01 + response: + body: + string: '{"response":{"total":"3","dateFormat":"YYYY-MM-DD","frequency":"daily","data":[{"period":"2007-01-01","facility":"46","facilityName":"Browns + Ferry","capacity":"3369.4","outage":"1100","percentOutage":"32.65","capacity-units":"megawatts","outage-units":"megawatts","percentOutage-units":"percent"}],"description":"Facility + level nuclear outages with capacity, outages, and percent outage. \n Source: Nuclear + Regulatory Commission''s Power Reactor Status Report. \n Interactive + data report: Daily Status of Nuclear Reactors."},"request":{"command":"\/v2\/nuclear-outages\/facility-nuclear-outages\/data\/","params":{"frequency":"daily","data":["capacity","outage","percentOutage"],"facets":{"facility":["46"]},"start":"2007-01-01","end":"2007-01-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:06:44 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:06:44 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '894' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/nuclear-outages/facility-nuclear-outages/data/?api_key=MOCK_API_KEY&data%5B0%5D=capacity&data%5B1%5D=outage&data%5B2%5D=percentOutage&end=2007-01-01&facets%5Bfacility%5D%5B%5D=46&frequency=daily&length=2&offset=1&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2007-01-01 + response: + body: + string: '{"warnings":[{"warning":"incomplete return","description":"The API + can only return 5000 rows in JSON format. Please consider constraining your + request with facet, start, or end, or using offset to paginate results."}],"response":{"total":"3","dateFormat":"YYYY-MM-DD","frequency":"daily","data":[],"description":"Facility + level nuclear outages with capacity, outages, and percent outage. \n Source: Nuclear + Regulatory Commission''s Power Reactor Status Report. \n Interactive + data report: Daily Status of Nuclear Reactors."},"request":{"command":"\/v2\/nuclear-outages\/facility-nuclear-outages\/data\/","params":{"frequency":"daily","data":["capacity","outage","percentOutage"],"facets":{"facility":["46"]},"start":"2007-01-01","end":"2007-01-01","sort":[{"column":"period","direction":"asc"}],"offset":"1","length":"2"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:06:45 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:06:45 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '892' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_nuclear_outages_generator_level_nuclear_outages_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_nuclear_outages_generator_level_nuclear_outages_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..0297a18abc9 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_nuclear_outages_generator_level_nuclear_outages_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/nuclear-outages/generator-nuclear-outages/data/?api_key=MOCK_API_KEY&data%5B0%5D=capacity&data%5B1%5D=outage&data%5B2%5D=percentOutage&end=2007-01-01&facets%5Bfacility%5D%5B%5D=46&facets%5Bgenerator%5D%5B%5D=1&frequency=daily&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2007-01-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"daily","data":[{"period":"2007-01-01","facility":"46","facilityName":"Browns + Ferry","generator":"1","capacity":"1100","outage":"1100","percentOutage":"100","capacity-units":"megawatts","outage-units":"megawatts","percentOutage-units":"percent"}],"description":"Generator + level nuclear outages with capacity, outages, and percent outage. \n Source: Nuclear + Regulatory Commission''s Power Reactor Status Report. \n Interactive + data report: Daily Status of Nuclear Reactors."},"request":{"command":"\/v2\/nuclear-outages\/generator-nuclear-outages\/data\/","params":{"frequency":"daily","data":["capacity","outage","percentOutage"],"facets":{"facility":["46"],"generator":["1"]},"start":"2007-01-01","end":"2007-01-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:06:45 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:06:45 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '926' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_nuclear_outages_us_nuclear_outages_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_nuclear_outages_us_nuclear_outages_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..3b012f48f7d --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_nuclear_outages_us_nuclear_outages_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/nuclear-outages/us-nuclear-outages/data/?api_key=MOCK_API_KEY&data%5B0%5D=capacity&data%5B1%5D=outage&data%5B2%5D=percentOutage&end=2007-01-01&frequency=daily&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2007-01-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"daily","data":[{"period":"2007-01-01","capacity":"101764.9","outage":"1995.074","percentOutage":"1.96","capacity-units":"megawatts","outage-units":"megawatts","percentOutage-units":"percent"}],"description":"Nuclear + outages daily with capacity, outages, and percent outage. \n Source: Nuclear + Regulatory Commission''s Power Reactor Status Report. \n Interactive + data report: Daily Status of Nuclear Reactors."},"request":{"command":"\/v2\/nuclear-outages\/us-nuclear-outages\/data\/","params":{"frequency":"daily","data":["capacity","outage","percentOutage"],"start":"2007-01-01","end":"2007-01-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '6' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:00:37 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:00:37 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '809' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_distillate_fuel_oil_and_kerosene_sales_by_end_use_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_distillate_fuel_oil_and_kerosene_sales_by_end_use_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..7d43e5184e3 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_distillate_fuel_oil_and_kerosene_sales_by_end_use_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/cons/821usea/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1984&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VAF&facets%5Bproduct%5D%5B%5D=EPD2D&facets%5Bseries%5D%5B%5D=K2DVAFNUS1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1984 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1984","duoarea":"NUS","area-name":"U.S.","product":"EPD2D","product-name":"No + 2 Diesel","process":"VAF","process-name":"Adj Sales\/Deliveries to Farm Consumers","series":"K2DVAFNUS1","series-description":"U.S. + No 2 Diesel Adj Sales\/Deliveries to Farm Consumers (Thousand Gallons)","value":"2793582","units":"MGAL"}]},"request":{"command":"\/v2\/petroleum\/cons\/821usea\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPD2D"],"process":["VAF"],"series":["K2DVAFNUS1"]},"start":"1984","end":"1984","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '5' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:00:42 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:00:42 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '813' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_sales_of_distillate_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_sales_of_distillate_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..623cb460b92 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_sales_of_distillate_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/cons/821dsta/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1984&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VAA&facets%5Bproduct%5D%5B%5D=EPD0&facets%5Bseries%5D%5B%5D=KD0VAANUS1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1984 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1984","duoarea":"NUS","area-name":"U.S.","product":"EPD0","product-name":"Distillate + Fuel Oil","process":"VAA","process-name":"Adj Sales\/Deliveries Total to End + Users","series":"KD0VAANUS1","series-description":"U.S. Total Distillate Adj + Sales\/Deliveries Total to End Users (Thousand Gallons)","value":"43731114","units":"MGAL"}]},"request":{"command":"\/v2\/petroleum\/cons\/821dsta\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPD0"],"process":["VAA"],"series":["KD0VAANUS1"]},"start":"1984","end":"1984","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '4' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:00:46 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:00:46 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '827' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_sales_of_kerosene_by_end_use_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_sales_of_kerosene_by_end_use_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..4b524d2f0a7 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_sales_of_kerosene_by_end_use_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/cons/821kera/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1984&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VAA&facets%5Bproduct%5D%5B%5D=EPPK&facets%5Bseries%5D%5B%5D=KDRVAANUS1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1984 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1984","duoarea":"NUS","area-name":"U.S.","product":"EPPK","product-name":"Kerosene","process":"VAA","process-name":"Adj + Sales\/Deliveries Total to End Users","series":"KDRVAANUS1","series-description":"U.S. + Kerosene Adj Sales\/Deliveries Total to End Users (Thousand Gallons)","value":"1771770","units":"MGAL"}]},"request":{"command":"\/v2\/petroleum\/cons\/821kera\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPPK"],"process":["VAA"],"series":["KDRVAANUS1"]},"start":"1984","end":"1984","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '5' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:00:51 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:00:51 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '807' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_sales_of_residual_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_sales_of_residual_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..d629a01db06 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_adjusted_sales_of_residual_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/cons/821rsda/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1984&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VAA&facets%5Bproduct%5D%5B%5D=EPPR&facets%5Bseries%5D%5B%5D=KPRVAANUS1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1984 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1984","duoarea":"NUS","area-name":"U.S.","product":"EPPR","product-name":"Residual + Fuel Oil","process":"VAA","process-name":"Adj Sales\/Deliveries Total to End + Users","series":"KPRVAANUS1","series-description":"U.S. Residual Fuel Oil + Adj Sales\/Deliveries Total to End Users (Thousand Gallons)","value":"21050358","units":"MGAL"}]},"request":{"command":"\/v2\/petroleum\/cons\/821rsda\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPPR"],"process":["VAA"],"series":["KPRVAANUS1"]},"start":"1984","end":"1984","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:00:52 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:00:52 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '826' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_average_depth_of_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_average_depth_of_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..540cdbaad18 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_average_depth_of_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/crd/welldep/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1949&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=XWD0&facets%5Bproduct%5D%5B%5D=ERTW0&facets%5Bseries%5D%5B%5D=E_ERTW0_XWD0_NUS_FW&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1949 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1949","duoarea":"NUS","area-name":"U.S.","product":"ERTW0","product-name":"Wells-Total","process":"XWD0","process-name":"Average + Depth of Exploratory and Developmental Wells Drilled","series":"E_ERTW0_XWD0_NUS_FW","series-description":"U.S. + Average Depth of Crude Oil, Natural Gas, and Dry Exploratory and Developmental Wells + Drilled (Feet per Well)","value":"3635","units":"F\/W"}]},"request":{"command":"\/v2\/petroleum\/crd\/welldep\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["ERTW0"],"process":["XWD0"],"series":["E_ERTW0_XWD0_NUS_FW"]},"start":"1949","end":"1949","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:00:53 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:00:53 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '890' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_biofuels_operable_production_capacity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_biofuels_operable_production_capacity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..078f4f830dc --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_biofuels_operable_production_capacity_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/capbio/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2021-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=8BDPC&facets%5Bproduct%5D%5B%5D=EPOORDB&facets%5Bseries%5D%5B%5D=M_EPOORDB_8BDPC_NUS_MMGL&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2021-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2021-01","duoarea":"NUS","area-name":"U.S.","product":"EPOORDB","product-name":"Biodiesel","process":"8BDPC","process-name":"Biodiesel + Production Capacity","series":"M_EPOORDB_8BDPC_NUS_MMGL","series-description":"U.S. + Biodiesel Production Capacity (Million Gallons)","value":"2395","units":"MMGL"}]},"request":{"command":"\/v2\/petroleum\/pnp\/capbio\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPOORDB"],"process":["8BDPC"],"series":["M_EPOORDB_8BDPC_NUS_MMGL"]},"start":"2021-01","end":"2021-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '4' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:00:57 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:00:57 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '823' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_blender_net_input_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_blender_net_input_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..309f2c56a96 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_blender_net_input_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/inpt3/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2005-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=YIB&facets%5Bproduct%5D%5B%5D=EPOBG&facets%5Bseries%5D%5B%5D=MBCRB_NUS_1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2005-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2005-01","duoarea":"NUS","area-name":"U.S.","product":"EPOBG","product-name":"Gasoline + Blending Components","process":"YIB","process-name":"Motor Gasoline Terminal + Blenders Net Input","series":"MBCRB_NUS_1","series-description":"U.S. Blender + Net Input of Gasoline Blending Components (Thousand Barrels)","value":"56154","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/pnp\/inpt3\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPOBG"],"process":["YIB"],"series":["MBCRB_NUS_1"]},"start":"2005-01","end":"2005-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:00:57 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:00:57 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '842' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_blender_net_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_blender_net_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..3ee6dfab3e4 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_blender_net_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/refp3/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2005-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=YPB&facets%5Bproduct%5D%5B%5D=EPM0RA&facets%5Bseries%5D%5B%5D=MG1RZ_NUS_1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2005-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2005-01","duoarea":"NUS","area-name":"U.S.","product":"EPM0RA","product-name":"Reformulated + Motor Gasoline with Alcohol","process":"YPB","process-name":"Motor Gasoline + Terminal Blenders Net Production","series":"MG1RZ_NUS_1","series-description":"U.S. + Blender Net Production of Reformulated Motor Gasoline with Fuel ALcohol (Thousand + Barrels)","value":"51702","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/pnp\/refp3\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPM0RA"],"process":["YPB"],"series":["MG1RZ_NUS_1"]},"start":"2005-01","end":"2005-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '3' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:01:01 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:01:01 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '883' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_costs_of_crude_oil_and_natural_gas_wells_drilled_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_costs_of_crude_oil_and_natural_gas_wells_drilled_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..a5e6d05d0a8 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_costs_of_crude_oil_and_natural_gas_wells_drilled_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/crd/wellcost/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1960&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=XWPR&facets%5Bproduct%5D%5B%5D=ERTW0&facets%5Bseries%5D%5B%5D=E_ERTW0_XWPR_NUS_DF&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1960 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1960","duoarea":"NUS","area-name":"U.S.","product":"ERTW0","product-name":"Wells-Total","process":"XWPR","process-name":"Real + Cost per Foot","series":"E_ERTW0_XWPR_NUS_DF","series-description":"U.S. Real + Cost per Foot of Crude Oil, Natural Gas, and Dry Wells Drilled (Dollars per + Foot)","value":"61.83","units":"$\/F"}]},"request":{"command":"\/v2\/petroleum\/crd\/wellcost\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["ERTW0"],"process":["XWPR"],"series":["E_ERTW0_XWPR_NUS_DF"]},"start":"1960","end":"1960","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '6' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:01:08 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:01:08 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '826' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_first_purchase_prices_selected_streams_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_first_purchase_prices_selected_streams_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..2da2a2d59ea --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_first_purchase_prices_selected_streams_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/dfp2/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1977-07&facets%5Bduoarea%5D%5B%5D=SAK&facets%5Bprocess%5D%5B%5D=FWA&facets%5Bproduct%5D%5B%5D=EPCANS&facets%5Bseries%5D%5B%5D=F005071__3&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1977-07 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1977-07","duoarea":"SAK","area-name":"USA-AK","product":"EPCANS","product-name":"ANS + Crude Oil","process":"FWA","process-name":"Wellhead Acquisition Price","series":"F005071__3","series-description":"Alaska + North Slope First Purchase Price (Dollars per Barrel)","value":"6.9","units":"$\/BBL"}]},"request":{"command":"\/v2\/petroleum\/pri\/dfp2\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["SAK"],"product":["EPCANS"],"process":["FWA"],"series":["F005071__3"]},"start":"1977-07","end":"1977-07","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:01:09 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:01:09 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '799' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_and_lease_condensate_production_by_api_gravity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_and_lease_condensate_production_by_api_gravity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..f1f125a816a --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_and_lease_condensate_production_by_api_gravity_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/crd/api/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2015-01&facets%5Bduoarea%5D%5B%5D=R3FM&facets%5Bduoarea%5D%5B%5D=R48&facets%5Bduoarea%5D%5B%5D=R98&facets%5Bprocess%5D%5B%5D=FPF&facets%5Bproduct%5D%5B%5D=EPC00U&facets%5Bseries%5D%5B%5D=M_EPC00U_FPF_R48_MBBLD&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2015-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2015-01","duoarea":"R48","area-name":"NA","product":"EPC00U","product-name":"Crude + Gravity of Unkown","process":"FPF","process-name":"Field Production","series":"M_EPC00U_FPF_R48_MBBLD","series-description":"Lower + 48 States Crude Oil and Lease Condensate Production for Unknown API Gravity + (Thousand Barrels per Day)","value":"106","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/crd\/api\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R98","R3FM","R48"],"product":["EPC00U"],"process":["FPF"],"series":["M_EPC00U_FPF_R48_MBBLD"]},"start":"2015-01","end":"2015-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:01:11 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:01:11 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '880' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_and_natural_gas_drilling_activity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_and_natural_gas_drilling_activity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..2f8f36a3c33 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_and_natural_gas_drilling_activity_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/crd/drill/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=XRS&facets%5Bproduct%5D%5B%5D=ERTS0&facets%5Bseries%5D%5B%5D=E_ERTS0_XRS_NUS_C&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS","area-name":"U.S.","product":"ERTS0","product-name":"Crude + Oil and Natural Gas","process":"XRS","process-name":"Active Well Service Rigs + in operation","series":"E_ERTS0_XRS_NUS_C","series-description":"U.S. Crude + Oil and Natural Gas Active Well Service Rigs in operation (Count)","value":"1549","units":"COUNT"}]},"request":{"command":"\/v2\/petroleum\/crd\/drill\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["ERTS0"],"process":["XRS"],"series":["E_ERTS0_XRS_NUS_C"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '4' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:01:15 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:01:15 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '849' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_and_natural_gas_exploratory_and_development_wells_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_and_natural_gas_exploratory_and_development_wells_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..2bf1c926a97 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_and_natural_gas_exploratory_and_development_wells_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/crd/wellend/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=XWC0&facets%5Bproduct%5D%5B%5D=ERTW0&facets%5Bseries%5D%5B%5D=E_ERTW0_XWC0_NUS_C&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS","area-name":"U.S.","product":"ERTW0","product-name":"Wells-Total","process":"XWC0","process-name":"Exploratory + and Developmental Wells Drilled","series":"E_ERTW0_XWC0_NUS_C","series-description":"U.S. + Crude Oil, Natural Gas, and Dry Exploratory and Developmental Wells Drilled + (Count)","value":"2166","units":"COUNT"}]},"request":{"command":"\/v2\/petroleum\/crd\/wellend\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["ERTW0"],"process":["XWC0"],"series":["E_ERTW0_XWC0_NUS_C"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:12:50 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:12:50 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '859' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_input_qualities_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_input_qualities_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..7a979fc9cea --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_input_qualities_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/crq/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1985-01&facets%5Bduoarea%5D%5B%5D=R2A&facets%5Bduoarea%5D%5B%5D=R2B&facets%5Bduoarea%5D%5B%5D=R2C&facets%5Bduoarea%5D%5B%5D=R3A&facets%5Bduoarea%5D%5B%5D=R3B&facets%5Bduoarea%5D%5B%5D=R3C&facets%5Bduoarea%5D%5B%5D=R3D&facets%5Bduoarea%5D%5B%5D=R3E&facets%5Bduoarea%5D%5B%5D=RAP&facets%5Bduoarea%5D%5B%5D=REC&facets%5Bprocess%5D%5B%5D=YCG&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCRAP2A2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1985-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1985-01","duoarea":"R2A","area-name":"NA","product":"EPC0","product-name":"Crude + Oil","process":"YCG","process-name":"Refinery Inputs, Average API Gravity","series":"MCRAP2A2","series-description":"Indiana, + Illinois, Kentucky Refinery District API Gravity (Weighted Average) of Crude + Oil Input to Refineries (Degrees)","value":"36.54","units":"D"}]},"request":{"command":"\/v2\/petroleum\/pnp\/crq\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R2A","R3B","R3A","REC","R3D","R3C","R2B","R2C","R3E","RAP"],"product":["EPC0"],"process":["YCG"],"series":["MCRAP2A2"]},"start":"1985-01","end":"1985-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '11' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:01:36 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:01:36 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '902' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..a1d883d20f3 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/crd/crpdn/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1920-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=FPF&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCRFPUS1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1920-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1920-01","duoarea":"NUS","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"FPF","process-name":"Field Production","series":"MCRFPUS1","series-description":"U.S. + Field Production of Crude Oil (Thousand Barrels)","value":"34008","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/crd\/crpdn\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPC0"],"process":["FPF"],"series":["MCRFPUS1"]},"start":"1920-01","end":"1920-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '6' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:01:42 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:01:42 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '769' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_proved_reserves_reserves_changes_and_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_proved_reserves_reserves_changes_and_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..c2d24edc280 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_proved_reserves_reserves_changes_and_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/crd/pres/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1899&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R01&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=RCRR01NUS_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1899 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1899","duoarea":"NUS","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"R01","process-name":"Proved Reserves","series":"RCRR01NUS_1","series-description":"U.S. + Crude Oil Proved Reserves (Million Barrels)","value":"2500","units":"MMBBL"}]},"request":{"command":"\/v2\/petroleum\/crd\/pres\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPC0"],"process":["R01"],"series":["RCRR01NUS_1"]},"start":"1899","end":"1899","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '6' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:01:49 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:01:49 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '754' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_stocks_at_tank_farms_pipelines_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_stocks_at_tank_farms_pipelines_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..519af431b24 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_oil_stocks_at_tank_farms_pipelines_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/stoc/cu/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1981-01&facets%5Bduoarea%5D%5B%5D=R10&facets%5Bprocess%5D%5B%5D=STT&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCRSFP11&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1981-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1981-01","duoarea":"R10","area-name":"PADD + 1","product":"EPC0","product-name":"Crude Oil","process":"STT","process-name":"Stocks + at Tank Farms","series":"MCRSFP11","series-description":"East Coast (PADD + 1) Crude Oil Stocks at Tank Farms and Pipelines (Thousand Barrels)","value":"2615","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/stoc\/cu\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R10"],"product":["EPC0"],"process":["STT"],"series":["MCRSFP11"]},"start":"1981-01","end":"1981-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '4' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:01:53 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:01:53 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '802' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_plus_lease_condensate_proved_reserves_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_plus_lease_condensate_proved_reserves_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..5d550ed0966 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_crude_plus_lease_condensate_proved_reserves_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/crd/cplc/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2009&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=R01&facets%5Bproduct%5D%5B%5D=EPCCOND&facets%5Bseries%5D%5B%5D=RES_EPCCOND_R01_NUS_MMBBL&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2009 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2009","duoarea":"NUS","area-name":"U.S.","product":"EPCCOND","product-name":"Crude + Oil + Lease Condensate","process":"R01","process-name":"Proved Reserves","series":"RES_EPCCOND_R01_NUS_MMBBL","series-description":"U.S. + Crude Oil + Lease Condensate Proved Reserves (Million Barrels)","value":"22315","units":"MMBBL"}]},"request":{"command":"\/v2\/petroleum\/crd\/cplc\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPCCOND"],"process":["R01"],"series":["RES_EPCCOND_R01_NUS_MMBBL"]},"start":"2009","end":"2009","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '5' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:01:58 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:01:58 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '827' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_distillate_fuel_oil_and_kerosene_sales_by_end_use_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_distillate_fuel_oil_and_kerosene_sales_by_end_use_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..3b0e7f36ed8 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_distillate_fuel_oil_and_kerosene_sales_by_end_use_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/cons/821use/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1984&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VCS&facets%5Bproduct%5D%5B%5D=EPD2F&facets%5Bseries%5D%5B%5D=K2FVCSNUS1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1984 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1984","duoarea":"NUS","area-name":"U.S.","product":"EPD2F","product-name":"No + 2 Fuel Oil \/ Heating Oil","process":"VCS","process-name":"Commercial Consumption","series":"K2FVCSNUS1","series-description":"U.S. + No 2 Fuel Oil \/ Heating Oil Sales\/Deliveries to Commercial Consumers (Thousand + Gallons)","value":"2272133","units":"MGAL"}]},"request":{"command":"\/v2\/petroleum\/cons\/821use\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPD2F"],"process":["VCS"],"series":["K2FVCSNUS1"]},"start":"1984","end":"1984","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:00 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:00 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '831' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_domestic_crude_oil_first_purchase_prices_by_api_gravity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_domestic_crude_oil_first_purchase_prices_by_api_gravity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..9f7e09048b0 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_domestic_crude_oil_first_purchase_prices_by_api_gravity_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/dfp3/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1993-10&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=FWA&facets%5Bproduct%5D%5B%5D=EPC20B&facets%5Bseries%5D%5B%5D=F000000013&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1993-10 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1993-10","duoarea":"NUS","area-name":"U.S.","product":"EPC20B","product-name":"Crude + Gravity 20.0 percent or less","process":"FWA","process-name":"Wellhead Acquisition + Price","series":"F000000013","series-description":"U.S. Domestic Crude Oil + First Purchase Prices with API Gravity 20.0 degrees or less (Dollars per Barrel)","value":"11.41","units":"$\/BBL"}]},"request":{"command":"\/v2\/petroleum\/pri\/dfp3\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPC20B"],"process":["FWA"],"series":["F000000013"]},"start":"1993-10","end":"1993-10","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '3' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:03 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:03 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '864' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_domestic_crude_oil_first_purchase_prices_by_area_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_domestic_crude_oil_first_purchase_prices_by_area_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..641bc183f68 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_domestic_crude_oil_first_purchase_prices_by_area_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/dfp1/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1974-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=FWA&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=F000000__3&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1974-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1974-01","duoarea":"NUS","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"FWA","process-name":"Wellhead Acquisition Price","series":"F000000__3","series-description":"U.S. + Crude Oil First Purchase Price (Dollars per Barrel)","value":"6.95","units":"$\/BBL"}]},"request":{"command":"\/v2\/petroleum\/pri\/dfp1\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPC0"],"process":["FWA"],"series":["F000000__3"]},"start":"1974-01","end":"1974-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:05 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:05 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '786' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_downstream_charge_capacity_of_operable_petroleum_refineries_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_downstream_charge_capacity_of_operable_petroleum_refineries_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..f23881459f0 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_downstream_charge_capacity_of_operable_petroleum_refineries_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/capchg/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1982&facets%5Bduoarea%5D%5B%5D=NPZ&facets%5Bprocess%5D%5B%5D=8CCF&facets%5Bseries%5D%5B%5D=8_NA_8CCF_NPZ_5&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1982 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1982","duoarea":"NPZ","area-name":"PRI","product":"(NA)","product-name":"Not + Applicable","process":"8CCF","process-name":"Refinery Catalytic Cracking, + Fresh Feed Downstream Charge Capacity","series":"8_NA_8CCF_NPZ_5","series-description":"Puerto + Rico Refinery Catalytic Cracking, Fresh Feed Downstream Charge Capacity as + of January 1 (Barrels per Stream Day)","value":"52000","units":"B\/SD"}]},"request":{"command":"\/v2\/petroleum\/pnp\/capchg\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NPZ"],"process":["8CCF"],"series":["8_NA_8CCF_NPZ_5"]},"start":"1982","end":"1982","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:12:51 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:12:51 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '874' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_downstream_processing_of_fresh_feed_input_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_downstream_processing_of_fresh_feed_input_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..2fdec3f0ee1 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_downstream_processing_of_fresh_feed_input_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/dwns/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1987-01&facets%5Bduoarea%5D%5B%5D=R2A&facets%5Bduoarea%5D%5B%5D=R2B&facets%5Bduoarea%5D%5B%5D=R2C&facets%5Bduoarea%5D%5B%5D=R3A&facets%5Bduoarea%5D%5B%5D=R3B&facets%5Bduoarea%5D%5B%5D=R3C&facets%5Bduoarea%5D%5B%5D=R3D&facets%5Bduoarea%5D%5B%5D=R3E&facets%5Bduoarea%5D%5B%5D=RAP&facets%5Bduoarea%5D%5B%5D=REC&facets%5Bprocess%5D%5B%5D=YDF&facets%5Bseries%5D%5B%5D=MCRDF2A2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1987-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1987-01","duoarea":"R2A","area-name":"NA","product":"(NA)","product-name":"Not + Applicable","process":"YDF","process-name":"Downstream Delayed Fluid Coking","series":"MCRDF2A2","series-description":"Refining + District Indiana-Illinois-Kentucky Downstream Processing of Fresh Feed Input + by Delayed and Fluid Coking Units (Thousand Barrels per Day)","value":"140","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/pnp\/dwns\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R2A","R3B","R3A","REC","R3D","R3C","R2B","R2C","R3E","RAP"],"process":["YDF"],"series":["MCRDF2A2"]},"start":"1987-01","end":"1987-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:16:40 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:16:40 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '915' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_exports_by_destination_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_exports_by_destination_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..b8060df8fdf --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_exports_by_destination_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/expc/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1920-01&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=EEX&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCREXUS1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1920-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1920-01","duoarea":"NUS-Z00","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"EEX","process-name":"Exports","series":"MCREXUS1","series-description":"U.S. + Exports of Crude Oil (Thousand Barrels)","value":"469","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/move\/expc\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00"],"product":["EPC0"],"process":["EEX"],"series":["MCREXUS1"]},"start":"1920-01","end":"1920-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '3' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:22 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:22 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '757' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_exports_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_exports_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..fd864f88ce9 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_exports_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/exp/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1920-01&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=EEX&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCREXUS1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1920-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1920-01","duoarea":"NUS-Z00","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"EEX","process-name":"Exports","series":"MCREXUS1","series-description":"U.S. + Exports of Crude Oil (Thousand Barrels)","value":"469","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/move\/exp\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00"],"product":["EPC0"],"process":["EEX"],"series":["MCREXUS1"]},"start":"1920-01","end":"1920-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:19 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:19 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '756' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_feedstocks_consumed_for_production_of_biofuels_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_feedstocks_consumed_for_production_of_biofuels_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..fe90f0bf7b3 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_feedstocks_consumed_for_production_of_biofuels_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/feedbiofuel/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2019-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=YIFBP&facets%5Bproduct%5D%5B%5D=EPOOBDAFO&facets%5Bseries%5D%5B%5D=M_EPOOBDAFO_YIFBP_NUS_MMLB&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2019-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2019-01","duoarea":"NUS","area-name":"U.S.","product":"EPOOBDAFO","product-name":"Other-Animal + Fats Inputs to Biodiesel Production","process":"YIFBP","process-name":"Feedstock + Inputs to Biodiesel Production","series":"M_EPOOBDAFO_YIFBP_NUS_MMLB","series-description":"Other + waste oil, fat, and grease inputs to biofuels production (Million Pounds)","value":"3","units":"MMLB"}]},"request":{"command":"\/v2\/petroleum\/pnp\/feedbiofuel\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPOOBDAFO"],"process":["YIFBP"],"series":["M_EPOOBDAFO_YIFBP_NUS_MMLB"]},"start":"2019-01","end":"2019-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:24 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:24 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '910' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fob_costs_of_imported_crude_oil_by_api_gravity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fob_costs_of_imported_crude_oil_by_api_gravity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..94500149670 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fob_costs_of_imported_crude_oil_by_api_gravity_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/imc3/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1983-01&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=INF&facets%5Bproduct%5D%5B%5D=EPC20B&facets%5Bseries%5D%5B%5D=I000000204&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1983-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1983-01","duoarea":"NUS-Z00","area-name":"NA","product":"EPC20B","product-name":"Crude + Gravity 20.0 percent or less","process":"INF","process-name":"FOB Costs","series":"I000000204","series-description":"U.S. + FOB Costs of Crude with API Gravity 20.0 degrees or less (Dollars per Barrel)","value":"21.58","units":"$\/BBL"}]},"request":{"command":"\/v2\/petroleum\/pri\/imc3\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00"],"product":["EPC20B"],"process":["INF"],"series":["I000000204"]},"start":"1983-01","end":"1983-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:26 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:26 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '831' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fob_costs_of_imported_crude_oil_by_area_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fob_costs_of_imported_crude_oil_by_area_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..f004f71e062 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fob_costs_of_imported_crude_oil_by_area_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/imc1/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-10&facets%5Bduoarea%5D%5B%5D=NUS-ME0&facets%5Bduoarea%5D%5B%5D=NUS-MN0&facets%5Bduoarea%5D%5B%5D=NUS-MP0&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=INF&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=I000000004&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-10 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-10","duoarea":"NUS-Z00","area-name":"NA","product":"EPC0","product-name":"Crude + Oil","process":"INF","process-name":"FOB Costs","series":"I000000004","series-description":"U.S. + FOB Costs of Crude Oil (Dollars per Barrel)","value":"4.24","units":"$\/BBL"}]},"request":{"command":"\/v2\/petroleum\/pri\/imc1\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00","NUS-ME0","NUS-MP0","NUS-MN0"],"product":["EPC0"],"process":["INF"],"series":["I000000004"]},"start":"1973-10","end":"1973-10","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:28 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:28 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '797' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fob_costs_of_imported_crude_oil_for_selected_crude_streams_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fob_costs_of_imported_crude_oil_for_selected_crude_streams_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..98e09993d6d --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fob_costs_of_imported_crude_oil_for_selected_crude_streams_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/imc2/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1983-01&facets%5Bduoarea%5D%5B%5D=NUS-NAO&facets%5Bprocess%5D%5B%5D=INF&facets%5Bproduct%5D%5B%5D=EPCAOCAB&facets%5Bseries%5D%5B%5D=IAO0300004&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1983-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1983-01","duoarea":"NUS-NAO","area-name":"AGO","product":"EPCAOCAB","product-name":"Angolan + Cabinda Crude Oil","process":"INF","process-name":"FOB Costs","series":"IAO0300004","series-description":"U.S. + FOB Costs of Angolan Cabinda Crude Oil (Dollars per Barrel)","value":null,"units":"$\/BBL"}]},"request":{"command":"\/v2\/petroleum\/pri\/imc2\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-NAO"],"product":["EPCAOCAB"],"process":["INF"],"series":["IAO0300004"]},"start":"1983-01","end":"1983-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:30 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:30 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '806' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_footage_drilled_for_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_footage_drilled_for_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..586b7c973b6 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_footage_drilled_for_crude_oil_and_natural_gas_wells_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/crd/wellfoot/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1949&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=XWFD&facets%5Bproduct%5D%5B%5D=ERTW0&facets%5Bseries%5D%5B%5D=E_ERTW0_XWFD_NUS_MF&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1949 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1949","duoarea":"NUS","area-name":"U.S.","product":"ERTW0","product-name":"Wells-Total","process":"XWFD","process-name":"Footage + Drilled for Developmental Wells","series":"E_ERTW0_XWFD_NUS_MF","series-description":"U.S. + Footage Drilled for Crude Oil, Natural Gas, and Dry Developmental Wells (Thousand + Feet)","value":"100821","units":"MF"}]},"request":{"command":"\/v2\/petroleum\/crd\/wellfoot\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["ERTW0"],"process":["XWFD"],"series":["E_ERTW0_XWFD_NUS_MF"]},"start":"1949","end":"1949","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:32 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:32 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '847' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fuel_consumed_at_biofuels_plants_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fuel_consumed_at_biofuels_plants_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..4211ba01104 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fuel_consumed_at_biofuels_plants_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/bioplfuel/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2021&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=819BG0&facets%5Bseries%5D%5B%5D=8_NA_819BG0_NUS_MMCF&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2021 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2021","duoarea":"NUS","area-name":"U.S.","product":"(NA)","product-name":"Not + Applicable","process":"819BG0","process-name":"Biogas Consumed at Biofuels + Plants","series":"8_NA_819BG0_NUS_MMCF","series-description":"U.S. Biogas + Consumed at Biofuels Plants (Million Cubic Feet)","value":"6842","units":"MMCF"}]},"request":{"command":"\/v2\/petroleum\/pnp\/bioplfuel\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"process":["819BG0"],"series":["8_NA_819BG0_NUS_MMCF"]},"start":"2021","end":"2021","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:16:40 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:16:40 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '799' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fuel_consumed_at_refineries_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fuel_consumed_at_refineries_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..0179fb0ba55 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_fuel_consumed_at_refineries_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/capfuel/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1985&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=8FC0&facets%5Bseries%5D%5B%5D=8_NA_8FC0_NUS_T&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1985 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1985","duoarea":"NUS","area-name":"U.S.","product":"(NA)","product-name":"Not + Applicable","process":"8FC0","process-name":"Coal Consumed at Refineries","series":"8_NA_8FC0_NUS_T","series-description":"U.S. + Coal Consumed at Refineries (Thousand Short Tons)","value":"246","units":"MST"}]},"request":{"command":"\/v2\/petroleum\/pnp\/capfuel\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"process":["8FC0"],"series":["8_NA_8FC0_NUS_T"]},"start":"1985","end":"1985","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:12:52 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:12:52 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '768' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_gasoline_prices_by_formulation_grade_sales_type_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_gasoline_prices_by_formulation_grade_sales_type_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..a188bf72094 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_gasoline_prices_by_formulation_grade_sales_type_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/allmg/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1994-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=PBS&facets%5Bproduct%5D%5B%5D=EPM0R&facets%5Bseries%5D%5B%5D=EMA_EPM0R_PBS_NUS_DPG&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1994-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1994-01","duoarea":"NUS","area-name":"U.S.","product":"EPM0R","product-name":"Reformulated + Motor Gasoline","process":"PBS","process-name":"Bulk Sales (Price)","series":"EMA_EPM0R_PBS_NUS_DPG","series-description":"U.S. + Reformulated Gasoline Bulk Sales Price by All Sellers (Dollars per Gallon)","value":null,"units":"$\/GAL"}]},"request":{"command":"\/v2\/petroleum\/pri\/allmg\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPM0R"],"process":["PBS"],"series":["EMA_EPM0R_PBS_NUS_DPG"]},"start":"1994-01","end":"1994-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:44 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:44 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '842' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_gulf_of_america_federal_offshore_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_gulf_of_america_federal_offshore_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..14a42003345 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_gulf_of_america_federal_offshore_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/crd/gom/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1992&facets%5Bduoarea%5D%5B%5D=R3FM&facets%5Bprocess%5D%5B%5D=R10&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=RCRR10R3FM_1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1992 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1992","duoarea":"R3FM","area-name":"NA","product":"EPC0","product-name":"Crude + Oil","process":"R10","process-name":"Production from Reserves","series":"RCRR10R3FM_1","series-description":"Gulf + of America Federal Offshore Crude Oil Production (Million Barrels)","value":"267","units":"MMBBL"}]},"request":{"command":"\/v2\/petroleum\/crd\/gom\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["R3FM"],"product":["EPC0"],"process":["R10"],"series":["RCRR10R3FM_1"]},"start":"1992","end":"1992","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:45 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:45 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '786' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_imports_by_area_of_entry_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_imports_by_area_of_entry_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..700d2ba7bb4 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_imports_by_area_of_entry_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/imp/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1920-01&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=IM0&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCRIMUS1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1920-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1920-01","duoarea":"NUS-Z00","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"IM0","process-name":"Imports","series":"MCRIMUS1","series-description":"U.S. + Imports of Crude Oil (Thousand Barrels)","value":"6294","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/move\/imp\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00"],"product":["EPC0"],"process":["IM0"],"series":["MCRIMUS1"]},"start":"1920-01","end":"1920-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:46 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:46 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '757' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_imports_by_processing_area_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_imports_by_processing_area_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..1987425b31c --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_imports_by_processing_area_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/imp2/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1981-01&facets%5Bduoarea%5D%5B%5D=R10-Z00&facets%5Bprocess%5D%5B%5D=IP0&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCRIPP11&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1981-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1981-01","duoarea":"R10-Z00","area-name":"PADD + 1","product":"EPC0","product-name":"Crude Oil","process":"IP0","process-name":"Imports + by PADD of Processing","series":"MCRIPP11","series-description":"East Coast + (PADD 1) Imports by PADD of Processing of Crude Oil (Thousand Barrels)","value":"36649","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/move\/imp2\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R10-Z00"],"product":["EPC0"],"process":["IP0"],"series":["MCRIPP11"]},"start":"1981-01","end":"1981-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:47 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:47 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '820' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_imports_of_residual_fuel_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_imports_of_residual_fuel_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..0edb14cdc5d --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_imports_of_residual_fuel_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/res/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1936-01&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=IM0&facets%5Bproduct%5D%5B%5D=EPPR&facets%5Bseries%5D%5B%5D=MREIMUS1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1936-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1936-01","duoarea":"NUS-Z00","area-name":"U.S.","product":"EPPR","product-name":"Residual + Fuel Oil","process":"IM0","process-name":"Imports","series":"MREIMUS1","series-description":"U.S. + Imports of Residual Fuel Oil (Thousand Barrels)","value":"1170","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/move\/res\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00"],"product":["EPPR"],"process":["IM0"],"series":["MREIMUS1"]},"start":"1936-01","end":"1936-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:49 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:48 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '773' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_landed_costs_of_imported_crude_by_api_gravity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_landed_costs_of_imported_crude_by_api_gravity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..dfe62cc2b18 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_landed_costs_of_imported_crude_by_api_gravity_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/land3/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1983-01&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=INL&facets%5Bproduct%5D%5B%5D=EPC20B&facets%5Bseries%5D%5B%5D=I000000208&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1983-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1983-01","duoarea":"NUS-Z00","area-name":"NA","product":"EPC20B","product-name":"Crude + Gravity 20.0 percent or less","process":"INL","process-name":"Landed Costs","series":"I000000208","series-description":"U.S. + Landed Costs of Crude with API Gravity 20.0 degrees or less (Dollars per Barrel)","value":"23.2","units":"$\/BBL"}]},"request":{"command":"\/v2\/petroleum\/pri\/land3\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00"],"product":["EPC20B"],"process":["INL"],"series":["I000000208"]},"start":"1983-01","end":"1983-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:49 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:49 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '837' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_landed_costs_of_imported_crude_by_area_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_landed_costs_of_imported_crude_by_area_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..95fe2140135 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_landed_costs_of_imported_crude_by_area_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/land1/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS-ME0&facets%5Bduoarea%5D%5B%5D=NUS-MN0&facets%5Bduoarea%5D%5B%5D=NUS-MP0&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=INL&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=I070000008&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS-MN0","area-name":"NA","product":"EPC0","product-name":"Crude + Oil","process":"INL","process-name":"Landed Costs","series":"I070000008","series-description":"U.S. + Landed Costs of Non-OPEC Countries Crude Oil (Dollars per Barrel)","value":null,"units":"$\/BBL"}]},"request":{"command":"\/v2\/petroleum\/pri\/land1\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00","NUS-ME0","NUS-MP0","NUS-MN0"],"product":["EPC0"],"process":["INL"],"series":["I070000008"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:50 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:50 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '821' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_landed_costs_of_imported_crude_for_selected_crude_streams_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_landed_costs_of_imported_crude_for_selected_crude_streams_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..e5750b0f776 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_landed_costs_of_imported_crude_for_selected_crude_streams_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/land2/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1983-01&facets%5Bduoarea%5D%5B%5D=NUS-NAO&facets%5Bprocess%5D%5B%5D=INL&facets%5Bproduct%5D%5B%5D=EPCAOCAB&facets%5Bseries%5D%5B%5D=IAO0300008&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1983-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1983-01","duoarea":"NUS-NAO","area-name":"AGO","product":"EPCAOCAB","product-name":"Angolan + Cabinda Crude Oil","process":"INL","process-name":"Landed Costs","series":"IAO0300008","series-description":"U.S. + Landed Costs of Angolan Cabinda Crude Oil (Dollars per Barrel)","value":null,"units":"$\/BBL"}]},"request":{"command":"\/v2\/petroleum\/pri\/land2\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-NAO"],"product":["EPCAOCAB"],"process":["INL"],"series":["IAO0300008"]},"start":"1983-01","end":"1983-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:51 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:51 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '813' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_maximum_us_active_seismic_crew_counts_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_maximum_us_active_seismic_crew_counts_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..1c02b1e3379 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_maximum_us_active_seismic_crew_counts_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/crd/seis/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2000-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=XS0&facets%5Bproduct%5D%5B%5D=ERTCES&facets%5Bseries%5D%5B%5D=E_ERTCES_XS0_NUS_C&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2000-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2000-01","duoarea":"NUS","area-name":"U.S.","product":"ERTCES","product-name":"Crews + Engaged in Seismic Exploration","process":"XS0","process-name":"Maximum Number + of Active Crews Engaged in Sismic Surveying","series":"E_ERTCES_XS0_NUS_C","series-description":"U.S. + Maximum Number of Active Crews Engaged in Seismic Surveying (Count)","value":"0","units":"COUNT"}]},"request":{"command":"\/v2\/petroleum\/crd\/seis\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["ERTCES"],"process":["XS0"],"series":["E_ERTCES_XS0_NUS_C"]},"start":"2000-01","end":"2000-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:52 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:52 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '877' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_between_pad_districts_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_between_pad_districts_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..cc06a813fd9 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_between_pad_districts_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/ptb/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1986-01&facets%5Bduoarea%5D%5B%5D=R10-R20&facets%5Bduoarea%5D%5B%5D=R20-R30&facets%5Bduoarea%5D%5B%5D=R20-R40&facets%5Bduoarea%5D%5B%5D=R40-R20&facets%5Bduoarea%5D%5B%5D=R50-R20&facets%5Bprocess%5D%5B%5D=TNR&facets%5Bproduct%5D%5B%5D=EPPA&facets%5Bseries%5D%5B%5D=MAPMXP1P21&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1986-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1986-01","duoarea":"R10-R20","area-name":"PADD + 2","product":"EPPA","product-name":"Asphalt and Road Oil","process":"TNR","process-name":"Receipts + by Pipeline, Tanker, Barge and Rail","series":"MAPMXP1P21","series-description":"East + Coast (PADD 1) Receipts by Pipeline, Tanker, Barge and Rail from Midwest (PADD + 2) of Asphalt and Road Oil (Thousand Barrels)","value":"77","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/move\/ptb\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R40-R20","R10-R20","R50-R20","R20-R30","R20-R40"],"product":["EPPA"],"process":["TNR"],"series":["MAPMXP1P21"]},"start":"1986-01","end":"1986-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:53 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:53 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '934' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_by_pipeline_between_pad_districts_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_by_pipeline_between_pad_districts_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..51d8d56479d --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_by_pipeline_between_pad_districts_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/pipe/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1986-01&facets%5Bduoarea%5D%5B%5D=R10-R20&facets%5Bduoarea%5D%5B%5D=R20-R30&facets%5Bduoarea%5D%5B%5D=R20-R40&facets%5Bduoarea%5D%5B%5D=R40-R20&facets%5Bprocess%5D%5B%5D=LMV&facets%5Bproduct%5D%5B%5D=EPOBG&facets%5Bseries%5D%5B%5D=MBCMPP1P21&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1986-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1986-01","duoarea":"R10-R20","area-name":"PADD + 2","product":"EPOBG","product-name":"Gasoline Blending Components","process":"LMV","process-name":"Movements + by Pipeline","series":"MBCMPP1P21","series-description":"East Coast (PADD + 1) Receipts by Pipeline from Midwest (PADD 2) of Gasoline Blending Components + (Thousand Barrels)","value":"0","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/move\/pipe\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R40-R20","R10-R20","R20-R30","R20-R40"],"product":["EPOBG"],"process":["LMV"],"series":["MBCMPP1P21"]},"start":"1986-01","end":"1986-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:54 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:54 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '895' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_by_rail_between_pad_districts_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_by_rail_between_pad_districts_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..a1aa8b62d66 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_by_rail_between_pad_districts_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/rail/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2010-01&facets%5Bduoarea%5D%5B%5D=R10-R20&facets%5Bduoarea%5D%5B%5D=R30-R20&facets%5Bduoarea%5D%5B%5D=R40-R20&facets%5Bduoarea%5D%5B%5D=R50-R20&facets%5Bprocess%5D%5B%5D=RAIL&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=ESM_EPC0_RAIL_R10-R20_MBBL&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2010-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2010-01","duoarea":"R10-R20","area-name":"PADD + 2","product":"EPC0","product-name":"Crude Oil","process":"RAIL","process-name":"Receipts + by Rail","series":"ESM_EPC0_RAIL_R10-R20_MBBL","series-description":"East + Coast (PADD 1) Receipts by Rail from Midwest (PADD 2) of Crude Oil (Thousand + Barrels)","value":"97","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/move\/rail\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R40-R20","R10-R20","R50-R20","R30-R20"],"product":["EPC0"],"process":["RAIL"],"series":["ESM_EPC0_RAIL_R10-R20_MBBL"]},"start":"2010-01","end":"2010-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:55 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:55 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '881' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_by_tanker_and_barge_between_pad_districts_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_by_tanker_and_barge_between_pad_districts_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..938771dd326 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_by_tanker_and_barge_between_pad_districts_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/tb/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1986-01&facets%5Bduoarea%5D%5B%5D=R1X-R30&facets%5Bprocess%5D%5B%5D=BMV&facets%5Bproduct%5D%5B%5D=EPPA&facets%5Bseries%5D%5B%5D=MAPMT1XP31&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1986-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1986-01","duoarea":"R1X-R30","area-name":"PADD + 3","product":"EPPA","product-name":"Asphalt and Road Oil","process":"BMV","process-name":"Movements + by Tanker and Barge","series":"MAPMT1XP31","series-description":"New England + (PADD 1A) Receipts by Tanker and Barge from Gulf Coast (PADD 3) of Asphalt + and Road Oil (Thousand Barrels)","value":"0","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/move\/tb\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R1X-R30"],"product":["EPPA"],"process":["BMV"],"series":["MAPMT1XP31"]},"start":"1986-01","end":"1986-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:56 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:56 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '866' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_of_crude_oil_and_selected_products_by_rail_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_of_crude_oil_and_selected_products_by_rail_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..43de0010b8a --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_movements_of_crude_oil_and_selected_products_by_rail_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/railNA/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2010-01&facets%5Bduoarea%5D%5B%5D=NCA-NUS&facets%5Bduoarea%5D%5B%5D=NUS-NUS&facets%5Bprocess%5D%5B%5D=RAIL&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=ESM_EPC0_RAIL_NUS-NUS_MBBL&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2010-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2010-01","duoarea":"NUS-NUS","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"RAIL","process-name":"Receipts by Rail","series":"ESM_EPC0_RAIL_NUS-NUS_MBBL","series-description":"U.S. + Crude Oil by Rail (Thousand Barrels)","value":"1215","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/move\/railNA\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NCA-NUS","NUS-NUS"],"product":["EPC0"],"process":["RAIL"],"series":["ESM_EPC0_RAIL_NUS-NUS_MBBL"]},"start":"2010-01","end":"2010-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:02:57 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:02:57 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '814' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_natural_gas_feedstock_for_hydrogen_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_natural_gas_feedstock_for_hydrogen_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..7a4a33d7e5f --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_natural_gas_feedstock_for_hydrogen_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/feedng/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2008&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=8NGFSHY&facets%5Bseries%5D%5B%5D=8_NA_8NGFSHY_NUS_MMCF&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2008 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2008","duoarea":"NUS","area-name":"U.S.","product":"(NA)","product-name":"Not + Applicable","process":"8NGFSHY","process-name":"Natural Gas Used as Feedstock + for Hydrogen Production","series":"8_NA_8NGFSHY_NUS_MMCF","series-description":"U.S. + Natural Gas Used as Feedstock for Hydrogen Production (Million Cubic Feet)","value":"188075","units":"MMCF"}]},"request":{"command":"\/v2\/petroleum\/pnp\/feedng\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"process":["8NGFSHY"],"series":["8_NA_8NGFSHY_NUS_MMCF"]},"start":"2008","end":"2008","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:12:52 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:12:52 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '840' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_natural_gas_plant_field_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_natural_gas_plant_field_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..120d1a4ee0d --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_natural_gas_plant_field_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/gp/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=FPF&facets%5Bproduct%5D%5B%5D=EPL2&facets%5Bseries%5D%5B%5D=M_EPL2_FPF_NUS_MBBLD&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","duoarea":"NUS","area-name":"U.S.","product":"EPL2","product-name":"Natural + Gas Plant Liquids","process":"FPF","process-name":"Field Production","series":"M_EPL2_FPF_NUS_MBBLD","series-description":"U.S. + Field Production of Natural Gas Liquids (Thousand Barrels per Day)","value":"1680","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/pnp\/gp\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPL2"],"process":["FPF"],"series":["M_EPL2_FPF_NUS_MBBLD"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:01 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:01 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '826' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_natural_gas_plant_stocks_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_natural_gas_plant_stocks_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..57fa6c6f59e --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_natural_gas_plant_stocks_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/stoc/gp/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1993-01&facets%5Bduoarea%5D%5B%5D=R2A&facets%5Bduoarea%5D%5B%5D=R2B&facets%5Bduoarea%5D%5B%5D=R2C&facets%5Bduoarea%5D%5B%5D=R3A&facets%5Bduoarea%5D%5B%5D=R3B&facets%5Bduoarea%5D%5B%5D=R3C&facets%5Bduoarea%5D%5B%5D=R3D&facets%5Bduoarea%5D%5B%5D=R3E&facets%5Bduoarea%5D%5B%5D=RAP&facets%5Bduoarea%5D%5B%5D=REC&facets%5Bprocess%5D%5B%5D=SKN&facets%5Bproduct%5D%5B%5D=EPLLB0I&facets%5Bseries%5D%5B%5D=MBISN2A1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1993-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1993-01","duoarea":"R2A","area-name":"NA","product":"EPLLB0I","product-name":"Isobutane-Isobutylene","process":"SKN","process-name":"Natural + Gas Plant Stocks","series":"MBISN2A1","series-description":"Refining District + Indiana-Illinois-Kentucky Isobutane-Isobutylene Stocks at Natural Gas Processing + Plants (Thousand Barrels)","value":"15","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/stoc\/gp\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R2A","R3B","R3A","REC","R3D","R3C","R2B","R2C","R3E","RAP"],"product":["EPLLB0I"],"process":["SKN"],"series":["MBISN2A1"]},"start":"1993-01","end":"1993-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:02 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:02 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '913' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_net_receipts_between_pad_districts_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_net_receipts_between_pad_districts_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..d94e1ef10c0 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_net_receipts_between_pad_districts_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/netr/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1981-01&facets%5Bduoarea%5D%5B%5D=R10-Z0P&facets%5Bprocess%5D%5B%5D=VNR&facets%5Bproduct%5D%5B%5D=EPPA&facets%5Bseries%5D%5B%5D=MAPNRP11&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1981-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1981-01","duoarea":"R10-Z0P","area-name":"PADD + 1","product":"EPPA","product-name":"Asphalt and Road Oil","process":"VNR","process-name":"Net + Receipts by Pipeline, Tanker, Barge and Rail","series":"MAPNRP11","series-description":"East + Coast (PADD 1) Net Receipts by Pipeline, Tanker, Barge and Rail from Other + PADDs of Asphalt and Road Oil (Thousand Barrels)","value":"190","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/move\/netr\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R10-Z0P"],"product":["EPPA"],"process":["VNR"],"series":["MAPNRP11"]},"start":"1981-01","end":"1981-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:03 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:03 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '895' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_no2_distillate_prices_by_sales_type_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_no2_distillate_prices_by_sales_type_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..909de6c46ad --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_no2_distillate_prices_by_sales_type_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/dist/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1983-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=PRT&facets%5Bproduct%5D%5B%5D=EPD2&facets%5Bseries%5D%5B%5D=EMA_EPD2_PRT_NUS_DPG&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1983-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1983-01","duoarea":"NUS","area-name":"U.S.","product":"EPD2","product-name":"No + 2 Distillate","process":"PRT","process-name":"Residential Price by All Sellers","series":"EMA_EPD2_PRT_NUS_DPG","series-description":"U.S. + No 2 Distillate Residential Price by All Sellers (Dollars per Gallon)","value":"1.15","units":"$\/GAL"}]},"request":{"command":"\/v2\/petroleum\/pri\/dist\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPD2"],"process":["PRT"],"series":["EMA_EPD2_PRT_NUS_DPG"]},"start":"1983-01","end":"1983-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:04 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:04 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '836' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_number_and_capacity_of_petroleum_refineries_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_number_and_capacity_of_petroleum_refineries_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..009effcc558 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_number_and_capacity_of_petroleum_refineries_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/cap1/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1982&facets%5Bduoarea%5D%5B%5D=NPZ&facets%5Bprocess%5D%5B%5D=8CCF&facets%5Bseries%5D%5B%5D=8_NA_8CCF_NPZ_5&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1982 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1982","duoarea":"NPZ","area-name":"PRI","product":"(NA)","product-name":"Not + Applicable","process":"8CCF","process-name":"Refinery Catalytic Cracking, + Fresh Feed Downstream Charge Capacity","series":"8_NA_8CCF_NPZ_5","series-description":"Puerto + Rico Refinery Catalytic Cracking, Fresh Feed Downstream Charge Capacity as + of January 1 (Barrels per Stream Day)","value":"52000","units":"B\/SD"}]},"request":{"command":"\/v2\/petroleum\/pnp\/cap1\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NPZ"],"process":["8CCF"],"series":["8_NA_8CCF_NPZ_5"]},"start":"1982","end":"1982","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:12:53 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:12:53 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '872' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_nymex_futures_prices_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_nymex_futures_prices_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..2543cf47e45 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_nymex_futures_prices_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/fut/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1980-01-04&facets%5Bduoarea%5D%5B%5D=Y35NY&facets%5Bprocess%5D%5B%5D=PE1&facets%5Bproduct%5D%5B%5D=EPD2F&facets%5Bseries%5D%5B%5D=EER_EPD2F_PE1_Y35NY_DPG&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1980-01-04 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"1980-01-04","duoarea":"Y35NY","area-name":"NEW + YORK CITY","product":"EPD2F","product-name":"No 2 Fuel Oil \/ Heating Oil","process":"PE1","process-name":"Future + Contract 1","series":"EER_EPD2F_PE1_Y35NY_DPG","series-description":"New York + Harbor No. 2 Heating Oil Future Contract 1 (Dollars per Gallon)","value":".833","units":"$\/GAL"}]},"request":{"command":"\/v2\/petroleum\/pri\/fut\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["Y35NY"],"product":["EPD2F"],"process":["PE1"],"series":["EER_EPD2F_PE1_Y35NY_DPG"]},"start":"1980-01-04","end":"1980-01-04","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:07 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:07 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '862' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_oxygenate_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_oxygenate_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..95efd6704d3 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_oxygenate_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/oxy/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1981-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=YOP&facets%5Bproduct%5D%5B%5D=EPOOXE&facets%5Bseries%5D%5B%5D=M_EPOOXE_YOP_NUS_1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1981-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1981-01","duoarea":"NUS","area-name":"U.S.","product":"EPOOXE","product-name":"Fuel + Ethanol","process":"YOP","process-name":"Oxygenate Plant Production","series":"M_EPOOXE_YOP_NUS_1","series-description":"U.S. + Oxygenate Plant Production of Fuel Ethanol (Thousand Barrels)","value":"168","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/pnp\/oxy\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPOOXE"],"process":["YOP"],"series":["M_EPOOXE_YOP_NUS_1"]},"start":"1981-01","end":"1981-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:08 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:08 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '815' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_pad_district_exports_by_destination_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_pad_district_exports_by_destination_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..bd5374c80fd --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_pad_district_exports_by_destination_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/expcp/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1981-01&facets%5Bduoarea%5D%5B%5D=R10-Z00&facets%5Bprocess%5D%5B%5D=EEX&facets%5Bproduct%5D%5B%5D=EPPA&facets%5Bseries%5D%5B%5D=MAPEXP11&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1981-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1981-01","duoarea":"R10-Z00","area-name":"PADD + 1","product":"EPPA","product-name":"Asphalt and Road Oil","process":"EEX","process-name":"Exports","series":"MAPEXP11","series-description":"East + Coast (PADD 1) Exports of Asphalt and Road Oil (Thousand Barrels)","value":"4","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/move\/expcp\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R10-Z00"],"product":["EPPA"],"process":["EEX"],"series":["MAPEXP11"]},"start":"1981-01","end":"1981-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:09 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:09 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '795' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_pad_district_imports_by_country_of_origin_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_pad_district_imports_by_country_of_origin_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..50b8afc2a2c --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_pad_district_imports_by_country_of_origin_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/impcp/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1981-01&facets%5Bduoarea%5D%5B%5D=R10-Z00&facets%5Bprocess%5D%5B%5D=IP0&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCRIPP11&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1981-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1981-01","duoarea":"R10-Z00","area-name":"PADD + 1","product":"EPC0","product-name":"Crude Oil","process":"IP0","process-name":"Imports + by PADD of Processing","series":"MCRIPP11","series-description":"East Coast + (PADD 1) Imports by PADD of Processing of Crude Oil (Thousand Barrels)","value":"36649","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/move\/impcp\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R10-Z00"],"product":["EPC0"],"process":["IP0"],"series":["MCRIPP11"]},"start":"1981-01","end":"1981-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:11 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:11 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '821' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_percentages_of_total_imported_crude_oil_by_api_gravity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_percentages_of_total_imported_crude_oil_by_api_gravity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..eaf46e27cbb --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_percentages_of_total_imported_crude_oil_by_api_gravity_fetcher_urllib3_v2.yaml @@ -0,0 +1,65 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/ipct/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1983-01&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=IMP&facets%5Bproduct%5D%5B%5D=EPC20B&facets%5Bseries%5D%5B%5D=I000000202&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1983-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1983-01","duoarea":"NUS-Z00","area-name":"NA","product":"EPC20B","product-name":"Crude + Gravity 20.0 percent or less","process":"IMP","process-name":"Percent Total + Imported by API Gravity","series":"I000000202","series-description":"U.S. + Percent Total Imported by API Gravity of Crude Gravity 20.0 percent or less + (%)","value":"2.72","units":"%"}]},"request":{"command":"\/v2\/petroleum\/pri\/ipct\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00"],"product":["EPC20B"],"process":["IMP"],"series":["I000000202"]},"start":"1983-01","end":"1983-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:12 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:12 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '855' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_prices_sales_volumes_stocks_by_state_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_prices_sales_volumes_stocks_by_state_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..fb63b2b8e93 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_prices_sales_volumes_stocks_by_state_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/sum/mkt/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1975-07&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=PTG&facets%5Bproduct%5D%5B%5D=EPJK&facets%5Bseries%5D%5B%5D=EMA_EPJK_PTG_NUS_DPG&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1975-07 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1975-07","duoarea":"NUS","area-name":"U.S.","product":"EPJK","product-name":"Kerosene-Type + Jet Fuel","process":"PTG","process-name":"Retail Sales by Refiners and Gas + Plants","series":"EMA_EPJK_PTG_NUS_DPG","series-description":"U.S. Kerosene-Type + Jet Fuel Retail Sales by Refiners (Dollars per Gallon)","value":".292","units":"$\/GAL"}]},"request":{"command":"\/v2\/petroleum\/sum\/mkt\/data\/","params":{"frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPJK"],"process":["PTG"],"series":["EMA_EPJK_PTG_NUS_DPG"]},"start":"1975-07","end":"1975-07","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:13 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:13 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '795' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_prime_supplier_sales_volumes_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_prime_supplier_sales_volumes_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..ef37aaeff36 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_prime_supplier_sales_volumes_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/cons/prim/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1983-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=P00&facets%5Bproduct%5D%5B%5D=EPM0&facets%5Bseries%5D%5B%5D=C100000001&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1983-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1983-01","duoarea":"NUS","area-name":"U.S.","product":"EPM0","product-name":"Total + Gasoline","process":"P00","process-name":"All Sales\/Deliveries","series":"C100000001","series-description":"U.S. + Total Gasoline All Sales\/Deliveries by Prime Supplier (Thousand Gallons per + Day)","value":"257881.5","units":"MGAL\/D"}]},"request":{"command":"\/v2\/petroleum\/cons\/prim\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPM0"],"process":["P00"],"series":["C100000001"]},"start":"1983-01","end":"1983-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:14 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:14 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '822' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_product_supplied_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_product_supplied_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..34c77666291 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_product_supplied_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/cons/psup/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1936-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VPP&facets%5Bproduct%5D%5B%5D=EPPR&facets%5Bseries%5D%5B%5D=MREUPUS1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1936-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1936-01","duoarea":"NUS","area-name":"U.S.","product":"EPPR","product-name":"Residual + Fuel Oil","process":"VPP","process-name":"Product Supplied","series":"MREUPUS1","series-description":"U.S. + Product Supplied of Residual Fuel Oil (Thousand Barrels)","value":"26597","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/cons\/psup\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPPR"],"process":["VPP"],"series":["MREUPUS1"]},"start":"1936-01","end":"1936-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:15 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:15 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '785' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_production_capacity_of_operable_petroleum_refineries_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_production_capacity_of_operable_petroleum_refineries_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..10a24dc48da --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_production_capacity_of_operable_petroleum_refineries_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/capprod/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1982&facets%5Bduoarea%5D%5B%5D=NPZ&facets%5Bprocess%5D%5B%5D=8PA&facets%5Bseries%5D%5B%5D=8_NA_8PA_NPZ_5&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1982 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1982","duoarea":"NPZ","area-name":"PRI","product":"(NA)","product-name":"Not + Applicable","process":"8PA","process-name":"Production Capacity of Alkylates","series":"8_NA_8PA_NPZ_5","series-description":"Puerto + Rico Refinery Alkylates Production Capacity as of January 1 (Barrels per Stream + Day)","value":"4500","units":"B\/SD"}]},"request":{"command":"\/v2\/petroleum\/pnp\/capprod\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NPZ"],"process":["8PA"],"series":["8_NA_8PA_NPZ_5"]},"start":"1982","end":"1982","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:12:53 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:12:53 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '808' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_propane_prices_by_sales_type_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_propane_prices_by_sales_type_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..1cb8418b96f --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_propane_prices_by_sales_type_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/prop/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1993-10&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=PRT&facets%5Bproduct%5D%5B%5D=EPLLPA&facets%5Bseries%5D%5B%5D=EMA_EPLLPA_PRT_NUS_DPG&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1993-10 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1993-10","duoarea":"NUS","area-name":"U.S.","product":"EPLLPA","product-name":"Propane","process":"PRT","process-name":"Residential + Price by All Sellers","series":"EMA_EPLLPA_PRT_NUS_DPG","series-description":"U.S. + Propane Residential Price by All Sellers (Dollars per Gallon)","value":".845","units":"$\/GAL"}]},"request":{"command":"\/v2\/petroleum\/pri\/prop\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPLLPA"],"process":["PRT"],"series":["EMA_EPLLPA_PRT_NUS_DPG"]},"start":"1993-10","end":"1993-10","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:18 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:18 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '828' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_proved_nonproducing_reserves_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_proved_nonproducing_reserves_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..5898a5f32a6 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_proved_nonproducing_reserves_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/crd/nprod/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1996&facets%5Bduoarea%5D%5B%5D=R1901F&facets%5Bduoarea%5D%5B%5D=R44F&facets%5Bduoarea%5D%5B%5D=R48&facets%5Bduoarea%5D%5B%5D=R5F&facets%5Bduoarea%5D%5B%5D=RCAC&facets%5Bduoarea%5D%5B%5D=RCAJ&facets%5Bduoarea%5D%5B%5D=RCAL&facets%5Bduoarea%5D%5B%5D=RCASF&facets%5Bduoarea%5D%5B%5D=RLAN&facets%5Bduoarea%5D%5B%5D=RLASF&facets%5Bduoarea%5D%5B%5D=RLASO&facets%5Bduoarea%5D%5B%5D=RNMEAST&facets%5Bduoarea%5D%5B%5D=RNMWEST&facets%5Bduoarea%5D%5B%5D=RTX01&facets%5Bduoarea%5D%5B%5D=RTX02&facets%5Bduoarea%5D%5B%5D=RTX03&facets%5Bduoarea%5D%5B%5D=RTX04&facets%5Bduoarea%5D%5B%5D=RTX05&facets%5Bduoarea%5D%5B%5D=RTX06&facets%5Bduoarea%5D%5B%5D=RTX07B&facets%5Bduoarea%5D%5B%5D=RTX07C&facets%5Bduoarea%5D%5B%5D=RTX08&facets%5Bduoarea%5D%5B%5D=RTX08A&facets%5Bduoarea%5D%5B%5D=RTX09&facets%5Bduoarea%5D%5B%5D=RTX10&facets%5Bduoarea%5D%5B%5D=RTXSF&facets%5Bduoarea%5D%5B%5D=RUSF&facets%5Bprocess%5D%5B%5D=R9910&facets%5Bproduct%5D%5B%5D=EPG0&facets%5Bseries%5D%5B%5D=RES_EPG0_R9910_R44F_BCF&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1996 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1996","duoarea":"R44F","area-name":"NA","product":"EPG0","product-name":"Natural + Gas","process":"R9910","process-name":"Associated-Dissolved, Reserves in Nonproducing + Reservoirs","series":"RES_EPG0_R9910_R44F_BCF","series-description":"Gulf + of America Federal Offshore (Western) Associated-Dissolved Natural Gas, Reserves + in Nonproducing Reservoirs, Wet (Bcf)","value":"384","units":"BCF"}]},"request":{"command":"\/v2\/petroleum\/crd\/nprod\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["RTX01","R44F","RTX07B","RNMWEST","RTX03","RTX05","RTXSF","RTX08A","RTX08","RCAC","RLASO","RTX07C","RCAL","RCASF","RLASF","RTX09","RUSF","R1901F","R5F","RNMEAST","RTX06","R48","RCAJ","RLAN","RTX02","RTX04","RTX10"],"product":["EPG0"],"process":["R9910"],"series":["RES_EPG0_R9910_R44F_BCF"]},"start":"1996","end":"1996","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:19 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:19 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1107' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_acquisition_cost_of_crude_oil_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_acquisition_cost_of_crude_oil_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..9669fdbc653 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_acquisition_cost_of_crude_oil_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/rac2/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1974-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=PFT&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=R1300____3&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1974-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1974-01","duoarea":"NUS","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"PFT","process-name":"Imported Acquisition Cost","series":"R1300____3","series-description":"U.S. + Crude Oil Imported Acquisition Cost by Refiners (Dollars per Barrel)","value":"9.59","units":"$\/BBL"}]},"request":{"command":"\/v2\/petroleum\/pri\/rac2\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPC0"],"process":["PFT"],"series":["R1300____3"]},"start":"1974-01","end":"1974-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:20 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:20 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '802' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_gasoline_prices_by_grade_and_sales_type_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_gasoline_prices_by_grade_and_sales_type_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..8d217901a2c --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_gasoline_prices_by_grade_and_sales_type_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/refmg/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1983-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=PTG&facets%5Bproduct%5D%5B%5D=EPM0&facets%5Bseries%5D%5B%5D=EMA_EPM0_PTG_NUS_DPG&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1983-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1983-01","duoarea":"NUS","area-name":"U.S.","product":"EPM0","product-name":"Total + Gasoline","process":"PTG","process-name":"Retail Sales by Refiners and Gas + Plants","series":"EMA_EPM0_PTG_NUS_DPG","series-description":"U.S. Total Gasoline + Retail Sales by Refiners (Dollars per Gallon)","value":".971","units":"$\/GAL"}]},"request":{"command":"\/v2\/petroleum\/pri\/refmg\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPM0"],"process":["PTG"],"series":["EMA_EPM0_PTG_NUS_DPG"]},"start":"1983-01","end":"1983-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:20 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:20 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '834' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_motor_gasoline_sales_volumes_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_motor_gasoline_sales_volumes_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..f3812c53ef0 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_motor_gasoline_sales_volumes_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/cons/refmg/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1983-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VTC&facets%5Bproduct%5D%5B%5D=EPM0&facets%5Bseries%5D%5B%5D=A103400001&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1983-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1983-01","duoarea":"NUS","area-name":"U.S.","product":"EPM0","product-name":"Total + Gasoline","process":"VTC","process-name":"Through Company Outlets Volume by + Refiners and Gas Plants","series":"A103400001","series-description":"U.S. + Total Gasoline Through Company Outlets Volume by Refiners (Thousand Gallons + per Day)","value":"37873.2","units":"MGAL\/D"}]},"request":{"command":"\/v2\/petroleum\/cons\/refmg\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPM0"],"process":["VTC"],"series":["A103400001"]},"start":"1983-01","end":"1983-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:21 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:21 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '861' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_petroleum_product_prices_by_sales_type_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_petroleum_product_prices_by_sales_type_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..0e3b7040c93 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_petroleum_product_prices_by_sales_type_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/refoth/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1975-07&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=PTG&facets%5Bproduct%5D%5B%5D=EPJK&facets%5Bseries%5D%5B%5D=EMA_EPJK_PTG_NUS_DPG&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1975-07 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1975-07","duoarea":"NUS","area-name":"U.S.","product":"EPJK","product-name":"Kerosene-Type + Jet Fuel","process":"PTG","process-name":"Retail Sales by Refiners and Gas + Plants","series":"EMA_EPJK_PTG_NUS_DPG","series-description":"U.S. Kerosene-Type + Jet Fuel Retail Sales by Refiners (Dollars per Gallon)","value":".292","units":"$\/GAL"}]},"request":{"command":"\/v2\/petroleum\/pri\/refoth\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPJK"],"process":["PTG"],"series":["EMA_EPJK_PTG_NUS_DPG"]},"start":"1975-07","end":"1975-07","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:22 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:22 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '851' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_residual_fuel_oil_and_no4_fuel_sales_volumes_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_residual_fuel_oil_and_no4_fuel_sales_volumes_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..a3d18e93486 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_residual_fuel_oil_and_no4_fuel_sales_volumes_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/cons/refres/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1983-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VTR&facets%5Bproduct%5D%5B%5D=EPPR&facets%5Bseries%5D%5B%5D=A303600001&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1983-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1983-01","duoarea":"NUS","area-name":"U.S.","product":"EPPR","product-name":"Residual + Fuel Oil","process":"VTR","process-name":"Retail Sales by Refiners and Gas + Plants","series":"A303600001","series-description":"U.S. Residual Fuel Oil + Retail Sales by Refiners (Thousand Gallons per Day)","value":"28599.8","units":"MGAL\/D"}]},"request":{"command":"\/v2\/petroleum\/cons\/refres\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPPR"],"process":["VTR"],"series":["A303600001"]},"start":"1983-01","end":"1983-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:22 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:22 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '832' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_sales_volumes_of_other_petroleum_products_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_sales_volumes_of_other_petroleum_products_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..650ae06e830 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refiner_sales_volumes_of_other_petroleum_products_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/cons/refoth/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1983-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VTR&facets%5Bproduct%5D%5B%5D=EPD2&facets%5Bseries%5D%5B%5D=A203600001&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1983-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1983-01","duoarea":"NUS","area-name":"U.S.","product":"EPD2","product-name":"No + 2 Distillate","process":"VTR","process-name":"Retail Sales by Refiners and + Gas Plants","series":"A203600001","series-description":"U.S. No 2 Distillate + Retail Sales by Refiners (Thousand Gallons per Day)","value":"24076.8","units":"MGAL\/D"}]},"request":{"command":"\/v2\/petroleum\/cons\/refoth\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPD2"],"process":["VTR"],"series":["A203600001"]},"start":"1983-01","end":"1983-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:23 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:23 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '828' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_blender_net_input_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_blender_net_input_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..dde700c991c --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_blender_net_input_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/inpt/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1961-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=YIR&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCRRIUS2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1961-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1961-01","duoarea":"NUS","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"YIR","process-name":"Refinery and Blender Net Input","series":"MCRRIUS2","series-description":"U.S. + Refinery and Blender Net Input of Crude Oil (Thousand Barrels per Day)","value":"8366","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/pnp\/inpt\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPC0"],"process":["YIR"],"series":["MCRRIUS2"]},"start":"1961-01","end":"1961-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:24 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:24 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '806' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_blender_net_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_blender_net_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..807a6d9c96b --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_blender_net_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/refp/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1936-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=YPR&facets%5Bproduct%5D%5B%5D=EPPR&facets%5Bseries%5D%5B%5D=MRERPUS1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1936-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1936-01","duoarea":"NUS","area-name":"U.S.","product":"EPPR","product-name":"Residual + Fuel Oil","process":"YPR","process-name":"Refinery and Blender Net Production","series":"MRERPUS1","series-description":"U.S. + Refinery and Blender Net Production of Residual Fuel Oil (Thousand Barrels)","value":"24196","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/pnp\/refp\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPPR"],"process":["YPR"],"series":["MRERPUS1"]},"start":"1936-01","end":"1936-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:24 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:24 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '822' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_bulk_terminal_and_natural_gas_plant_stocks_by_state_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_bulk_terminal_and_natural_gas_plant_stocks_by_state_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..bb992f390f6 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_bulk_terminal_and_natural_gas_plant_stocks_by_state_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/stoc/st/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1993-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=STR&facets%5Bproduct%5D%5B%5D=EPDM10&facets%5Bseries%5D%5B%5D=MD1S3_NUS_1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1993-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1993-01","duoarea":"NUS","area-name":"U.S.","product":"EPDM10","product-name":"Distillate + Fuel Oil, Greater than 15 to 500 ppm Sulfur","process":"STR","process-name":"Stocks + at Refineries, Bulk Terminals, and Natural Gas Plants","series":"MD1S3_NUS_1","series-description":"U.S. + Distillate Fuel Oil, Greater than 15 to 500 ppm Sulfur Stocks at Refineries, + Bulk Terminals, and Natural Gas Plants (Thousand Barrels)","value":"14360","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/stoc\/st\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPDM10"],"process":["STR"],"series":["MD1S3_NUS_1"]},"start":"1993-01","end":"1993-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:25 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:25 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '952' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_net_input_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_net_input_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..1d1d78769b9 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_net_input_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/inpt2/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1986-01&facets%5Bduoarea%5D%5B%5D=R2A&facets%5Bduoarea%5D%5B%5D=R2B&facets%5Bduoarea%5D%5B%5D=R2C&facets%5Bduoarea%5D%5B%5D=R3A&facets%5Bduoarea%5D%5B%5D=R3B&facets%5Bduoarea%5D%5B%5D=R3C&facets%5Bduoarea%5D%5B%5D=R3D&facets%5Bduoarea%5D%5B%5D=R3E&facets%5Bduoarea%5D%5B%5D=RAP&facets%5Bduoarea%5D%5B%5D=REC&facets%5Bprocess%5D%5B%5D=YRA&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MACNR2A1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1986-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1986-01","duoarea":"R2A","area-name":"NA","product":"EPC0","product-name":"Crude + Oil","process":"YRA","process-name":"Refinery Receipts of Alaskan Oil","series":"MACNR2A1","series-description":"Refining + District Indiana-Illinois-Kentucky Alaskan Crude Oil Refinery Receipts (Thousand + Barrels)","value":"425","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/pnp\/inpt2\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R2A","R3B","R3A","REC","R3D","R3C","R2B","R2C","R3E","RAP"],"product":["EPC0"],"process":["YRA"],"series":["MACNR2A1"]},"start":"1986-01","end":"1986-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:26 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:26 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '880' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_net_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_net_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..acf93283187 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_net_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/refp2/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1993-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=YPY&facets%5Bproduct%5D%5B%5D=EPJKC&facets%5Bseries%5D%5B%5D=M_EPJKC_YPY_NUS_MBBL&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1993-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1993-01","duoarea":"NUS","area-name":"U.S.","product":"EPJKC","product-name":"Commercial + Kerosene-Type Jet Fuel","process":"YPY","process-name":"Refinery Net Production","series":"M_EPJKC_YPY_NUS_MBBL","series-description":"U.S. + Refinery Net Production of Commercial Kerosene-Type Jet Fuel (Thousand Barrels)","value":"38227","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/pnp\/refp2\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPJKC"],"process":["YPY"],"series":["M_EPJKC_YPY_NUS_MBBL"]},"start":"1993-01","end":"1993-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:27 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:27 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '857' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_receipts_of_crude_oil_by_method_of_transportation_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_receipts_of_crude_oil_by_method_of_transportation_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..7282635b205 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_receipts_of_crude_oil_by_method_of_transportation_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/caprec/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1981&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=8RB0&facets%5Bseries%5D%5B%5D=8_NA_8RB0_NUS_MBBL&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1981 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1981","duoarea":"NUS","area-name":"U.S.","product":"(NA)","product-name":"Not + Applicable","process":"8RB0","process-name":"Crude Oil Refinery Receipts by + Barge","series":"8_NA_8RB0_NUS_MBBL","series-description":"U.S. Crude Oil + Refinery Receipts by Barge (Thousand Barrels)","value":"193247","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/pnp\/caprec\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"process":["8RB0"],"series":["8_NA_8RB0_NUS_MBBL"]},"start":"1981","end":"1981","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:12:54 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:12:54 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '792' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_stocks_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_stocks_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..4c866f4808a --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_stocks_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/stoc/ref/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1981-01&facets%5Bduoarea%5D%5B%5D=R10&facets%5Bprocess%5D%5B%5D=SKR&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCRRSP11&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1981-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1981-01","duoarea":"R10","area-name":"PADD + 1","product":"EPC0","product-name":"Crude Oil","process":"SKR","process-name":"Stocks + at Refineries","series":"MCRRSP11","series-description":"East Coast (PADD + 1) Crude Oil Stocks at Refineries (Thousand Barrels)","value":"16987","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/stoc\/ref\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R10"],"product":["EPC0"],"process":["SKR"],"series":["MCRRSP11"]},"start":"1981-01","end":"1981-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:31 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:31 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '790' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_utilization_and_capacity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_utilization_and_capacity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..ece7f2ff5c1 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_utilization_and_capacity_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/unc/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1985-01&facets%5Bduoarea%5D%5B%5D=R2A&facets%5Bduoarea%5D%5B%5D=R2B&facets%5Bduoarea%5D%5B%5D=R2C&facets%5Bduoarea%5D%5B%5D=R3A&facets%5Bduoarea%5D%5B%5D=R3B&facets%5Bduoarea%5D%5B%5D=R3C&facets%5Bduoarea%5D%5B%5D=R3D&facets%5Bduoarea%5D%5B%5D=R3E&facets%5Bduoarea%5D%5B%5D=RAP&facets%5Bduoarea%5D%5B%5D=REC&facets%5Bprocess%5D%5B%5D=YIY&facets%5Bproduct%5D%5B%5D=EPXXX2&facets%5Bseries%5D%5B%5D=MGIRI2A2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1985-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1985-01","duoarea":"R2A","area-name":"NA","product":"EPXXX2","product-name":"Gross + Inputs","process":"YIY","process-name":"Refinery Net Input","series":"MGIRI2A2","series-description":"Indiana, + Illinois, Kentucky Refinery District Gross Inputs to Refineries (Thousand + Barrels Per Day)","value":"1739","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/pnp\/unc\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R2A","R3B","R3A","REC","R3D","R3C","R2B","R2C","R3E","RAP"],"product":["EPXXX2"],"process":["YIY"],"series":["MGIRI2A2"]},"start":"1985-01","end":"1985-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:31 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:31 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '876' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_yield_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_yield_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..35391170469 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_refinery_yield_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/pct/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1993-01&facets%5Bduoarea%5D%5B%5D=R2A&facets%5Bduoarea%5D%5B%5D=R2B&facets%5Bduoarea%5D%5B%5D=R2C&facets%5Bduoarea%5D%5B%5D=R3A&facets%5Bduoarea%5D%5B%5D=R3B&facets%5Bduoarea%5D%5B%5D=R3C&facets%5Bduoarea%5D%5B%5D=R3D&facets%5Bduoarea%5D%5B%5D=R3E&facets%5Bduoarea%5D%5B%5D=RAP&facets%5Bduoarea%5D%5B%5D=REC&facets%5Bprocess%5D%5B%5D=YRY&facets%5Bproduct%5D%5B%5D=EPPA&facets%5Bseries%5D%5B%5D=MAPRY2A3&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1993-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1993-01","duoarea":"R2A","area-name":"NA","product":"EPPA","product-name":"Asphalt + and Road Oil","process":"YRY","process-name":"Refinery Yield","series":"MAPRY2A3","series-description":"Refining + District Indiana-Illinois-Kentucky Refinery Yield of Asphalt and Road Oil + (Percent)","value":"4.3","units":"%"}]},"request":{"command":"\/v2\/petroleum\/pnp\/pct\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["R2A","R3B","R3A","REC","R3D","R3C","R2B","R2C","R3E","RAP"],"product":["EPPA"],"process":["YRY"],"series":["MAPRY2A3"]},"start":"1993-01","end":"1993-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:32 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:32 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '862' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_residual_fuel_oil_prices_by_sales_type_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_residual_fuel_oil_prices_by_sales_type_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..f5144f9dd54 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_residual_fuel_oil_prices_by_sales_type_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/resid/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1983-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=PTA&facets%5Bproduct%5D%5B%5D=EPPRH&facets%5Bseries%5D%5B%5D=EMA_EPPRH_PTA_NUS_DPG&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1983-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1983-01","duoarea":"NUS","area-name":"U.S.","product":"EPPRH","product-name":"Residual + Fuel Oil, Greater Than 1% Sulfur","process":"PTA","process-name":"Retail Sales + by All Sellers","series":"EMA_EPPRH_PTA_NUS_DPG","series-description":"U.S. + Residual Fuel Oil Sulfur Greater Than 1% Retail Sales by All Sellers (Dollars + per Gallon)","value":".601","units":"$\/GAL"}]},"request":{"command":"\/v2\/petroleum\/pri\/resid\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPPRH"],"process":["PTA"],"series":["EMA_EPPRH_PTA_NUS_DPG"]},"start":"1983-01","end":"1983-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:33 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:33 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '882' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_sales_of_distillate_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_sales_of_distillate_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..f8b306e3bcb --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_sales_of_distillate_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/cons/821dst/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1984&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VCS&facets%5Bproduct%5D%5B%5D=EPD0&facets%5Bseries%5D%5B%5D=KD0VCSNUS1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1984 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1984","duoarea":"NUS","area-name":"U.S.","product":"EPD0","product-name":"Distillate + Fuel Oil","process":"VCS","process-name":"Commercial Consumption","series":"KD0VCSNUS1","series-description":"U.S. + Total Distillate Sales\/Deliveries to Commercial Consumers (Thousand Gallons)","value":"5538184","units":"MGAL"}]},"request":{"command":"\/v2\/petroleum\/cons\/821dst\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPD0"],"process":["VCS"],"series":["KD0VCSNUS1"]},"start":"1984","end":"1984","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:34 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:34 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '808' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_sales_of_kerosene_by_end_use_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_sales_of_kerosene_by_end_use_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..69acc67e7de --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_sales_of_kerosene_by_end_use_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/cons/821ker/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1984&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VCS&facets%5Bproduct%5D%5B%5D=EPPK&facets%5Bseries%5D%5B%5D=KDRVCSNUS1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1984 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1984","duoarea":"NUS","area-name":"U.S.","product":"EPPK","product-name":"Kerosene","process":"VCS","process-name":"Commercial + Consumption","series":"KDRVCSNUS1","series-description":"U.S. Kerosene Sales\/Deliveries + to Commercial Consumers (Thousand Gallons)","value":"265684","units":"MGAL"}]},"request":{"command":"\/v2\/petroleum\/cons\/821ker\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPPK"],"process":["VCS"],"series":["KDRVCSNUS1"]},"start":"1984","end":"1984","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:34 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:34 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '788' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_sales_of_residual_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_sales_of_residual_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..21191b8e6fd --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_sales_of_residual_fuel_oil_by_end_use_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/cons/821rsd/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1984&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VCS&facets%5Bproduct%5D%5B%5D=EPPR&facets%5Bseries%5D%5B%5D=KPRVCSNUS1&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1984 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1984","duoarea":"NUS","area-name":"U.S.","product":"EPPR","product-name":"Residual + Fuel Oil","process":"VCS","process-name":"Commercial Consumption","series":"KPRVCSNUS1","series-description":"U.S. + Residual Fuel Oil Sales\/Deliveries to Commercial Consumers (Thousand Gallons)","value":"1539124","units":"MGAL"}]},"request":{"command":"\/v2\/petroleum\/cons\/821rsd\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPPR"],"process":["VCS"],"series":["KPRVCSNUS1"]},"start":"1984","end":"1984","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:34 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:34 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '807' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_shell_storage_capacity_at_operable_refineries_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_shell_storage_capacity_at_operable_refineries_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..6d747f30e0b --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_shell_storage_capacity_at_operable_refineries_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/capshell/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1982&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=8SS0&facets%5Bseries%5D%5B%5D=8_NA_8SS0_NUS_MBBL&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1982 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1982","duoarea":"NUS","area-name":"U.S.","product":"(NA)","product-name":"Not + Applicable","process":"8SS0","process-name":"Shell Storage Capacity at Refineries","series":"8_NA_8SS0_NUS_MBBL","series-description":"U.S. + Refinery Shell Storage Capacity as of January 1 (Thousand Barrels)","value":"799034","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/pnp\/capshell\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"process":["8SS0"],"series":["8_NA_8SS0_NUS_MBBL"]},"start":"1982","end":"1982","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:12:54 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:12:54 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '805' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_spot_prices_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_spot_prices_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..4f4811cf0bf --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_spot_prices_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/spt/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1986-01-03&facets%5Bduoarea%5D%5B%5D=RGC&facets%5Bduoarea%5D%5B%5D=Y44MB&facets%5Bduoarea%5D%5B%5D=YCUOK&facets%5Bduoarea%5D%5B%5D=ZEU&facets%5Bprocess%5D%5B%5D=PF4&facets%5Bproduct%5D%5B%5D=EPCWTI&facets%5Bseries%5D%5B%5D=RWTC&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1986-01-03 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"1986-01-03","duoarea":"YCUOK","area-name":"NA","product":"EPCWTI","product-name":"WTI + Crude Oil","process":"PF4","process-name":"Spot Price FOB","series":"RWTC","series-description":"Cushing, + OK WTI Spot Price FOB (Dollars per Barrel)","value":"25.78","units":"$\/BBL"}]},"request":{"command":"\/v2\/petroleum\/pri\/spt\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["YCUOK","RGC","Y44MB","ZEU"],"product":["EPCWTI"],"process":["PF4"],"series":["RWTC"]},"start":"1986-01-03","end":"1986-01-03","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:39 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:39 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '797' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_stocks_by_type_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_stocks_by_type_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..975e9994a7c --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_stocks_by_type_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/stoc/typ/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1920-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=SAE&facets%5Bprocess%5D%5B%5D=SAEL&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCRSTUS1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1920-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1920-01","duoarea":"NUS","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"SAE","process-name":"Ending Stocks","series":"MCRSTUS1","series-description":"U.S. + Ending Stocks of Crude Oil (Thousand Barrels)","value":"132124","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/stoc\/typ\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPC0"],"process":["SAEL","SAE"],"series":["MCRSTUS1"]},"start":"1920-01","end":"1920-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:40 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:40 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '770' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_stocks_of_selected_products_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_stocks_of_selected_products_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..da031065e98 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_stocks_of_selected_products_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/stoc/ts/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1936-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=SAE&facets%5Bproduct%5D%5B%5D=EPPR&facets%5Bseries%5D%5B%5D=MRESTUS1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1936-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1936-01","duoarea":"NUS","area-name":"U.S.","product":"EPPR","product-name":"Residual + Fuel Oil","process":"SAE","process-name":"Ending Stocks","series":"MRESTUS1","series-description":"U.S. + Ending Stocks of Residual Fuel Oil (Thousand Barrels)","value":"83083","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/stoc\/ts\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPPR"],"process":["SAE"],"series":["MRESTUS1"]},"start":"1936-01","end":"1936-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:40 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:40 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '777' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_supply_and_disposition_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_supply_and_disposition_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..50a2b496a01 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_supply_and_disposition_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/sum/snd/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1920-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=SAE&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCRSTUS1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1920-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1920-01","duoarea":"NUS","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"SAE","process-name":"Ending Stocks","series":"MCRSTUS1","series-description":"U.S. + Ending Stocks of Crude Oil (Thousand Barrels)","value":"132124","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/sum\/snd\/data\/","params":{"frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00","NUS"],"product":["EPC0"],"process":["SAE"],"series":["MCRSTUS1"]},"start":"1920-01","end":"1920-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:42 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:42 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '719' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_biodiesel_production_capacity_sales_and_stocks_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_biodiesel_production_capacity_sales_and_stocks_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..e473be67201 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_biodiesel_production_capacity_sales_and_stocks_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/sum/b100/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2009-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=SAE&facets%5Bproduct%5D%5B%5D=EPOOBD&facets%5Bseries%5D%5B%5D=M_EPOOBD_SAE_NUS_MMGL&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2009-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"2009-01","duoarea":"NUS","area-name":"U.S.","product":"EPOOBD","product-name":"Biodiesel + Fuel B100","process":"SAE","process-name":"Ending Stocks","series":"M_EPOOBD_SAE_NUS_MMGL","series-description":"U.S. + Ending Stocks of B100 (Million Gallons)","value":"34","units":"MMGL"}]},"request":{"command":"\/v2\/petroleum\/sum\/b100\/data\/","params":{"frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPOOBD"],"process":["SAE"],"series":["M_EPOOBD_SAE_NUS_MMGL"]},"start":"2009-01","end":"2009-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:42 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:42 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '740' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_crude_oil_supply_disposition_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_crude_oil_supply_disposition_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..a2685d3efb1 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_crude_oil_supply_disposition_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/sum/crdsnd/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1920-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=SAE&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCRSTUS1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1920-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1920-01","duoarea":"NUS","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"SAE","process-name":"Ending Stocks","series":"MCRSTUS1","series-description":"U.S. + Ending Stocks of Crude Oil (Thousand Barrels)","value":"132124","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/sum\/crdsnd\/data\/","params":{"frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00","NUS"],"product":["EPC0"],"process":["SAE"],"series":["MCRSTUS1"]},"start":"1920-01","end":"1920-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:43 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:43 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '722' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_imports_by_country_of_origin_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_imports_by_country_of_origin_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..caab05d4111 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_imports_by_country_of_origin_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/impcus/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1920-01&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=IM0&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCRIMUS1&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1920-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1920-01","duoarea":"NUS-Z00","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"IM0","process-name":"Imports","series":"MCRIMUS1","series-description":"U.S. + Imports of Crude Oil (Thousand Barrels)","value":"6294","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/move\/impcus\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00"],"product":["EPC0"],"process":["IM0"],"series":["MCRIMUS1"]},"start":"1920-01","end":"1920-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:44 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:44 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '760' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_net_imports_by_country_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_net_imports_by_country_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..8a39faf1867 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_net_imports_by_country_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/neti/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1920-01&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=IMN&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=MCRNTUS2&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1920-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1920-01","duoarea":"NUS-Z00","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"IMN","process-name":"Net Imports","series":"MCRNTUS2","series-description":"U.S. + Net Imports of Crude Oil (Thousand Barrels per Day)","value":"188","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/move\/neti\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS-Z00"],"product":["EPC0"],"process":["IMN"],"series":["MCRNTUS2"]},"start":"1920-01","end":"1920-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:45 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:45 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '776' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_refiner_gasoline_prices_by_formulation_grade_sales_type_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_refiner_gasoline_prices_by_formulation_grade_sales_type_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..49358460898 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_refiner_gasoline_prices_by_formulation_grade_sales_type_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/refmg2/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1994-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=PTG&facets%5Bproduct%5D%5B%5D=EPM0R&facets%5Bseries%5D%5B%5D=EMA_EPM0R_PTG_NUS_DPG&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1994-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1994-01","duoarea":"NUS","area-name":"U.S.","product":"EPM0R","product-name":"Reformulated + Motor Gasoline","process":"PTG","process-name":"Retail Sales by Refiners and + Gas Plants","series":"EMA_EPM0R_PTG_NUS_DPG","series-description":"U.S. Reformulated + Gasoline Retail Sales by Refiners (Dollars per Gallon)","value":null,"units":"$\/GAL"}]},"request":{"command":"\/v2\/petroleum\/pri\/refmg2\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPM0R"],"process":["PTG"],"series":["EMA_EPM0R_PTG_NUS_DPG"]},"start":"1994-01","end":"1994-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:46 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:46 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '857' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_weekly_product_supplied_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_weekly_product_supplied_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..974c38c6cd7 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_us_weekly_product_supplied_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/cons/wpsup/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1990-11-09&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=VPP&facets%5Bproduct%5D%5B%5D=EPP0&facets%5Bseries%5D%5B%5D=WRPUPUS2&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1990-11-09 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"1990-11-09","duoarea":"NUS","area-name":"U.S.","product":"EPP0","product-name":"Total + Petroleum Products","process":"VPP","process-name":"Product Supplied","series":"WRPUPUS2","series-description":"U.S. + Product Supplied of Petroleum Products (Thousand Barrels per Day)","value":"16588","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/cons\/wpsup\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPP0"],"process":["VPP"],"series":["WRPUPUS2"]},"start":"1990-11-09","end":"1990-11-09","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:46 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:46 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '815' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_blender_net_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_blender_net_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..6522553251c --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_blender_net_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/wprodb/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2010-06-04&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=YPB&facets%5Bproduct%5D%5B%5D=EPD00H&facets%5Bseries%5D%5B%5D=W_EPD00H_YPB_NUS_MBBLD&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2010-06-04 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"2010-06-04","duoarea":"NUS","area-name":"U.S.","product":"EPD00H","product-name":"Distillate + Fuel Oil, Greater Than 500 ppm Sulfur","process":"YPB","process-name":"Motor + Gasoline Terminal Blenders Net Production","series":"W_EPD00H_YPB_NUS_MBBLD","series-description":"U.S. + Blender Net Production of Distillate Fuel Oil, Greater Than 500 ppm Sulfur + (Thousand Barrels per Day)","value":"-47","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/pnp\/wprodb\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPD00H"],"process":["YPB"],"series":["W_EPD00H_YPB_NUS_MBBLD"]},"start":"2010-06-04","end":"2010-06-04","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:47 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:47 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '936' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_crude_imports_by_top10_origins_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_crude_imports_by_top10_origins_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..c6392be4739 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_crude_imports_by_top10_origins_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/wimpc/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2010-06-04&facets%5Bduoarea%5D%5B%5D=NUS-NAG&facets%5Bprocess%5D%5B%5D=IM0&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=W_EPC0_IM0_NUS-NAG_MBBLD&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2010-06-04 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"2010-06-04","duoarea":"NUS-NAG","area-name":"DZA","product":"EPC0","product-name":"Crude + Oil","process":"IM0","process-name":"Imports","series":"W_EPC0_IM0_NUS-NAG_MBBLD","series-description":"U.S. + Imports from Algeria of Crude Oil (Thousand Barrels per Day)","value":"335","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/move\/wimpc\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["NUS-NAG"],"product":["EPC0"],"process":["IM0"],"series":["W_EPC0_IM0_NUS-NAG_MBBLD"]},"start":"2010-06-04","end":"2010-06-04","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:47 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:47 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '823' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_ethanol_plant_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_ethanol_plant_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..e9919b90015 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_ethanol_plant_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/wprode/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2010-06-04&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=YOP&facets%5Bproduct%5D%5B%5D=EPOOXE&facets%5Bseries%5D%5B%5D=W_EPOOXE_YOP_NUS_MBBLD&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2010-06-04 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"2010-06-04","duoarea":"NUS","area-name":"U.S.","product":"EPOOXE","product-name":"Fuel + Ethanol","process":"YOP","process-name":"Oxygenate Plant Production","series":"W_EPOOXE_YOP_NUS_MBBLD","series-description":"U.S. + Oxygenate Plant Production of Fuel Ethanol (Thousand Barrels per Day)","value":"839","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/pnp\/wprode\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPOOXE"],"process":["YOP"],"series":["W_EPOOXE_YOP_NUS_MBBLD"]},"start":"2010-06-04","end":"2010-06-04","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:48 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:48 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '847' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_heating_oil_and_propane_prices_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_heating_oil_and_propane_prices_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..c6a0c781d73 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_heating_oil_and_propane_prices_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/wfr/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1990-10-01&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=PRS&facets%5Bproduct%5D%5B%5D=EPD2F&facets%5Bseries%5D%5B%5D=W_EPD2F_PRS_NUS_DPG&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1990-10-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"1990-10-01","duoarea":"NUS","area-name":"U.S.","product":"EPD2F","product-name":"No + 2 Fuel Oil \/ Heating Oil","process":"PRS","process-name":"Price Delivered + to Residential Consumers","series":"W_EPD2F_PRS_NUS_DPG","series-description":"U.S. + Weekly No. 2 Heating Oil Residential Price (Dollars per Gallon)","value":"1.279","units":"$\/GAL"}]},"request":{"command":"\/v2\/petroleum\/pri\/wfr\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPD2F"],"process":["PRS"],"series":["W_EPD2F_PRS_NUS_DPG"]},"start":"1990-10-01","end":"1990-10-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:48 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:48 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '861' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_imports_exports_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_imports_exports_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..13d0f3136bd --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_imports_exports_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/move/wkly/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1982-08-20&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=IM0&facets%5Bproduct%5D%5B%5D=EPD0&facets%5Bseries%5D%5B%5D=WDIIMUS2&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1982-08-20 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"1982-08-20","duoarea":"NUS-Z00","area-name":"U.S.","product":"EPD0","product-name":"Distillate + Fuel Oil","process":"IM0","process-name":"Imports","series":"WDIIMUS2","series-description":"U.S. + Imports of Distillate Fuel Oil (Thousand Barrels per Day)","value":"58","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/move\/wkly\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["NUS-Z00"],"product":["EPD0"],"process":["IM0"],"series":["WDIIMUS2"]},"start":"1982-08-20","end":"1982-08-20","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:49 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:49 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '797' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_inputs_utilization_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_inputs_utilization_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..768d3e9e413 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_inputs_utilization_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/wiup/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1982-08-20&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=YIY&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=WCRRIUS2&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1982-08-20 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"1982-08-20","duoarea":"NUS","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"YIY","process-name":"Refinery Net Input","series":"WCRRIUS2","series-description":"U.S. + Refiner Net Input of Crude Oil (Thousand Barrels per Day)","value":"11722","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/pnp\/wiup\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPC0"],"process":["YIY"],"series":["WCRRIUS2"]},"start":"1982-08-20","end":"1982-08-20","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:49 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:49 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '792' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_refiner_blender_net_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_refiner_blender_net_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..a9befb11a82 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_refiner_blender_net_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/wprodrb/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1982-08-20&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=YPR&facets%5Bproduct%5D%5B%5D=EPD0&facets%5Bseries%5D%5B%5D=WDIRPUS2&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1982-08-20 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"1982-08-20","duoarea":"NUS","area-name":"U.S.","product":"EPD0","product-name":"Distillate + Fuel Oil","process":"YPR","process-name":"Refinery and Blender Net Production","series":"WDIRPUS2","series-description":"U.S. + Refiner and Blender Net Production of Distillate Fuel Oil (Thousand Barrels + per Day)","value":"2326","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/pnp\/wprodrb\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPD0"],"process":["YPR"],"series":["WDIRPUS2"]},"start":"1982-08-20","end":"1982-08-20","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:50 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:50 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '848' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_refiner_net_production_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_refiner_net_production_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..6f21100d7d5 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_refiner_net_production_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/wprodr/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2010-06-04&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=YPY&facets%5Bproduct%5D%5B%5D=EPD00H&facets%5Bseries%5D%5B%5D=W_EPD00H_YPY_NUS_MBBLD&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2010-06-04 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"2010-06-04","duoarea":"NUS","area-name":"U.S.","product":"EPD00H","product-name":"Distillate + Fuel Oil, Greater Than 500 ppm Sulfur","process":"YPY","process-name":"Refinery + Net Production","series":"W_EPD00H_YPY_NUS_MBBLD","series-description":"U.S. + Refiner Net Production of Distillate Fuel Oil, Greater Than 500 ppm Sulfur + (Thousand Barrels per Day)","value":"307","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/pnp\/wprodr\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPD00H"],"process":["YPY"],"series":["W_EPD00H_YPY_NUS_MBBLD"]},"start":"2010-06-04","end":"2010-06-04","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:51 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:51 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '912' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_retail_gasoline_and_diesel_prices_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_retail_gasoline_and_diesel_prices_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..a6d668dcdb6 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_retail_gasoline_and_diesel_prices_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pri/gnd/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1990-08-20&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=PTE&facets%5Bproduct%5D%5B%5D=EPMRU&facets%5Bseries%5D%5B%5D=EMM_EPMRU_PTE_NUS_DPG&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1990-08-20 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"1990-08-20","duoarea":"NUS","area-name":"U.S.","product":"EPMRU","product-name":"Conventional + Regular Gasoline","process":"PTE","process-name":"Retail Sales","series":"EMM_EPMRU_PTE_NUS_DPG","series-description":"U.S. + Regular Conventional Retail Gasoline Prices (Dollars per Gallon)","value":"1.191","units":"$\/GAL"}]},"request":{"command":"\/v2\/petroleum\/pri\/gnd\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPMRU"],"process":["PTE"],"series":["EMM_EPMRU_PTE_NUS_DPG"]},"start":"1990-08-20","end":"1990-08-20","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:52 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:52 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '839' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_stocks_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_stocks_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..765b66f9231 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_stocks_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/stoc/wstk/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1982-08-20&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=SAE&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=WCRSTUS1&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1982-08-20 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"1982-08-20","duoarea":"NUS","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"SAE","process-name":"Ending Stocks","series":"WCRSTUS1","series-description":"U.S. + Ending Stocks of Crude Oil (Thousand Barrels)","value":"609219","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/stoc\/wstk\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"weekly","data":["value"],"facets":{"duoarea":["NUS"],"product":["EPC0"],"process":["SAE"],"series":["WCRSTUS1"]},"start":"1982-08-20","end":"1982-08-20","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:52 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:52 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '774' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_supply_estimates_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_supply_estimates_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..3bb262e84cd --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_weekly_supply_estimates_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/sum/sndw/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1982-08-20&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bduoarea%5D%5B%5D=NUS-Z00&facets%5Bprocess%5D%5B%5D=YIY&facets%5Bproduct%5D%5B%5D=EPC0&facets%5Bseries%5D%5B%5D=WCRRIUS2&frequency=weekly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1982-08-20 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM-DD","frequency":"weekly","data":[{"period":"1982-08-20","duoarea":"NUS","area-name":"U.S.","product":"EPC0","product-name":"Crude + Oil","process":"YIY","process-name":"Refinery Net Input","series":"WCRRIUS2","series-description":"U.S. + Refiner Net Input of Crude Oil (Thousand Barrels per Day)","value":"11722","units":"MBBL\/D"}]},"request":{"command":"\/v2\/petroleum\/sum\/sndw\/data\/","params":{"frequency":"weekly","data":["value"],"facets":{"duoarea":["NUS-Z00","NUS"],"product":["EPC0"],"process":["YIY"],"series":["WCRRIUS2"]},"start":"1982-08-20","end":"1982-08-20","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:55 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:55 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '749' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_working_storage_capacity_at_operable_refineries_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_working_storage_capacity_at_operable_refineries_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..5596ac296e8 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_petroleum_working_storage_capacity_at_operable_refineries_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/petroleum/pnp/capwork/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1982&facets%5Bduoarea%5D%5B%5D=NUS&facets%5Bprocess%5D%5B%5D=8SW0&facets%5Bseries%5D%5B%5D=8_NA_8SW0_NUS_MBBL&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1982 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1982","duoarea":"NUS","area-name":"U.S.","product":"(NA)","product-name":"Not + Applicable","process":"8SW0","process-name":"Working Storage Capacity","series":"8_NA_8SW0_NUS_MBBL","series-description":"U.S. + Refinery Working Storage Capacity as of January 1 (Thousand Barrels)","value":"696626","units":"MBBL"}]},"request":{"command":"\/v2\/petroleum\/pnp\/capwork\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"duoarea":["NUS"],"process":["8SW0"],"series":["8_NA_8SW0_NUS_MBBL"]},"start":"1982","end":"1982","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:12:55 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:12:55 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '794' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_seds_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_seds_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..a3885649180 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_seds_fetcher_urllib3_v2.yaml @@ -0,0 +1,66 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/seds/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1960&facets%5BseriesId%5D%5B%5D=ABICB&facets%5BseriesId%5D%5B%5D=ABICP&facets%5BstateId%5D%5B%5D=AK&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1960 + response: + body: + string: '{"response":{"total":"2","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1960","seriesId":"ABICB","seriesDescription":"Aviation + gasoline blending components consumed by the industrial sector","stateId":"AK","stateDescription":"Alaska","value":"0","unit":"Billion + Btu"},{"period":"1960","seriesId":"ABICP","seriesDescription":"Aviation gasoline + blending components consumed by the industrial sector","stateId":"AK","stateDescription":"Alaska","value":"0","unit":"Thousand + barrels"}],"description":"Estimated production, consumption, price, and expenditure + data for all energy sources by state and sector. \r\n Source: https:\/\/www.eia.gov\/state\/seds\/seds-technical-notes-complete.php \r\n Product: SEDS + (https:\/\/www.eia.gov\/state\/seds\/)"},"request":{"command":"\/v2\/seds\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["value"],"facets":{"seriesId":["ABICP","ABICB"],"stateId":["AK"]},"start":"1960","end":"1960","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:03:59 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:03:59 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1133' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_short_term_energy_outlook_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_short_term_energy_outlook_fetcher_urllib3_v2.yaml index 88af0d14270..8c0fc7a1b08 100644 --- a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_short_term_energy_outlook_fetcher_urllib3_v2.yaml +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_short_term_energy_outlook_fetcher_urllib3_v2.yaml @@ -9,26 +9,20 @@ interactions: Connection: - keep-alive method: GET - uri: https://api.eia.gov/v2/steo/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2024-Q2&facets%5BseriesId%5D%5B%5D=SNGPRL48&facets%5BseriesId%5D%5B%5D=TOPRAC&facets%5BseriesId%5D%5B%5D=TOPRBK&facets%5BseriesId%5D%5B%5D=TOPREF&facets%5BseriesId%5D%5B%5D=TOPRL48&facets%5BseriesId%5D%5B%5D=TOPRMP&facets%5BseriesId%5D%5B%5D=TOPRNI&facets%5BseriesId%5D%5B%5D=TOPRPM&facets%5BseriesId%5D%5B%5D=TOPRR48&facets%5BseriesId%5D%5B%5D=TOPRWF&frequency=quarterly&length=5000&offset=0&start=2024-Q1 + uri: https://api.eia.gov/v2/steo/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2024-Q2&facets%5BseriesId%5D%5B%5D=SNGPRR48&facets%5BseriesId%5D%5B%5D=SNGPRWF&frequency=quarterly&length=5000&offset=0&start=2024-Q1 response: body: - string: !!binary | - H4sIAAAAAAAAALWXXXObOBSG/4qGq3YmJZIQQuQuTZNOdteJ89FkMnVnRwZhswFkSyJZb6b/vQc7 - pfYumdZZzHAliaOH90ivdJ48o+xMV1Z5B0+e004W3oFHsbfnpdKpE21K6aDlDp53I+8CXujKjJrX - qkoW0DOvpXHKFIvVJ9I7+PzkzZTJdbqMRNm7CwJ9FpqUPW0ar84+Di//YKJt/aBsYvKZy3XVdE9l - oVBqFqiSrjayQBNp0czotE6WQ/a8B1nUQOxFsc+wEEEYYArNdZU3sOO8KGAcSupxnqBMKYcACKVy - 4X3d+w8c3SEcjQIe4jiOXwv3L+Wuz4eXh0cvoF3nk6lDOi/WcFBmdIkOa+vyCh0B+z3KljndRPUJ - CSgnIQ7ZGmr5jDqWxqjCbiHiDjkFi3EQRzh8FWeHnu9/35rzvby/V1UnIfEJh6RzEoS9Kdk7oSAR - wTygpC8Nj0+2JjyWE9hIYDBpd6ZjwgmjcSwi1peOu6DkgYiJwEHQl5QvW08X5RqL8BmnnEU0Yq+D - 6VDsf8BwHpCV+/WlzGC4dfoGubXNO5vlsns3+IQKSmgYxqK3/bor0DAK4LSjcW+Knp1uDXqW67GR - RqIjnaqi6EZlnGPMAgELsi9Nd4YqSMjjmIeitwNlONgadahMuZF4u8YY+gGlERUxj/pSs39ExigO - YwZp70vGy628ZwWp3RTm+ORf+d2cPhgkx+DYYdibR+6IE3ZQSCkVvC89b7c//W61TrMXzz4sGFwh - BI4Ied1FokPMHUAGEaGEwWn0Kxn/AkXMxrwDXblpsUB2qo1DUOiU6A0RqGya3zYsf6kli0W1zasJ - uro+PodeMBwfoZEZVej5uVSzJoKsUpRXEEfCZw9qLQJqqic0NvoR/v8ArSK9eXx89FUu/Yl+GO1b - p/Ro/y1o6S0rMOuaqi3RZQlhAXa0/0C/j2qijfbhl2dggaVtBspZ/ue9aoo2O89uzplK3d0Ayhl6 - 8tvVdVbixNa38Z37h6qbm09zdjFXP6/1npUG3TKZKLec50dOP6/dItqaoL3Stney9tBsnb41qXZR - /NhqbYX2BXSwDpA2lr2qNleYzjKrmiFNUVuoauKmjWNhjL2vEABEuVHGrrJNfeI3Jnv8d6KKwzQ9 - rTb74JNvMXc1JjIPAAA= + string: '{"response":{"total":"4","dateFormat":"YYYY-\"Q\"Q","frequency":"quarterly","data":[{"period":"2024-Q2","seriesId":"SNGPRR48","seriesDescription":"Shale + natural gas production from other U.S. formations","value":"2.7995384615","unit":"billion + cubic feet per day"},{"period":"2024-Q2","seriesId":"SNGPRWF","seriesDescription":"Shale + natural gas production from Woodford formation","value":"2.5551978022","unit":"billion + cubic feet per day"},{"period":"2024-Q1","seriesId":"SNGPRR48","seriesDescription":"Shale + natural gas production from other U.S. formations","value":"2.8891538462","unit":"billion + cubic feet per day"},{"period":"2024-Q1","seriesId":"SNGPRWF","seriesDescription":"Shale + natural gas production from Woodford formation","value":"2.5115934066","unit":"billion + cubic feet per day"}],"description":"Monthly short term (18 month) projections + using STEO model. \r\n Report and interactive projection data browser: STEO + (www.eia.gov\/steo\/)"},"request":{"command":"\/v2\/steo\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"quarterly","data":["value"],"facets":{"seriesId":["SNGPRWF","SNGPRR48"]},"start":"2024-Q1","end":"2024-Q2","offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' headers: Access-Control-Allow-Headers: - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params @@ -37,27 +31,24 @@ interactions: Access-Control-Allow-Origin: - '*' Age: - - '0' + - '1' + Alt-Svc: + - h3=":443"; ma=93600 Cache-Control: - max-age=0, no-cache, no-store Connection: - keep-alive - Content-Encoding: - - gzip - Content-Length: - - '869' Content-Type: - application/json Date: - - Sun, 06 Oct 2024 18:59:51 GMT + - Thu, 09 Jul 2026 02:59:12 GMT Etag: null Expires: - - Sun, 06 Oct 2024 18:59:51 GMT + - Thu, 09 Jul 2026 02:59:12 GMT Pragma: - no-cache Strict-Transport-Security: - - max-age=63072000; includeSubdomains; - - max-age=31536000; preload + - max-age=31536000; includeSubDomains; preload Vary: - Accept-Encoding - Accept-Encoding @@ -71,8 +62,8 @@ interactions: X-Frame-Options: - SAMEORIGIN X-Vcap-Request-Id: null - X-Xss-Protection: - - 1; mode=block + content-length: + - '1269' status: code: 200 message: OK @@ -89,22 +80,49 @@ interactions: uri: https://api.eia.gov/v2/steo/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2024-Q2&facets%5BseriesId%5D%5B%5D=SNGPRBK&facets%5BseriesId%5D%5B%5D=SNGPRBN&facets%5BseriesId%5D%5B%5D=SNGPREF&facets%5BseriesId%5D%5B%5D=SNGPRFY&facets%5BseriesId%5D%5B%5D=SNGPRHA&facets%5BseriesId%5D%5B%5D=SNGPRMC&facets%5BseriesId%5D%5B%5D=SNGPRMP&facets%5BseriesId%5D%5B%5D=SNGPRNI&facets%5BseriesId%5D%5B%5D=SNGPRPM&facets%5BseriesId%5D%5B%5D=SNGPRUA&frequency=quarterly&length=5000&offset=0&start=2024-Q1 response: body: - string: !!binary | - H4sIAAAAAAAAAL2XbW/bNhDHvwqhVy2QKhRFkVLetV28ZoPTpGkyBHUxMNLZ0aInk5QzL+h379Fp - qxhTsEGTJuiFxSNPP/91vOM9eBpMU1cGvKMHz9ZWFd6Rx6h34GXKwqzWpbI4co3Xq4V3jjealhrW - LVTpFi3rVmkLutg+LlHe0acHrwGd19nOE+OvzgO0GRwCc+IGL05/Pvvw5tcfgz+BSXXe2LyunPVW - FUAqZVutCrJShjS6ztrUmclS1yV5o+7uAH/v4NyiA2+jihbc+3xOZRhwIWmCw22VO/qbvCjc6rS9 - yVOyBLAECUmmtt6Xg7/Rsv+RNko4o1RwyofS9mp7+h9odQXW9uIGvkRWKoWQg3F7xZ0KV8QySgIu - pRhT3ePZYNxjtcIZuKuyXmLuM5kEUZzIYNTonZI4ZFKyUMgxFZ5dD+adqS3GA2yQAXqJ/Rhpk1hg - FEdjajwxc8S4DHk0bp5493ow8zu1rcA8jxyEfkRDwWIqwjFlnhKZ+WEgKI14Mmq+mL8djDxXOoWi - aE1/+Yh8GnMWxxEdDNyn8ZTAEWUhx+IcjKrw2XDg3Bh3N02univSYYRlT9A4YqOqPC00hkUg4oSx - wZWkT+nTk8HQp3l9o5VW5G2dYYg8gy3jmOORCINkTK0nx04YpmbBw8G5rk/ss/lg6jPQ5V5smKeJ - TmJ0BHhElnzUiJ6QN+ZxGLNg1Lx8ObyUXNo8Vc8ciAKZxEmELcjgFNen7SSwoZ9EkQikCMW/VPYz - Nnl7r5/Xlb0ttsTc1toSbARL8iKISemGXzqUP2CHYkhr8mpFLj4ev0crbiWfkIVeVOTb9QEa50FV - Gckr9KNw2QaeeCCuuyQ3ur5HGY7Io6cX9/f3PuTKX9WbxaGxUC8OX6Km3q5DNdZ1tWldlugWYReH - G/Z9lvO2OMR/3eDmLo2bqJr89ztwTa1ZL6/ec8js9RzVZbNfLj4uS5qa9rfk2v7F4Orqcs3P1/DP - vfA3rVG3pUrB7t7TfdtPT7rLrhXqzuzdybI7/HQluisjXZLrNuL3sPmMahiLYHubAar9eKuXSwNu - imv9C6hW9hYfsPBR7ws6QGmuQJvHb8587ARx2vGfWOtfZ9lJtW/DJV8BKEucAlgQAAA= + string: '{"response":{"total":"20","dateFormat":"YYYY-\"Q\"Q","frequency":"quarterly","data":[{"period":"2024-Q2","seriesId":"SNGPRBK","seriesDescription":"Shale + natural gas production from Bakken formation","value":"2.6804835165","unit":"billion + cubic feet per day"},{"period":"2024-Q2","seriesId":"SNGPRBN","seriesDescription":"Shale + natural gas production from Barnett formation","value":"1.6291868132","unit":"billion + cubic feet per day"},{"period":"2024-Q2","seriesId":"SNGPREF","seriesDescription":"Shale + natural gas production from Eagle Ford formation","value":"4.2964065934","unit":"billion + cubic feet per day"},{"period":"2024-Q2","seriesId":"SNGPRFY","seriesDescription":"Shale + natural gas production from Fayetteville formation","value":".82368131868","unit":"billion + cubic feet per day"},{"period":"2024-Q2","seriesId":"SNGPRHA","seriesDescription":"Shale + natural gas production from Haynesville formation","value":"12.680164835","unit":"billion + cubic feet per day"},{"period":"2024-Q2","seriesId":"SNGPRMC","seriesDescription":"Shale + natural gas production from Marcellus formation","value":"25.655494505","unit":"billion + cubic feet per day"},{"period":"2024-Q2","seriesId":"SNGPRMP","seriesDescription":"Shale + natural gas production from Mississippian formation","value":"2.2931978022","unit":"billion + cubic feet per day"},{"period":"2024-Q2","seriesId":"SNGPRNI","seriesDescription":"Shale + natural gas production from Niobrara Codell formation","value":"2.7577802198","unit":"billion + cubic feet per day"},{"period":"2024-Q2","seriesId":"SNGPRPM","seriesDescription":"Shale + natural gas production from Permian formations","value":"18.836582418","unit":"billion + cubic feet per day"},{"period":"2024-Q2","seriesId":"SNGPRUA","seriesDescription":"Shale + natural gas production from Utica formation","value":"6.5375714286","unit":"billion + cubic feet per day"},{"period":"2024-Q1","seriesId":"SNGPRBK","seriesDescription":"Shale + natural gas production from Bakken formation","value":"2.4957252747","unit":"billion + cubic feet per day"},{"period":"2024-Q1","seriesId":"SNGPRBN","seriesDescription":"Shale + natural gas production from Barnett formation","value":"1.6476483516","unit":"billion + cubic feet per day"},{"period":"2024-Q1","seriesId":"SNGPREF","seriesDescription":"Shale + natural gas production from Eagle Ford formation","value":"4.2740659341","unit":"billion + cubic feet per day"},{"period":"2024-Q1","seriesId":"SNGPRFY","seriesDescription":"Shale + natural gas production from Fayetteville formation","value":".82079120879","unit":"billion + cubic feet per day"},{"period":"2024-Q1","seriesId":"SNGPRHA","seriesDescription":"Shale + natural gas production from Haynesville formation","value":"14.08478022","unit":"billion + cubic feet per day"},{"period":"2024-Q1","seriesId":"SNGPRMC","seriesDescription":"Shale + natural gas production from Marcellus formation","value":"26.666791209","unit":"billion + cubic feet per day"},{"period":"2024-Q1","seriesId":"SNGPRMP","seriesDescription":"Shale + natural gas production from Mississippian formation","value":"2.3477802198","unit":"billion + cubic feet per day"},{"period":"2024-Q1","seriesId":"SNGPRNI","seriesDescription":"Shale + natural gas production from Niobrara Codell formation","value":"2.7522307692","unit":"billion + cubic feet per day"},{"period":"2024-Q1","seriesId":"SNGPRPM","seriesDescription":"Shale + natural gas production from Permian formations","value":"18.083527473","unit":"billion + cubic feet per day"},{"period":"2024-Q1","seriesId":"SNGPRUA","seriesDescription":"Shale + natural gas production from Utica formation","value":"6.6804505495","unit":"billion + cubic feet per day"}],"description":"Monthly short term (18 month) projections + using STEO model. \r\n Report and interactive projection data browser: STEO + (www.eia.gov\/steo\/)"},"request":{"command":"\/v2\/steo\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"quarterly","data":["value"],"facets":{"seriesId":["SNGPRBK","SNGPRBN","SNGPREF","SNGPRFY","SNGPRHA","SNGPRMC","SNGPRMP","SNGPRNI","SNGPRPM","SNGPRUA"]},"start":"2024-Q1","end":"2024-Q2","offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' headers: Access-Control-Allow-Headers: - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params @@ -113,27 +131,24 @@ interactions: Access-Control-Allow-Origin: - '*' Age: - - '0' + - '1' + Alt-Svc: + - h3=":443"; ma=93600 Cache-Control: - max-age=0, no-cache, no-store Connection: - keep-alive - Content-Encoding: - - gzip - Content-Length: - - '848' Content-Type: - application/json Date: - - Sun, 06 Oct 2024 18:59:51 GMT + - Thu, 09 Jul 2026 02:59:12 GMT Etag: null Expires: - - Sun, 06 Oct 2024 18:59:51 GMT + - Thu, 09 Jul 2026 02:59:12 GMT Pragma: - no-cache Strict-Transport-Security: - - max-age=63072000; includeSubdomains; - - max-age=31536000; preload + - max-age=31536000; includeSubDomains; preload Vary: - Accept-Encoding - Accept-Encoding @@ -147,8 +162,8 @@ interactions: X-Frame-Options: - SAMEORIGIN X-Vcap-Request-Id: null - X-Xss-Protection: - - 1; mode=block + content-length: + - '4188' status: code: 200 message: OK @@ -162,20 +177,50 @@ interactions: Connection: - keep-alive method: GET - uri: https://api.eia.gov/v2/steo/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2024-Q2&facets%5BseriesId%5D%5B%5D=SNGPRR48&facets%5BseriesId%5D%5B%5D=SNGPRWF&frequency=quarterly&length=5000&offset=0&start=2024-Q1 + uri: https://api.eia.gov/v2/steo/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=2024-Q2&facets%5BseriesId%5D%5B%5D=SNGPRL48&facets%5BseriesId%5D%5B%5D=TOPRAC&facets%5BseriesId%5D%5B%5D=TOPRBK&facets%5BseriesId%5D%5B%5D=TOPREF&facets%5BseriesId%5D%5B%5D=TOPRL48&facets%5BseriesId%5D%5B%5D=TOPRMP&facets%5BseriesId%5D%5B%5D=TOPRNI&facets%5BseriesId%5D%5B%5D=TOPRPM&facets%5BseriesId%5D%5B%5D=TOPRR48&facets%5BseriesId%5D%5B%5D=TOPRWF&frequency=quarterly&length=5000&offset=0&start=2024-Q1 response: body: - string: !!binary | - H4sIAAAAAAAAAL2Tb2/aMBDGv8rJr1qpDU5Iyp93k1amTuo6oAVVTTWZ5ALZHDvYDoyhfvedoWuL - NmlTtc3Km9xzfvzz+W7LDNpaK4usv2VOOyFZn8XshOXC4UCbSjgK3NI6TdmQPpIKg8sGVbYhZdkI - 49DIzX6LYP27LavRlDonNeJRfDoMSbMUQnvhg+MP7z6ORnH3KfoWbWbK2pVaeXkhJIISrjFCwlxY - qI3Om8zLUBhdgXYLNHATjAModoSkWHJbCdmgPzWIeNJp98544g9pVOnvMCul9BZZMyszKBAdECfk - YsMeTn5ijv47c5hEnbjXa58lr2X+VZ2ng1cjT7XOiTV/Bj7g7fK4HSVh3G7/zRr/Q96EmoKHPR7+ - Ge89NfQBwaVWbiE3YBfaOKCmr+Ao7ELlw8ee5jPuaCw0tlRzGF+fX5GaowwAUpMqeFwjrL2DUDmU - inwEbVvhCwfwkwQzo9dUiT7snY7W63WApQjmepW2rEOdto6prGw3jdb5Ac50VZEtwaatVfQjy7ul - Lbp1LYyorE8UdfnpC/oBtstichVj7m4vqcDR4P34uqh4Zptp79Z9i3AyuVnGwyX+fu4fa011K0SG - bnfO8/PevXjfp2m6J3zryOmgh1Ed9oguCos+hdOPRDV3C/pJOOfsgQzoLhM0dv9INEdBh9LOv2Yo - 3+T5hTrUaMt3uNK6i/QEAAA= + string: '{"response":{"total":"20","dateFormat":"YYYY-\"Q\"Q","frequency":"quarterly","data":[{"period":"2024-Q2","seriesId":"SNGPRL48","seriesDescription":"Shale + dry natural gas production","value":"83.545285714","unit":"billion cubic feet + per day"},{"period":"2024-Q2","seriesId":"TOPRAC","seriesDescription":"Tight + oil production from Austin Chalk formation","value":".12834065934","unit":"million + barrels per day"},{"period":"2024-Q2","seriesId":"TOPRBK","seriesDescription":"Tight + oil production from Bakken formation","value":"1.2292197802","unit":"million + barrels per day"},{"period":"2024-Q2","seriesId":"TOPREF","seriesDescription":"Tight + oil production from Eagle Ford formation","value":"1.0291208791","unit":"million + barrels per day"},{"period":"2024-Q2","seriesId":"TOPRL48","seriesDescription":"Tight + oil production","value":"9.0526813187","unit":"million barrels per day"},{"period":"2024-Q2","seriesId":"TOPRMP","seriesDescription":"Tight + oil production from Mississippian formation","value":".11931868132","unit":"million + barrels per day"},{"period":"2024-Q2","seriesId":"TOPRNI","seriesDescription":"Tight + oil production from Niobrara Codell formation","value":".45472527473","unit":"million + barrels per day"},{"period":"2024-Q2","seriesId":"TOPRPM","seriesDescription":"Tight + oil production from Permian formations","value":"5.6815714286","unit":"million + barrels per day"},{"period":"2024-Q2","seriesId":"TOPRR48","seriesDescription":"Tight + oil production from other U.S. formations","value":".32669230769","unit":"million + barrels per day"},{"period":"2024-Q2","seriesId":"TOPRWF","seriesDescription":"Tight + oil production from Woodford formation","value":".083692307692","unit":"million + barrels per day"},{"period":"2024-Q1","seriesId":"SNGPRL48","seriesDescription":"Shale + dry natural gas production","value":"85.254538462","unit":"billion cubic feet + per day"},{"period":"2024-Q1","seriesId":"TOPRAC","seriesDescription":"Tight + oil production from Austin Chalk formation","value":".11959340659","unit":"million + barrels per day"},{"period":"2024-Q1","seriesId":"TOPRBK","seriesDescription":"Tight + oil production from Bakken formation","value":"1.2103846154","unit":"million + barrels per day"},{"period":"2024-Q1","seriesId":"TOPREF","seriesDescription":"Tight + oil production from Eagle Ford formation","value":".94148351648","unit":"million + barrels per day"},{"period":"2024-Q1","seriesId":"TOPRL48","seriesDescription":"Tight + oil production","value":"8.7621868132","unit":"million barrels per day"},{"period":"2024-Q1","seriesId":"TOPRMP","seriesDescription":"Tight + oil production from Mississippian formation","value":".12654945055","unit":"million + barrels per day"},{"period":"2024-Q1","seriesId":"TOPRNI","seriesDescription":"Tight + oil production from Niobrara Codell formation","value":".46550549451","unit":"million + barrels per day"},{"period":"2024-Q1","seriesId":"TOPRPM","seriesDescription":"Tight + oil production from Permian formations","value":"5.5070549451","unit":"million + barrels per day"},{"period":"2024-Q1","seriesId":"TOPRR48","seriesDescription":"Tight + oil production from other U.S. formations","value":".31197802198","unit":"million + barrels per day"},{"period":"2024-Q1","seriesId":"TOPRWF","seriesDescription":"Tight + oil production from Woodford formation","value":".079637362637","unit":"million + barrels per day"}],"description":"Monthly short term (18 month) projections + using STEO model. \r\n Report and interactive projection data browser: STEO + (www.eia.gov\/steo\/)"},"request":{"command":"\/v2\/steo\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"quarterly","data":["value"],"facets":{"seriesId":["TOPRL48","TOPRAC","TOPRBK","TOPREF","TOPRMP","TOPRNI","TOPRPM","TOPRWF","TOPRR48","SNGPRL48"]},"start":"2024-Q1","end":"2024-Q2","offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' headers: Access-Control-Allow-Headers: - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params @@ -184,27 +229,24 @@ interactions: Access-Control-Allow-Origin: - '*' Age: - - '0' + - '1' + Alt-Svc: + - h3=":443"; ma=93600 Cache-Control: - max-age=0, no-cache, no-store Connection: - keep-alive - Content-Encoding: - - gzip - Content-Length: - - '530' Content-Type: - application/json Date: - - Sun, 06 Oct 2024 18:59:51 GMT + - Thu, 09 Jul 2026 02:59:12 GMT Etag: null Expires: - - Sun, 06 Oct 2024 18:59:51 GMT + - Thu, 09 Jul 2026 02:59:12 GMT Pragma: - no-cache Strict-Transport-Security: - - max-age=63072000; includeSubdomains; - - max-age=31536000; preload + - max-age=31536000; includeSubDomains; preload Vary: - Accept-Encoding - Accept-Encoding @@ -218,8 +260,8 @@ interactions: X-Frame-Options: - SAMEORIGIN X-Vcap-Request-Id: null - X-Xss-Protection: - - 1; mode=block + content-length: + - '3893' status: code: 200 message: OK diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_advanced_metering_infrastructure_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_advanced_metering_infrastructure_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..79a06eef14e --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_advanced_metering_infrastructure_fetcher_urllib3_v2.yaml @@ -0,0 +1,66 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/state-electricity-profiles/meters/data/?api_key=MOCK_API_KEY&data%5B0%5D=meters&end=2013&facets%5Bsector%5D%5B%5D=COM&facets%5Bstate%5D%5B%5D=AK&facets%5Btechnology%5D%5B%5D=Advanced+Meter+Infrastructure&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2013 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2013","state":"AK","stateName":"Alaska","technology":"Advanced + Meter Infrastructure","sector":"COM","sectorName":"commercial","meters":"679","meters-units":"number + of meters"}],"description":"Advanced meterting counts by technology, state, + and sector\n Source: Forms EIA-861, EIA-861S\n Product: State Electricity + Profiles, Table 12"},"request":{"command":"\/v2\/electricity\/state-electricity-profiles\/meters\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["meters"],"facets":{"state":["AK"],"technology":["Advanced + Meter Infrastructure"],"sector":["COM"]},"start":"2013","end":"2013","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:04:00 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:04:00 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '859' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_costs_and_savings_from_energy_efficiency_programs_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_costs_and_savings_from_energy_efficiency_programs_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..9d0fed8c101 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_costs_and_savings_from_energy_efficiency_programs_fetcher_urllib3_v2.yaml @@ -0,0 +1,66 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/state-electricity-profiles/energy-efficiency/data/?api_key=MOCK_API_KEY&data%5B0%5D=all-other-costs&data%5B1%5D=customer-incentive&data%5B2%5D=energy-savings&data%5B3%5D=potential-peak-savings&end=2013&facets%5Bsector%5D%5B%5D=COM&facets%5Bstate%5D%5B%5D=AK&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2013 + response: + body: + string: '{"response":{"total":"2","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2013","state":"AK","stateName":"Alaska","timePeriod":"Expected + Life Cycle of Programs","sector":"COM","sectorName":"commercial","all-other-costs":"251","customer-incentive":"0","energy-savings":"2535","potential-peak-savings":".8","all-other-costs-units":"thousand + dollars","customer-incentive-units":"thousand dollars","energy-savings-units":"megawatthours","potential-peak-savings-units":"megawatts"},{"period":"2013","state":"AK","stateName":"Alaska","timePeriod":"Reporting + Year","sector":"COM","sectorName":"commercial","all-other-costs":"251","customer-incentive":"0","energy-savings":"988","potential-peak-savings":".3","all-other-costs-units":"thousand + dollars","customer-incentive-units":"thousand dollars","energy-savings-units":"megawatthours","potential-peak-savings-units":"megawatts"}],"description":"Costs + and savings from energy efficiency programs by state and sector\n Source: + Form EIA-861\n Product: State Electricity Profiles, Table 13"},"request":{"command":"\/v2\/electricity\/state-electricity-profiles\/energy-efficiency\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["all-other-costs","customer-incentive","energy-savings","potential-peak-savings"],"facets":{"state":["AK"],"sector":["COM"]},"start":"2013","end":"2013","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:12:55 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:12:55 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1518' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_electricity_net_metering_customers_and_capacity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_electricity_net_metering_customers_and_capacity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..09e225115b6 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_electricity_net_metering_customers_and_capacity_fetcher_urllib3_v2.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/state-electricity-profiles/net-metering/data/?api_key=MOCK_API_KEY&data%5B0%5D=capacity&data%5B1%5D=customers&end=2023&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2023 + response: + body: + string: '{"response":{"total":"0","dateFormat":"YYYY","frequency":"annual","data":[],"description":"Electricity + net metering customer counts and capacity by state, sector, and generating + technology.\n Source: Form EIA-861\n Product: State Electricity Profiles, + Table 11"},"request":{"command":"\/v2\/electricity\/state-electricity-profiles\/net-metering\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["capacity","customers"],"start":"2023","end":"2023","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:04:02 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:04:02 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '632' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_emissions_by_state_by_fuel_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_emissions_by_state_by_fuel_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..1f4f1b25b35 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_emissions_by_state_by_fuel_fetcher_urllib3_v2.yaml @@ -0,0 +1,69 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/state-electricity-profiles/emissions-by-state-by-fuel/data/?api_key=MOCK_API_KEY&data%5B0%5D=co2-rate-lbs-mwh&data%5B1%5D=co2-thousand-metric-tons&data%5B2%5D=nox-rate-lbs-mwh&data%5B3%5D=nox-short-tons&data%5B4%5D=so2-rate-lbs-mwh&data%5B5%5D=so2-short-tons&end=1990&facets%5Bfuelid%5D%5B%5D=ALL&facets%5Bstateid%5D%5B%5D=AK&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1990 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1990","stateid":"AK","stateDescription":"Alaska","fuelid":"ALL","fuelDescription":"Total","co2-rate-lbs-mwh":"1654","co2-thousand-metric-tons":"4209","nox-rate-lbs-mwh":"4.9","nox-short-tons":"13847","so2-rate-lbs-mwh":"7.4","so2-short-tons":"20658","co2-rate-lbs-mwh-units":"pounds + per megawatthour","co2-thousand-metric-tons-units":"thousand metric tons","nox-rate-lbs-mwh-units":"pounds + per megawatthour","nox-short-tons-units":"short tons","so2-rate-lbs-mwh-units":"pounds + per megawatthour","so2-short-tons-units":"short tons"}],"description":"Emissions + from electricity generation and the production of useful thermal output at + conventional power plants and combined-heat-and-power plants.\n See Electric + Power Annual, Technical Notes for a description of the sources and methodology + used to develop the emissions estimates.\n Sources: Forms EIA-860, EIA-923, + and calculations made by the Office of Energy Production, Conversion & Delivery + (EPCD)\n Product: State Electricity Profiles, Table 7"},"request":{"command":"\/v2\/electricity\/state-electricity-profiles\/emissions-by-state-by-fuel\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["co2-rate-lbs-mwh","co2-thousand-metric-tons","nox-rate-lbs-mwh","nox-short-tons","so2-rate-lbs-mwh","so2-short-tons"],"facets":{"stateid":["AK"],"fuelid":["ALL"]},"start":"1990","end":"1990","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:04:02 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:04:02 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1613' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_generating_capacity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_generating_capacity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..da6720e0840 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_generating_capacity_fetcher_urllib3_v2.yaml @@ -0,0 +1,63 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/state-electricity-profiles/capability/data/?api_key=MOCK_API_KEY&data%5B0%5D=capability&end=1990&facets%5Benergysourceid%5D%5B%5D=ALL&facets%5Bproducertypeid%5D%5B%5D=EU&facets%5BstateId%5D%5B%5D=AK&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1990 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1990","stateId":"AK","stateDescription":"Alaska","producertypeid":"EU","producerTypeDescription":"Electric + Utilities","energysourceid":"ALL","energySourceDescription":"All","capability":"1547","capability-units":"megawatts"}],"description":"Electric + generating capacity (summer capacity) by state, energy source, and sector.\n Source: + Form EIA-860\n Product: State Electricity Profiles, Table 4"},"request":{"command":"\/v2\/electricity\/state-electricity-profiles\/capability\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["capability"],"facets":{"stateId":["AK"],"producertypeid":["EU"],"energysourceid":["ALL"]},"start":"1990","end":"1990","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:04:03 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:04:03 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '916' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_state_rankings_for_key_statistics_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_state_rankings_for_key_statistics_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..ca2164cf8cc --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_state_rankings_for_key_statistics_fetcher_urllib3_v2.yaml @@ -0,0 +1,67 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/state-electricity-profiles/summary/data/?api_key=MOCK_API_KEY&data%5B0%5D=average-retail-price&data%5B10%5D=direct-use&data%5B11%5D=direct-use-rank&data%5B12%5D=eop-sales&data%5B13%5D=eop-sales-rank&data%5B14%5D=fsp-sales-rank&data%5B15%5D=fsp-service-provider-sales&data%5B16%5D=generation-elect-utils&data%5B17%5D=generation-elect-utils-rank&data%5B18%5D=generation-ipp&data%5B19%5D=generation-ipp-rank&data%5B1%5D=average-retail-price-rank&data%5B20%5D=net-generation&data%5B21%5D=net-generation-rank&data%5B22%5D=net-summer-capacity&data%5B23%5D=net-summer-capacity-rank&data%5B24%5D=nitrogen-oxide&data%5B25%5D=nitrogen-oxide-lbs&data%5B26%5D=nitrogen-oxide-rank&data%5B27%5D=nitrogen-oxide-rank-lbs&data%5B28%5D=prime-source&data%5B29%5D=sulfer-dioxide&data%5B2%5D=capacity-elec-utilities&data%5B30%5D=sulfer-dioxide-lbs&data%5B31%5D=sulfer-dioxide-rank&data%5B32%5D=sulfer-dioxide-rank-lbs&data%5B33%5D=total-retail-sales&data%5B34%5D=total-retail-sales-rank&data%5B3%5D=capacity-elect-utilities-rank&data%5B4%5D=capacity-ipp&data%5B5%5D=capacity-ipp-rank&data%5B6%5D=carbon-dioxide&data%5B7%5D=carbon-dioxide-lbs&data%5B8%5D=carbon-dioxide-rank&data%5B9%5D=carbon-dioxide-rank-lbs&end=2008&facets%5BstateID%5D%5B%5D=AK&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=2008 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"2008","stateID":"AK","stateDescription":"Alaska","average-retail-price":"14.74","average-retail-price-rank":"6","capacity-elec-utilities":"1847","capacity-elect-utilities-rank":"39","capacity-ipp":"148","capacity-ipp-rank":"50","carbon-dioxide":"4376","carbon-dioxide-lbs":"1421","carbon-dioxide-rank":"46","carbon-dioxide-rank-lbs":"24","direct-use":"328146","direct-use-rank":"37","eop-sales":null,"eop-sales-rank":null,"fsp-sales-rank":"48","fsp-service-provider-sales":"6325944","generation-elect-utils":"6262148","generation-elect-utils-rank":"39","generation-ipp":"512687","generation-ipp-rank":"48","net-generation":"6774834","net-generation-rank":"50","net-summer-capacity":"1995","net-summer-capacity-rank":"48","nitrogen-oxide":"16236","nitrogen-oxide-lbs":"4.8","nitrogen-oxide-rank":"41","nitrogen-oxide-rank-lbs":"2","prime-source":"Natural + Gas","sulfer-dioxide":"3884","sulfer-dioxide-lbs":"1.1","sulfer-dioxide-rank":"48","sulfer-dioxide-rank-lbs":"42","total-retail-sales":"6325944","total-retail-sales-rank":"50","average-retail-price-units":"cents + per kilowatthour","average-retail-price-rank-units":"rank","capacity-elec-utilities-units":"megawatts","capacity-elect-utilities-rank-units":"rank","capacity-ipp-units":"megawatts","capacity-ipp-rank-units":"rank","carbon-dioxide-units":"thousand + metric tons","carbon-dioxide-lbs-units":"pounds per megawatthour","carbon-dioxide-rank-units":"rank","carbon-dioxide-rank-lbs-units":"rank","direct-use-units":"megawatthours","direct-use-rank-units":"rank","eop-sales-units":"megawatthours","eop-sales-rank-units":"rank","fsp-sales-rank-units":"rank","fsp-service-provider-sales-units":"megawatthours","generation-elect-utils-units":"megawatthours","generation-elect-utils-rank-units":"rank","generation-ipp-units":"megawatthours","generation-ipp-rank-units":"rank","net-generation-units":"megawatthours","net-generation-rank-units":"rank","net-summer-capacity-units":"megawatts","net-summer-capacity-rank-units":"rank","nitrogen-oxide-units":"short + tons","nitrogen-oxide-lbs-units":"pounds per megawatthour","nitrogen-oxide-rank-units":"rank","nitrogen-oxide-rank-lbs-units":"rank","sulfer-dioxide-units":"short + tons","sulfer-dioxide-lbs-units":"pounds per megawatthour","sulfer-dioxide-rank-units":"rank","sulfer-dioxide-rank-lbs-units":"rank","total-retail-sales-units":"megawatthours","total-retail-sales-rank-units":"rank"}],"description":"State + rankings for key electricity statistics by state\n Source: Forms EIA-860, + EIA-861, EIA-923\n Product: State Electricity Profiles, Table 1"},"request":{"command":"\/v2\/electricity\/state-electricity-profiles\/summary\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["average-retail-price","average-retail-price-rank","capacity-elec-utilities","capacity-elect-utilities-rank","capacity-ipp","capacity-ipp-rank","carbon-dioxide","carbon-dioxide-lbs","carbon-dioxide-rank","carbon-dioxide-rank-lbs","direct-use","direct-use-rank","eop-sales","eop-sales-rank","fsp-sales-rank","fsp-service-provider-sales","generation-elect-utils","generation-elect-utils-rank","generation-ipp","generation-ipp-rank","net-generation","net-generation-rank","net-summer-capacity","net-summer-capacity-rank","nitrogen-oxide","nitrogen-oxide-lbs","nitrogen-oxide-rank","nitrogen-oxide-rank-lbs","prime-source","sulfer-dioxide","sulfer-dioxide-lbs","sulfer-dioxide-rank","sulfer-dioxide-rank-lbs","total-retail-sales","total-retail-sales-rank"],"facets":{"stateID":["AK"]},"start":"2008","end":"2008","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:04:04 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:04:04 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '3759' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_supply_and_disposition_of_electricity_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_supply_and_disposition_of_electricity_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..00362557f66 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_state_electricity_profiles_supply_and_disposition_of_electricity_fetcher_urllib3_v2.yaml @@ -0,0 +1,62 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/electricity/state-electricity-profiles/source-disposition/data/?api_key=MOCK_API_KEY&data%5B0%5D=combined-heat-and-pwr-comm&data%5B10%5D=independent-power-producers&data%5B11%5D=indust-and-comm-gen-subtotal&data%5B12%5D=net-interstate-trade&data%5B13%5D=net-trade-index&data%5B14%5D=total-disposition&data%5B15%5D=total-elect-indust&data%5B16%5D=total-international-exports&data%5B17%5D=total-international-imports&data%5B18%5D=total-net-generation&data%5B19%5D=total-supply&data%5B1%5D=combined-heat-and-pwr-elect&data%5B20%5D=unaccounted&data%5B2%5D=combined-heat-and-pwr-indust&data%5B3%5D=direct-use&data%5B4%5D=elect-pwr-sector-gen-subtotal&data%5B5%5D=electric-utilities&data%5B6%5D=energy-only-providers&data%5B7%5D=estimated-losses&data%5B8%5D=facility-direct&data%5B9%5D=full-service-providers&end=1990&facets%5Bstate%5D%5B%5D=AK&frequency=annual&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1990 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY","frequency":"annual","data":[{"period":"1990","state":"AK","stateDescription":"Alaska","combined-heat-and-pwr-comm":"265533","combined-heat-and-pwr-elect":"0","combined-heat-and-pwr-indust":"840950","direct-use":"1106473","elect-pwr-sector-gen-subtotal":"4493024","electric-utilities":"4493024","energy-only-providers":"0","estimated-losses":"322955","facility-direct":"0","full-service-providers":"4253840","independent-power-producers":"0","indust-and-comm-gen-subtotal":"1106482","net-interstate-trade":"0","net-trade-index":"1","total-disposition":"5600415","total-elect-indust":"4253840","total-international-exports":"0","total-international-imports":"909","total-net-generation":"5599506","total-supply":"5600415","unaccounted":"5272100","combined-heat-and-pwr-comm-units":"megawatthours","combined-heat-and-pwr-elect-units":"megawatthours","combined-heat-and-pwr-indust-units":"megawatthours","direct-use-units":"megawatthours","elect-pwr-sector-gen-subtotal-units":"megawatthours","electric-utilities-units":"megawatthours","energy-only-providers-units":"megawatthours","estimated-losses-units":"megawatthours","facility-direct-units":"megawatthours","full-service-providers-units":"megawatthours","independent-power-producers-units":"megawatthours","indust-and-comm-gen-subtotal-units":"megawatthours","net-interstate-trade-units":"megawatthours","net-trade-index-units":"ratio","total-disposition-units":"megawatthours","total-elect-indust-units":"megawatthours","total-international-exports-units":"megawatthours","total-international-imports-units":"megawatthours","total-net-generation-units":"megawatthours","total-supply-units":"megawatthours","unaccounted-units":"megawatthours"}],"description":"Supply + and disposition of electricity by state.\n Sources: Forms EIA-860, EIA-861, + and EIA-923\n Product: State Electricity Profiles, Table 10"},"request":{"command":"\/v2\/electricity\/state-electricity-profiles\/source-disposition\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"annual","data":["combined-heat-and-pwr-comm","combined-heat-and-pwr-elect","combined-heat-and-pwr-indust","direct-use","elect-pwr-sector-gen-subtotal","electric-utilities","energy-only-providers","estimated-losses","facility-direct","full-service-providers","independent-power-producers","indust-and-comm-gen-subtotal","net-interstate-trade","net-trade-index","total-disposition","total-elect-indust","total-international-exports","total-international-imports","total-net-generation","total-supply","unaccounted"],"facets":{"state":["AK"]},"start":"1990","end":"1990","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:04:04 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:04:04 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '2778' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_total_energy_fetcher_urllib3_v2.yaml b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_total_energy_fetcher_urllib3_v2.yaml new file mode 100644 index 00000000000..9d37b212c63 --- /dev/null +++ b/openbb_platform/providers/eia/tests/record/http/test_eia_fetchers/test_eia_total_energy_fetcher_urllib3_v2.yaml @@ -0,0 +1,67 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api.eia.gov/v2/total-energy/data/?api_key=MOCK_API_KEY&data%5B0%5D=value&end=1973-01&facets%5Bmsn%5D%5B%5D=ARICBUS&frequency=monthly&length=5000&offset=0&sort%5B0%5D%5Bcolumn%5D=period&sort%5B0%5D%5Bdirection%5D=asc&start=1973-01 + response: + body: + string: '{"response":{"total":"1","dateFormat":"YYYY-MM","frequency":"monthly","data":[{"period":"1973-01","msn":"ARICBUS","seriesDescription":"Asphalt + and Road Oil Consumed by the Industrial Sector in Trillion Btu","value":"37.779","unit":"Trillion + Btu"}],"description":"These data represent the most recent comprehensive energy + statistics integrated across all energy sources. The data includes total + energy production, consumption, stocks, and trade; energy prices; overviews + of petroleum, natural gas, coal, electricity, nuclear energy, renewable energy, + and carbon dioxide emissions; and data unit conversions values. Source: https:\/\/www.eia.gov\/totalenergy\/data\/monthly\/pdf\/mer_a_doc.pdf Report: MER + (https:\/\/www.eia.gov\/totalenergy\/data\/monthly\/)"},"request":{"command":"\/v2\/total-energy\/data\/","params":{"api_key":"MOCK_API_KEY","frequency":"monthly","data":["value"],"facets":{"msn":["ARICBUS"]},"start":"1973-01","end":"1973-01","sort":[{"column":"period","direction":"asc"}],"offset":"0","length":"5000"}},"apiVersion":"2.1.13","ExcelAddInVersion":"2.1.0"}' + headers: + Access-Control-Allow-Headers: + - Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Params + Access-Control-Allow-Methods: + - GET,POST,PATCH,PUT,DELETE,OPTIONS + Access-Control-Allow-Origin: + - '*' + Age: + - '7' + Alt-Svc: + - h3=":443"; ma=93600 + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Type: + - application/json + Date: + - Thu, 09 Jul 2026 03:04:11 GMT + Etag: null + Expires: + - Thu, 09 Jul 2026 03:04:11 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Vary: + - Accept-Encoding + - Accept-Encoding + Via: null + X-Amz-Cf-Id: null + X-Amz-Cf-Pop: null + X-Api-Umbrella-Request-Id: null + X-Cache: null + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Vcap-Request-Id: null + content-length: + - '1107' + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/eia/tests/test_api_models.py b/openbb_platform/providers/eia/tests/test_api_models.py new file mode 100644 index 00000000000..29cacf55919 --- /dev/null +++ b/openbb_platform/providers/eia/tests/test_api_models.py @@ -0,0 +1,357 @@ +"""Tests for the EIA APIv2 dataset models and their shared fetcher pipeline.""" + +from datetime import date + +import pytest +from openbb_core.app.model.abstract.error import OpenBBError +from pydantic import ValidationError + +from openbb_us_eia import eia_provider +from openbb_us_eia.models.registry import DATASET_FETCHERS +from openbb_us_eia.utils import catalog +from openbb_us_eia.utils.api_query import EiaApiQueryParams +from openbb_us_eia.utils.catalog import DATASET_GROUPS, STANDARD_FIELDS, model_name + +API_MODELS = { + name: fetcher + for name, fetcher in eia_provider.fetcher_dict.items() + if isinstance(fetcher, type) + and issubclass(fetcher.query_params_type, EiaApiQueryParams) + and name.startswith("Eia") +} + +COAL_EXPORTS = DATASET_FETCHERS["EiaCoalExportsImportsQuantityPrice"] +COAL_PRICE_BY_RANK = DATASET_FETCHERS["EiaCoalPriceByRank"] +GRID_DEMAND = DATASET_FETCHERS["EiaElectricityGridDemand"] +COALBED_PRODUCTION = DATASET_FETCHERS["EiaNaturalGasCoalbedMethaneProduction"] + + +def dataset_facets(query_type) -> dict: + """Return the facets that apply to a model, merged for whole-group models.""" + group = query_type.__group__ + if query_type.__dataset__: + return catalog.get_dataset(group, query_type.__dataset__)["facets"] + merged: dict = {} + for spec in catalog.get_group(group)["datasets"].values(): + for facet, detail in spec["facets"].items(): + merged.setdefault(facet, detail) + return merged + + +def split_facets(facets: dict) -> tuple[set, set]: + """Split facets into real filters and fixed single-value facets.""" + filterable = { + facet: detail + for facet, detail in facets.items() + if detail.get("filterable", True) + } + fixed = { + facet + for facet, detail in filterable.items() + if len(detail.get("choices") or []) == 1 + } + return set(filterable) - fixed, fixed + + +class TestModelRegistration: + """Every catalog dataset and group is served by a registered, wired model.""" + + def test_every_dataset_has_a_fetcher(self): + for group in DATASET_GROUPS: + for dataset in catalog.dataset_choices(group): + name = model_name(group, dataset) + assert name in eia_provider.fetcher_dict + assert DATASET_FETCHERS[name] is eia_provider.fetcher_dict[name] + + def test_all_groups_covered(self): + groups = { + fetcher.query_params_type.__group__ for fetcher in API_MODELS.values() + } + assert groups == set(catalog.load_catalog()) + + @pytest.mark.parametrize("name", sorted(API_MODELS)) + def test_generics_resolve(self, name): + fetcher = API_MODELS[name] + assert issubclass(fetcher.query_params_type, EiaApiQueryParams) + assert fetcher.data_type.__name__ == f"{name}Data" + + @pytest.mark.parametrize("name", sorted(API_MODELS)) + def test_facet_fields_match_catalog(self, name): + query_type = API_MODELS[name].query_params_type + declared = set(query_type.model_fields) - STANDARD_FIELDS + filters, fixed = split_facets(dataset_facets(query_type)) + assert declared == filters + assert not declared & fixed + + @pytest.mark.parametrize("name", sorted(API_MODELS)) + def test_default_query_validates(self, name): + fetcher = API_MODELS[name] + query = fetcher.transform_query({}) + assert query.dataset_key in catalog.dataset_choices(query.__group__) + + +class TestSingleValueParametersAreNotParameters: + """A dimension with exactly one possible value is applied, never exposed.""" + + def test_single_frequency_dataset_has_no_frequency_field(self): + spec = catalog.get_dataset("coal", "price_by_rank") + assert list(spec["frequencies"]) == ["annual"] + assert "frequency" not in COAL_PRICE_BY_RANK.query_params_type.model_fields + + def test_single_column_dataset_has_no_data_type_field(self): + spec = catalog.get_dataset("coal", "price_by_rank") + assert list(spec["data_columns"]) == ["price"] + assert "data_type" not in COAL_PRICE_BY_RANK.query_params_type.__annotations__ + + def test_fixed_facet_is_not_a_query_parameter(self): + query_type = COALBED_PRODUCTION.query_params_type + _, fixed = split_facets(dataset_facets(query_type)) + assert fixed == {"process", "product"} + assert not fixed & set(query_type.model_fields) + + def test_fixed_facet_is_rejected_as_an_unknown_parameter(self): + with pytest.raises(OpenBBError, match="Unknown parameter"): + COALBED_PRODUCTION.transform_query({"product": "EPG0"}) + + @pytest.mark.asyncio + async def test_fixed_facet_still_filters_the_request(self, monkeypatch): + from openbb_core.provider.utils import helpers as core_helpers + + captured: dict = {} + + async def fake_amake_request(url, response_callback=None, **kwargs): + captured["url"] = url + return { + "response": { + "total": "1", + "dateFormat": "YYYY", + "data": [{"period": "2023", "value": "7"}], + } + } + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + rows = await COALBED_PRODUCTION.fetch_data({}, {"eia_api_key": "MOCK_KEY"}) + assert "facets%5Bprocess%5D%5B%5D=R52" in captured["url"] + assert "facets%5Bproduct%5D%5B%5D=EPG0" in captured["url"] + assert rows[0].model_dump()["value"] == 7.0 + + def test_single_frequency_still_selects_the_dataset_default(self): + spec = catalog.get_dataset("coal", "price_by_rank") + frequency, detail = catalog.resolve_frequency(spec, None) + assert frequency == "annual" + assert detail["format"] == "YYYY" + + def test_single_column_still_requests_that_column(self): + spec = catalog.get_dataset("coal", "price_by_rank") + assert catalog.resolve_data_columns(spec, None) == [ + spec["data_columns"]["price"]["id"] + ] + + +class TestTransformQueryValidation: + """The catalog validation surfaces clear errors at query time.""" + + def test_invalid_frequency_rejected_by_literal(self): + with pytest.raises(ValidationError, match="frequency"): + COAL_EXPORTS.transform_query({"frequency": "hourly"}) + + def test_invalid_data_type_raises(self): + with pytest.raises(OpenBBError, match="Invalid data_type"): + COAL_EXPORTS.transform_query({"data_type": "capacity"}) + + def test_frequency_restricted_facet_raises(self): + with pytest.raises(OpenBBError, match="only applies"): + GRID_DEMAND.transform_query({"timezone": "eastern"}) + + def test_invalid_facet_value_lists_choices(self): + with pytest.raises(OpenBBError, match="metallurgical") as excinfo: + COAL_EXPORTS.transform_query({"coal_rank": "ANTHRACITE"}) + assert "Invalid coal_rank value(s): ANTHRACITE" in str(excinfo.value) + + def test_facet_value_casing_corrected(self): + query = COAL_EXPORTS.transform_query({"coal_rank": "met"}) + assert query.coal_rank == "met" + + def test_unknown_parameter_lists_valid_filters(self): + with pytest.raises(OpenBBError, match="Unknown parameter") as excinfo: + GRID_DEMAND.transform_query({"region": "united_states_lower_48"}) + assert "respondent" in str(excinfo.value) + + +class TestSchemaIsolation: + """Per-model schema extras must not leak through the shared base class. + + The registry map walks the class family and lets a base-class field + overwrite the child's, so ``data_type`` must be declared on every concrete + model rather than on ``EiaApiQueryParams``. + """ + + def test_base_class_does_not_declare_data_type(self): + assert "data_type" not in EiaApiQueryParams.model_fields + + @pytest.mark.parametrize("name", sorted(API_MODELS)) + def test_data_type_declared_only_when_the_dataset_has_a_choice(self, name): + query_type = API_MODELS[name].query_params_type + dataset = ( + query_type.__dataset__ or catalog.dataset_choices(query_type.__group__)[-1] + ) + columns = catalog.get_dataset(query_type.__group__, dataset)["data_columns"] + declared = "data_type" in query_type.__annotations__ + if query_type.__dataset__: + assert declared is (len(columns) > 1) + + def test_data_type_choices_are_model_specific(self): + nuclear = DATASET_FETCHERS["EiaNuclearOutagesUsNuclearOutages"] + coal_choices = COAL_EXPORTS.query_params_type.__json_schema_extra__[ + "data_type" + ]["choices"] + nuclear_choices = nuclear.query_params_type.__json_schema_extra__["data_type"][ + "choices" + ] + assert coal_choices == ["price", "quantity"] + assert nuclear_choices == ["capacity", "outage", "percent_outage"] + + +SAMPLE_PERIODS = { + "YYYY": "2024", + "YYYY-MM": "2024-01", + 'YYYY-"Q"Q': "2024-Q1", + "YYYY-MM-DD": "2024-01-05", + 'YYYY-MM-DD"T"HH24': "2024-01-05T00", + 'YYYY-MM-DD"T"HH24TZH': "2024-01-05T00-05", +} + + +class TestEveryModelPipeline: + """Every generated model runs its full TET pipeline over a stubbed page.""" + + @pytest.mark.asyncio + @pytest.mark.parametrize("name", sorted(API_MODELS)) + async def test_fetch_data_round_trip(self, name, monkeypatch): + from openbb_core.provider.utils import helpers as core_helpers + + fetcher = API_MODELS[name] + query_type = fetcher.query_params_type + group = query_type.__group__ + dataset = query_type.__dataset__ or catalog.dataset_choices(group)[-1] + spec = catalog.get_dataset(group, dataset) + _, freq_spec = catalog.resolve_frequency(spec, None) + period = SAMPLE_PERIODS[freq_spec["format"]] + row: dict = {"period": period} + for detail in spec["facets"].values(): + row[detail["id"]] = "X" + for detail in spec["data_columns"].values(): + row[detail["id"]] = "1.5" if detail.get("numeric", True) else "text" + + async def fake_amake_request(url, response_callback=None, **kwargs): + return { + "response": { + "total": "1", + "dateFormat": freq_spec["format"], + "data": [row], + } + } + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + rows = await fetcher.fetch_data({}, {"eia_api_key": "MOCK_KEY"}) + assert len(rows) == 1 + record = rows[0].model_dump(exclude_none=True) + for column, detail in spec["data_columns"].items(): + assert record[column] == (1.5 if detail.get("numeric", True) else "text") + + +class TestFetcherPipeline: + """The shared fetcher pipeline over stubbed HTTP responses.""" + + @pytest.mark.asyncio + async def test_fetch_data_end_to_end(self, monkeypatch): + from openbb_core.provider.utils import helpers as core_helpers + + captured: dict = {} + + async def fake_amake_request(url, response_callback=None, **kwargs): + captured["url"] = url + return { + "response": { + "total": "2", + "dateFormat": 'YYYY-"Q"Q', + "data": [ + { + "period": "2023-Q2", + "coalRankId": "MET", + "quantity": "10", + "price": "1.5", + }, + { + "period": "2023-Q1", + "coalRankId": "MET", + "quantity": "20", + "price": "2.5", + }, + ], + } + } + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + rows = await COAL_EXPORTS.fetch_data( + { + "frequency": "quarterly", + "coal_rank": "MET", + "start_date": date(2023, 1, 1), + "end_date": date(2023, 6, 30), + }, + {"eia_api_key": "MOCK_KEY"}, + ) + assert "facets%5BcoalRankId%5D%5B%5D=MET" in captured["url"] + assert "start=2023-Q1" in captured["url"] + assert "end=2023-Q2" in captured["url"] + assert [row.date for row in rows] == [date(2023, 1, 1), date(2023, 4, 1)] + assert rows[0].model_dump()["quantity"] == 20.0 + + @pytest.mark.asyncio + async def test_grid_daily_frequency_routes_to_daily_path(self, monkeypatch): + from openbb_core.provider.utils import helpers as core_helpers + + captured: dict = {} + + async def fake_amake_request(url, response_callback=None, **kwargs): + captured["url"] = url + return { + "response": { + "total": "1", + "dateFormat": "YYYY-MM-DD", + "data": [{"period": "2025-06-01", "value": "42"}], + } + } + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + rows = await GRID_DEMAND.fetch_data( + {"frequency": "daily", "timezone": "eastern"}, + {"eia_api_key": "MOCK_KEY"}, + ) + assert "/electricity/rto/daily-region-data/data/" in captured["url"] + assert rows[0].model_dump()["value"] == 42.0 + + @pytest.mark.asyncio + async def test_desc_sort_and_limit_applied(self, monkeypatch): + from openbb_core.provider.utils import helpers as core_helpers + + async def fake_amake_request(url, response_callback=None, **kwargs): + return { + "response": { + "total": "3", + "dateFormat": "YYYY", + "data": [ + {"period": "2022", "price": "3"}, + {"period": "2021", "price": "2"}, + {"period": "2020", "price": "1"}, + ], + } + } + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + rows = await COAL_PRICE_BY_RANK.fetch_data( + {"sort": "desc", "limit": 2}, + {"eia_api_key": "MOCK_KEY"}, + ) + assert [row.date.year for row in rows] == [2022, 2021] diff --git a/openbb_platform/providers/eia/tests/test_api_query.py b/openbb_platform/providers/eia/tests/test_api_query.py new file mode 100644 index 00000000000..caa57c4a9f2 --- /dev/null +++ b/openbb_platform/providers/eia/tests/test_api_query.py @@ -0,0 +1,382 @@ +"""Tests for the shared EIA APIv2 query, pagination, and transform machinery.""" + +from datetime import date +from urllib.parse import parse_qs, urlparse + +import pytest +from openbb_core.app.model.abstract.error import OpenBBError +from openbb_core.provider.utils.errors import EmptyDataError + +from openbb_us_eia.models.crude_oil_imports import EiaCrudeOilImportsQueryParams +from openbb_us_eia.models.ieo import EiaIeoQueryParams +from openbb_us_eia.models.registry import DATASET_FETCHERS +from openbb_us_eia.utils import catalog +from openbb_us_eia.utils.api_query import ( + MAX_AUTO_ROWS, + empty_result_message, + maybe_float, + paginate, + to_float, + transform_rows, +) +from openbb_us_eia.utils.helpers import build_data_url + +CoalReceiptsQueryParams = DATASET_FETCHERS["EiaCoalReceipts"].query_params_type + + +class TestQueryParamProperties: + """Dataset resolution and facet collection on the base query params.""" + + def test_dataset_key_from_dataset_class_attribute(self): + query = CoalReceiptsQueryParams() + assert query.dataset_key == "receipts" + + def test_dataset_key_from_release_field(self): + query = EiaIeoQueryParams(release="2021") + assert query.dataset_key == "2021" + + def test_dataset_key_single_dataset_group(self): + query = EiaCrudeOilImportsQueryParams() + assert query.dataset_key == "crude_oil_imports" + + def test_dataset_key_falls_back_to_first_of_group(self): + from openbb_us_eia.utils.api_query import EiaApiQueryParams + + class BareSedsQuery(EiaApiQueryParams): + """Synthetic query with neither __dataset__ nor a release field.""" + + __group__ = "seds" + + assert BareSedsQuery().dataset_key == "seds" + + def test_facet_values_exclude_standard_fields(self): + query = CoalReceiptsQueryParams(coal_rank="MET", limit=10, sort="desc") + facets = query.facet_values + assert facets["coal_rank"] == "MET" + assert "limit" not in facets + assert "sort" not in facets + assert "dataset" not in facets + + +class TestBuildDataUrl: + """URL rendering for one page of an EIA data request.""" + + def test_full_request(self): + request = { + "path": "coal/receipts", + "api_key": "KEY", + "frequency": "quarterly", + "data_columns": ["quantity", "price"], + "facets": {"coalRankId": ["MET", "STM"]}, + "start": "2020-Q1", + "end": "2021-Q4", + "sort": "asc", + } + url = build_data_url(request, offset=5000, length=2500) + parsed = urlparse(url) + assert parsed.path == "/v2/coal/receipts/data/" + params = parse_qs(parsed.query) + assert params["api_key"] == ["KEY"] + assert params["frequency"] == ["quarterly"] + assert params["data[0]"] == ["quantity"] + assert params["data[1]"] == ["price"] + assert params["facets[coalRankId][]"] == ["MET", "STM"] + assert params["start"] == ["2020-Q1"] + assert params["end"] == ["2021-Q4"] + assert params["sort[0][column]"] == ["period"] + assert params["sort[0][direction]"] == ["asc"] + assert params["offset"] == ["5000"] + assert params["length"] == ["2500"] + + def test_optional_parts_omitted(self): + request = {"path": "steo", "api_key": "KEY"} + params = parse_qs(urlparse(build_data_url(request, 0, 5000)).query) + assert "frequency" not in params + assert "start" not in params + assert "end" not in params + assert params["sort[0][direction]"] == ["desc"] + + +def _page(rows, total, date_format="YYYY"): + return {"response": {"data": rows, "total": str(total), "dateFormat": date_format}} + + +def _stub_http(pages): + """Build amake_request/amake_requests stubs serving canned pages by offset.""" + calls = {"urls": []} + + async def amake_request(url, response_callback=None, **kwargs): + calls["urls"].append(url) + offset = int(parse_qs(urlparse(url).query)["offset"][0]) + return pages[offset] + + async def amake_requests(urls, response_callback=None, **kwargs): + calls["urls"].extend(urls) + return [pages[int(parse_qs(urlparse(url).query)["offset"][0])] for url in urls] + + return amake_request, amake_requests, calls + + +async def _noop_callback(response, session): + return {} + + +class TestPaginate: + """Automatic pagination against the response total.""" + + @pytest.mark.asyncio + async def test_single_page(self): + rows = [{"period": "2020", "value": "1"}] + amake_request, amake_requests, calls = _stub_http({0: _page(rows, 1)}) + result = await paginate( + build_data_url, + {"path": "seds", "api_key": "K"}, + limit=None, + amake_request=amake_request, + amake_requests=amake_requests, + response_callback=_noop_callback, + ) + assert result["rows"] == rows + assert result["total"] == 1 + assert result["date_format"] == "YYYY" + assert len(calls["urls"]) == 1 + + @pytest.mark.asyncio + async def test_multiple_pages(self): + pages = { + 0: _page([{"period": str(y)} for y in range(5000)], 12000), + 5000: _page([{"period": str(y)} for y in range(5000)], 12000), + 10000: _page([{"period": str(y)} for y in range(2000)], 12000), + } + amake_request, amake_requests, calls = _stub_http(pages) + result = await paginate( + build_data_url, + {"path": "seds", "api_key": "K"}, + limit=None, + amake_request=amake_request, + amake_requests=amake_requests, + response_callback=_noop_callback, + ) + assert len(result["rows"]) == 12000 + assert len(calls["urls"]) == 3 + + @pytest.mark.asyncio + async def test_limit_caps_requests_and_rows(self): + pages = { + 0: _page([{"period": str(y)} for y in range(5000)], 50000), + 5000: _page([{"period": str(y)} for y in range(2000)], 50000), + } + amake_request, amake_requests, calls = _stub_http(pages) + result = await paginate( + build_data_url, + {"path": "seds", "api_key": "K"}, + limit=7000, + amake_request=amake_request, + amake_requests=amake_requests, + response_callback=_noop_callback, + ) + assert len(result["rows"]) == 7000 + assert len(calls["urls"]) == 2 + last = parse_qs(urlparse(calls["urls"][-1]).query) + assert last["length"] == ["2000"] + + @pytest.mark.asyncio + async def test_empty_response_raises(self): + amake_request, amake_requests, _ = _stub_http({0: _page([], 0)}) + with pytest.raises(EmptyDataError): + await paginate( + build_data_url, + {"path": "seds", "api_key": "K"}, + limit=None, + amake_request=amake_request, + amake_requests=amake_requests, + response_callback=_noop_callback, + ) + + @pytest.mark.asyncio + async def test_auto_ceiling_raises_without_limit(self): + pages = {0: _page([{"period": "2020"}] * 5000, MAX_AUTO_ROWS + 1)} + amake_request, amake_requests, _ = _stub_http(pages) + with pytest.raises(OpenBBError, match="pagination ceiling"): + await paginate( + build_data_url, + {"path": "seds", "api_key": "K"}, + limit=None, + amake_request=amake_request, + amake_requests=amake_requests, + response_callback=_noop_callback, + ) + + @pytest.mark.asyncio + async def test_explicit_limit_bypasses_ceiling(self): + pages = {0: _page([{"period": "2020"}] * 100, MAX_AUTO_ROWS + 1)} + amake_request, amake_requests, _ = _stub_http(pages) + result = await paginate( + build_data_url, + {"path": "seds", "api_key": "K"}, + limit=100, + amake_request=amake_request, + amake_requests=amake_requests, + response_callback=_noop_callback, + ) + assert len(result["rows"]) == 100 + + +class TestEmptyResultMessage: + """Empty results are explained against the live facet vocabularies.""" + + @staticmethod + def _facet_server(vocabularies): + async def amake_request(url, response_callback=None, **kwargs): + facet_id = url.split("/facet/")[1].split("?")[0] + if vocabularies.get(facet_id) is None: + raise ValueError("facet endpoint unavailable") + return { + "response": { + "facets": [ + {"id": value, "name": label} + for value, label in vocabularies[facet_id].items() + ] + } + } + + return amake_request + + @pytest.mark.asyncio + async def test_invalid_value_lists_valid_choices(self): + request = { + "path": "petroleum/pri/spt", + "api_key": "K", + "facets": {"series": ["RWTC"], "process": ["VAM"]}, + "facet_params": {"series": "series", "process": "process"}, + } + amake_request = self._facet_server( + { + "series": {"RWTC": "Cushing, OK WTI Spot Price FOB"}, + "process": {"PF4": "Spot Price FOB"}, + } + ) + message = await empty_result_message(request, amake_request, _noop_callback) + assert "process: VAM is not valid for this dataset" in message + assert "PF4 = Spot Price FOB" in message + + @pytest.mark.asyncio + async def test_valid_combination_explains_no_intersection(self): + request = { + "path": "petroleum/pri/spt", + "api_key": "K", + "facets": {"duoarea": ["NUS"], "series": ["RWTC"]}, + "facet_params": {"duoarea": "region", "series": "series"}, + "coverage": ("1986-01-02", "2026-06-30"), + "start": "2026-01-01", + } + amake_request = self._facet_server( + { + "duoarea": {"NUS": "U.S."}, + "series": {"RWTC": "Cushing, OK WTI Spot Price FOB"}, + } + ) + message = await empty_result_message(request, amake_request, _noop_callback) + assert "combination does not match" in message + assert "region: NUS (U.S.)" in message + assert "series: RWTC (Cushing, OK WTI Spot Price FOB)" in message + assert "The dataset covers 1986-01-02 to 2026-06-30" in message + + @pytest.mark.asyncio + async def test_facet_endpoint_failure_falls_back_to_codes(self): + request = { + "path": "petroleum/pri/spt", + "api_key": "K", + "facets": {"series": ["RWTC"]}, + "facet_params": {"series": "series"}, + } + amake_request = self._facet_server({"series": None}) + message = await empty_result_message(request, amake_request, _noop_callback) + assert "series: RWTC" in message + + @pytest.mark.asyncio + async def test_no_facets_reports_date_range(self): + request = { + "path": "seds", + "api_key": "K", + "facets": {}, + "coverage": ("1960", "2023"), + "start": "2030", + "end": "2031", + } + message = await empty_result_message(request, None, _noop_callback) + assert message.startswith("The request returned no data.") + assert "Requested period: 2030 to 2031" in message + assert "The dataset covers 1960 to 2023" in message + + +class TestTransformRows: + """Row normalization for catalog datasets.""" + + def test_facet_and_data_column_renames(self): + spec = catalog.get_dataset("coal", "exports_imports_quantity_price") + rows = [ + { + "period": "2023-Q1", + "exportImportType": "Exports", + "coalRankId": "MET", + "coalRankDescription": "Metallurgical", + "countryId": "CA", + "countryDescription": "Canada", + "quantity": "100.5", + "price": "not-a-number", + "quantity-units": "short tons", + } + ] + out = transform_rows(spec, rows, 'YYYY-"Q"Q') + record = out[0] + assert record["date"] == date(2023, 1, 1) + assert record["export_import_type"] == "Exports" + assert record["coal_rank"] == "MET" + assert record["coal_rank_name"] == "Metallurgical" + assert record["country_name"] == "Canada" + assert record["quantity"] == 100.5 + assert record["price"] is None + assert "quantity_units" not in record + + def test_unknown_columns_snake_cased(self): + spec = catalog.get_dataset("seds", "seds") + rows = [ + { + "period": "2020", + "seriesId": "TETPB", + "seriesDescription": "Total energy", + "stateId": "TX", + "stateDescription": "Texas", + "value": "285.1", + "unit": "million Btu", + "surpriseColumn": "x", + } + ] + record = transform_rows(spec, rows, "YYYY")[0] + assert record["series"] == "TETPB" + assert record["series_name"] == "Total energy" + assert record["state"] == "TX" + assert record["state_name"] == "Texas" + assert record["value"] == 285.1 + assert record["surprise_column"] == "x" + + +class TestNumericCasting: + """Numeric columns are floats; withheld flags become null.""" + + def test_to_float_casts_numeric_strings(self): + assert to_float("1.5") == 1.5 + + def test_to_float_nulls_withheld_flags(self): + assert to_float("W") is None + assert to_float("NA") is None + + def test_to_float_passes_numbers_and_none(self): + assert to_float(None) is None + assert to_float(2) == 2 + + def test_maybe_float_for_raw_browser_columns(self): + assert maybe_float("1.5") == 1.5 + assert maybe_float("W") == "W" + assert maybe_float(None) is None diff --git a/openbb_platform/providers/eia/tests/test_browsers.py b/openbb_platform/providers/eia/tests/test_browsers.py new file mode 100644 index 00000000000..14c23f88a27 --- /dev/null +++ b/openbb_platform/providers/eia/tests/test_browsers.py @@ -0,0 +1,2784 @@ +"""Tests for the EIA data-browser widgets and reverse proxy.""" + +import json +import shutil +import subprocess +import tempfile +from pathlib import Path + +import pytest +from fastapi import Request + +from openbb_us_eia import browsers + +MAPS_HTML = """ +<ul> + <li><label for="maps-eia-tab-1"><b>Recent</b> maps</label></li> + <li><label for="maps-eia-tab-2">Historical maps</label></li> +</ul> +<div class="tab-content"> +<h1>Lower 48</h1> +<h2 class="list-header">Overview & boundaries</h2> +<a href="/maps/images/shale_2023.pdf" title="Shale plays, Lower 48 States (12/13/2023)(pdf)">PDF</a> +<a href="/maps/images/shale_2023.jpg" title="Shale plays, Lower 48 States (12/13/2023)(jpg)">JPG</a> +<a href="/maps/images/tight_gas.pdf" title="Major tight gas plays(pdf)">PDF</a> +</div> +<div class="tab-content"> +<h2>Historical basins</h2> +<a href="/maps/images/old_map.jpg" title="Historic basin map (6/1/2011)(jpg)">JPG</a> +<a href="/maps/data.zip" title="Ignored (1/1/2011)(zip)">ZIP</a> +<a href="/maps/images/field_maps/app_boe.pdf" title="Historical basins: Western Area BOE (pdf)">BOE</a> +</div> +""" + +PROXY_PREFIX = "/api/v1/eia_proxy" +INTERNATIONAL = browsers.EIA_DATA_BROWSERS["international"]["path"] +IMPORTS = browsers.EIA_DATA_BROWSERS["petroleum_imports"]["path"] +ELECTRICITY = browsers.EIA_DATA_BROWSERS["electricity"]["path"] + + +def make_info(path, query="", method="GET", body=b"", referer="", user=""): + """Build the request_info mapping the proxy endpoints consume.""" + return { + "url": f"http://test{path}", + "query": query, + "path": path, + "method": method, + "body": body, + "content_type": "application/x-www-form-urlencoded" if body else "", + "referer": referer, + "user": user, + } + + +@pytest.fixture(autouse=True) +def isolate_state(monkeypatch, tmp_path): + """Keep every test off the shared caches, disk, and view stores.""" + monkeypatch.setattr( + "openbb_core.app.utils.get_user_cache_directory", + lambda: str(tmp_path / "cache"), + ) + monkeypatch.setattr(browsers, "_MAPS_CATALOG", None) + stores = ( + browsers._PROXY_CACHE, + browsers._REDIRECTS, + browsers._REWRITE_CACHE, + browsers._TABLE_ROWS, + browsers._LAST_DATA, + browsers._VIEW_DATA, + browsers._CURRENT_VIEW, + browsers._WIDGET_STATE, + browsers._INTL_LABELS, + browsers._IMPORTS_LABELS, + ) + for store in stores: + store.clear() + yield + for store in stores: + store.clear() + + +class FakeUpstream: + """Stand in for eia.gov at the one place the code touches the network.""" + + def __init__(self, responses): + self.responses = responses + self.calls = [] + + def __call__(self, target): + self.calls.append(target) + result = self.responses[target] + if isinstance(result, BaseException): + raise result + body, content_type = result[0], result[1] + status = result[2] if len(result) > 2 else 200 + landed = result[3] if len(result) > 3 else target + return body, content_type, status, landed + + def install(self, monkeypatch): + monkeypatch.setattr(browsers, "_fetch_sync", self) + return self + + +class TestRequestInfo: + """The proxy reads deepcopy-safe primitives off the request.""" + + @pytest.mark.asyncio + async def test_extracts_url_query_path_and_method(self): + request = Request( + scope={ + "type": "http", + "method": "GET", + "scheme": "http", + "server": ("test", 80), + "path": "/api/v1/eia_proxy/coal/", + "query_string": b"a=1", + "headers": [(b"x-openbb-user", b"analyst@example.com")], + } + ) + info = await browsers.request_info(request) + assert info["url"] == "http://test/api/v1/eia_proxy/coal/" + assert info["query"] == "a=1" + assert info["path"] == "/api/v1/eia_proxy/coal/" + assert info["method"] == "GET" + assert "analyst@example.com" not in json.dumps(info, default=str) + + @pytest.mark.asyncio + async def test_the_user_is_stashed_as_an_opaque_key(self): + def info_for(headers): + return browsers.request_info( + Request( + scope={ + "type": "http", + "method": "GET", + "scheme": "http", + "server": ("test", 80), + "path": "/api/v1/coal_browser", + "query_string": b"", + "headers": headers, + } + ) + ) + + alice = (await info_for([(b"x-openbb-user", b"alice@x.com")]))["user"] + bob = (await info_for([(b"x-openbb-user", b"bob@x.com")]))["user"] + assert alice and bob and alice != bob + assert "alice@x.com" not in alice + assert (await info_for([]))["user"] == "" + + @pytest.mark.asyncio + async def test_post_body_is_read(self): + async def receive(): + return {"type": "http.request", "body": b"a=1", "more_body": False} + + request = Request( + scope={ + "type": "http", + "method": "POST", + "scheme": "http", + "server": ("test", 80), + "path": "/api/v1/eia_proxy/x", + "query_string": b"", + "headers": [(b"content-type", b"application/json")], + }, + receive=receive, + ) + info = await browsers.request_info(request) + assert info["method"] == "POST" + assert info["body"] == b"a=1" + assert info["content_type"] == "application/json" + + @pytest.mark.asyncio + async def test_unreadable_post_body_is_empty(self): + async def receive(): + raise RuntimeError("disconnected") + + request = Request( + scope={ + "type": "http", + "method": "POST", + "scheme": "http", + "server": ("test", 80), + "path": "/api/v1/eia_proxy/x", + "query_string": b"", + "headers": [], + }, + receive=receive, + ) + assert (await browsers.request_info(request))["body"] == b"" + + +class TestSplitWidgetParams: + """Widget markers are consumed by the proxy, never forwarded upstream.""" + + def test_splits_markers_and_keeps_the_rest(self): + query = ( + f"obb_theme=dark&obb_browser={INTERNATIONAL}&obb_user=abc123" + "&obb_view=international%2Fdata&obb_seq=1700&frequency=A&pid=44" + ) + rest, dark, browser, view, seq, user = browsers._split_widget_params(query) + assert rest == "frequency=A&pid=44" + assert dark is True + assert browser == INTERNATIONAL + assert view == "international/data" + assert seq == 1700.0 + assert user == "abc123" + + def test_light_theme_and_unknown_browser_are_dropped(self): + rest, dark, browser, view, seq, user = browsers._split_widget_params( + "obb_theme=light&obb_browser=bogus" + ) + assert rest == "" + assert dark is False + assert browser == "" + assert view == "" + assert seq == 0.0 + assert user == "" + + def test_a_malformed_sequence_is_ignored(self): + assert browsers._split_widget_params("obb_seq=nope")[4] == 0.0 + + +class TestDeriveBrowser: + """Angular SPAs issue untagged requests, so the path must identify the app.""" + + def test_maps_app_root_to_browser(self): + assert browsers._derive_browser("international/api/data/data") == INTERNATIONAL + assert ( + browsers._derive_browser("states/api/x") + == (browsers.EIA_DATA_BROWSERS["states"]["path"]) + ) + + def test_outlooks_keeps_two_segments(self): + assert browsers._app_root("outlooks/steo/data/browser/") == "outlooks/steo/" + + def test_unknown_path_has_no_browser(self): + assert browsers._derive_browser("nowhere/x") == "" + + +class TestIsDataResponse: + """Only a view's table payload counts as its data.""" + + @pytest.mark.parametrize( + "target", + [ + "https://www.eia.gov/international/api/data/data?x=1", + "https://www.eia.gov/international/api/ranking/latestWorldTop", + "https://www.eia.gov/coal/data/browser/data/index.php?x=1", + ], + ) + def test_table_payloads_are_data(self, target): + assert browsers.is_data_response(target, "application/json") is True + + @pytest.mark.parametrize( + "target", + [ + "https://www.eia.gov/international/api/articles/getLatestArticles", + "https://www.eia.gov/international/api/countries/data", + "https://www.eia.gov/states/api/Projects/States/Json/geo.json", + "https://www.eia.gov/global/x.json", + "https://www.eia.gov/coal/data/browser/?method=getConfig", + ], + ) + def test_config_and_chrome_payloads_are_not_data(self, target): + assert browsers.is_data_response(target, "application/json") is False + + def test_non_json_is_never_data(self): + assert browsers.is_data_response("https://www.eia.gov/x", "text/html") is False + + def test_ngqs_report_config_and_report_table_are_distinguished(self): + base = "https://www.eia.gov/naturalgas/ngqs/data/report" + assert browsers.is_data_response(base, "application/json") is False + assert browsers.is_data_response(f"{base}/1", "application/json") is True + + +class TestRenderedTable: + """``raw`` serves the table the page has rendered -- the current view itself.""" + + ROWS = [ + {"category": "All grades", "2024": None}, + {"category": "World", "2024": None}, + {"category": "Total U.S.", "2024": 2410516.0}, + ] + + @pytest.mark.asyncio + async def test_the_page_publishes_its_table(self): + info = make_info( + "/api/v1/eia_table", + query=f"obb_browser={IMPORTS}&obb_seq=2000", + method="POST", + body=json.dumps(self.ROWS).encode(), + ) + response = await browsers.eia_table(info) + assert response.status_code == 204 + assert browsers.get_table_rows(IMPORTS) == self.ROWS + + @pytest.mark.asyncio + async def test_raw_serves_the_rendered_table_verbatim(self, monkeypatch): + browsers.set_table_rows(IMPORTS, self.ROWS, 2000) + spec = browsers.EIA_DATA_BROWSERS["petroleum_imports"] + assert await browsers.raw_table("petroleum_imports", spec) == self.ROWS + + @pytest.mark.asyncio + async def test_imports_raw_prefers_the_hierarchical_payload(self, monkeypatch): + spec = browsers.EIA_DATA_BROWSERS["petroleum_imports"] + target = f"{browsers._EIA_ORIGIN}/petroleum/imports/browser/data/index.php?x=1" + payload = { + "TABLE_DATA": [ + { + "seriesID": "PET_IMPORTS.WORLD-RP_3-LSO.A", + "data": {"2009": 100, "2011": 300, "2010": 200}, + } + ] + } + FakeUpstream( + { + f"{browsers._EIA_ORIGIN}/{browsers._IMPORTS_CONFIG}": ( + json.dumps(IMPORTS_CONFIG).encode(), + "application/json", + ), + target: (json.dumps(payload).encode(), "application/json"), + } + ).install(monkeypatch) + browsers._IMPORTS_LABELS.clear() + browsers.set_table_rows(IMPORTS, [{"category": "Texas", "2009 ": 1}], 2000) + browsers.set_current_view(spec["path"], "imports/view") + browsers.set_data_target( + spec["path"], "imports/view", {"url": target, "method": "GET"} + ) + rows = await browsers.raw_table("petroleum_imports", spec) + assert rows[0]["category"] == ( + "Imports of Light Sour from World to PADD3 (Gulf Coast), annual" + ) + assert rows[0]["origin"] == "World" + assert rows[0]["destination"] == "PADD3 (Gulf Coast)" + assert rows[0]["grade"] == "Light Sour" + assert list(rows[0])[-3:] == ["2009 ", "2010 ", "2011 "] + browsers._IMPORTS_LABELS.clear() + + @pytest.mark.asyncio + async def test_a_later_table_replaces_an_earlier_one(self): + browsers.set_table_rows(IMPORTS, self.ROWS, 2000) + newer = [{"category": "Light Sweet", "2024": 7.0}] + browsers.set_table_rows(IMPORTS, newer, 3000) + assert browsers.get_table_rows(IMPORTS) == newer + + @pytest.mark.asyncio + async def test_a_table_from_a_view_the_user_left_is_ignored(self): + browsers.set_table_rows(IMPORTS, self.ROWS, 3000) + stale = [{"category": "STALE", "2024": 1.0}] + browsers.set_table_rows(IMPORTS, stale, 1000) + assert browsers.get_table_rows(IMPORTS) == self.ROWS + + @pytest.mark.asyncio + async def test_an_unknown_browser_publishes_nothing(self): + await browsers.eia_table( + make_info( + "/api/v1/eia_table", + query="obb_browser=bogus", + method="POST", + body=json.dumps(self.ROWS).encode(), + ) + ) + assert not browsers._TABLE_ROWS + + @pytest.mark.asyncio + async def test_a_malformed_body_publishes_nothing(self): + for body in (b"not json", b"[]", b'["junk"]', b'{"a":1}'): + await browsers.eia_table( + make_info( + "/api/v1/eia_table", + query=f"obb_browser={IMPORTS}", + method="POST", + body=body, + ) + ) + assert not browsers._TABLE_ROWS + + def test_the_extractor_is_injected_into_the_page(self): + page = browsers.rewrite_html("<head></head>", PROXY_PREFIX, browser=IMPORTS) + assert browsers._table_bridge_js(IMPORTS) in page + assert "eia:table" in page + assert "/eia_table" in page + assert "forEachNodeAfterFilterAndSort" in page + + def test_the_extractor_is_not_injected_without_a_browser(self): + page = browsers.rewrite_html("<head></head>", PROXY_PREFIX) + assert "eia:table" not in page + + @pytest.mark.asyncio + async def test_raw_does_not_fall_back_to_the_default_view(self, monkeypatch): + spec = browsers.EIA_DATA_BROWSERS["electricity"] + browsers.set_table_rows(ELECTRICITY, self.ROWS, 2000) + + def unused(_target): + raise AssertionError("raw must not re-fetch when a table was published") + + monkeypatch.setattr(browsers, "_fetch_sync", unused) + assert await browsers.raw_table("electricity", spec) == self.ROWS + + +NODE = shutil.which("node") or "/usr/local/bin/node" + +HARNESS = """ +var posted = null, sent = null; +var listeners = {}; +global.window = global; +global.location = { pathname: "/api/v1/eia_proxy/electricity/data/browser/", + search: "", hash: "", origin: "http://test" }; +global.document = { + documentElement: {}, + querySelectorAll: function () { return []; }, +}; +global.MutationObserver = function () { return { observe: function () {} }; }; +global.fetch = function (url, init) { + sent = { + url: url, + body: init && init.body, + keepalive: !!(init && init.keepalive), + }; + return { catch: function () {} }; +}; +window.parent = { postMessage: function (msg) { posted = msg; } }; +window.addEventListener = function (name, fn) { listeners[name] = fn; }; + +__BRIDGE__ + +__GRID__ + +setTimeout(function () { + process.stdout.write(JSON.stringify({ posted: posted, sent: sent }), function () { + process.exit(0); + }); +}, 1600); +""" + +XHR_TAG_HARNESS = """ +var beacon = null; +global.window = global; +global.location = { + pathname: "/api/v1/eia_proxy/totalenergy/data/browser/", + search: "__SEARCH__", hash: "#/?f=M", origin: "http://test", + href: "http://test/api/v1/eia_proxy/totalenergy/data/browser/", +}; +global.document = { baseURI: location.href }; +var store = __STORE__; +global.sessionStorage = { + getItem: function (k) { return k in store ? store[k] : null; }, + setItem: function (k, v) { store[k] = v; }, +}; +try { global.navigator = { sendBeacon: function (u) { beacon = u; return true; } }; } +catch (e) { /* node ships a read-only navigator; the beacon falls back to fetch */ } +global.history = { pushState: function () {}, replaceState: function () {} }; +global.XMLHttpRequest = function () {}; +global.XMLHttpRequest.prototype = { open: function () {} }; +global.fetch = function (url) { + if (typeof url === "string" && url.indexOf("/eia_view") >= 0) beacon = url; + return { catch: function () {} }; +}; +window.addEventListener = function () {}; + +__SCRIPT__ + +process.stdout.write(JSON.stringify({ beacon: beacon, store: store })); +""" + + +@pytest.mark.skipif(not Path(NODE).exists(), reason="node is not installed") +class TestProxyRequestTagger: + """The tagger keeps every proxied request bound to its user across reloads.""" + + def run(self, search, store): + script = ( + browsers._xhr_tag_js("totalenergy/data/browser/", "") + .replace("<script>", "") + .replace("</script>", "") + ) + source = ( + XHR_TAG_HARNESS.replace("__SEARCH__", search) + .replace("__STORE__", json.dumps(store)) + .replace("__SCRIPT__", script) + ) + result = subprocess.run( # noqa: S603 + [NODE, "-e", source], + capture_output=True, + text=True, + timeout=30, + check=True, + ) + return json.loads(result.stdout) + + def test_the_user_key_is_persisted_on_the_first_load(self): + out = self.run("?obb_theme=dark&obb_user=HASH123", {}) + assert out["store"]["obb_user"] == "HASH123" + assert "obb_user=HASH123" in out["beacon"] + + def test_the_user_key_survives_a_query_clobbering_navigation(self): + out = self.run("?tbl=T09.05", {"obb_user": "HASH123"}) + assert "obb_user=HASH123" in out["beacon"] + + +@pytest.mark.skipif(not Path(NODE).exists(), reason="node is not installed") +class TestHostRestore: + """The host rebuilds the iframe src from the saved nav, per browser.""" + + def run(self, browser, src, nav): + html = browsers._TEMPLATE.read_text(encoding="utf-8") + funcs = html[html.index("var storeKey") : html.index("function reportView")] + data = {"browser": browser, "user": "U9", "src": src} + store = {f"eia:view:{browser}:U9": json.dumps(nav)} + source = ( + "global.window = global;\n" + f"var _store = {json.dumps(store)};\n" + "global.localStorage = { getItem: function (k) { return _store[k] || null; }," + " setItem: function () {}, removeItem: function () {} };\n" + f"var DATA = {json.dumps(data)};\n" + f"{funcs}\n" + "process.stdout.write(restoredSrc());" + ) + return subprocess.run( # noqa: S603 + [NODE, "-e", source], + capture_output=True, + text=True, + timeout=30, + check=True, + ).stdout + + def test_mer_restores_the_full_state_including_the_range(self): + out = self.run( + "total_energy", + "http://h/api/v1/eia_proxy/totalenergy/data/browser/?obb_theme=dark&obb_user=U9", + { + "pathname": "/api/v1/eia_proxy/totalenergy/data/browser/", + "search": "?tbl=T09.01", + "hash": "#/?f=M&start=201506&end=202604&charted=1-2", + }, + ) + assert out.endswith( + "/totalenergy/data/browser/?obb_theme=dark&obb_user=U9&tbl=T09.01" + "#/?f=M&start=201506&end=202604&charted=1-2" + ) + + def test_other_browsers_restore_the_full_hash(self): + out = self.run( + "electricity", + "http://h/api/v1/eia_proxy/electricity/data/browser/?obb_theme=dark&obb_user=U9", + { + "pathname": "/api/v1/eia_proxy/electricity/data/browser/", + "search": "", + "hash": "#/topic/0?agg=2,0,1&fuel=vtvv", + }, + ) + assert out.endswith("#/topic/0?agg=2,0,1&fuel=vtvv") + + def test_the_frame_is_nudged_to_repaint_the_grid(self): + html = browsers._TEMPLATE.read_text(encoding="utf-8") + nudge = html[html.index("function nudge()") : html.index("function ready()")] + source = ( + "var dispatched = [];\n" + "global.Event = function (t) { this.type = t; };\n" + "var frame = { contentWindow: { dispatchEvent: function (e) {" + " dispatched.push(e.type); } } };\n" + "global.setTimeout = function (fn) { fn(); };\n" + f"{nudge}\n" + "nudge();\n" + "process.stdout.write(JSON.stringify({ dispatched: dispatched }));" + ) + out = json.loads( + subprocess.run( # noqa: S603 + [NODE, "-e", source], + capture_output=True, + text=True, + timeout=30, + check=True, + ).stdout + ) + assert out["dispatched"] == ["resize", "resize", "resize", "resize"] + + +@pytest.mark.skipif(not Path(NODE).exists(), reason="node is not installed") +class TestSlickGridExtraction: + """The classic browsers draw with SlickGrid, and raw must read what they drew.""" + + GRID = """ + function resolver(field, datum) { + var path = field.split('.'); + var ret = datum; + for (var i = 0; i < path.length; i++) { + ret = ret[path[i]]; + if (!ret || typeof ret == 'undefined') break; + } + return ret; + } + var descriptionOutputFormatter = function (row, cell, value, columnDef, datum) { + return datum.CHART_NAME || value; + }; + var numericalDataFormatter = function (row, cell, value, columnDef, datum) { + if (!datum.HAS_DATA) return ''; + var ret = isNaN(parseFloat(value)) + ? value + : Number(value).toFixed(datum.PRECISION !== undefined ? datum.PRECISION : 0) + .replace(/\\B(?=(\\d{3})+(?!\\d))/g, ','); + return ret === undefined || ret === '' || ret === null ? '--' : ret; + }; + var COLUMNS = __COLUMNS__; + for (var i = 0; i < COLUMNS.length; i++) { + if (COLUMNS[i].outputFormatter === '@description') + COLUMNS[i].outputFormatter = descriptionOutputFormatter; + if (COLUMNS[i].dataFormatter === '@numerical') + COLUMNS[i].dataFormatter = numericalDataFormatter; + } + var OPTIONS = { + frozenColumn: 2, + addSpacerColumn: true, + dataItemColumnValueExtractor: function (item, colDef) { + if (colDef && colDef.field) return resolver(colDef.field, item); + return null; + } + }; + function Grid(container, data, columns, options) { + this.data = data; this.columns = columns; this.options = options; + this.onRendered = { subscribe: function () {} }; + } + Grid.prototype.getColumns = function () { return this.columns; }; + Grid.prototype.getOptions = function () { return this.options; }; + Grid.prototype.getDataLength = function () { return this.data.length; }; + Grid.prototype.getDataItem = function (i) { return this.data[i]; }; + window.Slick = { Grid: Grid }; + setTimeout(function () { + new window.Slick.Grid("#g", __DATA__, COLUMNS, OPTIONS); + }, __DELAY__); + """ + + COLUMNS = [ + {"id": "pinKey", "field": "HAS_DATA", "output": False}, + { + "id": "description", + "field": "DESCRIPTION", + "outputFormatter": "@description", + }, + {"id": "chart", "field": "HAS_DATA", "output": False}, + {"id": "units", "name": "units", "field": "UNITS", "display": False}, + { + "id": "source key", + "name": "source key", + "field": "SERIES_ID", + "display": False, + }, + { + "id": "200101", + "name": "Jan 2001", + "field": "DATA.200101", + "rseField": "RSE_DATA.200101", + "dataFormatter": "@numerical", + }, + {"id": "spacer", "name": " ", "autoWidth": True}, + ] + DATA = [ + { + "DESCRIPTION": "United States", + "LEVEL": 0, + "CHART_NAME": "United States", + "SERIES_ID": "ELEC.GEN..M", + "HAS_DATA": False, + "PRECISION": 0, + "DATA": {"200101": "--"}, + }, + { + "DESCRIPTION": "All fuels", + "LEVEL": 2, + "CHART_NAME": "United States : all fuels (utility-scale)", + "SERIES_ID": "ELEC.GEN.ALL-US-99.M", + "HAS_DATA": True, + "PRECISION": 0, + "UNITS": "thousand megawatthours", + "DATA": {"200101": 332493.16}, + }, + { + "DESCRIPTION": "Coal", + "LEVEL": 3, + "CHART_NAME": "United States : coal", + "SERIES_ID": "ELEC.GEN.COW-US-99.M", + "HAS_DATA": True, + "PRECISION": 0, + "UNITS": "thousand megawatthours", + "DATA": {"200101": 177287.111}, + }, + ] + + ANNUAL_COLUMNS = [ + {"id": "pinKey", "field": "HAS_DATA", "output": False}, + { + "id": "description", + "field": "DESCRIPTION", + "outputFormatter": "@description", + }, + ] + [ + { + "id": str(year), + "name": str(year), + "field": f"DATA.{year}", + "dataFormatter": "@numerical", + } + for year in (2014, 2015, 2009, 2010) + ] + ANNUAL_DATA = [ + { + "DESCRIPTION": "Total U.S.", + "LEVEL": 0, + "CHART_NAME": "Total U.S.", + "SERIES_ID": "PET_IMPORTS.WORLD-US-ALL.A", + "HAS_DATA": True, + "PRECISION": 0, + "UNITS": "thousand barrels", + "DATA": {"2009": 100, "2010": 200, "2014": 239554, "2015": 244173}, + }, + ] + + def run(self, data=None, columns=None, delay=120): + script = browsers._table_bridge_js(ELECTRICITY) + bridge = script.replace("<script>", "").replace("</script>", "") + grid = ( + self.GRID.replace( + "__DATA__", json.dumps(self.DATA if data is None else data) + ) + .replace( + "__COLUMNS__", + json.dumps(self.COLUMNS if columns is None else columns), + ) + .replace("__DELAY__", str(delay)) + ) + source = HARNESS.replace("__BRIDGE__", bridge).replace("__GRID__", grid) + with tempfile.TemporaryDirectory() as tmp: + script_path = Path(tmp) / "harness.js" + script_path.write_text(source, encoding="utf-8") + result = subprocess.run( # noqa: S603 + [NODE, str(script_path)], + capture_output=True, + text=True, + timeout=30, + check=True, + ) + return json.loads(result.stdout) + + def test_the_rendered_grid_is_published_to_the_shell(self): + posted = self.run()["posted"] + assert posted["type"] == "eia:table" + assert posted["rows"] == [ + {"category": "United States", "Jan 2001": None}, + { + "category": "United States : all fuels (utility-scale)", + "Jan 2001": 332493.16, + }, + {"category": "United States : coal", "Jan 2001": 177287.111}, + ] + + def test_the_same_rows_are_posted_to_the_backend(self): + result = self.run() + assert result["sent"]["url"].startswith("/api/v1/eia_table?obb_browser=") + assert json.loads(result["sent"]["body"]) == result["posted"]["rows"] + + def test_a_period_value_is_read_through_its_dotted_field_path(self): + posted = self.run()["posted"] + assert [row["Jan 2001"] for row in posted["rows"]] == [ + None, + 332493.16, + 177287.111, + ] + + def test_full_precision_survives_the_grids_own_formatter(self): + posted = self.run()["posted"] + assert posted["rows"][2]["Jan 2001"] == 177287.111 + + def test_the_hierarchy_is_the_one_the_grid_renders(self): + posted = self.run()["posted"] + assert [row["category"] for row in posted["rows"]] == [ + "United States", + "United States : all fuels (utility-scale)", + "United States : coal", + ] + + def test_only_the_columns_on_screen_are_published(self): + posted = self.run()["posted"] + for row in posted["rows"]: + assert list(row) == ["category", "Jan 2001"] + + def test_an_annual_table_keeps_its_label_column_first(self): + result = self.run(data=self.ANNUAL_DATA, columns=self.ANNUAL_COLUMNS) + rows = json.loads(result["sent"]["body"]) + assert list(rows[0]) == ["category", "2009 ", "2010 ", "2014 ", "2015 "] + assert rows[0]["category"] == "Total U.S." + assert rows[0]["2014 "] == 239554 + + def test_icon_button_columns_are_dropped(self): + columns = [ + { + "id": "sourcekey", + "field": "HAS_DATA", + "output": False, + "iconClass": "sourcekey", + }, + { + "id": "remove", + "name": "", + "field": "DESCRIPTION", + "output": True, + "iconClass": "remove", + }, + { + "id": "description", + "name": "", + "field": "DESCRIPTION", + "outputFormatter": "@description", + }, + {"id": "map", "field": "HAS_DATA", "output": True, "iconClass": "map"}, + { + "id": "linechart", + "field": "HAS_DATA", + "output": True, + "iconClass": "chart", + }, + { + "id": "200101", + "name": "Jan 2001", + "field": "DATA.200101", + "dataFormatter": "@numerical", + }, + ] + posted = self.run(columns=columns)["posted"] + for row in posted["rows"]: + assert list(row) == ["category", "Jan 2001"] + + def test_a_row_with_no_data_yields_nulls_not_the_dash(self): + posted = self.run()["posted"] + assert posted["rows"][0]["Jan 2001"] is None + + def test_the_post_does_not_use_keepalive(self): + assert self.run()["sent"]["keepalive"] is False + + def test_a_table_over_the_keepalive_limit_is_posted_whole(self): + columns = ( + self.COLUMNS[:5] + + [ + { + "id": str(200101 + n), + "name": f"period {n}", + "field": f"DATA.{200101 + n}", + "dataFormatter": "@numerical", + } + for n in range(305) + ] + + [self.COLUMNS[-1]] + ) + data = [ + { + "DESCRIPTION": f"Fuel {r}", + "CHART_NAME": f"United States : fuel {r}", + "SERIES_ID": f"ELEC.GEN.F{r}-US-99.M", + "HAS_DATA": True, + "PRECISION": 0, + "DATA": {str(200101 + n): 177287.111 + n for n in range(305)}, + } + for r in range(21) + ] + sent = self.run(data=data, columns=columns)["sent"] + assert len(sent["body"]) > 64 * 1024 + rows = json.loads(sent["body"]) + assert len(rows) == 21 + assert rows[0]["period 0"] == 177287.111 + + def test_a_grid_with_no_rows_publishes_nothing(self): + assert self.run(data=[])["posted"] is None + + def test_a_grid_built_much_later_is_still_captured(self): + assert self.run(delay=500)["posted"]["rows"] + + def test_the_page_is_left_holding_a_working_grid(self): + source = HARNESS.replace( + "__BRIDGE__", + browsers._table_bridge_js(ELECTRICITY) + .replace("<script>", "") + .replace("</script>", ""), + ).replace( + "__GRID__", + self.GRID.replace("__DATA__", json.dumps(self.DATA)) + .replace("__COLUMNS__", json.dumps(self.COLUMNS)) + .replace("__DELAY__", "120") + .replace( + 'new window.Slick.Grid("#g", ', + 'var g = new window.Slick.Grid("#g", ', + ) + .replace( + "}, 120);", + " if (!(g instanceof window.Slick.Grid)) throw new Error('broke instanceof');" + " if (g.getDataLength() !== 3) throw new Error('broke the grid');" + "}, 120);", + ), + ) + subprocess.run( # noqa: S603 + [NODE, "-e", source], capture_output=True, text=True, timeout=30, check=True + ) + + +LIFECYCLE_GRID = """ +var DOC = { contains: function (n) { return n._attached; } }; +function makeNode(attached, visible) { + var n = { + _attached: attached, _viewport: true, ownerDocument: DOC, + querySelector: function (sel) { + return (n._viewport && sel === '.slick-viewport') ? {} : null; + }, + getClientRects: function () { return visible ? [{}] : []; }, + offsetParent: visible ? {} : null, + }; + return n; +} +var COLUMNS = [ + { id: 'description', field: 'DESCRIPTION' }, + { id: '200101', name: 'Jan 2001', field: 'DATA.200101' }, +]; +var OPTIONS = { + dataItemColumnValueExtractor: function (item, colDef) { + var path = colDef.field.split('.'), ret = item; + for (var i = 0; i < path.length; i++) ret = ret[path[i]]; + return ret; + }, +}; +function Grid(container, data, columns, options) { + this.node = container; this.data = data; + this.columns = columns; this.options = options; + this.onRendered = { subscribe: function () {} }; +} +Grid.prototype.getColumns = function () { return this.columns; }; +Grid.prototype.getOptions = function () { return this.options; }; +Grid.prototype.getDataLength = function () { return this.data.length; }; +Grid.prototype.getDataItem = function (i) { return this.data[i]; }; +Grid.prototype.getContainerNode = function () { return this.node; }; +Grid.prototype.destroy = function () { this.node._viewport = false; }; +window.Slick = { Grid: Grid }; +setTimeout(function () { + var stale = new window.Slick.Grid(makeNode(true, true), __STALE__, COLUMNS, OPTIONS); + new window.Slick.Grid(makeNode(true, true), __CURRENT__, COLUMNS, OPTIONS); + __TEARDOWN__ +}, 120); +""" + + +def _rows(label, count): + """Build ``count`` grid rows carrying ``label`` as their description.""" + return [ + {"DESCRIPTION": f"{label} {n}", "DATA": {"200101": float(n)}} + for n in range(count) + ] + + +@pytest.mark.skipif(not Path(NODE).exists(), reason="node is not installed") +class TestGridLifecycle: + """A view the user left must never supply the table ``raw`` answers with. + + EIA rebuilds the grid per view and calls ``destroy()`` on the old one, which + only empties the container -- the instance keeps answering + ``getDataLength()`` with the row count of the view it drew. A stale grid is + routinely larger than the current one, so picking by row count alone hands + ``raw`` the table of a view that is no longer on screen. + """ + + def run(self, stale, current, teardown): + script = browsers._table_bridge_js(ELECTRICITY) + bridge = script.replace("<script>", "").replace("</script>", "") + grid = ( + LIFECYCLE_GRID.replace("__STALE__", json.dumps(stale)) + .replace("__CURRENT__", json.dumps(current)) + .replace("__TEARDOWN__", teardown) + ) + source = HARNESS.replace("__BRIDGE__", bridge).replace("__GRID__", grid) + result = subprocess.run( # noqa: S603 + [NODE, "-e", source], capture_output=True, text=True, timeout=30, check=True + ) + return json.loads(result.stdout) + + def test_a_destroyed_grid_does_not_supply_the_table(self): + posted = self.run(_rows("STALE", 6), _rows("CURRENT", 2), "stale.destroy();") + assert [row["category"] for row in posted["posted"]["rows"]] == [ + "CURRENT 0", + "CURRENT 1", + ] + + def test_a_detached_grid_does_not_supply_the_table(self): + posted = self.run( + _rows("STALE", 6), _rows("CURRENT", 2), "stale.node._attached = false;" + ) + assert [row["category"] for row in posted["posted"]["rows"]] == [ + "CURRENT 0", + "CURRENT 1", + ] + + def test_a_hidden_grid_does_not_supply_the_table(self): + posted = self.run( + _rows("STALE", 6), + _rows("CURRENT", 2), + "stale.node.offsetParent = null; stale.node.getClientRects = " + "function () { return []; };", + ) + assert [row["category"] for row in posted["posted"]["rows"]] == [ + "CURRENT 0", + "CURRENT 1", + ] + + def test_the_larger_live_grid_still_wins(self): + posted = self.run(_rows("STALE", 6), _rows("CURRENT", 2), "") + assert len(posted["posted"]["rows"]) == 6 + + def test_the_scrape_names_the_view_it_was_taken_from(self): + sent = self.run(_rows("STALE", 6), _rows("CURRENT", 2), "stale.destroy();")[ + "sent" + ] + assert "obb_view=electricity%2Fdata%2Fbrowser%2F" in sent["url"] + + +SYNC_HARNESS = """ +var intervals = [], listeners = {}; +global.window = global; +var select = { + tagName: 'SELECT', + value: '-1', + options: [ + { value: '-1', text: 'Select a view' }, + { value: '0', text: 'Imports of all grades to US' }, + { value: '8', text: 'Top 10 light crude oil importing refineries in 2013' }, + ], +}; +global.location = { + pathname: '/api/v1/eia_proxy/petroleum/imports/browser/', + hash: '#/?vs=PET_IMPORTS.WORLD-US-ALL.A', +}; +global.document = { + getElementsByTagName: function (tag) { return tag === 'select' ? [select] : []; }, +}; +global.window.addEventListener = function (name, fn) { listeners[name] = fn; }; +global.setInterval = function (fn) { intervals.push(fn); return intervals.length; }; +var CONFIG = __CONFIG__; +global.fetch = function () { + return Promise.resolve({ json: function () { return Promise.resolve(CONFIG); } }); +}; + +__SCRIPT__ + +function tick() { for (var i = 0; i < intervals.length; i++) intervals[i](); } +setTimeout(function () { + __DRIVER__ + process.stdout.write(JSON.stringify({ value: select.value })); +}, 80); +""" + +V0_VS = "PET_IMPORTS.WORLD-US-ALL.A" +V8_VS = "PET_IMPORTS.WORLD-RF_465-O.A~PET_IMPORTS.WORLD-RF_225-O.A" +CONFIG_WITH_VIEWS = { + "views": [ + {"id": "0", "json": json.dumps({"vs": V0_VS})}, + { + "id": "8", + "json": json.dumps({"columnendpoints": "2", "d": "abc", "vs": V8_VS}), + }, + ] +} +CONFIG_NO_VIEWS = {"status": "OK"} + + +@pytest.mark.skipif(not Path(NODE).exists(), reason="node is not installed") +class TestFeaturedViewSync: + """The Featured views select must mirror the view encoded in the live hash.""" + + def run(self, driver, config=None): + script = browsers._VIEW_SELECT_SYNC_JS.replace("<script>", "").replace( + "</script>", "" + ) + source = ( + SYNC_HARNESS.replace( + "__CONFIG__", + json.dumps(CONFIG_WITH_VIEWS if config is None else config), + ) + .replace("__SCRIPT__", script) + .replace("__DRIVER__", driver) + ) + result = subprocess.run( # noqa: S603 + [NODE, "-e", source], + capture_output=True, + text=True, + timeout=30, + check=True, + ) + return json.loads(result.stdout) + + def test_the_default_view_is_reflected_on_load(self): + assert self.run("")["value"] == "0" + + def test_a_view_in_the_hash_is_reflected(self): + driver = ( + f"location.hash = '#/?d=xyz&f=a&vs=' + encodeURIComponent('{V8_VS}');" + "tick();" + ) + assert self.run(driver)["value"] == "8" + + def test_matching_ignores_the_other_view_params(self): + driver = ( + f"location.hash = '#/?vs=' + encodeURIComponent('{V8_VS}') + '&d=DIFF';" + "tick();" + ) + assert self.run(driver)["value"] == "8" + + def test_a_hashchange_event_drives_the_sync(self): + driver = ( + f"location.hash = '#/?vs=' + encodeURIComponent('{V8_VS}');" + "listeners['hashchange']();" + ) + assert self.run(driver)["value"] == "8" + + def test_an_unmatched_state_clears_to_the_placeholder(self): + driver = "location.hash = '#/?vs=PET_IMPORTS.NO_SUCH_SERIES.A';tick();" + assert self.run(driver)["value"] == "-1" + + def test_a_browser_without_view_config_is_left_untouched(self): + driver = "select.value = '0';tick();" + assert self.run(driver, config=CONFIG_NO_VIEWS)["value"] == "0" + + def test_the_script_is_injected_into_the_classic_browser_page(self): + page = browsers.rewrite_html( + "<head></head><body></body>", + PROXY_PREFIX, + browser=IMPORTS, + ) + assert browsers._VIEW_SELECT_SYNC_JS in page + + +class TestText: + def test_strips_tags_and_unescapes(self): + assert browsers._text("<b>A &\n B</b>") == "A & B" + + +class TestParseMapsPage: + def test_groups_formats_by_document(self): + entries = browsers.parse_maps_page(MAPS_HTML) + assert len(entries) == 4 + shale = entries[0] + assert shale["tab"] == "Recent maps" + assert shale["section"] == "Overview & boundaries" + assert shale["title"] == "Shale plays, Lower 48 States" + assert shale["date"] == "12/13/2023" + assert shale["pdf"] == "/maps/images/shale_2023.pdf" + assert shale["image"] == "/maps/images/shale_2023.jpg" + + def test_title_without_date_strips_format_suffix(self): + assert browsers.parse_maps_page(MAPS_HTML)[1] == { + "tab": "Recent maps", + "section": "Overview & boundaries", + "title": "Major tight gas plays", + "date": "", + "pdf": "/maps/images/tight_gas.pdf", + } + + def test_second_tab_and_image_only(self): + assert browsers.parse_maps_page(MAPS_HTML)[2] == { + "tab": "Historical maps", + "section": "Historical basins", + "title": "Historic basin map", + "date": "6/1/2011", + "image": "/maps/images/old_map.jpg", + } + + def test_section_prefix_stripped_from_title(self): + assert browsers.parse_maps_page(MAPS_HTML)[3] == { + "tab": "Historical maps", + "section": "Historical basins", + "title": "Western Area BOE", + "date": "", + "pdf": "/maps/images/field_maps/app_boe.pdf", + } + + def test_unsupported_format_skipped(self): + assert not any( + entry.get("pdf", "").endswith(".zip") + for entry in browsers.parse_maps_page(MAPS_HTML) + ) + + def test_anchor_outside_tabs_skipped(self): + html = '<a href="/maps/x.pdf" title="Loose (1/1/2020)(pdf)">PDF</a>' + assert browsers.parse_maps_page(html) == [] + + def test_more_tabs_than_labels_get_placeholder(self): + html = ( + '<div class="tab-content">' + '<a href="/maps/a.pdf" title="A (1/1/2020)(pdf)">PDF</a></div>' + ) + assert browsers.parse_maps_page(html)[0]["tab"] == "Maps 1" + + +class TestFetchMapsCatalog: + @pytest.mark.asyncio + async def test_fetches_parses_and_caches(self, monkeypatch): + target = f"{browsers._EIA_ORIGIN}/{browsers.MAPS_PAGE}" + upstream = FakeUpstream({target: (MAPS_HTML.encode(), "text/html")}) + upstream.install(monkeypatch) + first = await browsers.fetch_maps_catalog() + second = await browsers.fetch_maps_catalog() + assert first is second + assert len(upstream.calls) == 1 + assert first[0]["title"] == "Shale plays, Lower 48 States" + + +class TestRewriteHtml: + """Injected CSS/JS must hide EIA's site chrome without eating its apps.""" + + def test_rewrites_root_paths_and_injects_into_head(self): + html = '<head></head><body><a href="/coal/">x</a><img src="/img.png"/></body>' + out = browsers.rewrite_html(html, PROXY_PREFIX) + assert f'"{PROXY_PREFIX}/coal/"' in out + assert f'"{PROXY_PREFIX}/img.png"' in out + assert out.index("<style>") < out.index("</head>") + + def test_without_head_prepends_injection(self): + assert browsers.rewrite_html("<body></body>", "/p").startswith("<style>") + + def test_protocol_relative_untouched(self): + out = browsers.rewrite_html('<head></head><a href="//cdn/x.js">', "/p") + assert '"//cdn/x.js"' in out + + def test_absolute_eia_urls_repointed_at_the_proxy(self): + out = browsers.rewrite_html( + '<head></head><a href="https://www.eia.gov/coal/">x</a>', PROXY_PREFIX + ) + assert "https://www.eia.gov/coal/" not in out + assert f'"{PROXY_PREFIX}/coal/"' in out + + def test_chrome_hidden_but_app_headers_survive(self): + out = browsers.rewrite_html("<head></head>", PROXY_PREFIX) + hide = out.split("{display:none!important}", 1)[0] + assert "header" in hide + assert "#sticker" in hide + assert ".l-row.header" not in hide + assert ".sub-navigation" not in hide + assert ".title-banner" not in hide + + def test_article_pages_hide_their_own_banner(self): + out = browsers.rewrite_html("<head></head>", PROXY_PREFIX, article=True) + assert browsers._ARTICLE_CSS in out + + def test_browser_pages_do_not_get_the_article_chrome(self): + out = browsers.rewrite_html( + "<head></head>", PROXY_PREFIX, browser=INTERNATIONAL + ) + assert browsers._ARTICLE_CSS not in out + + def test_dark_root_background_inverts_to_dark(self): + out = browsers.rewrite_html("<head></head>", PROXY_PREFIX, dark=True) + assert "background:#fff!important" in out + assert "#111418" not in out + + def test_dark_mode_uninverts_country_flags(self): + out = browsers.rewrite_html("<head></head>", PROXY_PREFIX, dark=True) + dark = out[out.index("filter:invert(0.92)") :] + assert dark.index('img[src*=".svg"]') < dark.index('img[src*="flags/"]') + + def test_light_mode_has_no_filter(self): + out = browsers.rewrite_html("<head></head>", PROXY_PREFIX, dark=False) + assert "invert(0.92)" not in out + + def test_asset_fixer_injected_for_runtime_root_absolute_images(self): + out = browsers.rewrite_html("<head></head>", PROXY_PREFIX) + assert browsers._ASSET_FIX_JS in out + + def test_the_table_bridge_is_bound_to_its_browser(self): + out = browsers.rewrite_html( + "<head></head>", PROXY_PREFIX, browser=INTERNATIONAL + ) + assert f"browser='{INTERNATIONAL}'" in out + assert "eia:table" in out + + def test_the_tagger_binds_each_request_to_its_view(self): + out = browsers.rewrite_html( + "<head></head>", PROXY_PREFIX, browser=INTERNATIONAL + ) + assert "XMLHttpRequest.prototype.open" in out + assert "obb_view" in out + assert "obb_token" not in out + + def test_the_tagger_leaves_the_widgets_own_endpoints_alone(self): + """A tagged POST to ``/eia_table`` would be proxied to eia.gov.""" + out = browsers.rewrite_html( + "<head></head>", PROXY_PREFIX, browser=INTERNATIONAL + ) + assert "var mine=[parts[0]+'/eia_table',parts[0]+'/eia_view'];" in out + assert ( + "for(var m=0;m<mine.length;m++)if(u.pathname===mine[m])return raw;" in out + ) + + def test_tagger_omitted_without_a_browser(self): + out = browsers.rewrite_html("<head></head>", PROXY_PREFIX) + assert "obb_browser" not in out + + def test_analytics_and_akamai_scripts_dropped(self): + html = ( + "<head>" + '<script src="https://www.googletagmanager.com/gtag/js?id=X"></script>' + '<script src="/akam/13/abc" defer></script>' + "</head>" + ) + out = browsers.rewrite_html(html, PROXY_PREFIX) + assert "googletagmanager" not in out + assert "/akam/" not in out + + @pytest.mark.parametrize( + ("browser", "css"), + [ + ("electricity/data/browser/", "_MAP_LAYOUT_CSS"), + ("coal/data/browser/", "_MAP_LAYOUT_CSS"), + ("naturalgas/ngqs/", "_NGQS_GRID_CSS"), + ("states/", "_STATES_CSS"), + ("international/overview/world", "_INTERNATIONAL_CSS"), + ], + ) + def test_per_browser_css_only_reaches_its_own_browser(self, browser, css): + expected = getattr(browsers, css) + assert expected in browsers.rewrite_html( + "<head></head>", PROXY_PREFIX, browser=browser + ) + assert expected not in browsers.rewrite_html( + "<head></head>", PROXY_PREFIX, browser="outlooks/steo/data/browser/" + ) + + +class TestRewrittenCache: + """Rewritten static assets are cached; the cache is bounded.""" + + def test_second_rewrite_is_served_from_cache(self): + calls = [] + + def build(): + calls.append(1) + return "rewritten" + + key = ("https://t/a.js", "/p") + assert browsers._rewritten(key, build) == "rewritten" + assert browsers._rewritten(key, build) == "rewritten" + assert len(calls) == 1 + + def test_cache_is_bounded(self, monkeypatch): + monkeypatch.setattr(browsers, "_REWRITE_CACHE_MAX", 2) + for index in range(4): + browsers._rewritten((f"https://t/{index}.js", "/p"), lambda: "x") + assert len(browsers._REWRITE_CACHE) <= 2 + + @pytest.mark.asyncio + async def test_spa_bundle_rewrites_only_its_own_app_roots(self, monkeypatch): + script = b'fetch("/states/api/geo.json");var api="/api/analysis";var s="/";' + FakeUpstream( + { + "https://www.eia.gov/states/main.js": ( + script, + "application/javascript", + ) + } + ).install(monkeypatch) + response = await browsers.eia_proxy( + "states/main.js", make_info("/api/v1/eia_proxy/states/main.js") + ) + text = response.body.decode() + assert f'"{PROXY_PREFIX}/states/api/geo.json"' in text + assert 'var api="/api/analysis"' in text + assert 'var s="/"' in text + + +class TestRedirects: + """An upstream redirect is mapped back onto the proxy, keeping the markers.""" + + def test_redirect_target_keeps_the_theme(self): + location = browsers._redirect_target( + PROXY_PREFIX, f"{browsers._EIA_ORIGIN}/coal/?a=1", True + ) + assert location.startswith(f"{PROXY_PREFIX}/coal/?") + assert "a=1" in location + assert "obb_theme=dark" in location + + def test_light_theme_is_carried_through(self): + location = browsers._redirect_target( + PROXY_PREFIX, f"{browsers._EIA_ORIGIN}/coal/", False + ) + assert "obb_theme=light" in location + assert "obb_token" not in location + + @pytest.mark.asyncio + async def test_proxy_redirects_the_iframe_to_where_it_landed(self, monkeypatch): + target = "https://www.eia.gov/from" + landed = "https://www.eia.gov/to" + FakeUpstream({target: (b"<head></head>", "text/html", 200, landed)}).install( + monkeypatch + ) + response = await browsers.eia_proxy( + "from", make_info("/api/v1/eia_proxy/from", query="obb_theme=dark") + ) + assert response.status_code == 307 + assert response.headers["location"].startswith(f"{PROXY_PREFIX}/to?") + + @pytest.mark.asyncio + async def test_landing_on_the_same_path_is_served_not_redirected(self, monkeypatch): + target = "https://www.eia.gov/coal/" + FakeUpstream({target: (b"<head></head>", "text/html", 200, target)}).install( + monkeypatch + ) + response = await browsers.eia_proxy( + "coal/", make_info("/api/v1/eia_proxy/coal/") + ) + assert response.status_code == 200 + + +class TestProxyPost: + """NGQS submits its query as a POST, which must be proxied and recorded.""" + + @pytest.mark.asyncio + async def test_post_is_forwarded_with_its_body(self, monkeypatch): + captured: dict = {} + + def fake_post(target, body, content_type): + captured.update(target=target, body=body, content_type=content_type) + return b'{"TABLE_DATA":[]}', "application/json", 200 + + monkeypatch.setattr(browsers, "_post_sync", fake_post) + ngqs = browsers.EIA_DATA_BROWSERS["natural_gas_query"]["path"] + await browsers.eia_proxy( + "naturalgas/ngqs/data/report/1", + make_info( + "/api/v1/eia_proxy/naturalgas/ngqs/data/report/1", + query=f"obb_browser={ngqs}", + method="POST", + body=b"items=1", + ), + ) + assert captured["body"] == b"items=1" + assert captured["content_type"] == "application/x-www-form-urlencoded" + assert captured["target"] == ( + "https://www.eia.gov/naturalgas/ngqs/data/report/1" + ) + + +class TestFetchUpstream: + """Memory, then disk, then network.""" + + @pytest.mark.asyncio + async def test_caches_successful_fetch_in_memory(self, monkeypatch): + upstream = FakeUpstream({"https://t/x": (b"payload", "text/plain")}) + upstream.install(monkeypatch) + assert await browsers._fetch_upstream("https://t/x") == ( + b"payload", + "text/plain", + ) + assert await browsers._fetch_upstream("https://t/x") == ( + b"payload", + "text/plain", + ) + assert len(upstream.calls) == 1 + + @pytest.mark.asyncio + async def test_non_200_not_cached(self, monkeypatch): + upstream = FakeUpstream({"https://t/x": (b"gone", "text/plain", 404)}) + upstream.install(monkeypatch) + await browsers._fetch_upstream("https://t/x") + await browsers._fetch_upstream("https://t/x") + assert len(upstream.calls) == 2 + + @pytest.mark.asyncio + async def test_cache_evicts_oldest(self, monkeypatch): + monkeypatch.setattr(browsers, "_PROXY_CACHE_MAX", 1) + upstream = FakeUpstream( + {"https://t/a": (b"a", "text/plain"), "https://t/b": (b"b", "text/plain")} + ) + upstream.install(monkeypatch) + await browsers._fetch_upstream("https://t/a") + await browsers._fetch_upstream("https://t/b") + assert "https://t/a" not in browsers._PROXY_CACHE + assert "https://t/b" in browsers._PROXY_CACHE + + @pytest.mark.asyncio + async def test_expired_entry_refetched(self, monkeypatch): + upstream = FakeUpstream({"https://t/x": (b"payload", "text/plain")}) + upstream.install(monkeypatch) + await browsers._fetch_upstream("https://t/x") + stamp, body, content_type = browsers._PROXY_CACHE["https://t/x"] + browsers._PROXY_CACHE["https://t/x"] = ( + stamp - browsers._PROXY_CACHE_TTL - 1, + body, + content_type, + ) + await browsers._fetch_upstream("https://t/x") + assert len(upstream.calls) == 2 + + @pytest.mark.asyncio + async def test_static_asset_persisted_to_disk_and_served_from_it(self, monkeypatch): + target = "https://t/app.js" + upstream = FakeUpstream({target: (b"code", "application/javascript")}) + upstream.install(monkeypatch) + await browsers._fetch_upstream(target) + body_path, type_path = browsers._cache_paths(target) + assert body_path.read_bytes() == b"code" + assert type_path.read_text() == "application/javascript" + + browsers._PROXY_CACHE.clear() + assert await browsers._fetch_upstream(target) == ( + b"code", + "application/javascript", + ) + assert len(upstream.calls) == 1 + + @pytest.mark.asyncio + async def test_html_is_never_written_to_disk(self, monkeypatch): + target = "https://t/page.html" + FakeUpstream({target: (b"<html>", "text/html")}).install(monkeypatch) + await browsers._fetch_upstream(target) + assert not browsers._cache_paths(target)[0].exists() + + @pytest.mark.asyncio + async def test_redirect_target_remembered(self, monkeypatch): + target = "https://t/from" + landed = "https://t/to" + FakeUpstream({target: (b"x", "text/html", 200, landed)}).install(monkeypatch) + await browsers._fetch_upstream(target) + assert browsers._REDIRECTS[target] == landed + + +class TestEiaProxy: + """The proxy rewrites what it must and passes the rest through untouched.""" + + @pytest.mark.asyncio + async def test_html_rewritten_and_query_forwarded(self, monkeypatch): + upstream = FakeUpstream( + { + "https://www.eia.gov/coal/?a=1": ( + b'<head></head><a href="/x">x</a>', + "text/html", + ) + } + ) + upstream.install(monkeypatch) + response = await browsers.eia_proxy( + "coal/", make_info("/api/v1/eia_proxy/coal/", query="a=1") + ) + assert f'"{PROXY_PREFIX}/x"' in response.body.decode() + assert upstream.calls == ["https://www.eia.gov/coal/?a=1"] + + @pytest.mark.asyncio + async def test_html_is_never_cached_by_the_browser(self, monkeypatch): + FakeUpstream( + {"https://www.eia.gov/coal/": (b"<head></head>", "text/html")} + ).install(monkeypatch) + response = await browsers.eia_proxy( + "coal/", make_info("/api/v1/eia_proxy/coal/") + ) + assert response.headers["Cache-Control"] == "no-store" + + @pytest.mark.asyncio + async def test_widget_markers_stripped_before_upstream(self, monkeypatch): + upstream = FakeUpstream( + {"https://www.eia.gov/coal/?a=1": (b"<head></head>", "text/html")} + ) + upstream.install(monkeypatch) + await browsers.eia_proxy( + "coal/", + make_info( + "/api/v1/eia_proxy/coal/", + query="a=1&obb_theme=dark", + ), + ) + assert "obb_" not in upstream.calls[0] + + @pytest.mark.asyncio + async def test_css_urls_rewritten(self, monkeypatch): + FakeUpstream( + { + "https://www.eia.gov/s.css": ( + b"body{background:url(/img.png)}", + "text/css", + ) + } + ).install(monkeypatch) + response = await browsers.eia_proxy( + "s.css", make_info("/api/v1/eia_proxy/s.css") + ) + assert f"url({PROXY_PREFIX}/img.png)".encode() in response.body + + @pytest.mark.asyncio + async def test_js_spa_roots_rewritten_but_bare_slash_untouched(self, monkeypatch): + script = b'fetch("/states/api/x");var sep="/";var g="/global/a.js";' + FakeUpstream( + {"https://www.eia.gov/app.js": (script, "application/javascript")} + ).install(monkeypatch) + response = await browsers.eia_proxy( + "app.js", make_info("/api/v1/eia_proxy/app.js") + ) + text = response.body.decode() + assert f'"{PROXY_PREFIX}/states/api/x"' in text + assert f'"{PROXY_PREFIX}/global/a.js"' in text + assert 'sep="/"' in text + + @pytest.mark.asyncio + async def test_binary_passthrough(self, monkeypatch): + FakeUpstream( + {"https://www.eia.gov/m.pdf": (b"%PDF-1.6", "application/pdf")} + ).install(monkeypatch) + response = await browsers.eia_proxy( + "m.pdf", make_info("/api/v1/eia_proxy/m.pdf") + ) + assert response.body == b"%PDF-1.6" + assert response.media_type == "application/pdf" + + @pytest.mark.asyncio + async def test_upstream_error_returns_502(self, monkeypatch): + FakeUpstream({"https://www.eia.gov/x": RuntimeError("boom")}).install( + monkeypatch + ) + response = await browsers.eia_proxy("x", make_info("/api/v1/eia_proxy/x")) + assert response.status_code == 502 + assert response.body == b"Upstream request failed." + assert b"boom" not in response.body + + @pytest.mark.asyncio + async def test_deep_linked_spa_route_still_gets_the_bridge(self, monkeypatch): + """A deep-linked sub-route is not the root path, but still needs the bridge.""" + target = "https://www.eia.gov/international/overview/USA" + FakeUpstream({target: (b"<head></head>", "text/html")}).install(monkeypatch) + response = await browsers.eia_proxy( + "international/overview/USA", + make_info("/api/v1/eia_proxy/international/overview/USA"), + ) + page = response.body.decode() + assert f"browser='{INTERNATIONAL}'" in page + assert "/eia_table" in page + + @pytest.mark.asyncio + async def test_article_pages_get_no_tagger(self, monkeypatch): + target = "https://www.eia.gov/todayinenergy/detail.php?id=1" + FakeUpstream({target: (b"<head></head>", "text/html")}).install(monkeypatch) + response = await browsers.eia_proxy( + "todayinenergy/detail.php", + make_info("/api/v1/eia_proxy/todayinenergy/detail.php", query="id=1"), + ) + assert "obb_browser" not in response.body.decode() + + +class TestRenderBrowser: + """Each browser is its own widget, carrying EIA's own description.""" + + @pytest.mark.asyncio + async def test_site_payload(self): + info = make_info("/api/v1/coal_browser") + response = await browsers.render_browser("coal", "light", False, info) + text = response.body.decode() + assert '"mode": "site"' in text + assert '"theme": "light"' in text + assert "eia_proxy/coal/data/browser/" in text + assert browsers.EIA_DATA_BROWSERS["coal"]["description"][:40] in text + + @pytest.mark.asyncio + async def test_unknown_browser_falls_back_to_electricity(self): + info = make_info("/api/v1/bogus_browser") + response = await browsers.render_browser("bogus", "dark", False, info) + text = response.body.decode() + assert "electricity/data/browser/" in text + assert '"theme": "dark"' in text + + @pytest.mark.asyncio + async def test_site_payload_without_request_info(self): + response = await browsers.render_browser("aeo", "dark", False, None) + text = response.body.decode() + assert '"mode": "site"' in text + assert '"endpoint": "http://127.0.0.1:6900/api/v1/eia/aeo_browser"' in text + assert "eia_proxy/outlooks/aeo/data/browser/" in text + + @pytest.mark.asyncio + async def test_endpoint_without_request_info_returns_html_text(self): + endpoint = browsers._browser_endpoint("maps") + out = await endpoint(theme="dark", raw=False) + assert isinstance(out, str) + assert "<!DOCTYPE html>" in out + + @pytest.mark.asyncio + async def test_petroleum_imports_lands_on_its_default_view(self): + info = make_info("/api/v1/petroleum_imports_browser") + response = await browsers.render_browser( + "petroleum_imports", "dark", False, info + ) + assert "%23/?vs=PET_IMPORTS.WORLD-US-ALL.A" in response.body.decode() or ( + "#/?vs=PET_IMPORTS.WORLD-US-ALL.A" in response.body.decode() + ) + + @pytest.mark.asyncio + async def test_maps_mode_embeds_catalog_and_escapes_html(self, monkeypatch): + async def fake_catalog(): + return [{"tab": "R", "section": "S", "title": "T<'&", "pdf": "/maps/x.pdf"}] + + monkeypatch.setattr(browsers, "fetch_maps_catalog", fake_catalog) + info = make_info("/api/v1/maps_browser") + response = await browsers.render_browser("maps", "dark", False, info) + text = response.body.decode() + assert '"mode": "maps"' in text + assert "\\u003c" in text + assert "\\u0026" in text + assert "/maps/x.pdf" in text + + @pytest.mark.asyncio + async def test_raw_serves_the_table_the_page_published(self, monkeypatch): + rows = [{"category": "Production", "2023": 1.5}] + browsers.set_table_rows(INTERNATIONAL, rows, 2000) + + def unused(_target): + raise AssertionError("raw must not reach upstream") + + monkeypatch.setattr(browsers, "_fetch_sync", unused) + info = make_info("/api/v1/international_browser") + response = await browsers.render_browser("international", "dark", True, info) + assert json.loads(response.body) == rows + + @pytest.mark.asyncio + async def test_raw_replays_the_view_the_page_is_showing(self, monkeypatch): + """Grids whose API the page cannot reach are served from their payload.""" + spec = browsers.EIA_DATA_BROWSERS["electricity"] + target = "https://www.eia.gov/electricity/x?method=getAggregateData" + payload = json.dumps( + { + "TABLEDATA": { + "ROWS": [ + { + "DESCRIPTION": "United States", + "LEVEL": 0, + "UNITS": "thousand megawatthours", + "SERIES_ID": "ELEC.GEN.ALL-US-99.M", + "DATA": {"200101": 332493.16}, + } + ], + "DATACOLUMNS": [200101], + } + } + ).encode() + FakeUpstream({target: (payload, "application/json")}).install(monkeypatch) + browsers.set_current_view(spec["path"], "electricity/data/browser/#/topic/0") + browsers.set_data_target( + spec["path"], + "electricity/data/browser/#/topic/0", + {"url": target, "method": "GET"}, + ) + info = make_info("/api/v1/electricity_browser") + response = await browsers.render_browser("electricity", "dark", True, info) + rows = json.loads(response.body) + assert rows[0]["category"] == "United States" + assert rows[0]["2001-01"] == 332493.16 + + @pytest.mark.asyncio + async def test_raw_for_maps_returns_the_catalog(self, monkeypatch): + async def fake_catalog(): + return [{"tab": "R", "section": "S", "title": "T", "pdf": "/x.pdf"}] + + monkeypatch.setattr(browsers, "fetch_maps_catalog", fake_catalog) + info = make_info("/api/v1/maps_browser") + response = await browsers.render_browser("maps", "dark", True, info) + assert json.loads(response.body)[0]["title"] == "T" + + +class TestWidgetStateRestore: + """Each user's iframe navigation is stashed and restored across the raw toggle.""" + + MER = browsers.EIA_DATA_BROWSERS["total_energy"]["path"] + + def test_state_stores_isolate_users(self): + browsers.set_current_view(self.MER, "mer#/topic/1", 1000, "alice") + browsers.set_current_view(self.MER, "mer#/topic/2", 1000, "bob") + assert browsers.get_current_view(self.MER, "alice") == "mer#/topic/1" + assert browsers.get_current_view(self.MER, "bob") == "mer#/topic/2" + assert browsers.get_current_view(self.MER) == "" + browsers.set_table_rows(self.MER, [{"a": 1}], 1000, "alice") + assert browsers.get_table_rows(self.MER, "alice") == [{"a": 1}] + assert browsers.get_table_rows(self.MER, "bob") is None + + @pytest.mark.asyncio + async def test_the_iframe_restores_the_users_last_view(self): + view = f"{self.MER}?obb_theme=dark&obb_user=u123#/topic/5?agg=2,0,1" + browsers.set_current_view(self.MER, view, 2000, "u123") + info = make_info("/api/v1/total_energy_browser", user="u123") + response = await browsers.render_browser("total_energy", "dark", False, info) + text = response.body.decode() + assert "topic/5" in text + assert "obb_user=u123" in text + + @pytest.mark.asyncio + async def test_the_default_view_is_used_without_a_stash(self): + info = make_info("/api/v1/total_energy_browser", user="u123") + response = await browsers.render_browser("total_energy", "dark", False, info) + text = response.body.decode() + assert f"eia_proxy/{self.MER}" in text + assert "topic/" not in text + + @pytest.mark.asyncio + async def test_a_users_view_never_leaks_into_another_users_iframe(self): + browsers.set_current_view(self.MER, f"{self.MER}#/topic/9", 2000, "alice") + info = make_info("/api/v1/total_energy_browser", user="bob") + response = await browsers.render_browser("total_energy", "dark", False, info) + assert "topic/9" not in response.body.decode() + + @pytest.mark.asyncio + async def test_the_beacon_keys_the_view_by_user(self): + await browsers.eia_view( + make_info( + "/api/v1/eia_view", + query=f"obb_browser={self.MER}&obb_user=carol&obb_view=mer%23%2Ftopic%2F7&obb_seq=3000", + ) + ) + assert browsers.get_current_view(self.MER, "carol") == "mer#/topic/7" + assert browsers.get_current_view(self.MER, "dave") == "" + + @pytest.mark.asyncio + async def test_raw_serves_each_user_their_own_table(self, monkeypatch): + browsers.set_current_view( + self.MER, f"{self.MER}?tbl=T09.05#/?f=M", 2000, "alice" + ) + browsers.set_current_view(self.MER, f"{self.MER}?tbl=T01.01#/?f=M", 2000, "bob") + + def table(desc): + return ( + '<script>var sampleData = {"UNITS":"u","ROWS":' + '[{"MSN":"X","DESCRIPTION":"' + + desc + + '","DATA":{"2024":"1"}}]};</script>' + ).encode() + + FakeUpstream( + { + f"{browsers._EIA_ORIGIN}/{self.MER}?tbl=T09.05": ( + table("Refiner Prices"), + "text/html", + ), + f"{browsers._EIA_ORIGIN}/{self.MER}?tbl=T01.01": ( + table("Primary Energy"), + "text/html", + ), + } + ).install(monkeypatch) + alice = await browsers.render_browser( + "total_energy", "dark", True, make_info("/api/v1/x", user="alice") + ) + bob = await browsers.render_browser( + "total_energy", "dark", True, make_info("/api/v1/x", user="bob") + ) + assert json.loads(alice.body)[0]["category"] == "Refiner Prices" + assert json.loads(bob.body)[0]["category"] == "Primary Energy" + + def test_the_bridges_carry_the_user_key(self): + xhr = browsers._xhr_tag_js(self.MER, "u9") + tbl = browsers._table_bridge_js(self.MER, "u9") + assert "user='u9'" in xhr and "obb_user" in xhr + assert "user='u9'" in tbl and "obb_user" in tbl + assert "obb_user" in browsers._NAV_GUARD_JS + + def test_the_view_bridge_reports_the_query_string(self): + assert "search:location.search" in browsers._view_bridge_js() + + def test_a_view_query_keeps_page_params_and_drops_widget_markers(self): + view = f"{self.MER}?obb_theme=dark&obb_user=X&tbl=T09.05#/?f=M" + assert browsers._view_query(view) == "tbl=T09.05" + assert browsers._view_query("") == "" + + @pytest.mark.asyncio + async def test_the_host_carries_the_user_and_path_for_state_reporting(self): + info = make_info("/api/v1/total_energy_browser", user="HASH9") + response = await browsers.render_browser("total_energy", "dark", False, info) + text = response.body.decode() + assert '"user": "HASH9"' in text + assert '"path": "totalenergy/data/browser/"' in text + assert "reportView" in text and "restoredSrc" in text + + @pytest.mark.asyncio + async def test_home_is_the_default_view_not_the_restored_one(self): + browsers.set_current_view( + self.MER, f"{self.MER}?tbl=T09.05#/?f=M&start=201506", 2000, "u123" + ) + info = make_info("/api/v1/total_energy_browser", user="u123") + text = ( + await browsers.render_browser("total_energy", "dark", False, info) + ).body.decode() + marker = '<script id="browser-data" type="application/json">' + blob = text.split(marker, 1)[1].split("</script>", 1)[0] + data = json.loads( + blob.replace("\\u003c", "<").replace("\\u003e", ">").replace("\\u0026", "&") + ) + assert "tbl=T09.05" in data["src"] + assert "tbl=T09.05" not in data["home"] and "start=" not in data["home"] + + +class TestRouterRegistration: + """Every browser is registered as its own Workspace widget.""" + + def routes(self): + return {route.path: route for route in browsers.router._api_router.routes} + + def test_proxy_and_table_sink_are_registered_and_hidden(self): + routes = self.routes() + assert "/eia_proxy/{path:path}" in routes + assert "/eia_table" in routes + assert routes["/eia_proxy/{path:path}"].include_in_schema is False + assert routes["/eia_table"].include_in_schema is False + + def test_the_view_beacon_is_registered_and_hidden(self): + routes = self.routes() + assert "/eia_view" in routes + assert routes["/eia_view"].include_in_schema is False + + def test_one_widget_route_per_browser(self): + routes = self.routes() + for browser in browsers.EIA_DATA_BROWSERS: + assert browsers.widget_route(browser) in routes + + @pytest.mark.parametrize("browser", sorted(browsers.EIA_DATA_BROWSERS)) + def test_widget_config_metadata(self, browser): + route = self.routes()[browsers.widget_route(browser)] + config = route.openapi_extra["widget_config"] + spec = browsers.EIA_DATA_BROWSERS[browser] + assert config["name"] == f"EIA {spec['label']} Browser" + assert config["description"] == spec["description"] + assert config["category"] == "EIA" + assert config["subCategory"] == "Data Browsers" + assert config["source"] == ["EIA"] + assert config["widgetId"] == browsers.widget_id(browser) + assert config["raw"] is True + params = {p["paramName"]: p for p in config["params"]} + assert params["theme"]["show"] is False + assert params["raw"]["show"] is False + + @pytest.mark.parametrize("browser", sorted(browsers.EIA_DATA_BROWSERS)) + def test_the_browser_widget_never_refetches_itself(self, browser): + config = self.routes()[browsers.widget_route(browser)].openapi_extra[ + "widget_config" + ] + assert config["refetchInterval"] is False + assert config["staleTime"] == 1000 + + def test_iframe_protocol_does_not_expose_browser_as_a_param(self): + template = browsers._TEMPLATE.read_text(encoding="utf-8") + assert 'paramName: "browser"' not in template + assert "params: []" in template + + def test_frame_load_event_reveals_the_browser(self): + template = browsers._TEMPLATE.read_text(encoding="utf-8") + assert 'frame.addEventListener("load", ready);' in template + + +class TestViewTracking: + """``raw`` must answer for the view on screen, including after click-throughs.""" + + OVERVIEW = "international/overview/world" + COUNTRY = "international/data/country/USA/infographic/total-production" + + def test_raw_follows_the_current_view(self): + browsers.set_current_view(INTERNATIONAL, self.OVERVIEW) + browsers.set_data_target( + INTERNATIONAL, self.OVERVIEW, {"url": "OVERVIEW", "method": "GET"} + ) + assert browsers.get_data_target(INTERNATIONAL)["url"] == "OVERVIEW" + + browsers.set_current_view(INTERNATIONAL, self.COUNTRY) + browsers.set_data_target( + INTERNATIONAL, self.COUNTRY, {"url": "COUNTRY", "method": "GET"} + ) + assert browsers.get_data_target(INTERNATIONAL)["url"] == "COUNTRY" + + def test_returning_to_a_cached_view_resolves_that_view(self): + for view, url in ((self.OVERVIEW, "OVERVIEW"), (self.COUNTRY, "COUNTRY")): + browsers.set_current_view(INTERNATIONAL, view) + browsers.set_data_target(INTERNATIONAL, view, {"url": url, "method": "GET"}) + browsers.set_current_view(INTERNATIONAL, self.OVERVIEW) + assert browsers.get_data_target(INTERNATIONAL)["url"] == "OVERVIEW" + + def test_unseen_view_falls_back_to_the_last_request(self): + browsers.set_data_target( + INTERNATIONAL, self.OVERVIEW, {"url": "OVERVIEW", "method": "GET"} + ) + browsers.set_current_view(INTERNATIONAL, "international/rankings/world") + assert browsers.get_data_target(INTERNATIONAL)["url"] == "OVERVIEW" + + def test_tokenless_spa_requests_resolve_for_a_known_user(self): + browsers.set_current_view(INTERNATIONAL, self.OVERVIEW) + browsers.set_data_target( + INTERNATIONAL, self.OVERVIEW, {"url": "OVERVIEW", "method": "GET"} + ) + assert browsers.get_data_target(INTERNATIONAL)["url"] == "OVERVIEW" + + def test_nothing_recorded_yields_no_target(self): + assert browsers.get_data_target(INTERNATIONAL) is None + + def test_user_falls_back_to_anon_view_data(self): + browsers.set_current_view(INTERNATIONAL, self.OVERVIEW, 1000, "alice") + browsers.set_data_target( + INTERNATIONAL, self.OVERVIEW, {"url": "ANON", "method": "GET"}, 1000, "" + ) + assert browsers.get_data_target(INTERNATIONAL, "alice")["url"] == "ANON" + + def test_user_falls_back_to_anon_last_data(self): + browsers.set_current_view(INTERNATIONAL, "international/unseen", 1000, "alice") + browsers.set_data_target( + INTERNATIONAL, + self.OVERVIEW, + {"url": "LAST_ANON", "method": "GET"}, + 1000, + "", + ) + assert browsers.get_data_target(INTERNATIONAL, "alice")["url"] == "LAST_ANON" + + +class TestEiaViewBeacon: + """The iframe reports each navigation so the server knows the current view.""" + + @pytest.mark.asyncio + async def test_beacon_records_the_view(self): + info = make_info( + "/api/v1/eia_view", + query=f"obb_browser={INTERNATIONAL}&obb_view=international%2Fdata", + method="POST", + ) + response = await browsers.eia_view(info) + assert response.status_code == 204 + assert browsers.get_current_view(INTERNATIONAL) == "international/data" + + @pytest.mark.asyncio + async def test_beacon_without_a_known_browser_records_nothing(self): + await browsers.eia_view( + make_info("/api/v1/eia_view", query="obb_browser=bogus&obb_view=x") + ) + assert not browsers._CURRENT_VIEW + + +class TestWidgetStateBeacon: + @pytest.mark.asyncio + async def test_state_beacon_records_view_and_widget_state(self): + info = make_info( + "/api/v1/eia_state", + query=f"obb_browser={INTERNATIONAL}&obb_view=international%2Fdata&obb_seq=7&obb_user=u1", + method="POST", + body=b'{"selected":"oil"}', + user="u1", + ) + response = await browsers.eia_state(info) + assert response.status_code == 204 + assert browsers.get_current_view(INTERNATIONAL, "u1") == "international/data" + assert browsers.get_widget_state(INTERNATIONAL, "u1") == {"selected": "oil"} + + @pytest.mark.asyncio + async def test_state_beacon_invalid_json_defaults_to_empty_dict(self): + info = make_info( + "/api/v1/eia_state", + query=f"obb_browser={INTERNATIONAL}&obb_view=international%2Fdata&obb_seq=8&obb_user=u2", + method="POST", + body=b"{", + user="u2", + ) + response = await browsers.eia_state(info) + assert response.status_code == 204 + assert browsers.get_widget_state(INTERNATIONAL, "u2") == {} + + @pytest.mark.asyncio + async def test_state_beacon_unknown_browser_is_ignored(self): + response = await browsers.eia_state( + make_info( + "/api/v1/eia_state", + query="obb_browser=bogus", + method="POST", + body=b"{}", + ) + ) + assert response.status_code == 204 + assert not browsers._WIDGET_STATE + + def test_widget_state_uses_freshest_any_user_when_user_unknown(self): + browsers.set_widget_state(INTERNATIONAL, {"value": "older"}, 1, "alice") + browsers.set_widget_state(INTERNATIONAL, {"value": "newer"}, 2, "bob") + assert browsers.get_widget_state(INTERNATIONAL, "carol") == {"value": "newer"} + + def test_widget_state_user_falls_back_to_anon_bucket(self): + browsers.set_widget_state(INTERNATIONAL, {"value": "anon"}, 1, "") + assert browsers.get_widget_state(INTERNATIONAL, "alice") == {"value": "anon"} + + +class TestMcpStateEndpoint: + @pytest.mark.asyncio + async def test_mcp_state_known_browser_uses_raw_table(self, monkeypatch): + async def fake_raw(browser, spec, user): + assert browser == "international" + assert spec == browsers.EIA_DATA_BROWSERS["international"] + assert user == "u1" + return [{"x": 1}] + + monkeypatch.setattr(browsers, "raw_table", fake_raw) + response = await browsers.eia_mcp_state("international", "u1") + assert response.status_code == 200 + assert json.loads(response.body) == [{"x": 1}] + assert response.headers["cache-control"] == "no-store" + + @pytest.mark.asyncio + async def test_mcp_state_unknown_browser_returns_empty(self): + response = await browsers.eia_mcp_state("bogus", "u1") + assert response.status_code == 200 + assert json.loads(response.body) == [] + + +class TestRawTable: + """``raw`` replays the recorded request, falling back to the default view.""" + + @pytest.mark.asyncio + async def test_total_energy_falls_back_to_the_inline_table(self, monkeypatch): + spec = browsers.EIA_DATA_BROWSERS["total_energy"] + html = ( + '<script>var sampleData = {"UNITS":"u","ROWS":' + '[{"MSN":"TETCB","DESCRIPTION":"Total","DATA":{"2024":"1"}}]};</script>' + ) + FakeUpstream( + {f"{browsers._EIA_ORIGIN}/{spec['path']}": (html.encode(), "text/html")} + ).install(monkeypatch) + rows = await browsers.raw_table("total_energy", spec) + assert rows == [ + {"category": "Total", "units": "u", "source_key": "TETCB", "2024 ": 1.0} + ] + + @pytest.mark.asyncio + async def test_falls_back_to_the_browser_default_view(self, monkeypatch): + spec = browsers.EIA_DATA_BROWSERS["electricity"] + captured: dict = {} + + def fake_fetch(target): + captured["target"] = target + return b'{"TABLEDATA":{"ROWS":[]}}', "application/json", 200, target + + monkeypatch.setattr(browsers, "_fetch_sync", fake_fetch) + await browsers.raw_table("electricity", spec) + assert browsers._TABLE_ENDPOINT in captured["target"] + assert f"method={browsers._TABLE_METHOD}" in captured["target"] + + @pytest.mark.asyncio + async def test_browser_without_a_default_view_yields_no_rows(self, monkeypatch): + spec = dict(browsers.EIA_DATA_BROWSERS["electricity"], hash="") + assert await browsers.raw_table("electricity", spec) == [] + + @pytest.mark.asyncio + async def test_recorded_post_is_replayed_as_a_post(self, monkeypatch): + spec = browsers.EIA_DATA_BROWSERS["natural_gas_query"] + captured: dict = {} + + def fake_post(target, body, content_type): + captured.update(target=target, body=body, content_type=content_type) + return b'{"TABLE_DATA":[]}', "application/json", 200 + + monkeypatch.setattr(browsers, "_post_sync", fake_post) + browsers.set_current_view(spec["path"], "ngqs") + browsers.set_data_target( + spec["path"], + "ngqs", + { + "url": "https://www.eia.gov/naturalgas/ngqs/data/report", + "method": "POST", + "body": b"payload", + "content_type": "application/json", + }, + ) + assert await browsers.raw_table("natural_gas_query", spec) == [] + assert captured["body"] == b"payload" + assert captured["content_type"] == "application/json" + + @pytest.mark.asyncio + async def test_non_json_response_yields_no_rows(self, monkeypatch): + spec = browsers.EIA_DATA_BROWSERS["electricity"] + target = "https://www.eia.gov/x" + FakeUpstream({target: (b"<html>", "text/html")}).install(monkeypatch) + browsers.set_current_view(spec["path"], "v") + browsers.set_data_target(spec["path"], "v", {"url": target, "method": "GET"}) + assert await browsers.raw_table("electricity", spec) == [] + + +INTL_FEEDS = { + "countries": [{"iso": "USA", "name": "United States"}], + "political_groups": [{"iso": "OPEC", "name": "OPEC"}], + "units": [{"code": "QBTU", "short_name": "quad Btu"}], + "products": [ + {"id": 44, "name": "primary energy", "parent": None}, + {"id": 80, "name": "fuel ethanol", "parent": 79}, + ], + "activities": [{"id": 1, "name": "production"}], +} + + +def intl_upstream() -> FakeUpstream: + """Serve every International label feed the pivot needs.""" + origin = browsers._EIA_ORIGIN + return FakeUpstream( + { + f"{origin}/international/api/{feed}/data": ( + json.dumps({"data": records}).encode(), + "application/json", + ) + for feed, records in INTL_FEEDS.items() + } + ) + + +class TestTotalEnergyState: + """The MER raw reflects the full tracked state: table, frequency and range.""" + + MER = browsers.EIA_DATA_BROWSERS["total_energy"]["path"] + SPEC = browsers.EIA_DATA_BROWSERS["total_energy"] + PAGE = ( + '<script>var sampleData = {"UNITS":"u","ROWS":[{"MSN":"X",' + '"DESCRIPTION":"Series","DATA":{"2018":"10","2019":"11",' + '"201812":"1.2","201901":"1.3","202604":"9.9"}}]};</script>' + ) + + async def _raw(self, monkeypatch, view, page=None): + browsers.set_current_view(self.MER, view, 2000, "u1") + query = browsers._view_query(view) + url = f"{browsers._EIA_ORIGIN}/{self.MER}" + (f"?{query}" if query else "") + FakeUpstream( + {url: ((page if page is not None else self.PAGE).encode(), "text/html")} + ).install(monkeypatch) + return await browsers.raw_table("total_energy", self.SPEC, "u1") + + def _periods(self, rows): + return [k for k in rows[0] if k not in ("category", "units", "source_key")] + + @pytest.mark.asyncio + async def test_monthly_range_narrows_to_the_slider(self, monkeypatch): + rows = await self._raw( + monkeypatch, f"{self.MER}?tbl=T09.01#/?f=M&start=201812&end=201901" + ) + assert self._periods(rows) == ["2018-12", "2019-01"] + + @pytest.mark.asyncio + async def test_annual_frequency_keeps_yearly_columns(self, monkeypatch): + rows = await self._raw(monkeypatch, f"{self.MER}?tbl=T09.01#/?f=A") + assert self._periods(rows) == ["2018 ", "2019 "] + + @pytest.mark.asyncio + async def test_no_hash_defaults_to_monthly_full_range(self, monkeypatch): + rows = await self._raw(monkeypatch, f"{self.MER}?tbl=T09.01") + assert self._periods(rows) == ["2018-12", "2019-01", "2026-04"] + + @pytest.mark.asyncio + async def test_a_page_without_inline_data_is_empty(self, monkeypatch): + assert ( + await self._raw(monkeypatch, f"{self.MER}?tbl=T99", "<html>no</html>") == [] + ) + + def test_hash_state_reads_frequency_and_range(self): + assert browsers._mer_hash_state( + f"{self.MER}?tbl=T01.01#/?f=M&start=201812&end=202604" + ) == ("M", "201812", "202604") + assert browsers._mer_hash_state("no-hash") == ("", "", "") + + def test_filter_skips_non_dict_rows(self): + payload = {"ROWS": ["junk", {"DATA": {"201812": "1"}}]} + browsers._filter_mer_payload(payload, "M", "", "") + assert payload["ROWS"][1]["DATA"] == {"201812": "1"} + + +class TestInternationalLabelMaps: + """Names for country, unit, product and activity are fetched once and cached.""" + + @pytest.mark.asyncio + async def test_labels_fetched_once_then_cached(self, monkeypatch): + upstream = intl_upstream() + upstream.install(monkeypatch) + labels = await browsers._intl_label_maps() + assert labels["region"] == {"USA": "United States", "OPEC": "OPEC"} + assert labels["unit"] == {"QBTU": "quad Btu"} + assert labels["product"] == {"44": "primary energy", "80": "fuel ethanol"} + assert labels["activity"] == {"1": "production"} + assert labels["parent"] == {"44": None, "80": 79} + + await browsers._intl_label_maps() + assert len(upstream.calls) == len(INTL_FEEDS) + + @pytest.mark.asyncio + async def test_unreachable_labels_degrade_to_codes(self, monkeypatch): + async def fake_fetch(_target): + raise OSError("offline") + + monkeypatch.setattr(browsers, "_fetch_upstream", fake_fetch) + assert await browsers._intl_label_maps() == {} + + @pytest.mark.asyncio + async def test_overview_payload_uses_the_infographic_pivot(self, monkeypatch): + intl_upstream().install(monkeypatch) + rows = await browsers._intl_rows( + { + "data": [ + { + "series_id": "INTL.44-1-USA-QBTU.A", + "iso": "USA", + "unit": "QBTU", + "frequency": "A", + "data": [{"date": 1672531200000, "value": 96.34}], + } + ] + } + ) + assert rows == [ + { + "category": "Production", + "country": "United States", + "units": "quad Btu", + "source_key": "INTL.44-1-USA-QBTU.A", + "2023 ": 96.34, + } + ] + + @pytest.mark.asyncio + async def test_unrecognised_payload_is_not_labelled(self): + assert await browsers._intl_rows({"data": [1, 2]}) is None + + +IMPORTS_CONFIG = { + "countries": [{"id": "SA", "name": "Saudi Arabia"}], + "regions": [{"id": "WORLD", "name": "World"}], + "opecNonOpec": [{"id": "Y", "name": "OPEC"}, {"id": "N", "name": "Non-OPEC"}], + "refineries": [{"id": "465", "name": "Motiva Port Arthur"}], + "ports": [{"id": "US", "name": "Total U.S."}], + "states": [{"id": "TX", "name": "Texas"}], + "padds": [{"id": "3", "name": "PADD3 (Gulf Coast)"}], + "grades": [{"id": "LSO", "name": "Light Sour"}], +} + + +class TestBrowserSpecificLabelling: + """Imports and NGQS label their tables from sources the payload does not carry.""" + + @pytest.mark.asyncio + async def test_imports_config_fetched_once_then_cached(self, monkeypatch): + browsers._IMPORTS_LABELS.clear() + upstream = FakeUpstream( + { + f"{browsers._EIA_ORIGIN}/{browsers._IMPORTS_CONFIG}": ( + json.dumps(IMPORTS_CONFIG).encode(), + "application/json", + ) + } + ) + upstream.install(monkeypatch) + labels = await browsers._imports_label_maps() + assert labels["origin"]["REG"] == {"WORLD": "World"} + assert labels["origin"]["OPN"]["Y"] == "OPEC" + assert labels["destination"]["RP"] == {"3": "PADD3 (Gulf Coast)"} + assert labels["destination"]["RS"] == {"TX": "Texas"} + assert labels["grade"] == {"LSO": "Light Sour"} + + await browsers._imports_label_maps() + assert len(upstream.calls) == 1 + browsers._IMPORTS_LABELS.clear() + + @pytest.mark.asyncio + async def test_unreachable_imports_config_degrades_to_codes(self, monkeypatch): + browsers._IMPORTS_LABELS.clear() + + async def fake_fetch(_target): + raise OSError("offline") + + monkeypatch.setattr(browsers, "_fetch_upstream", fake_fetch) + assert await browsers._imports_label_maps() == {} + + @pytest.mark.asyncio + async def test_imports_payload_is_labelled(self, monkeypatch): + browsers._IMPORTS_LABELS.clear() + FakeUpstream( + { + f"{browsers._EIA_ORIGIN}/{browsers._IMPORTS_CONFIG}": ( + json.dumps(IMPORTS_CONFIG).encode(), + "application/json", + ) + } + ).install(monkeypatch) + rows = await browsers._labelled_rows( + "petroleum_imports", + { + "TABLE_DATA": [ + { + "seriesID": "PET_IMPORTS.WORLD-RP_3-LSO.M", + "data": {"200901": 9091}, + } + ] + }, + ) + assert rows[0]["category"] == ( + "Imports of Light Sour from World to PADD3 (Gulf Coast), monthly" + ) + browsers._IMPORTS_LABELS.clear() + + @pytest.mark.asyncio + async def test_empty_imports_payload_is_not_labelled(self): + assert ( + await browsers._labelled_rows("petroleum_imports", {"TABLE_DATA": []}) + is None + ) + + @pytest.mark.asyncio + async def test_international_overview_ranking_is_labelled(self, monkeypatch): + browsers._INTL_LABELS.clear() + feeds = { + "countries": [{"iso": "CHN", "name": "China"}], + "political_groups": [], + "units": [{"code": "QBTU", "short_name": "quad Btu"}], + "products": [{"id": 44, "name": "primary energy", "parent": None}], + "activities": [{"id": 1, "name": "production"}], + } + FakeUpstream( + { + f"{browsers._EIA_ORIGIN}/international/api/{feed}/data": ( + json.dumps({"data": rows}).encode(), + "application/json", + ) + for feed, rows in feeds.items() + } + ).install(monkeypatch) + rows = await browsers._labelled_rows( + "international", + { + "data": [ + { + "productid": 44, + "activityid": 1, + "frequency": "A", + "ranking": 1, + "iso": "CHN", + "date": "2024-01-01", + "value": 130.757, + "unitcode": "QBTU", + "ug_bmi": 0, + }, + "not a record", + ] + }, + ) + assert rows == [ + { + "category": "Primary energy production", + "country": "China", + "rank": 1.0, + "value": 130.757, + "units": "quad Btu", + "period": "2024", + "source_key": "CHN", + } + ] + browsers._INTL_LABELS.clear() + + @pytest.mark.asyncio + async def test_ngqs_payload_uses_its_grid_headers(self): + rows = await browsers._labelled_rows( + "natural_gas_query", + { + "columns": [{"headerName": "Area", "field": "a"}], + "data": [{"a": "U.S. Total"}], + }, + ) + assert rows == [{"Area": "U.S. Total"}] + + @pytest.mark.asyncio + async def test_ngqs_headers_strip_their_html_line_breaks(self): + rows = await browsers._labelled_rows( + "natural_gas_query", + { + "columns": [ + {"headerName": "Report<BR>State<BR>", "field": "s"}, + {"headerName": "Gas<BR>Field Code", "field": "g", "numeric": True}, + ], + "data": [{"s": "AK", "g": "691992"}], + }, + ) + assert rows == [{"Report State": "AK", "Gas Field Code": 691992.0}] + + @pytest.mark.asyncio + async def test_other_browsers_use_the_shared_pivot(self): + assert await browsers._labelled_rows("electricity", {"TABLEDATA": {}}) is None + + @pytest.mark.asyncio + async def test_non_dict_payload_is_not_labelled(self): + assert await browsers._labelled_rows("international", []) is None + + +class TestPlantAndMineLists: + """The plant-, mine- and shipment-level views are a record per site.""" + + PAYLOAD = { + "SINGLE_STATE": False, + "DATA": [ + { + "id": 66729, + "Plant Name": "(3K) 59 Hetcheltown Rd", + "Plant Code": 66729, + "State": "NY", + "Sector Name": "Electric utility non-cogen", + "lat": 42.87657, + "lon": -73.91048, + "HAS_DATA": True, + } + ], + "DATA_COLUMNS": ["Plant Name", "Plant Code", "State", "Sector Name"], + "DESCRIPTION": "List of plants", + } + + def test_only_the_columns_the_grid_shows_are_kept(self): + rows = browsers._plant_list_rows(self.PAYLOAD) + assert rows == [ + { + "Plant Name": "(3K) 59 Hetcheltown Rd", + "Plant Code": 66729, + "State": "NY", + "Sector Name": "Electric utility non-cogen", + } + ] + + def test_the_record_carries_more_than_the_table_does(self): + rows = browsers._plant_list_rows(self.PAYLOAD) + assert "lat" not in rows[0] + assert "HAS_DATA" not in rows[0] + + def test_a_plant_list_is_dispatched_by_rows_from_payload(self): + rows = browsers.rows_from_payload(self.PAYLOAD) + assert rows[0]["Plant Name"] == "(3K) 59 Hetcheltown Rd" + + @pytest.mark.parametrize( + "payload", + [ + {"DATA": [], "DATA_COLUMNS": ["Plant Name"]}, + {"DATA": ["junk"], "DATA_COLUMNS": ["Plant Name"]}, + {"DATA": [{"a": 1}], "DATA_COLUMNS": [7]}, + {"DATA": [{"a": 1}]}, + {"DATA_COLUMNS": ["Plant Name"]}, + ], + ) + def test_anything_that_is_not_a_site_list_is_declined(self, payload): + assert browsers._plant_list_rows(payload) is None + + @pytest.mark.parametrize( + "method", + ["method=getPlantList", "method=getMineList", "method=getShipmentList"], + ) + def test_the_site_lists_count_as_table_data(self, method): + """These were being discarded, so the plant/mine views served nothing.""" + target = f"https://www.eia.gov/coal/data/browser/data/index.php?{method}" + assert browsers.is_data_response(target, "application/json") is True + + +class TestPagedPayload: + """A view whose data arrives in pages must be replayed to its end.""" + + def _payload(self, keys, total): + return { + "data": {key: {"2023": [1.0, 1.0]} for key in keys}, + "totalCount": total, + "recordCount": len(keys), + } + + @pytest.mark.asyncio + async def test_every_page_is_followed(self, monkeypatch): + base = ( + "https://www.eia.gov/international/api/series_data/data" + "?frequency=A&limit=2&offset=0" + ) + page2 = ( + "https://www.eia.gov/international/api/series_data/data" + "?frequency=A&limit=2&offset=2" + ) + FakeUpstream( + { + page2: ( + json.dumps(self._payload(["c", "d"], 4)).encode(), + "application/json", + ) + } + ).install(monkeypatch) + merged = await browsers._all_pages({"url": base}, self._payload(["a", "b"], 4)) + assert sorted(merged["data"]) == ["a", "b", "c", "d"] + assert merged["recordCount"] == 4 + + @pytest.mark.asyncio + async def test_a_complete_payload_is_left_alone(self, monkeypatch): + def unused(_target): + raise AssertionError("a complete payload must not be re-fetched") + + monkeypatch.setattr(browsers, "_fetch_sync", unused) + payload = self._payload(["a", "b"], 2) + assert ( + await browsers._all_pages({"url": "https://x/y?limit=2"}, payload) + is payload + ) + + @pytest.mark.asyncio + @pytest.mark.parametrize( + "url", + [ + "https://www.eia.gov/x?limit=0", + "https://www.eia.gov/x?limit=nope", + "https://www.eia.gov/x", + ], + ) + async def test_a_payload_with_no_usable_page_size_is_left_alone(self, url): + payload = self._payload(["a"], 9) + assert await browsers._all_pages({"url": url}, payload) is payload + + @pytest.mark.asyncio + @pytest.mark.parametrize( + "payload", + [ + {"data": [1, 2]}, + {"data": {"a": {}}, "totalCount": "many"}, + "not a payload", + ], + ) + async def test_an_unpaged_shape_is_left_alone(self, payload): + assert ( + await browsers._all_pages({"url": "https://x?limit=2"}, payload) is payload + ) + + @pytest.mark.asyncio + async def test_a_broken_page_stops_the_walk(self, monkeypatch): + base = "https://www.eia.gov/x?limit=2&offset=0" + FakeUpstream( + { + "https://www.eia.gov/x?limit=2&offset=2": ( + b"not json", + "application/json", + ) + } + ).install(monkeypatch) + merged = await browsers._all_pages({"url": base}, self._payload(["a", "b"], 6)) + assert sorted(merged["data"]) == ["a", "b"] + + @pytest.mark.asyncio + async def test_an_empty_page_stops_the_walk(self, monkeypatch): + base = "https://www.eia.gov/x?limit=2&offset=0" + FakeUpstream( + { + "https://www.eia.gov/x?limit=2&offset=2": ( + json.dumps({"data": {}}).encode(), + "application/json", + ) + } + ).install(monkeypatch) + merged = await browsers._all_pages({"url": base}, self._payload(["a", "b"], 6)) + assert sorted(merged["data"]) == ["a", "b"] + + +class TestRecordedViewOrdering: + """A late report must never drag the current view backwards.""" + + def test_an_older_report_does_not_overwrite_a_newer_one(self): + path = ELECTRICITY + browsers.set_data_target(path, "view/new", {"url": "NEW"}, 2000) + browsers.set_data_target(path, "view/old", {"url": "OLD"}, 1000) + assert browsers.get_data_target(path)["url"] == "NEW" + + @pytest.mark.asyncio + async def test_a_data_response_records_the_view_that_asked_for_it( + self, monkeypatch + ): + target = "https://www.eia.gov/international/api/data/data?x=1" + FakeUpstream({target: (b'{"response":{}}', "application/json")}).install( + monkeypatch + ) + await browsers.eia_proxy( + "international/api/data/data", + make_info( + "/api/v1/eia_proxy/international/api/data/data", + query=f"x=1&obb_browser={INTERNATIONAL}" + "&obb_view=international%2Fdata&obb_seq=5", + ), + ) + assert browsers.get_current_view(INTERNATIONAL) == "international/data" + assert browsers.get_data_target(INTERNATIONAL)["url"] == target + + +class TestInternationalRawEndToEnd: + """International's grid API is unreachable, so raw is served from its payload.""" + + LABEL_FEEDS = { + "countries": [{"iso": "USA", "name": "United States"}], + "political_groups": [], + "units": [{"code": "QBTU", "short_name": "quad Btu"}], + "products": [{"id": 44, "name": "primary energy", "parent": None}], + "activities": [{"id": 1, "name": "production"}], + } + + def _upstream(self, target, payload): + responses = { + f"{browsers._EIA_ORIGIN}/international/api/{feed}/data": ( + json.dumps({"data": rows}).encode(), + "application/json", + ) + for feed, rows in self.LABEL_FEEDS.items() + } + responses[target] = (json.dumps(payload).encode(), "application/json") + return FakeUpstream(responses) + + @pytest.mark.asyncio + async def test_raw_serves_the_view_the_page_is_showing(self, monkeypatch): + spec = browsers.EIA_DATA_BROWSERS["international"] + target = f"{browsers._EIA_ORIGIN}/international/api/series_data/data" + payload = {"data": {"INTL.44-1-USA-QBTU.A": {"2023": [96.0, 96.34]}}} + self._upstream(target, payload).install(monkeypatch) + + browsers.set_current_view(spec["path"], "international/data/world") + browsers.set_data_target( + spec["path"], "international/data/world", {"url": target, "method": "GET"} + ) + rows = await browsers.raw_table("international", spec) + assert rows == [ + { + "category": "Production", + "country": "United States", + "units": "quad Btu", + "source_key": "INTL.44-1-USA-QBTU.A", + "2023 ": 96.34, + } + ] + + @pytest.mark.asyncio + async def test_the_widget_endpoint_serves_those_rows(self, monkeypatch): + spec = browsers.EIA_DATA_BROWSERS["international"] + target = f"{browsers._EIA_ORIGIN}/international/api/series_data/data" + payload = {"data": {"INTL.44-1-USA-QBTU.A": {"2023": [96.0, 96.34]}}} + self._upstream(target, payload).install(monkeypatch) + browsers.set_current_view(spec["path"], "international/data/world") + browsers.set_data_target( + spec["path"], "international/data/world", {"url": target, "method": "GET"} + ) + + routes = {r.path: r for r in browsers.router._api_router.routes} + endpoint = routes["/international_browser"].endpoint + response = await endpoint( + theme="dark", raw=True, info=make_info("/api/v1/international_browser") + ) + assert json.loads(response.body)[0]["country"] == "United States" + + +class TestBrowserEndpointNoRequest: + @pytest.mark.asyncio + async def test_raw_endpoint_without_request_info_unwraps_json(self, monkeypatch): + endpoint = browsers._browser_endpoint("international") + + async def fake_render(_browser, _theme, _raw, _info): + return browsers.JSONResponse( + content=[{"row": 1}], headers={"Cache-Control": "no-store"} + ) + + monkeypatch.setattr(browsers, "render_browser", fake_render) + out = await endpoint(theme="dark", raw=True) + assert out == [{"row": 1}] + + +class TestMapContrast: + """The map series is unreadable at eia.gov's own colours on a white page.""" + + def _page(self, dark): + return browsers.rewrite_html( + "<head></head>", PROXY_PREFIX, dark=dark, browser=INTERNATIONAL + ) + + @pytest.mark.parametrize("dark", [False, True]) + def test_regions_with_no_value_are_given_a_readable_fill(self, dark): + page = self._page(dark) + assert ( + ".highcharts-map-series .highcharts-null-point{fill:#dde2e8!important}" + in page + ) + + @pytest.mark.parametrize("dark", [False, True]) + def test_every_region_is_outlined_so_the_shapes_read(self, dark): + page = self._page(dark) + assert ( + ".highcharts-map-series .highcharts-point" + "{stroke:#98a2b0!important;stroke-width:0.7px!important}" in page + ) + + def test_a_choropleths_own_colours_are_left_alone(self): + """A shaded map's fill is the data; only no-data regions may be recoloured.""" + page = self._page(False) + assert ".highcharts-map-series .highcharts-point{fill:" not in page diff --git a/openbb_platform/providers/eia/tests/test_catalog.py b/openbb_platform/providers/eia/tests/test_catalog.py new file mode 100644 index 00000000000..da9179cbbcf --- /dev/null +++ b/openbb_platform/providers/eia/tests/test_catalog.py @@ -0,0 +1,365 @@ +"""Tests for the EIA dataset catalog runtime module.""" + +from datetime import date, datetime + +import pytest +from openbb_core.app.model.abstract.error import OpenBBError + +from openbb_us_eia.utils import catalog + +GROUPS = [ + "aeo", + "coal", + "crude_oil_imports", + "densified_biomass", + "electricity", + "electricity_grid", + "ieo", + "international", + "natural_gas", + "nuclear_outages", + "petroleum", + "seds", + "state_electricity_profiles", + "total_energy", +] + + +class TestCatalogIntegrity: + """The packaged catalog asset is complete and well-formed.""" + + def test_all_groups_present(self): + assert sorted(catalog.load_catalog()) == GROUPS + + @pytest.mark.parametrize("group", GROUPS) + def test_dataset_specs_well_formed(self, group): + datasets = catalog.get_group(group)["datasets"] + assert datasets + for slug, spec in datasets.items(): + assert len(slug) <= 60 + if group not in ("aeo", "ieo"): + assert slug == catalog.snake_case(slug) + assert spec["path"] + assert spec["name"] + assert spec["frequencies"] + assert spec["default_frequency"] in spec["frequencies"] + for freq in spec["frequencies"].values(): + assert freq["path"] + catalog.parse_period("2020-01-01T00", 'YYYY-MM-DD"T"HH24') + assert freq["format"] + assert spec["data_columns"] + for column, detail in spec["data_columns"].items(): + assert column == catalog.snake_case(column) + assert detail["id"] + for facet, detail in spec["facets"].items(): + assert facet == catalog.snake_case(facet) + assert detail["id"] + + @pytest.mark.parametrize("group", GROUPS) + def test_period_formats_supported(self, group): + for spec in catalog.get_group(group)["datasets"].values(): + for freq in spec["frequencies"].values(): + catalog.format_period(date(2024, 5, 15), freq["format"]) + + def test_grid_group_merges_daily_routes(self): + spec = catalog.get_dataset("electricity_grid", "demand") + assert spec["frequencies"]["daily"]["path"].startswith("electricity/rto/daily") + assert spec["frequencies"]["hourly"]["path"] == "electricity/rto/region-data" + assert spec["facets"]["timezone"]["frequencies"] == ["daily"] + + def test_petroleum_duplicates_dropped(self): + paths = { + spec["path"] for spec in catalog.get_group("petroleum")["datasets"].values() + } + assert "petroleum/move/imc1" not in paths + assert "petroleum/pri/imc1" in paths + + +class TestCatalogLookups: + """Lookup helpers resolve entries and raise on unknown keys.""" + + def test_get_group_unknown_raises(self): + with pytest.raises(OpenBBError, match="Unknown EIA group"): + catalog.get_group("wind") + + def test_get_dataset_unknown_raises(self): + with pytest.raises(OpenBBError, match="Unknown dataset"): + catalog.get_dataset("coal", "not_a_dataset") + + def test_dataset_choices(self): + assert "receipts" in catalog.dataset_choices("coal") + + def test_facet_choices_embedded(self): + choices = catalog.facet_choices("coal", "coal_rank") + assert {"value", "label", "param"} == set(choices[0]) + + def test_facet_choices_too_large_is_empty(self): + assert catalog.facet_choices("petroleum", "region") == [] + + def test_facet_schema_with_choices(self): + schema = catalog.facet_schema("coal", "coal_rank") + assert schema["multiple_items_allowed"] is True + assert "metallurgical" in schema["choices"] + + def test_facet_schema_without_choices(self): + assert catalog.facet_schema("petroleum", "series") == { + "multiple_items_allowed": True + } + + def test_facet_description_lists_applicability(self): + text = catalog.facet_description("coal", "country") + assert "comma-separated" in text + assert "exports_imports_quantity_price" in text + + def test_facet_description_single_select(self): + text = catalog.facet_description("coal", "market_type", multiple=False) + assert "comma-separated" not in text + + def test_facet_description_uncatalogued_values(self): + text = catalog.facet_description("petroleum", "series") + assert "facet_options" in text + + def test_snake_case(self): + assert catalog.snake_case("percentOutage") == "percent_outage" + assert catalog.snake_case("heat-content") == "heat_content" + assert catalog.snake_case("stateID") == "state_id" + + +class TestResolveFrequency: + """Frequency resolution validates against the dataset.""" + + def test_default_frequency(self): + spec = catalog.get_dataset("coal", "consumption_and_quality") + frequency, freq_spec = catalog.resolve_frequency(spec, None) + assert frequency == spec["default_frequency"] + assert freq_spec["path"] == spec["path"] + + def test_explicit_frequency(self): + spec = catalog.get_dataset("coal", "consumption_and_quality") + frequency, _ = catalog.resolve_frequency(spec, "annual") + assert frequency == "annual" + + def test_invalid_frequency_raises(self): + spec = catalog.get_dataset("coal", "consumption_and_quality") + with pytest.raises(OpenBBError, match="not available"): + catalog.resolve_frequency(spec, "hourly") + + def test_missing_default_falls_back_to_first(self): + spec = {"path": "x", "frequencies": {"annual": {}}, "default_frequency": None} + frequency, _ = catalog.resolve_frequency(spec, None) + assert frequency == "annual" + + +class TestResolveDataColumns: + """Data column resolution maps snake names onto API ids.""" + + def test_default_returns_all(self): + spec = catalog.get_dataset("nuclear_outages", "us_nuclear_outages") + assert catalog.resolve_data_columns(spec, None) == [ + "capacity", + "outage", + "percentOutage", + ] + + def test_subset_and_normalization(self): + spec = catalog.get_dataset("nuclear_outages", "us_nuclear_outages") + assert catalog.resolve_data_columns(spec, "percent_outage, capacity") == [ + "percentOutage", + "capacity", + ] + + def test_invalid_raises(self): + spec = catalog.get_dataset("nuclear_outages", "us_nuclear_outages") + with pytest.raises(OpenBBError, match="Invalid data_type"): + catalog.resolve_data_columns(spec, "megawatts") + + +class TestResolveFacets: + """Facet resolution maps canonical parameters onto API facet ids.""" + + def test_maps_and_splits_values(self): + spec = catalog.get_dataset("coal", "exports_imports_quantity_price") + query = catalog.resolve_facets( + spec, "quarterly", {"coal_rank": "MET, STM", "country": "CA"} + ) + assert query == {"coalRankId": ["MET", "STM"], "countryId": ["CA"]} + + def test_none_and_empty_skipped(self): + spec = catalog.get_dataset("coal", "exports_imports_quantity_price") + assert ( + catalog.resolve_facets(spec, "annual", {"coal_rank": None, "country": ""}) + == {} + ) + + def test_inapplicable_facet_raises(self): + spec = catalog.get_dataset("coal", "exports_imports_quantity_price") + with pytest.raises(OpenBBError, match="does not apply"): + catalog.resolve_facets(spec, "annual", {"mine_state": "PA"}) + + def test_frequency_restricted_facet(self): + spec = catalog.get_dataset("electricity_grid", "demand") + assert catalog.resolve_facets(spec, "daily", {"timezone": "Eastern"}) == { + "timezone": ["Eastern"] + } + with pytest.raises(OpenBBError, match="only applies"): + catalog.resolve_facets(spec, "hourly", {"timezone": "Eastern"}) + + def test_embedded_choices_correct_casing(self): + spec = catalog.get_dataset("coal", "exports_imports_quantity_price") + query = catalog.resolve_facets(spec, "quarterly", {"coal_rank": "met,stm"}) + assert query == {"coalRankId": ["MET", "STM"]} + + def test_embedded_choices_map_param_slugs_to_codes(self): + spec = catalog.get_dataset("coal", "exports_imports_quantity_price") + query = catalog.resolve_facets( + spec, "quarterly", {"coal_rank": "metallurgical,steam_coal"} + ) + assert query == {"coalRankId": ["MET", "STM"]} + + def test_embedded_choices_invalid_value_lists_choices(self): + spec = catalog.get_dataset("coal", "exports_imports_quantity_price") + with pytest.raises(OpenBBError, match="metallurgical") as excinfo: + catalog.resolve_facets(spec, "quarterly", {"coal_rank": "ANTHRACITE"}) + assert "Invalid coal_rank value(s): ANTHRACITE" in str(excinfo.value) + assert "steam_coal" in str(excinfo.value) + + def test_invalid_value_on_large_vocabulary_caps_choices(self): + spec = catalog.get_dataset("seds", "seds") + with pytest.raises(OpenBBError, match=r"plus \d+ more") as excinfo: + catalog.resolve_facets(spec, "annual", {"series": "NOT_A_SERIES"}) + assert "facet_options" in str(excinfo.value) + + +class TestLabelSlugs: + """Readable parameter slugs derived from display labels.""" + + @pytest.mark.parametrize( + ("label", "slug"), + [ + ("Battery storage", "battery_storage"), + ("Spot Price FOB", "spot_price_fob"), + ( + "U.S. Gulf Coast Kerosene-Type Jet Fuel", + "us_gulf_coast_kerosene_type_jet_fuel", + ), + ( + "Alcoa Power Generating, Inc. - Yadkin Division", + "alcoa_power_generating_yadkin_division", + ), + ("Table 73. Hydrogen Market Projections", "hydrogen_market_projections"), + ("Wind & Solar (test)", "wind_and_solar"), + ("", "value"), + ], + ) + def test_label_slug(self, label, slug): + assert catalog.label_slug(label) == slug + + def test_label_slug_caps_length_at_word_boundary(self): + slug = catalog.label_slug("word " * 30) + assert len(slug) <= 60 + assert not slug.endswith("_") + + def test_attach_params_identical_labels_share_one_slug(self): + choices = catalog.attach_params( + [ + {"value": "5-0", "label": "United States"}, + {"value": "1-0", "label": "United States"}, + ] + ) + assert [choice["param"] for choice in choices] == [ + "united_states", + "united_states", + ] + + def test_attach_params_distinct_labels_keep_parenthetical(self): + choices = catalog.attach_params( + [ + {"value": "8023", "label": "Columbia (WI)"}, + {"value": "2123", "label": "Columbia (SC)"}, + ] + ) + assert [choice["param"] for choice in choices] == [ + "columbia_wi", + "columbia_sc", + ] + + def test_attach_params_code_suffix_is_last_resort(self): + choices = catalog.attach_params( + [ + {"value": "A1", "label": "Columbia (WI)"}, + {"value": "A2", "label": "Columbia ( WI )"}, + ] + ) + params = [choice["param"] for choice in choices] + assert params[0] == "columbia_wi" + assert params[1] == "columbia_wi_a2" + + def test_shared_slug_resolves_to_every_code(self): + spec = catalog.get_dataset("aeo", "2025") + query = catalog.resolve_facets(spec, "annual", {"region": "united_states"}) + assert sorted(query["regionId"]) == ["1-0", "5-0"] + + +class TestFormatChoiceList: + """Choice list rendering for error messages.""" + + def test_renders_sorted_by_label(self): + text = catalog.format_choice_list({"B": "beta", "A": "alpha"}, "fuel") + assert text.index("A = alpha") < text.index("B = beta") + + def test_caps_and_hints_overflow(self): + vocabulary = {f"V{i:03d}": f"Label {i:03d}" for i in range(60)} + text = catalog.format_choice_list(vocabulary, "series") + assert "V049" in text + assert "V051" not in text + assert "... 10 more" in text + assert "facet_options" in text + + +class TestPeriodConversion: + """Period strings round-trip through format and parse helpers.""" + + @pytest.mark.parametrize( + ("fmt", "value", "expected"), + [ + ("YYYY", date(2024, 5, 15), "2024"), + ("YYYY-MM", date(2024, 5, 15), "2024-05"), + ('YYYY-"Q"Q', date(2024, 5, 15), "2024-Q2"), + ("YYYY-MM-DD", date(2024, 5, 15), "2024-05-15"), + ('YYYY-MM-DD"T"HH24', date(2024, 5, 15), "2024-05-15T00"), + ( + 'YYYY-MM-DD"T"HH24', + datetime(2024, 5, 15, 7, 30), + "2024-05-15T07", + ), + ('YYYY-MM-DD"T"HH24TZH', date(2024, 5, 15), "2024-05-15T00"), + ], + ) + def test_format_period(self, fmt, value, expected): + assert catalog.format_period(value, fmt) == expected + + def test_format_period_unknown_raises(self): + with pytest.raises(OpenBBError, match="Unsupported"): + catalog.format_period(date(2024, 1, 1), "WW") + + @pytest.mark.parametrize( + ("fmt", "value", "expected"), + [ + ("YYYY", "2024", date(2024, 1, 1)), + ("YYYY-MM", "2024-05", date(2024, 5, 1)), + ('YYYY-"Q"Q', "2024-Q3", date(2024, 7, 1)), + ("YYYY-MM-DD", "2024-05-15", date(2024, 5, 15)), + ('YYYY-MM-DD"T"HH24', "2024-05-15T07", datetime(2024, 5, 15, 7)), + ( + 'YYYY-MM-DD"T"HH24TZH', + "2024-05-15T07-04", + datetime.fromisoformat("2024-05-15T07:00-04:00"), + ), + ], + ) + def test_parse_period(self, fmt, value, expected): + assert catalog.parse_period(value, fmt) == expected + + def test_parse_period_unknown_raises(self): + with pytest.raises(OpenBBError, match="Unsupported"): + catalog.parse_period("2024", "WW") diff --git a/openbb_platform/providers/eia/tests/test_data_browser.py b/openbb_platform/providers/eia/tests/test_data_browser.py new file mode 100644 index 00000000000..011590fbc03 --- /dev/null +++ b/openbb_platform/providers/eia/tests/test_data_browser.py @@ -0,0 +1,173 @@ +"""Tests for the EIA Data Browser model.""" + +from datetime import date + +import pytest +from openbb_core.app.model.abstract.error import OpenBBError + +from openbb_us_eia.models.data_browser import ( + EiaDataBrowserFetcher, + EiaDataBrowserQueryParams, +) + +METADATA = { + "response": { + "id": "spt", + "frequency": [ + {"id": "daily", "format": "YYYY-MM-DD"}, + {"id": "monthly", "format": "YYYY-MM"}, + ], + "defaultFrequency": "daily", + "data": {"value": {"units": "$/BBL"}}, + "facets": [{"id": "duoarea"}, {"id": "product"}], + } +} + +PAGE = { + "response": { + "total": "2", + "dateFormat": "YYYY-MM", + "data": [ + {"period": "2024-02", "product": "EPCBRENT", "value": "83.5"}, + {"period": "2024-01", "product": "EPCBRENT", "value": "80.1"}, + ], + } +} + + +def _stub(monkeypatch, metadata=METADATA, page=PAGE): + from openbb_core.provider.utils import helpers as core_helpers + + calls = {"urls": []} + + async def fake_amake_request(url, response_callback=None, **kwargs): + calls["urls"].append(url) + return metadata if "/data/" not in url else page + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + return calls + + +class TestDataBrowserQueryParams: + """Route cleaning and facet string parsing.""" + + def test_route_cleaned(self): + query = EiaDataBrowserQueryParams(route=" /petroleum/pri/spt/data/ ") + assert query.route == "petroleum/pri/spt" + + def test_facet_query_parses_pairs(self): + query = EiaDataBrowserQueryParams( + route="x", facets="duoarea:NUS; product:EPCBRENT,EPCWTI" + ) + assert query.facet_query == { + "duoarea": ["NUS"], + "product": ["EPCBRENT", "EPCWTI"], + } + + def test_facet_query_empty(self): + assert EiaDataBrowserQueryParams(route="x").facet_query == {} + + def test_facet_query_invalid_pair_raises(self): + query = EiaDataBrowserQueryParams(route="x", facets="duoarea=NUS") + with pytest.raises(OpenBBError, match="Invalid facet filter"): + _ = query.facet_query + + def test_transform_query_validates_facets(self): + with pytest.raises(OpenBBError, match="Invalid facet filter"): + EiaDataBrowserFetcher.transform_query({"route": "x", "facets": "bad"}) + + +class TestDataBrowserFetcher: + """Live-metadata resolution and the request pipeline.""" + + @pytest.mark.asyncio + async def test_fetch_data_end_to_end(self, monkeypatch): + calls = _stub(monkeypatch) + rows = await EiaDataBrowserFetcher.fetch_data( + { + "route": "petroleum/pri/spt", + "frequency": "monthly", + "facets": "product:EPCBRENT", + "start_date": date(2024, 1, 1), + "end_date": date(2024, 2, 29), + }, + {"eia_api_key": "MOCK_KEY"}, + ) + assert len(rows) == 2 + assert rows[0].date == date(2024, 1, 1) + assert rows[0].model_dump()["value"] == 80.1 + data_url = calls["urls"][-1] + assert "start=2024-01" in data_url + assert "end=2024-02" in data_url + assert "facets%5Bproduct%5D%5B%5D=EPCBRENT" in data_url + + @pytest.mark.asyncio + async def test_default_frequency_used(self, monkeypatch): + calls = _stub(monkeypatch) + await EiaDataBrowserFetcher.fetch_data( + {"route": "petroleum/pri/spt"}, {"eia_api_key": "MOCK_KEY"} + ) + assert "frequency=daily" in calls["urls"][-1] + + @pytest.mark.asyncio + async def test_category_route_raises(self, monkeypatch): + metadata = {"response": {"routes": [{"id": "spt"}, {"id": "gnd"}]}} + _stub(monkeypatch, metadata=metadata) + with pytest.raises(OpenBBError, match="not a data route"): + await EiaDataBrowserFetcher.fetch_data( + {"route": "petroleum/pri"}, {"eia_api_key": "MOCK_KEY"} + ) + + @pytest.mark.asyncio + async def test_unknown_route_raises(self, monkeypatch): + _stub(monkeypatch, metadata={"response": {}}) + with pytest.raises(OpenBBError, match="not a valid EIA data route"): + await EiaDataBrowserFetcher.fetch_data( + {"route": "nonsense"}, {"eia_api_key": "MOCK_KEY"} + ) + + @pytest.mark.asyncio + async def test_invalid_frequency_raises(self, monkeypatch): + _stub(monkeypatch) + with pytest.raises(OpenBBError, match="Frequency 'hourly'"): + await EiaDataBrowserFetcher.fetch_data( + {"route": "petroleum/pri/spt", "frequency": "hourly"}, + {"eia_api_key": "MOCK_KEY"}, + ) + + @pytest.mark.asyncio + async def test_data_type_subset_requested(self, monkeypatch): + calls = _stub(monkeypatch) + await EiaDataBrowserFetcher.fetch_data( + {"route": "petroleum/pri/spt", "data_type": "value"}, + {"eia_api_key": "MOCK_KEY"}, + ) + assert "data%5B0%5D=value" in calls["urls"][-1] + + @pytest.mark.asyncio + async def test_invalid_data_type_raises(self, monkeypatch): + _stub(monkeypatch) + with pytest.raises(OpenBBError, match="Invalid data_type"): + await EiaDataBrowserFetcher.fetch_data( + {"route": "petroleum/pri/spt", "data_type": "quantity"}, + {"eia_api_key": "MOCK_KEY"}, + ) + + @pytest.mark.asyncio + async def test_unknown_facet_raises(self, monkeypatch): + _stub(monkeypatch) + with pytest.raises(OpenBBError, match="Invalid facet id"): + await EiaDataBrowserFetcher.fetch_data( + {"route": "petroleum/pri/spt", "facets": "stateId:TX"}, + {"eia_api_key": "MOCK_KEY"}, + ) + + @pytest.mark.asyncio + async def test_desc_sort_and_limit(self, monkeypatch): + _stub(monkeypatch) + rows = await EiaDataBrowserFetcher.fetch_data( + {"route": "petroleum/pri/spt", "sort": "desc", "limit": 1}, + {"eia_api_key": "MOCK_KEY"}, + ) + assert len(rows) == 1 + assert rows[0].date == date(2024, 2, 1) diff --git a/openbb_platform/providers/eia/tests/test_eia_fetchers.py b/openbb_platform/providers/eia/tests/test_eia_fetchers.py index 88fae8aa971..b689fc56fc5 100644 --- a/openbb_platform/providers/eia/tests/test_eia_fetchers.py +++ b/openbb_platform/providers/eia/tests/test_eia_fetchers.py @@ -1,10 +1,15 @@ """EIA Fetcher Tests.""" -import datetime +import re +from datetime import date import pytest from openbb_core.app.service.user_service import UserService +from openbb_core.provider.utils.errors import EmptyDataError + +from openbb_us_eia.models.data_browser import EiaDataBrowserFetcher from openbb_us_eia.models.petroleum_status_report import EiaPetroleumStatusReportFetcher +from openbb_us_eia.models.registry import DATASET_FETCHERS from openbb_us_eia.models.short_term_energy_outlook import ( EiaShortTermEnergyOutlookFetcher, ) @@ -24,6 +29,22 @@ def scrub_string(key): return before_record_response +def scrub_api_key(response): + """Scrub the API key echoed inside the response body.""" + body = response["body"]["string"] + is_bytes = isinstance(body, bytes) + if is_bytes: + try: + text = body.decode("utf-8") + except UnicodeDecodeError: + return response + else: + text = body + text = re.sub(r'"api_key":\s*"[^"]*"', '"api_key":"MOCK_API_KEY"', text) + response["body"]["string"] = text.encode("utf-8") if is_bytes else text + return response + + @pytest.fixture(scope="module") def vcr_config(): """VCR configuration.""" @@ -32,7 +53,9 @@ def vcr_config(): "filter_query_parameters": [ ("api_key", "MOCK_API_KEY"), ], + "decode_compressed_response": True, "before_record_response": [ + scrub_api_key, scrub_string("X-Amz-Cf-Id"), scrub_string("Etag"), scrub_string("Via"), @@ -46,8 +69,13 @@ def vcr_config(): @pytest.mark.record_http def test_eia_petroleum_status_report_fetcher(credentials=None): - """Test EIA petroleum status report fetcher.""" - params = {"category": "crude_petroleum_stocks", "table": "all"} + """Test the EIA petroleum status report fetcher.""" + params = { + "category": "crude_petroleum_stocks", + "table": "all", + "start_date": date(2024, 1, 5), + "end_date": date(2024, 3, 29), + } fetcher = EiaPetroleumStatusReportFetcher() result = fetcher.test(params, credentials) @@ -56,14 +84,3777 @@ def test_eia_petroleum_status_report_fetcher(credentials=None): @pytest.mark.record_http def test_eia_short_term_energy_outlook_fetcher(credentials=test_credentials): - """Test EIA short term energy outlook fetcher.""" + """Test the EIA short term energy outlook fetcher.""" params = { "table": "10b", - "start_date": datetime.date(2024, 1, 1), - "end_date": datetime.date(2024, 4, 1), + "start_date": date(2024, 1, 1), + "end_date": date(2024, 4, 1), "frequency": "quarter", } fetcher = EiaShortTermEnergyOutlookFetcher() result = fetcher.test(params, credentials) assert result is None + + +@pytest.mark.record_http +def test_eia_data_browser_fetcher(credentials=test_credentials): + """Test the EIA data browser fetcher.""" + params = { + "route": "petroleum/pri/spt", + "frequency": "monthly", + "facets": "product:EPCBRENT", + "start_date": date(2025, 1, 1), + "end_date": date(2025, 3, 1), + } + + fetcher = EiaDataBrowserFetcher() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_aeo_fetcher(credentials=test_credentials): + """Test the EIA aeo fetcher.""" + params = { + "release": "2026", + "history": "projection", + "region": "united_states", + "scenario": "alternative_electricity", + "series": "NA_NA_NA_NA_NA_NA_NA_NA", + "table": "73", + "start_date": date(2025, 1, 1), + "end_date": date(2025, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaAeo"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_coal_aggregate_production_fetcher(credentials=test_credentials): + """Test the EIA coal aggregate production fetcher.""" + params = { + "coal_rank": "subbituminous", + "mine_type": "all", + "state_region": "alaska", + "start_date": date(2001, 1, 1), + "end_date": date(2001, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaCoalAggregateProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_coal_by_mine_by_plant_fetcher(credentials=test_credentials): + """Test the EIA coal by mine by plant fetcher.""" + params = { + "frequency": "annual", + "coal_rank": "all", + "coal_supplier": "TWENTY MILE", + "mine": "100114", + "mine_state": "alabama", + "plant": "genoa", + "plant_state": "wisconsin", + "start_date": date(2008, 1, 1), + "end_date": date(2008, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaCoalByMineByPlant"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_coal_consumption_and_quality_fetcher(credentials=test_credentials): + """Test the EIA coal consumption and quality fetcher.""" + params = { + "frequency": "annual", + "sector": "other_industrial", + "state_region": "alaska", + "start_date": date(2000, 1, 1), + "end_date": date(2000, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaCoalConsumptionAndQuality"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_coal_exports_imports_quantity_price_fetcher(credentials=test_credentials): + """Test the EIA coal exports imports quantity price fetcher.""" + params = { + "frequency": "annual", + "coal_rank": "coke", + "country": "mexico", + "customs_district": "baltimore_md", + "export_import_type": "exports", + "start_date": date(2000, 1, 1), + "end_date": date(2000, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaCoalExportsImportsQuantityPrice"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_coal_market_sales_price_fetcher(credentials=test_credentials): + """Test the EIA coal market sales price fetcher.""" + params = { + "market_type": "open_market", + "state_region": "alaska", + "start_date": date(2001, 1, 1), + "end_date": date(2001, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaCoalMarketSalesPrice"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_coal_mine_aggregates_fetcher(credentials=test_credentials): + """Test the EIA coal mine aggregates fetcher.""" + params = { + "frequency": "annual", + "coal_rank": "bituminous", + "mine": "100114", + "mine_state": "alabama", + "start_date": date(2008, 1, 1), + "end_date": date(2008, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaCoalMineAggregates"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_coal_mine_production_fetcher(credentials=test_credentials): + """Test the EIA coal mine production fetcher.""" + params = { + "census_region": "east_south_central", + "coal_rank": "preparation_plant", + "mine": "100329", + "mine_county": "jefferson", + "mine_region": "south", + "mine_status": "active", + "mine_type": "surface", + "mississippi_region": "east_of_mississippi_river", + "state_region": "alabama", + "supply_region": "appalachia_southern", + "start_date": date(2001, 1, 1), + "end_date": date(2001, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaCoalMineProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_coal_mine_state_aggregates_fetcher(credentials=test_credentials): + """Test the EIA coal mine state aggregates fetcher.""" + params = { + "frequency": "annual", + "coal_rank": "subbituminous", + "mine_state": "alaska", + "start_date": date(2008, 1, 1), + "end_date": date(2008, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaCoalMineStateAggregates"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_coal_plant_aggregates_fetcher(credentials=test_credentials): + """Test the EIA coal plant aggregates fetcher.""" + params = { + "frequency": "annual", + "coal_rank": "bituminous", + "plant": "barry", + "state_region": "overseas", + "start_date": date(2008, 1, 1), + "end_date": date(2008, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaCoalPlantAggregates"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_coal_plant_state_aggregates_fetcher(credentials=test_credentials): + """Test the EIA coal plant state aggregates fetcher.""" + params = { + "frequency": "annual", + "coal_rank": "subbituminous", + "plant_state": "alaska", + "start_date": date(2008, 1, 1), + "end_date": date(2008, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaCoalPlantStateAggregates"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_coal_price_by_rank_fetcher(credentials=test_credentials): + """Test the EIA coal price by rank fetcher.""" + params = { + "coal_rank": "subbituminous", + "state_region": "alaska", + "start_date": date(2001, 1, 1), + "end_date": date(2001, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaCoalPriceByRank"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_coal_receipts_fetcher(credentials=test_credentials): + """Test the EIA coal receipts fetcher.""" + params = { + "frequency": "annual", + "coal_rank": "bituminous", + "coal_supplier": "TWENTY MILE", + "contract_type": "spot_market_purchase", + "mine": "100114", + "mine_basin": "appalachia_southern", + "mine_county": "127", + "mine_state": "alabama", + "mine_type": "surface", + "plant": "genoa", + "plant_state": "wisconsin", + "transportation_mode": "rail", + "start_date": date(2008, 1, 1), + "end_date": date(2008, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaCoalReceipts"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_coal_reserves_capacity_fetcher(credentials=test_credentials): + """Test the EIA coal reserves capacity fetcher.""" + params = { + "mine_type": "surface", + "state_region": "alaska", + "start_date": date(2001, 1, 1), + "end_date": date(2001, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaCoalReservesCapacity"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_crude_oil_imports_fetcher(credentials=test_credentials): + """Test the EIA crude oil imports fetcher.""" + params = { + "frequency": "monthly", + "destination": "padd5", + "destination_type": "port_padd", + "grade": "light_sour", + "origin": "united_arab_emirates", + "origin_type": "country", + "start_date": date(2009, 1, 1), + "end_date": date(2009, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaCrudeOilImports"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_densified_biomass_capacity_by_region_fetcher(credentials=test_credentials): + """Test the EIA densified biomass capacity by region fetcher.""" + params = { + "region": "east", + "start_date": date(2016, 1, 1), + "end_date": date(2016, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaDensifiedBiomassCapacityByRegion"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_densified_biomass_characteristics_by_region_fetcher( + credentials=test_credentials, +): + """Test the EIA densified biomass characteristics by region fetcher.""" + params = { + "fuel_type": "wood_pellets_premium_standard", + "region": "east", + "start_date": date(2016, 1, 1), + "end_date": date(2016, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaDensifiedBiomassCharacteristicsByRegion"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_densified_biomass_export_sales_and_price_fetcher( + credentials=test_credentials, +): + """Test the EIA densified biomass export sales and price fetcher.""" + params = { + "start_date": date(2016, 1, 1), + "end_date": date(2016, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaDensifiedBiomassExportSalesAndPrice"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_densified_biomass_feedstocks_and_costs_fetcher( + credentials=test_credentials, +): + """Test the EIA densified biomass feedstocks and costs fetcher.""" + params = { + "fuel_type": "other_residuals", + "start_date": date(2016, 1, 1), + "end_date": date(2016, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaDensifiedBiomassFeedstocksAndCosts"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_densified_biomass_inventories_by_region_fetcher( + credentials=test_credentials, +): + """Test the EIA densified biomass inventories by region fetcher.""" + params = { + "fuel_type": "compressed_bricks_log", + "region": "east", + "start_date": date(2016, 1, 1), + "end_date": date(2016, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaDensifiedBiomassInventoriesByRegion"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_densified_biomass_production_by_region_fetcher( + credentials=test_credentials, +): + """Test the EIA densified biomass production by region fetcher.""" + params = { + "fuel_type": "compressed_bricks_log", + "region": "east", + "start_date": date(2016, 1, 1), + "end_date": date(2016, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaDensifiedBiomassProductionByRegion"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_densified_biomass_sales_and_price_by_region_fetcher( + credentials=test_credentials, +): + """Test the EIA densified biomass sales and price by region fetcher.""" + params = { + "region": "east", + "start_date": date(2016, 1, 1), + "end_date": date(2016, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaDensifiedBiomassSalesAndPriceByRegion"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_densified_biomass_wood_pellet_plant_capacity_fetcher( + credentials=test_credentials, +): + """Test the EIA densified biomass wood pellet plant capacity fetcher.""" + params = { + "region": "east", + "respondent": "allegheny_pellet_corporation", + "state": "pennsylvania", + "status": "currently_operating", + "start_date": date(2016, 1, 1), + "end_date": date(2016, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaDensifiedBiomassWoodPelletPlantCapacity"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_electricity_electric_power_operations_fetcher( + credentials=test_credentials, +): + """Test the EIA electricity electric power operations fetcher.""" + params = { + "frequency": "monthly", + "fuel": "all_fuels", + "sector": "electric_utility", + "state": "alaska", + "start_date": date(2001, 1, 1), + "end_date": date(2001, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaElectricityElectricPowerOperations"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_electricity_electric_power_operations_for_individual_power_plants_fetcher( + credentials=test_credentials, +): + """Test the EIA electricity electric power operations for individual power plants fetcher.""" + params = { + "frequency": "monthly", + "fuel": "total", + "fuel_type": "total", + "plant": "2", + "prime_mover": "all", + "state": "alabama", + "start_date": date(2001, 1, 1), + "end_date": date(2001, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaElectricityElectricPowerOperationsForIndividualPowerPlants" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_electricity_electricity_sales_to_ultimate_customers_fetcher( + credentials=test_credentials, +): + """Test the EIA electricity electricity sales to ultimate customers fetcher.""" + params = { + "frequency": "monthly", + "sector": "all_sectors", + "state": "alaska", + "start_date": date(2001, 1, 1), + "end_date": date(2001, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaElectricityElectricitySalesToUltimateCustomers"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_electricity_grid_demand_fetcher(credentials=test_credentials): + """Test the EIA electricity grid demand fetcher.""" + params = { + "frequency": "hourly", + "respondent": "powersouth_energy_cooperative", + "series_type": "demand", + "start_date": date(2019, 1, 2), + "end_date": date(2019, 1, 2), + } + + fetcher = DATASET_FETCHERS["EiaElectricityGridDemand"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_electricity_grid_demand_by_subregion_fetcher(credentials=test_credentials): + """Test the EIA electricity grid demand by subregion fetcher.""" + params = { + "frequency": "hourly", + "parent": "california_independent_system_operator", + "subregion": "pacific_gas_and_electric", + "start_date": date(2019, 1, 2), + "end_date": date(2019, 1, 2), + } + + fetcher = DATASET_FETCHERS["EiaElectricityGridDemandBySubregion"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_electricity_grid_generation_by_fuel_fetcher(credentials=test_credentials): + """Test the EIA electricity grid generation by fuel fetcher.""" + params = { + "frequency": "hourly", + "fuel_type": "coal", + "respondent": "powersouth_energy_cooperative", + "start_date": date(2019, 1, 2), + "end_date": date(2019, 1, 2), + } + + fetcher = DATASET_FETCHERS["EiaElectricityGridGenerationByFuel"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_electricity_grid_interchange_fetcher(credentials=test_credentials): + """Test the EIA electricity grid interchange fetcher.""" + params = { + "frequency": "hourly", + "from_ba": "powersouth_energy_cooperative", + "to_ba": "midcontinent_independent_system_operator", + "start_date": date(2019, 1, 2), + "end_date": date(2019, 1, 2), + } + + fetcher = DATASET_FETCHERS["EiaElectricityGridInterchange"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_electricity_inventory_of_operable_generators_fetcher( + credentials=test_credentials, +): + """Test the EIA electricity inventory of operable generators fetcher.""" + params = { + "energy_source": "water", + "generator": "1", + "plant": "2", + "prime_mover": "hy", + "sector": "electric_utility", + "state": "alabama", + "status": "operating", + "technology": "conventional_hydroelectric", + "start_date": date(2008, 1, 1), + "end_date": date(2008, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaElectricityInventoryOfOperableGenerators"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_ieo_fetcher(credentials=test_credentials): + """Test the EIA ieo fetcher.""" + params = { + "release": "2023", + "history": "historic", + "region": "middle_east", + "scenario": "high_economic_growth", + "series": "cnsm_bl_cm_cl_qbtu", + "table": "buildings_delivered_energy_consumption_by_end_use_sector", + "start_date": date(2020, 1, 1), + "end_date": date(2020, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaIeo"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_international_fetcher(credentials=test_credentials): + """Test the EIA international fetcher.""" + params = { + "frequency": "monthly", + "activity": "production", + "country": "angola", + "country_type": "country", + "product": "crude_oil_including_lease_condensate", + "unit": "thousand_barrels_per_day", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaInternational"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_associated_dissolved_proved_reserves_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas associated dissolved proved reserves fetcher.""" + params = { + "process": "associated_dissolved_proved_reserves", + "region": "us", + "series": "us_associated_dissolved_natural_gas_wet_after_lease_separation_proved_reserves_billion_cubic_feet", + "start_date": date(1979, 1, 1), + "end_date": date(1979, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasAssociatedDissolvedProvedReserves"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_average_depth_of_crude_oil_and_natural_gas_wells_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas average depth of crude oil and natural gas wells fetcher.""" + params = { + "process": "average_depth_of_exploratory_and_developmental_wells_drilled", + "product": "wells_total", + "series": "us_average_depth_of_crude_oil_natural_gas_and_dry_exploratory_and_developmental_wells_drilled_feet_per_well", + "start_date": date(1949, 1, 1), + "end_date": date(1949, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasAverageDepthOfCrudeOilAndNaturalGasWells" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_coalbed_methane_fetcher(credentials=test_credentials): + """Test the EIA natural gas coalbed methane fetcher.""" + params = { + "process": "coalbed_methane_proved_reserves", + "region": "us", + "series": "us_coalbed_methane_proved_reserves", + "start_date": date(1989, 1, 1), + "end_date": date(1989, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasCoalbedMethane"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_coalbed_methane_production_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas coalbed methane production fetcher.""" + params = { + "region": "us", + "series": "us_coalbed_methane_production", + "start_date": date(1989, 1, 1), + "end_date": date(1989, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasCoalbedMethaneProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_costs_of_crude_oil_and_natural_gas_wells_drilled_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas costs of crude oil and natural gas wells drilled fetcher.""" + params = { + "process": "real_cost_per_foot", + "product": "wells_total", + "series": "us_real_cost_per_foot_of_crude_oil_natural_gas_and_dry", + "start_date": date(1960, 1, 1), + "end_date": date(1960, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasCostsOfCrudeOilAndNaturalGasWellsDrilled" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_crude_oil_and_natural_gas_drilling_activity_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas crude oil and natural gas drilling activity fetcher.""" + params = { + "frequency": "monthly", + "process": "active_well_service_rigs_in_operation", + "product": "crude_oil_and_natural_gas", + "region": "us", + "series": "us_crude_oil_and_natural_gas_active_well_service_rigs_in", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasCrudeOilAndNaturalGasDrillingActivity"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_crude_oil_and_natural_gas_exploratory_and_development_wells_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas crude oil and natural gas exploratory and development wells fetcher.""" + params = { + "frequency": "monthly", + "process": "exploratory_and_developmental_wells_drilled", + "product": "wells_total", + "series": "us_crude_oil_natural_gas_and_dry_exploratory_and", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasCrudeOilAndNaturalGasExploratoryAndDevelopmentWells" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_crude_oil_plus_lease_condensate_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas crude oil plus lease condensate fetcher.""" + params = { + "process": "proved_reserves", + "region": "us", + "series": "us_crude_oil_lease_condensate_proved_reserves", + "start_date": date(2009, 1, 1), + "end_date": date(2009, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasCrudeOilPlusLeaseCondensate"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_dry_natural_gas_proved_reserves_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas dry natural gas proved reserves fetcher.""" + params = { + "process": "dry_expected_future_production", + "region": "us", + "series": "us_dry_natural_gas_expected_future_production", + "start_date": date(1925, 1, 1), + "end_date": date(1925, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasDryNaturalGasProvedReserves"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_federal_offshore_gulf_of_america_proved_reserves_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas federal offshore gulf of america proved reserves fetcher.""" + params = { + "process": "proved_reserves", + "product": "crude_oil", + "series": "gulf_of_america_federal_offshore_crude_oil_proved_reserves_million_barrels", + "start_date": date(1992, 1, 1), + "end_date": date(1992, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasFederalOffshoreGulfOfAmericaProvedReserves" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_footage_drilled_for_crude_oil_and_natural_gas_wells_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas footage drilled for crude oil and natural gas wells fetcher.""" + params = { + "process": "footage_drilled_for_developmental_wells", + "product": "wells_total", + "series": "us_footage_drilled_for_crude_oil_natural_gas_and_dry_developmental_wells_thousand_feet", + "start_date": date(1949, 1, 1), + "end_date": date(1949, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasFootageDrilledForCrudeOilAndNaturalGasWells" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_gulf_of_america_federal_offshore_production_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas gulf of america federal offshore production fetcher.""" + params = { + "process": "production_from_reserves", + "product": "crude_oil", + "series": "gulf_of_america_federal_offshore_crude_oil_production", + "start_date": date(1992, 1, 1), + "end_date": date(1992, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasGulfOfAmericaFederalOffshoreProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_heat_content_of_natural_gas_consumed_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas heat content of natural gas consumed fetcher.""" + params = { + "frequency": "monthly", + "region": "us", + "series": "us_heat_content_of_natural_gas_deliveries_to_consumers", + "start_date": date(2012, 1, 1), + "end_date": date(2012, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasHeatContentOfNaturalGasConsumed"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_international_interstate_movements_of_natural_gas_by_state_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas international interstate movements of natural gas by state fetcher.""" + params = { + "process": "exports_intransit", + "region": "us", + "series": "NA1280_NUS_2", + "start_date": date(1930, 1, 1), + "end_date": date(1930, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasInternationalInterstateMovementsOfNaturalGasByState" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_lease_condensate_fetcher(credentials=test_credentials): + """Test the EIA natural gas lease condensate fetcher.""" + params = { + "process": "lease_condensate_proved_reserves", + "region": "us", + "series": "us_natural_gas_liquids_lease_condensate_proved_reserves_million_barrels", + "start_date": date(1979, 1, 1), + "end_date": date(1979, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasLeaseCondensate"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_lease_condensate_production_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas lease condensate production fetcher.""" + params = { + "region": "us", + "series": "us_natural_gas_liquids_lease_condensate_reserves_based", + "start_date": date(1979, 1, 1), + "end_date": date(1979, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasLeaseCondensateProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_lng_storage_additions_and_withdrawals_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas lng storage additions and withdrawals fetcher.""" + params = { + "process": "lng_storage_net_withdrawals", + "region": "us", + "series": "us_natural_gas_lng_storage_net_withdrawals", + "start_date": date(1969, 1, 1), + "end_date": date(1969, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasLngStorageAdditionsAndWithdrawals"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_maximum_us_active_seismic_crew_counts_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas maximum us active seismic crew counts fetcher.""" + params = { + "process": "maximum_number_of_active_crews_engaged_in_sismic_surveying", + "region": "us", + "series": "us_maximum_number_of_active_crews_engaged_in_seismic", + "start_date": date(2000, 1, 1), + "end_date": date(2000, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasMaximumUsActiveSeismicCrewCounts"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_natural_gas_annual_supply_disposition_by_state_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas natural gas annual supply disposition by state fetcher.""" + params = { + "frequency": "monthly", + "process": "underground_storage_injections", + "region": "us", + "series": "us_total_natural_gas_injections_into_underground_storage", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasNaturalGasAnnualSupplyDispositionByState" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_natural_gas_consumption_by_end_use_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas natural gas consumption by end use fetcher.""" + params = { + "frequency": "monthly", + "process": "commercial_consumption", + "region": "us", + "series": "natural_gas_deliveries_to_commercial_consumers_in_the_us", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasNaturalGasConsumptionByEndUse"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_natural_gas_delivered_for_the_account_of_others_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas natural gas delivered for the account of others fetcher.""" + params = { + "process": "delivered_to_industrial_consumers_for_the_account_of_others", + "region": "us", + "series": "us_natural_gas_delivered_to_industrial_consumers_for_the", + "start_date": date(1982, 1, 1), + "end_date": date(1982, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasNaturalGasDeliveredForTheAccountOfOthers" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_natural_gas_gross_withdrawals_and_production_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas natural gas gross withdrawals and production fetcher.""" + params = { + "frequency": "monthly", + "process": "removed_from_natural_gas", + "region": "us", + "series": "us_nonhydrocarbon_gases_removed_from_natural_gas", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasNaturalGasGrossWithdrawalsAndProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_natural_gas_liquids_proved_reserves_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas natural gas liquids proved reserves fetcher.""" + params = { + "process": "proved_reserves", + "region": "us", + "series": "us_natural_gas_plant_liquids_proved_reserves", + "start_date": date(1979, 1, 1), + "end_date": date(1979, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasNaturalGasLiquidsProvedReserves"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_natural_gas_plant_liquids_production_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas natural gas plant liquids production fetcher.""" + params = { + "region": "us", + "series": "us_natural_gas_plant_liquids_reserves_based_production", + "start_date": date(1979, 1, 1), + "end_date": date(1979, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasNaturalGasPlantLiquidsProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_natural_gas_plant_processing_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas natural gas plant processing fetcher.""" + params = { + "frequency": "monthly", + "region": "us", + "series": "us_natural_gas_plant_liquids_production", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasNaturalGasPlantProcessing"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_natural_gas_prices_fetcher(credentials=test_credentials): + """Test the EIA natural gas natural gas prices fetcher.""" + params = { + "frequency": "monthly", + "process": "price_delivered_to_residential_consumers", + "region": "us", + "series": "us_price_of_natural_gas_delivered_to_residential_consumers", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasNaturalGasPrices"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_natural_gas_proved_reserves_wet_after_lease_separation_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas natural gas proved reserves wet after lease separation fetcher.""" + params = { + "process": "wet_after_lease_separation_reserves_revision_increases", + "region": "us", + "series": "us_natural_gas_wet_after_lease_separation_reserves_revision_increases_billion_cubic_feet", + "start_date": date(1979, 1, 1), + "end_date": date(1979, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasNaturalGasProvedReservesWetAfterLeaseSeparation" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_natural_gas_reserves_summary_as_of_dec31_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas natural gas reserves summary as of dec31 fetcher.""" + params = { + "process": "dry_expected_future_production", + "product": "natural_gas", + "region": "us", + "series": "us_dry_natural_gas_expected_future_production", + "start_date": date(1925, 1, 1), + "end_date": date(1925, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasNaturalGasReservesSummaryAsOfDec31"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_natural_gas_spot_and_futures_prices_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas natural gas spot and futures prices fetcher.""" + params = { + "frequency": "weekly", + "process": "future_contract_4", + "region": "new_york_city", + "series": "natural_gas_futures_contract_4", + "start_date": date(1993, 12, 24), + "end_date": date(1993, 12, 24), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasNaturalGasSpotAndFuturesPrices"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_natural_gas_summary_fetcher(credentials=test_credentials): + """Test the EIA natural gas natural gas summary fetcher.""" + params = { + "frequency": "monthly", + "process": "price_delivered_to_residential_consumers", + "region": "us", + "series": "N3010US3", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasNaturalGasSummary"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_natural_gas_wellhead_value_and_marketed_production_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas natural gas wellhead value and marketed production fetcher.""" + params = { + "frequency": "monthly", + "process": "marketed_production", + "region": "us", + "series": "us_natural_gas_marketed_production", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasNaturalGasWellheadValueAndMarketedProduction" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_nonassociated_proved_reserves_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas nonassociated proved reserves fetcher.""" + params = { + "process": "nonassociated_proved_reserves", + "region": "us", + "series": "us_nonassociated_natural_gas_wet_after_lease_separation_proved_reserves_billion_cubic_feet", + "start_date": date(1979, 1, 1), + "end_date": date(1979, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasNonassociatedProvedReserves"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_number_of_gas_producing_oil_wells_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas number of gas producing oil wells fetcher.""" + params = { + "region": "us", + "series": "us_natural_gas_number_of_oil_wells", + "start_date": date(2011, 1, 1), + "end_date": date(2011, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasNumberOfGasProducingOilWells"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_number_of_natural_gas_consumers_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas number of natural gas consumers fetcher.""" + params = { + "process": "average_annual_consumption_per_commercial_consumer", + "region": "us", + "series": "us_natural_gas_average_annual_consumption_per_commercial", + "start_date": date(1967, 1, 1), + "end_date": date(1967, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasNumberOfNaturalGasConsumers"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_number_of_producing_gas_wells_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas number of producing gas wells fetcher.""" + params = { + "region": "us", + "series": "us_natural_gas_number_of_gas_and_gas_condensate_wells", + "start_date": date(1989, 1, 1), + "end_date": date(1989, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasNumberOfProducingGasWells"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_offshore_gross_withdrawals_of_natural_gas_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas offshore gross withdrawals of natural gas fetcher.""" + params = { + "frequency": "monthly", + "process": "withdrawals_from_gas_wells", + "series": "federal_offshore_gulf_of_america_natural_gas_gross_withdrawals_from_gas_wells_mmcf", + "start_date": date(1997, 1, 1), + "end_date": date(1997, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasOffshoreGrossWithdrawalsOfNaturalGas"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_plant_liquids_in_proved_reserves_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas plant liquids in proved reserves fetcher.""" + params = { + "region": "us", + "series": "us_natural_gas_plant_liquids_expected_future_production", + "start_date": date(1979, 1, 1), + "end_date": date(1979, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasPlantLiquidsInProvedReserves"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_proved_nonproducing_reserves_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas proved nonproducing reserves fetcher.""" + params = { + "process": "associated_dissolved_reserves_in_nonproducing_reservoirs", + "product": "natural_gas", + "region": "na", + "series": "gulf_of_america_federal_offshore_western_associated_dissolved_natural_gas_reserves_in_nonproducing_reservoirs_wet_bcf", + "start_date": date(1996, 1, 1), + "end_date": date(1996, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasProvedNonproducingReserves"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_residential_and_commercial_prices_selected_states_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas residential and commercial prices selected states fetcher.""" + params = { + "frequency": "monthly", + "process": "price_delivered_to_residential_consumers", + "region": "usa_dc", + "series": "district_of_columbia_price_of_natural_gas_delivered_to", + "start_date": date(1989, 1, 1), + "end_date": date(1989, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasResidentialAndCommercialPricesSelectedStates" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_shale_gas_fetcher(credentials=test_credentials): + """Test the EIA natural gas shale gas fetcher.""" + params = { + "process": "shale_proved_reserves", + "region": "us", + "series": "us_shale_proved_reserves", + "start_date": date(2007, 1, 1), + "end_date": date(2007, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasShaleGas"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_shale_gas_production_fetcher(credentials=test_credentials): + """Test the EIA natural gas shale gas production fetcher.""" + params = { + "region": "us", + "series": "us_shale_production", + "start_date": date(2007, 1, 1), + "end_date": date(2007, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasShaleGasProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_share_of_total_us_natural_gas_delivered_to_consumers_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas share of total us natural gas delivered to consumers fetcher.""" + params = { + "process": "of_total_residential_deliveries", + "region": "us", + "series": "us_natural_gas_of_total_residential_deliveries", + "start_date": date(1993, 1, 1), + "end_date": date(1993, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasShareOfTotalUsNaturalGasDeliveredToConsumers" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_supplemental_gas_supplies_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas supplemental gas supplies fetcher.""" + params = { + "frequency": "monthly", + "start_date": date(1980, 1, 1), + "end_date": date(1980, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasSupplementalGasSupplies"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_underground_natural_gas_storage_by_all_operators_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas underground natural gas storage by all operators fetcher.""" + params = { + "frequency": "monthly", + "process": "underground_storage_base_gas", + "region": "us", + "series": "us_total_natural_gas_in_underground_storage_base_gas_mmcf", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasUndergroundNaturalGasStorageByAllOperators" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_underground_natural_gas_storage_capacity_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas underground natural gas storage capacity fetcher.""" + params = { + "frequency": "monthly", + "process": "total_underground_storage_capacity", + "region": "us", + "series": "us_total_natural_gas_underground_storage_capacity", + "start_date": date(1989, 1, 1), + "end_date": date(1989, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasUndergroundNaturalGasStorageCapacity"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_us_natural_gas_exports_and_re_exports_by_country_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas us natural gas exports and re exports by country fetcher.""" + params = { + "frequency": "monthly", + "process": "exports", + "region": "us", + "series": "us_natural_gas_exports", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasUsNaturalGasExportsAndReExportsByCountry" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_us_natural_gas_exports_and_re_exports_by_point_of_exit_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas us natural gas exports and re exports by point of exit fetcher.""" + params = { + "frequency": "monthly", + "process": "liquefied_natural_gas_exports_price", + "region": "jpn", + "series": "price_of_liquefied_us_natural_gas_exports_to_japan", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasUsNaturalGasExportsAndReExportsByPointOfExit" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_us_natural_gas_imports_by_country_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas us natural gas imports by country fetcher.""" + params = { + "frequency": "monthly", + "process": "imports", + "region": "us", + "series": "us_natural_gas_imports", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasUsNaturalGasImportsByCountry"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_us_natural_gas_imports_by_point_of_entry_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas us natural gas imports by point of entry fetcher.""" + params = { + "frequency": "monthly", + "process": "liquefied_natural_gas_imports", + "region": "dza", + "series": "us_liquefied_natural_gas_imports_from_algeria", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasUsNaturalGasImportsByPointOfEntry"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_us_natural_gas_imports_exports_by_state_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas us natural gas imports exports by state fetcher.""" + params = { + "frequency": "monthly", + "process": "exports", + "series": "us_natural_gas_exports", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasUsNaturalGasImportsExportsByState"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_us_natural_gas_monthly_supply_and_disposition_balance_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas us natural gas monthly supply and disposition balance fetcher.""" + params = { + "process": "net_imports", + "region": "us", + "series": "us_natural_gas_net_imports", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasUsNaturalGasMonthlySupplyAndDispositionBalance" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_us_underground_natural_gas_storage_by_storage_type_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas us underground natural gas storage by storage type fetcher.""" + params = { + "frequency": "monthly", + "process": "underground_storage_base_gas", + "series": "us_total_natural_gas_in_underground_storage_base_gas_mmcf", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaNaturalGasUsUndergroundNaturalGasStorageByStorageType" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_natural_gas_weekly_working_gas_in_underground_storage_fetcher( + credentials=test_credentials, +): + """Test the EIA natural gas weekly working gas in underground storage fetcher.""" + params = { + "process": "non_salt_underground_storage_working_gas", + "region": "na", + "series": "weekly_nonsalt_region_natural_gas_working_underground", + "start_date": date(2010, 1, 1), + "end_date": date(2010, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNaturalGasWeeklyWorkingGasInUndergroundStorage"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_nuclear_outages_facility_level_nuclear_outages_fetcher( + credentials=test_credentials, +): + """Test the EIA nuclear outages facility level nuclear outages fetcher.""" + params = { + "facility": "browns_ferry", + "start_date": date(2007, 1, 1), + "end_date": date(2007, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNuclearOutagesFacilityLevelNuclearOutages"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_nuclear_outages_generator_level_nuclear_outages_fetcher( + credentials=test_credentials, +): + """Test the EIA nuclear outages generator level nuclear outages fetcher.""" + params = { + "facility": "browns_ferry", + "generator": "1", + "start_date": date(2007, 1, 1), + "end_date": date(2007, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNuclearOutagesGeneratorLevelNuclearOutages"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_nuclear_outages_us_nuclear_outages_fetcher(credentials=test_credentials): + """Test the EIA nuclear outages us nuclear outages fetcher.""" + params = { + "start_date": date(2007, 1, 1), + "end_date": date(2007, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaNuclearOutagesUsNuclearOutages"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_adjusted_distillate_fuel_oil_and_kerosene_sales_by_end_use_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum adjusted distillate fuel oil and kerosene sales by end use fetcher.""" + params = { + "process": "adj_sales_deliveries_to_farm_consumers", + "product": "no_2_diesel", + "region": "us", + "series": "K2DVAFNUS1", + "start_date": date(1984, 1, 1), + "end_date": date(1984, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumAdjustedDistillateFuelOilAndKeroseneSalesByEndUse" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_adjusted_sales_of_distillate_fuel_oil_by_end_use_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum adjusted sales of distillate fuel oil by end use fetcher.""" + params = { + "process": "adj_sales_deliveries_total_to_end_users", + "product": "distillate_fuel_oil", + "region": "us", + "series": "us_total_distillate_adj_sales_deliveries_total_to_end_users", + "start_date": date(1984, 1, 1), + "end_date": date(1984, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumAdjustedSalesOfDistillateFuelOilByEndUse"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_adjusted_sales_of_kerosene_by_end_use_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum adjusted sales of kerosene by end use fetcher.""" + params = { + "process": "adj_sales_deliveries_total_to_end_users", + "region": "us", + "series": "us_kerosene_adj_sales_deliveries_total_to_end_users", + "start_date": date(1984, 1, 1), + "end_date": date(1984, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumAdjustedSalesOfKeroseneByEndUse"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_adjusted_sales_of_residual_fuel_oil_by_end_use_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum adjusted sales of residual fuel oil by end use fetcher.""" + params = { + "process": "adj_sales_deliveries_total_to_end_users", + "region": "us", + "series": "us_residual_fuel_oil_adj_sales_deliveries_total_to_end_users", + "start_date": date(1984, 1, 1), + "end_date": date(1984, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumAdjustedSalesOfResidualFuelOilByEndUse"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_average_depth_of_crude_oil_and_natural_gas_wells_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum average depth of crude oil and natural gas wells fetcher.""" + params = { + "process": "average_depth_of_exploratory_and_developmental_wells_drilled", + "product": "wells_total", + "series": "us_average_depth_of_crude_oil_natural_gas_and_dry_exploratory_and_developmental_wells_drilled_feet_per_well", + "start_date": date(1949, 1, 1), + "end_date": date(1949, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumAverageDepthOfCrudeOilAndNaturalGasWells"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_biofuels_operable_production_capacity_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum biofuels operable production capacity fetcher.""" + params = { + "product": "biodiesel", + "series": "us_biodiesel_production_capacity", + "start_date": date(2021, 1, 1), + "end_date": date(2021, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumBiofuelsOperableProductionCapacity"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_blender_net_input_fetcher(credentials=test_credentials): + """Test the EIA petroleum blender net input fetcher.""" + params = { + "frequency": "monthly", + "product": "gasoline_blending_components", + "region": "us", + "series": "us_blender_net_input_of_gasoline_blending_components_thousand_barrels", + "start_date": date(2005, 1, 1), + "end_date": date(2005, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumBlenderNetInput"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_blender_net_production_fetcher(credentials=test_credentials): + """Test the EIA petroleum blender net production fetcher.""" + params = { + "frequency": "monthly", + "product": "reformulated_motor_gasoline_with_alcohol", + "region": "us", + "series": "us_blender_net_production_of_reformulated_motor_gasoline_with_fuel_alcohol_thousand_barrels", + "start_date": date(2005, 1, 1), + "end_date": date(2005, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumBlenderNetProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_costs_of_crude_oil_and_natural_gas_wells_drilled_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum costs of crude oil and natural gas wells drilled fetcher.""" + params = { + "process": "real_cost_per_foot", + "product": "wells_total", + "series": "us_real_cost_per_foot_of_crude_oil_natural_gas_and_dry", + "start_date": date(1960, 1, 1), + "end_date": date(1960, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumCostsOfCrudeOilAndNaturalGasWellsDrilled"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_crude_first_purchase_prices_selected_streams_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum crude first purchase prices selected streams fetcher.""" + params = { + "frequency": "monthly", + "product": "ans_crude_oil", + "region": "usa_ak", + "series": "alaska_north_slope_first_purchase_price", + "start_date": date(1977, 7, 1), + "end_date": date(1977, 7, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumCrudeFirstPurchasePricesSelectedStreams"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_crude_oil_and_lease_condensate_production_by_api_gravity_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum crude oil and lease condensate production by api gravity fetcher.""" + params = { + "product": "crude_gravity_of_unkown", + "region": "na", + "series": "lower_48_states_crude_oil_and_lease_condensate_production_for_unknown_api_gravity_thousand_barrels_per_day", + "start_date": date(2015, 1, 1), + "end_date": date(2015, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumCrudeOilAndLeaseCondensateProductionByApiGravity" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_crude_oil_and_natural_gas_drilling_activity_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum crude oil and natural gas drilling activity fetcher.""" + params = { + "frequency": "monthly", + "process": "active_well_service_rigs_in_operation", + "product": "crude_oil_and_natural_gas", + "region": "us", + "series": "us_crude_oil_and_natural_gas_active_well_service_rigs_in", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumCrudeOilAndNaturalGasDrillingActivity"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_crude_oil_and_natural_gas_exploratory_and_development_wells_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum crude oil and natural gas exploratory and development wells fetcher.""" + params = { + "frequency": "monthly", + "process": "exploratory_and_developmental_wells_drilled", + "product": "wells_total", + "series": "us_crude_oil_natural_gas_and_dry_exploratory_and", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumCrudeOilAndNaturalGasExploratoryAndDevelopmentWells" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_crude_oil_input_qualities_fetcher(credentials=test_credentials): + """Test the EIA petroleum crude oil input qualities fetcher.""" + params = { + "frequency": "monthly", + "process": "refinery_inputs_average_api_gravity", + "region": "na", + "series": "indiana_illinois_kentucky_refinery_district_api_gravity_of", + "start_date": date(1985, 1, 1), + "end_date": date(1985, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumCrudeOilInputQualities"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_crude_oil_production_fetcher(credentials=test_credentials): + """Test the EIA petroleum crude oil production fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_oil", + "region": "us", + "series": "us_field_production_of_crude_oil_thousand_barrels", + "start_date": date(1920, 1, 1), + "end_date": date(1920, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumCrudeOilProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_crude_oil_proved_reserves_reserves_changes_and_production_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum crude oil proved reserves reserves changes and production fetcher.""" + params = { + "process": "proved_reserves", + "region": "us", + "series": "us_crude_oil_proved_reserves", + "start_date": date(1899, 1, 1), + "end_date": date(1899, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumCrudeOilProvedReservesReservesChangesAndProduction" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_crude_oil_stocks_at_tank_farms_pipelines_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum crude oil stocks at tank farms pipelines fetcher.""" + params = { + "frequency": "monthly", + "process": "stocks_at_tank_farms", + "region": "padd_1", + "series": "east_coast_crude_oil_stocks_at_tank_farms_and_pipelines", + "start_date": date(1981, 1, 1), + "end_date": date(1981, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumCrudeOilStocksAtTankFarmsPipelines"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_crude_plus_lease_condensate_proved_reserves_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum crude plus lease condensate proved reserves fetcher.""" + params = { + "process": "proved_reserves", + "region": "us", + "series": "us_crude_oil_lease_condensate_proved_reserves", + "start_date": date(2009, 1, 1), + "end_date": date(2009, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumCrudePlusLeaseCondensateProvedReserves"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_distillate_fuel_oil_and_kerosene_sales_by_end_use_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum distillate fuel oil and kerosene sales by end use fetcher.""" + params = { + "process": "commercial_consumption", + "product": "no_2_fuel_oil_heating_oil", + "region": "us", + "series": "K2FVCSNUS1", + "start_date": date(1984, 1, 1), + "end_date": date(1984, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumDistillateFuelOilAndKeroseneSalesByEndUse" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_domestic_crude_oil_first_purchase_prices_by_api_gravity_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum domestic crude oil first purchase prices by api gravity fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_gravity_20_0_percent_or_less", + "series": "us_domestic_crude_oil_first_purchase_prices_with_api_gravity_20_0_degrees_or_less_dollars_per_barrel", + "start_date": date(1993, 10, 1), + "end_date": date(1993, 10, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumDomesticCrudeOilFirstPurchasePricesByApiGravity" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_domestic_crude_oil_first_purchase_prices_by_area_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum domestic crude oil first purchase prices by area fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_oil", + "region": "us", + "series": "us_crude_oil_first_purchase_price", + "start_date": date(1974, 1, 1), + "end_date": date(1974, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumDomesticCrudeOilFirstPurchasePricesByArea" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_downstream_charge_capacity_of_operable_petroleum_refineries_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum downstream charge capacity of operable petroleum refineries fetcher.""" + params = { + "process": "refinery_catalytic_cracking_fresh_feed_downstream_charge", + "region": "pri", + "series": "8_NA_8CCF_NPZ_5", + "start_date": date(1982, 1, 1), + "end_date": date(1982, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumDownstreamChargeCapacityOfOperablePetroleumRefineries" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_downstream_processing_of_fresh_feed_input_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum downstream processing of fresh feed input fetcher.""" + params = { + "frequency": "monthly", + "process": "downstream_delayed_fluid_coking", + "region": "na", + "series": "refining_district_indiana_illinois_kentucky_downstream_processing_of_fresh_feed_input_by_delayed_and_fluid_coking_units_thousand_barrels_per_day", + "start_date": date(1987, 1, 1), + "end_date": date(1987, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumDownstreamProcessingOfFreshFeedInput"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_exports_fetcher(credentials=test_credentials): + """Test the EIA petroleum exports fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_oil", + "region": "us", + "series": "us_exports_of_crude_oil_thousand_barrels", + "start_date": date(1920, 1, 1), + "end_date": date(1920, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumExports"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_exports_by_destination_fetcher(credentials=test_credentials): + """Test the EIA petroleum exports by destination fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_oil", + "region": "us", + "series": "MCREXUS1", + "start_date": date(1920, 1, 1), + "end_date": date(1920, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumExportsByDestination"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_feedstocks_consumed_for_production_of_biofuels_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum feedstocks consumed for production of biofuels fetcher.""" + params = { + "product": "other_animal_fats_inputs_to_biodiesel_production", + "series": "other_waste_oil_fat_and_grease_inputs_to_biofuels_production", + "start_date": date(2019, 1, 1), + "end_date": date(2019, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumFeedstocksConsumedForProductionOfBiofuels" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_fob_costs_of_imported_crude_oil_by_api_gravity_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum fob costs of imported crude oil by api gravity fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_gravity_20_0_percent_or_less", + "series": "us_fob_costs_of_crude_with_api_gravity_20_0_degrees_or_less", + "start_date": date(1983, 1, 1), + "end_date": date(1983, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumFobCostsOfImportedCrudeOilByApiGravity"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_fob_costs_of_imported_crude_oil_by_area_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum fob costs of imported crude oil by area fetcher.""" + params = { + "frequency": "monthly", + "region": "na", + "series": "us_fob_costs_of_crude_oil", + "start_date": date(1973, 10, 1), + "end_date": date(1973, 10, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumFobCostsOfImportedCrudeOilByArea"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_fob_costs_of_imported_crude_oil_for_selected_crude_streams_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum fob costs of imported crude oil for selected crude streams fetcher.""" + params = { + "frequency": "monthly", + "product": "angolan_cabinda_crude_oil", + "region": "ago", + "series": "us_fob_costs_of_angolan_cabinda_crude_oil", + "start_date": date(1983, 1, 1), + "end_date": date(1983, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumFobCostsOfImportedCrudeOilForSelectedCrudeStreams" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_footage_drilled_for_crude_oil_and_natural_gas_wells_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum footage drilled for crude oil and natural gas wells fetcher.""" + params = { + "process": "footage_drilled_for_developmental_wells", + "product": "wells_total", + "series": "us_footage_drilled_for_crude_oil_natural_gas_and_dry_developmental_wells_thousand_feet", + "start_date": date(1949, 1, 1), + "end_date": date(1949, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumFootageDrilledForCrudeOilAndNaturalGasWells" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_fuel_consumed_at_biofuels_plants_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum fuel consumed at biofuels plants fetcher.""" + params = { + "process": "biogas_consumed_at_biofuels_plants", + "series": "us_biogas_consumed_at_biofuels_plants", + "start_date": date(2021, 1, 1), + "end_date": date(2021, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumFuelConsumedAtBiofuelsPlants"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_fuel_consumed_at_refineries_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum fuel consumed at refineries fetcher.""" + params = { + "process": "coal_consumed_at_refineries", + "region": "us", + "series": "us_coal_consumed_at_refineries", + "start_date": date(1985, 1, 1), + "end_date": date(1985, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumFuelConsumedAtRefineries"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_gasoline_prices_by_formulation_grade_sales_type_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum gasoline prices by formulation grade sales type fetcher.""" + params = { + "frequency": "monthly", + "process": "bulk_sales", + "product": "reformulated_motor_gasoline", + "region": "us", + "series": "EMA_EPM0R_PBS_NUS_DPG", + "start_date": date(1994, 1, 1), + "end_date": date(1994, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumGasolinePricesByFormulationGradeSalesType" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_gulf_of_america_federal_offshore_production_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum gulf of america federal offshore production fetcher.""" + params = { + "process": "production_from_reserves", + "product": "crude_oil", + "series": "gulf_of_america_federal_offshore_crude_oil_production", + "start_date": date(1992, 1, 1), + "end_date": date(1992, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumGulfOfAmericaFederalOffshoreProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_imports_by_area_of_entry_fetcher(credentials=test_credentials): + """Test the EIA petroleum imports by area of entry fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_oil", + "region": "us", + "series": "us_imports_of_crude_oil_thousand_barrels", + "start_date": date(1920, 1, 1), + "end_date": date(1920, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumImportsByAreaOfEntry"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_imports_by_processing_area_fetcher(credentials=test_credentials): + """Test the EIA petroleum imports by processing area fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_oil", + "region": "padd_1", + "series": "east_coast_padd_1_imports_by_padd_of_processing_of_crude_oil_thousand_barrels", + "start_date": date(1981, 1, 1), + "end_date": date(1981, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumImportsByProcessingArea"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_imports_of_residual_fuel_fetcher(credentials=test_credentials): + """Test the EIA petroleum imports of residual fuel fetcher.""" + params = { + "frequency": "monthly", + "product": "residual_fuel_oil", + "region": "us", + "series": "us_imports_of_residual_fuel_oil_thousand_barrels", + "start_date": date(1936, 1, 1), + "end_date": date(1936, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumImportsOfResidualFuel"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_landed_costs_of_imported_crude_by_api_gravity_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum landed costs of imported crude by api gravity fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_gravity_20_0_percent_or_less", + "series": "us_landed_costs_of_crude_with_api_gravity_20_0_degrees_or", + "start_date": date(1983, 1, 1), + "end_date": date(1983, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumLandedCostsOfImportedCrudeByApiGravity"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_landed_costs_of_imported_crude_by_area_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum landed costs of imported crude by area fetcher.""" + params = { + "frequency": "monthly", + "region": "na", + "series": "us_landed_costs_of_non_opec_countries_crude_oil", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumLandedCostsOfImportedCrudeByArea"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_landed_costs_of_imported_crude_for_selected_crude_streams_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum landed costs of imported crude for selected crude streams fetcher.""" + params = { + "frequency": "monthly", + "product": "angolan_cabinda_crude_oil", + "region": "ago", + "series": "us_landed_costs_of_angolan_cabinda_crude_oil", + "start_date": date(1983, 1, 1), + "end_date": date(1983, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumLandedCostsOfImportedCrudeForSelectedCrudeStreams" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_maximum_us_active_seismic_crew_counts_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum maximum us active seismic crew counts fetcher.""" + params = { + "process": "maximum_number_of_active_crews_engaged_in_sismic_surveying", + "region": "us", + "series": "us_maximum_number_of_active_crews_engaged_in_seismic", + "start_date": date(2000, 1, 1), + "end_date": date(2000, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumMaximumUsActiveSeismicCrewCounts"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_movements_between_pad_districts_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum movements between pad districts fetcher.""" + params = { + "frequency": "monthly", + "product": "asphalt_and_road_oil", + "region": "padd_2", + "series": "east_coast_padd_1_receipts_by_pipeline_tanker_barge_and_rail_from_midwest_padd_2_of_asphalt_and_road_oil_thousand_barrels", + "start_date": date(1986, 1, 1), + "end_date": date(1986, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumMovementsBetweenPadDistricts"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_movements_by_pipeline_between_pad_districts_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum movements by pipeline between pad districts fetcher.""" + params = { + "frequency": "monthly", + "product": "gasoline_blending_components", + "region": "padd_2", + "series": "east_coast_receipts_by_pipeline_from_midwest_of_gasoline", + "start_date": date(1986, 1, 1), + "end_date": date(1986, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumMovementsByPipelineBetweenPadDistricts"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_movements_by_rail_between_pad_districts_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum movements by rail between pad districts fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_oil", + "region": "padd_2", + "series": "east_coast_receipts_by_rail_from_midwest_of_crude_oil", + "start_date": date(2010, 1, 1), + "end_date": date(2010, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumMovementsByRailBetweenPadDistricts"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_movements_by_tanker_and_barge_between_pad_districts_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum movements by tanker and barge between pad districts fetcher.""" + params = { + "frequency": "monthly", + "product": "asphalt_and_road_oil", + "region": "padd_1a", + "series": "new_england_padd_1a_receipts_by_tanker_and_barge_from_gulf_coast_padd_3_of_asphalt_and_road_oil_thousand_barrels", + "start_date": date(1986, 1, 1), + "end_date": date(1986, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumMovementsByTankerAndBargeBetweenPadDistricts" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_movements_of_crude_oil_and_selected_products_by_rail_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum movements of crude oil and selected products by rail fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_oil", + "region": "us", + "series": "us_crude_oil_by_rail", + "start_date": date(2010, 1, 1), + "end_date": date(2010, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumMovementsOfCrudeOilAndSelectedProductsByRail" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_natural_gas_feedstock_for_hydrogen_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum natural gas feedstock for hydrogen fetcher.""" + params = { + "region": "us", + "series": "us_natural_gas_used_as_feedstock_for_hydrogen_production", + "start_date": date(2008, 1, 1), + "end_date": date(2008, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumNaturalGasFeedstockForHydrogen"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_natural_gas_plant_field_production_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum natural gas plant field production fetcher.""" + params = { + "frequency": "monthly", + "product": "natural_gas_plant_liquids", + "region": "us", + "series": "us_field_production_of_natural_gas_liquids_thousand_barrels_per_day", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumNaturalGasPlantFieldProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_natural_gas_plant_stocks_fetcher(credentials=test_credentials): + """Test the EIA petroleum natural gas plant stocks fetcher.""" + params = { + "frequency": "monthly", + "product": "isobutane_isobutylene", + "region": "na", + "series": "refining_district_indiana_illinois_kentucky_isobutane", + "start_date": date(1993, 1, 1), + "end_date": date(1993, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumNaturalGasPlantStocks"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_net_receipts_between_pad_districts_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum net receipts between pad districts fetcher.""" + params = { + "frequency": "monthly", + "process": "net_receipts_by_pipeline_tanker_barge_and_rail", + "product": "asphalt_and_road_oil", + "region": "padd_1", + "series": "east_coast_padd_1_net_receipts_by_pipeline_tanker_barge_and_rail_from_other_padds_of_asphalt_and_road_oil_thousand_barrels", + "start_date": date(1981, 1, 1), + "end_date": date(1981, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumNetReceiptsBetweenPadDistricts"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_no2_distillate_prices_by_sales_type_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum no2 distillate prices by sales type fetcher.""" + params = { + "frequency": "monthly", + "process": "residential_price_by_all_sellers", + "product": "no_2_distillate", + "region": "us", + "series": "us_no_2_distillate_residential_price_by_all_sellers", + "start_date": date(1983, 1, 1), + "end_date": date(1983, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumNo2DistillatePricesBySalesType"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_number_and_capacity_of_petroleum_refineries_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum number and capacity of petroleum refineries fetcher.""" + params = { + "process": "refinery_catalytic_cracking_fresh_feed_downstream_charge", + "region": "pri", + "series": "8_NA_8CCF_NPZ_5", + "start_date": date(1982, 1, 1), + "end_date": date(1982, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumNumberAndCapacityOfPetroleumRefineries"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_nymex_futures_prices_fetcher(credentials=test_credentials): + """Test the EIA petroleum nymex futures prices fetcher.""" + params = { + "frequency": "weekly", + "process": "future_contract_1", + "product": "no_2_fuel_oil_heating_oil", + "region": "new_york_city", + "series": "new_york_harbor_no_2_heating_oil_future_contract_1", + "start_date": date(1980, 1, 4), + "end_date": date(1980, 1, 4), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumNymexFuturesPrices"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_oxygenate_production_fetcher(credentials=test_credentials): + """Test the EIA petroleum oxygenate production fetcher.""" + params = { + "frequency": "monthly", + "process": "oxygenate_plant_production", + "product": "fuel_ethanol", + "region": "us", + "series": "us_oxygenate_plant_production_of_fuel_ethanol_thousand_barrels", + "start_date": date(1981, 1, 1), + "end_date": date(1981, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumOxygenateProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_pad_district_exports_by_destination_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum pad district exports by destination fetcher.""" + params = { + "frequency": "monthly", + "product": "asphalt_and_road_oil", + "region": "padd_1", + "series": "MAPEXP11", + "start_date": date(1981, 1, 1), + "end_date": date(1981, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumPadDistrictExportsByDestination"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_pad_district_imports_by_country_of_origin_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum pad district imports by country of origin fetcher.""" + params = { + "frequency": "monthly", + "process": "imports_by_padd_of_processing", + "product": "crude_oil", + "region": "padd_1", + "series": "MCRIPP11", + "start_date": date(1981, 1, 1), + "end_date": date(1981, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumPadDistrictImportsByCountryOfOrigin"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_percentages_of_total_imported_crude_oil_by_api_gravity_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum percentages of total imported crude oil by api gravity fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_gravity_20_0_percent_or_less", + "series": "us_percent_total_imported_by_api_gravity_of_crude_gravity_20_0_percent_or_less", + "start_date": date(1983, 1, 1), + "end_date": date(1983, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumPercentagesOfTotalImportedCrudeOilByApiGravity" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_prices_sales_volumes_stocks_by_state_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum prices sales volumes stocks by state fetcher.""" + params = { + "frequency": "monthly", + "process": "retail_sales_by_refiners_and_gas_plants", + "product": "kerosene_type_jet_fuel", + "region": "us", + "series": "EMA_EPJK_PTG_NUS_DPG", + "start_date": date(1975, 7, 1), + "end_date": date(1975, 7, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumPricesSalesVolumesStocksByState"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_prime_supplier_sales_volumes_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum prime supplier sales volumes fetcher.""" + params = { + "frequency": "monthly", + "product": "total_gasoline", + "region": "us", + "series": "C100000001", + "start_date": date(1983, 1, 1), + "end_date": date(1983, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumPrimeSupplierSalesVolumes"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_product_supplied_fetcher(credentials=test_credentials): + """Test the EIA petroleum product supplied fetcher.""" + params = { + "frequency": "monthly", + "product": "residual_fuel_oil", + "region": "us", + "series": "us_product_supplied_of_residual_fuel_oil_thousand_barrels", + "start_date": date(1936, 1, 1), + "end_date": date(1936, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumProductSupplied"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_production_capacity_of_operable_petroleum_refineries_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum production capacity of operable petroleum refineries fetcher.""" + params = { + "process": "production_capacity_of_alkylates", + "region": "pri", + "series": "puerto_rico_refinery_alkylates_production_capacity_as_of", + "start_date": date(1982, 1, 1), + "end_date": date(1982, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumProductionCapacityOfOperablePetroleumRefineries" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_propane_prices_by_sales_type_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum propane prices by sales type fetcher.""" + params = { + "frequency": "monthly", + "process": "residential_price_by_all_sellers", + "region": "us", + "series": "us_propane_residential_price_by_all_sellers", + "start_date": date(1993, 10, 1), + "end_date": date(1993, 10, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumPropanePricesBySalesType"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_proved_nonproducing_reserves_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum proved nonproducing reserves fetcher.""" + params = { + "process": "associated_dissolved_reserves_in_nonproducing_reservoirs", + "product": "natural_gas", + "region": "na", + "series": "gulf_of_america_federal_offshore_western_associated_dissolved_natural_gas_reserves_in_nonproducing_reservoirs_wet_bcf", + "start_date": date(1996, 1, 1), + "end_date": date(1996, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumProvedNonproducingReserves"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refiner_acquisition_cost_of_crude_oil_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum refiner acquisition cost of crude oil fetcher.""" + params = { + "frequency": "monthly", + "process": "imported_acquisition_cost", + "region": "us", + "series": "us_crude_oil_imported_acquisition_cost_by_refiners", + "start_date": date(1974, 1, 1), + "end_date": date(1974, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumRefinerAcquisitionCostOfCrudeOil"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refiner_gasoline_prices_by_grade_and_sales_type_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum refiner gasoline prices by grade and sales type fetcher.""" + params = { + "frequency": "monthly", + "process": "retail_sales_by_refiners_and_gas_plants", + "product": "total_gasoline", + "region": "us", + "series": "us_total_gasoline_retail_sales_by_refiners", + "start_date": date(1983, 1, 1), + "end_date": date(1983, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumRefinerGasolinePricesByGradeAndSalesType"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refiner_motor_gasoline_sales_volumes_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum refiner motor gasoline sales volumes fetcher.""" + params = { + "frequency": "monthly", + "process": "through_company_outlets_volume_by_refiners_and_gas_plants", + "product": "total_gasoline", + "region": "us", + "series": "A103400001", + "start_date": date(1983, 1, 1), + "end_date": date(1983, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumRefinerMotorGasolineSalesVolumes"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refiner_petroleum_product_prices_by_sales_type_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum refiner petroleum product prices by sales type fetcher.""" + params = { + "frequency": "monthly", + "process": "retail_sales_by_refiners_and_gas_plants", + "product": "kerosene_type_jet_fuel", + "region": "us", + "series": "us_kerosene_type_jet_fuel_retail_sales_by_refiners", + "start_date": date(1975, 7, 1), + "end_date": date(1975, 7, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumRefinerPetroleumProductPricesBySalesType"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refiner_residual_fuel_oil_and_no4_fuel_sales_volumes_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum refiner residual fuel oil and no4 fuel sales volumes fetcher.""" + params = { + "frequency": "monthly", + "process": "retail_sales_by_refiners_and_gas_plants", + "product": "residual_fuel_oil", + "region": "us", + "series": "us_residual_fuel_oil_retail_sales_by_refiners", + "start_date": date(1983, 1, 1), + "end_date": date(1983, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumRefinerResidualFuelOilAndNo4FuelSalesVolumes" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refiner_sales_volumes_of_other_petroleum_products_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum refiner sales volumes of other petroleum products fetcher.""" + params = { + "frequency": "monthly", + "process": "retail_sales_by_refiners_and_gas_plants", + "product": "no_2_distillate", + "region": "us", + "series": "A203600001", + "start_date": date(1983, 1, 1), + "end_date": date(1983, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumRefinerSalesVolumesOfOtherPetroleumProducts" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refinery_blender_net_input_fetcher(credentials=test_credentials): + """Test the EIA petroleum refinery blender net input fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_oil", + "region": "us", + "series": "MCRRIUS2", + "start_date": date(1961, 1, 1), + "end_date": date(1961, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumRefineryBlenderNetInput"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refinery_blender_net_production_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum refinery blender net production fetcher.""" + params = { + "frequency": "monthly", + "product": "residual_fuel_oil", + "region": "us", + "series": "MRERPUS1", + "start_date": date(1936, 1, 1), + "end_date": date(1936, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumRefineryBlenderNetProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refinery_bulk_terminal_and_natural_gas_plant_stocks_by_state_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum refinery bulk terminal and natural gas plant stocks by state fetcher.""" + params = { + "frequency": "monthly", + "product": "distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "region": "us", + "series": "us_distillate_fuel_oil_greater_than_15_to_500_ppm_sulfur", + "start_date": date(1993, 1, 1), + "end_date": date(1993, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumRefineryBulkTerminalAndNaturalGasPlantStocksByState" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refinery_net_input_fetcher(credentials=test_credentials): + """Test the EIA petroleum refinery net input fetcher.""" + params = { + "frequency": "monthly", + "process": "refinery_receipts_of_alaskan_oil", + "product": "crude_oil", + "region": "na", + "series": "MACNR2A1", + "start_date": date(1986, 1, 1), + "end_date": date(1986, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumRefineryNetInput"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refinery_net_production_fetcher(credentials=test_credentials): + """Test the EIA petroleum refinery net production fetcher.""" + params = { + "frequency": "monthly", + "product": "commercial_kerosene_type_jet_fuel", + "region": "us", + "series": "M_EPJKC_YPY_NUS_MBBL", + "start_date": date(1993, 1, 1), + "end_date": date(1993, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumRefineryNetProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refinery_receipts_of_crude_oil_by_method_of_transportation_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum refinery receipts of crude oil by method of transportation fetcher.""" + params = { + "process": "crude_oil_refinery_receipts_by_barge", + "region": "us", + "series": "us_crude_oil_refinery_receipts_by_barge", + "start_date": date(1981, 1, 1), + "end_date": date(1981, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumRefineryReceiptsOfCrudeOilByMethodOfTransportation" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refinery_stocks_fetcher(credentials=test_credentials): + """Test the EIA petroleum refinery stocks fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_oil", + "region": "padd_1", + "series": "MCRRSP11", + "start_date": date(1981, 1, 1), + "end_date": date(1981, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumRefineryStocks"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refinery_utilization_and_capacity_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum refinery utilization and capacity fetcher.""" + params = { + "frequency": "monthly", + "process": "refinery_net_input", + "region": "na", + "series": "indiana_illinois_kentucky_refinery_district_gross_inputs_to", + "start_date": date(1985, 1, 1), + "end_date": date(1985, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumRefineryUtilizationAndCapacity"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_refinery_yield_fetcher(credentials=test_credentials): + """Test the EIA petroleum refinery yield fetcher.""" + params = { + "frequency": "monthly", + "product": "asphalt_and_road_oil", + "region": "na", + "series": "refining_district_indiana_illinois_kentucky_refinery_yield_of_asphalt_and_road_oil_percent", + "start_date": date(1993, 1, 1), + "end_date": date(1993, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumRefineryYield"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_residual_fuel_oil_prices_by_sales_type_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum residual fuel oil prices by sales type fetcher.""" + params = { + "frequency": "monthly", + "process": "retail_sales_by_all_sellers", + "product": "residual_fuel_oil_greater_than_1_sulfur", + "region": "us", + "series": "us_residual_fuel_oil_sulfur_greater_than_1_retail_sales_by", + "start_date": date(1983, 1, 1), + "end_date": date(1983, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumResidualFuelOilPricesBySalesType"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_sales_of_distillate_fuel_oil_by_end_use_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum sales of distillate fuel oil by end use fetcher.""" + params = { + "process": "commercial_consumption", + "product": "distillate_fuel_oil", + "region": "us", + "series": "us_total_distillate_sales_deliveries_to_commercial_consumers", + "start_date": date(1984, 1, 1), + "end_date": date(1984, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumSalesOfDistillateFuelOilByEndUse"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_sales_of_kerosene_by_end_use_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum sales of kerosene by end use fetcher.""" + params = { + "process": "commercial_consumption", + "region": "us", + "series": "us_kerosene_sales_deliveries_to_commercial_consumers", + "start_date": date(1984, 1, 1), + "end_date": date(1984, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumSalesOfKeroseneByEndUse"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_sales_of_residual_fuel_oil_by_end_use_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum sales of residual fuel oil by end use fetcher.""" + params = { + "process": "commercial_consumption", + "region": "us", + "series": "us_residual_fuel_oil_sales_deliveries_to_commercial", + "start_date": date(1984, 1, 1), + "end_date": date(1984, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumSalesOfResidualFuelOilByEndUse"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_shell_storage_capacity_at_operable_refineries_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum shell storage capacity at operable refineries fetcher.""" + params = { + "process": "shell_storage_capacity_at_refineries", + "region": "us", + "series": "us_refinery_shell_storage_capacity_as_of_january_1", + "start_date": date(1982, 1, 1), + "end_date": date(1982, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumShellStorageCapacityAtOperableRefineries"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_spot_prices_fetcher(credentials=test_credentials): + """Test the EIA petroleum spot prices fetcher.""" + params = { + "frequency": "weekly", + "product": "wti_crude_oil", + "region": "na", + "series": "cushing_ok_wti_spot_price_fob", + "start_date": date(1986, 1, 3), + "end_date": date(1986, 1, 3), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumSpotPrices"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_stocks_by_type_fetcher(credentials=test_credentials): + """Test the EIA petroleum stocks by type fetcher.""" + params = { + "frequency": "monthly", + "process": "ending_stocks", + "product": "crude_oil", + "region": "us", + "series": "MCRSTUS1", + "start_date": date(1920, 1, 1), + "end_date": date(1920, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumStocksByType"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_stocks_of_selected_products_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum stocks of selected products fetcher.""" + params = { + "frequency": "monthly", + "product": "residual_fuel_oil", + "region": "us", + "series": "us_ending_stocks_of_residual_fuel_oil", + "start_date": date(1936, 1, 1), + "end_date": date(1936, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumStocksOfSelectedProducts"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_supply_and_disposition_fetcher(credentials=test_credentials): + """Test the EIA petroleum supply and disposition fetcher.""" + params = { + "frequency": "monthly", + "process": "ending_stocks", + "product": "crude_oil", + "region": "us", + "series": "MCRSTUS1", + "start_date": date(1920, 1, 1), + "end_date": date(1920, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumSupplyAndDisposition"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_us_biodiesel_production_capacity_sales_and_stocks_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum us biodiesel production capacity sales and stocks fetcher.""" + params = { + "frequency": "monthly", + "process": "ending_stocks", + "region": "us", + "series": "us_ending_stocks_of_b100", + "start_date": date(2009, 1, 1), + "end_date": date(2009, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumUsBiodieselProductionCapacitySalesAndStocks" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_us_crude_oil_supply_disposition_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum us crude oil supply disposition fetcher.""" + params = { + "frequency": "monthly", + "process": "ending_stocks", + "region": "us", + "series": "us_ending_stocks_of_crude_oil", + "start_date": date(1920, 1, 1), + "end_date": date(1920, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumUsCrudeOilSupplyDisposition"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_us_imports_by_country_of_origin_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum us imports by country of origin fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_oil", + "region": "us", + "series": "MCRIMUS1", + "start_date": date(1920, 1, 1), + "end_date": date(1920, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumUsImportsByCountryOfOrigin"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_us_net_imports_by_country_fetcher(credentials=test_credentials): + """Test the EIA petroleum us net imports by country fetcher.""" + params = { + "frequency": "monthly", + "product": "crude_oil", + "region": "us", + "series": "MCRNTUS2", + "start_date": date(1920, 1, 1), + "end_date": date(1920, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumUsNetImportsByCountry"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_us_refiner_gasoline_prices_by_formulation_grade_sales_type_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum us refiner gasoline prices by formulation grade sales type fetcher.""" + params = { + "frequency": "monthly", + "process": "retail_sales_by_refiners_and_gas_plants", + "product": "reformulated_motor_gasoline", + "series": "us_reformulated_gasoline_retail_sales_by_refiners", + "start_date": date(1994, 1, 1), + "end_date": date(1994, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumUsRefinerGasolinePricesByFormulationGradeSalesType" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_us_weekly_product_supplied_fetcher(credentials=test_credentials): + """Test the EIA petroleum us weekly product supplied fetcher.""" + params = { + "frequency": "weekly", + "product": "total_petroleum_products", + "series": "us_product_supplied_of_petroleum_products", + "start_date": date(1990, 11, 9), + "end_date": date(1990, 11, 9), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumUsWeeklyProductSupplied"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_weekly_blender_net_production_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum weekly blender net production fetcher.""" + params = { + "frequency": "weekly", + "product": "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "region": "us", + "series": "us_blender_net_production_of_distillate_fuel_oil_greater_than_500_ppm_sulfur_thousand_barrels_per_day", + "start_date": date(2010, 6, 4), + "end_date": date(2010, 6, 4), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumWeeklyBlenderNetProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_weekly_crude_imports_by_top10_origins_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum weekly crude imports by top10 origins fetcher.""" + params = { + "frequency": "weekly", + "region": "dza", + "series": "us_imports_from_algeria_of_crude_oil", + "start_date": date(2010, 6, 4), + "end_date": date(2010, 6, 4), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumWeeklyCrudeImportsByTop10Origins"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_weekly_ethanol_plant_production_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum weekly ethanol plant production fetcher.""" + params = { + "frequency": "weekly", + "region": "us", + "series": "us_oxygenate_plant_production_of_fuel_ethanol", + "start_date": date(2010, 6, 4), + "end_date": date(2010, 6, 4), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumWeeklyEthanolPlantProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_weekly_heating_oil_and_propane_prices_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum weekly heating oil and propane prices fetcher.""" + params = { + "frequency": "weekly", + "process": "price_delivered_to_residential_consumers", + "product": "no_2_fuel_oil_heating_oil", + "region": "us", + "series": "us_weekly_no_2_heating_oil_residential_price", + "start_date": date(1990, 10, 1), + "end_date": date(1990, 10, 1), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumWeeklyHeatingOilAndPropanePrices"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_weekly_imports_exports_fetcher(credentials=test_credentials): + """Test the EIA petroleum weekly imports exports fetcher.""" + params = { + "frequency": "weekly", + "process": "imports", + "product": "distillate_fuel_oil", + "region": "us", + "series": "us_imports_of_distillate_fuel_oil", + "start_date": date(1982, 8, 20), + "end_date": date(1982, 8, 20), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumWeeklyImportsExports"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_weekly_inputs_utilization_fetcher(credentials=test_credentials): + """Test the EIA petroleum weekly inputs utilization fetcher.""" + params = { + "frequency": "weekly", + "process": "refinery_net_input", + "product": "crude_oil", + "region": "us", + "series": "us_refiner_net_input_of_crude_oil", + "start_date": date(1982, 8, 20), + "end_date": date(1982, 8, 20), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumWeeklyInputsUtilization"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_weekly_refiner_blender_net_production_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum weekly refiner blender net production fetcher.""" + params = { + "frequency": "weekly", + "process": "refinery_and_blender_net_production", + "product": "distillate_fuel_oil", + "region": "us", + "series": "us_refiner_and_blender_net_production_of_distillate_fuel_oil", + "start_date": date(1982, 8, 20), + "end_date": date(1982, 8, 20), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumWeeklyRefinerBlenderNetProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_weekly_refiner_net_production_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum weekly refiner net production fetcher.""" + params = { + "frequency": "weekly", + "product": "distillate_fuel_oil_greater_than_500_ppm_sulfur", + "region": "us", + "series": "us_refiner_net_production_of_distillate_fuel_oil_greater_than_500_ppm_sulfur_thousand_barrels_per_day", + "start_date": date(2010, 6, 4), + "end_date": date(2010, 6, 4), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumWeeklyRefinerNetProduction"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_weekly_retail_gasoline_and_diesel_prices_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum weekly retail gasoline and diesel prices fetcher.""" + params = { + "frequency": "weekly", + "product": "conventional_regular_gasoline", + "region": "us", + "series": "us_regular_conventional_retail_gasoline_prices", + "start_date": date(1990, 8, 20), + "end_date": date(1990, 8, 20), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumWeeklyRetailGasolineAndDieselPrices"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_weekly_stocks_fetcher(credentials=test_credentials): + """Test the EIA petroleum weekly stocks fetcher.""" + params = { + "process": "ending_stocks", + "product": "crude_oil", + "region": "us", + "series": "us_ending_stocks_of_crude_oil", + "start_date": date(1982, 8, 20), + "end_date": date(1982, 8, 20), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumWeeklyStocks"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_weekly_supply_estimates_fetcher(credentials=test_credentials): + """Test the EIA petroleum weekly supply estimates fetcher.""" + params = { + "frequency": "weekly", + "process": "refinery_net_input", + "product": "crude_oil", + "region": "us", + "series": "us_refiner_net_input_of_crude_oil", + "start_date": date(1982, 8, 20), + "end_date": date(1982, 8, 20), + } + + fetcher = DATASET_FETCHERS["EiaPetroleumWeeklySupplyEstimates"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_petroleum_working_storage_capacity_at_operable_refineries_fetcher( + credentials=test_credentials, +): + """Test the EIA petroleum working storage capacity at operable refineries fetcher.""" + params = { + "process": "working_storage_capacity", + "region": "us", + "series": "us_refinery_working_storage_capacity_as_of_january_1", + "start_date": date(1982, 1, 1), + "end_date": date(1982, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaPetroleumWorkingStorageCapacityAtOperableRefineries" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_seds_fetcher(credentials=test_credentials): + """Test the EIA seds fetcher.""" + params = { + "series": "aviation_gasoline_blending_components_consumed_by_the", + "state": "alaska", + "start_date": date(1960, 1, 1), + "end_date": date(1960, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaSeds"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_state_electricity_profiles_advanced_metering_infrastructure_fetcher( + credentials=test_credentials, +): + """Test the EIA state electricity profiles advanced metering infrastructure fetcher.""" + params = { + "sector": "commercial", + "state": "alaska", + "technology": "advanced_metering_infrastructure", + "start_date": date(2013, 1, 1), + "end_date": date(2013, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaStateElectricityProfilesAdvancedMeteringInfrastructure" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_state_electricity_profiles_costs_and_savings_from_energy_efficiency_programs_fetcher( + credentials=test_credentials, +): + """Test the EIA state electricity profiles costs and savings from energy efficiency programs fetcher.""" + params = { + "sector": "commercial", + "state": "alaska", + "start_date": date(2013, 1, 1), + "end_date": date(2013, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaStateElectricityProfilesCostsAndSavingsFromEnergyEfficiencyPrograms" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_state_electricity_profiles_electricity_net_metering_customers_and_capacity_fetcher( + credentials=test_credentials, +): + """Test the EIA state electricity profiles electricity net metering customers and capacity fetcher.""" + params = { + "start_date": date(2023, 1, 1), + "end_date": date(2023, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaStateElectricityProfilesElectricityNetMeteringCustomersAndCapacity" + ]() + with pytest.raises(EmptyDataError): + fetcher.test(params, credentials) + + +@pytest.mark.record_http +def test_eia_state_electricity_profiles_emissions_by_state_by_fuel_fetcher( + credentials=test_credentials, +): + """Test the EIA state electricity profiles emissions by state by fuel fetcher.""" + params = { + "fuel": "total", + "state": "alaska", + "start_date": date(1990, 1, 1), + "end_date": date(1990, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaStateElectricityProfilesEmissionsByStateByFuel"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_state_electricity_profiles_generating_capacity_fetcher( + credentials=test_credentials, +): + """Test the EIA state electricity profiles generating capacity fetcher.""" + params = { + "energy_source": "all", + "producer_type": "electric_utilities", + "state": "alaska", + "start_date": date(1990, 1, 1), + "end_date": date(1990, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaStateElectricityProfilesGeneratingCapacity"]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_state_electricity_profiles_state_rankings_for_key_statistics_fetcher( + credentials=test_credentials, +): + """Test the EIA state electricity profiles state rankings for key statistics fetcher.""" + params = { + "state": "alaska", + "start_date": date(2008, 1, 1), + "end_date": date(2008, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaStateElectricityProfilesStateRankingsForKeyStatistics" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_state_electricity_profiles_supply_and_disposition_of_electricity_fetcher( + credentials=test_credentials, +): + """Test the EIA state electricity profiles supply and disposition of electricity fetcher.""" + params = { + "state": "alaska", + "start_date": date(1990, 1, 1), + "end_date": date(1990, 1, 1), + } + + fetcher = DATASET_FETCHERS[ + "EiaStateElectricityProfilesSupplyAndDispositionOfElectricity" + ]() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_eia_total_energy_fetcher(credentials=test_credentials): + """Test the EIA total energy fetcher.""" + params = { + "frequency": "monthly", + "msn": "asphalt_and_road_oil_consumed_by_the_industrial_sector_in_trillion_btu", + "start_date": date(1973, 1, 1), + "end_date": date(1973, 1, 1), + } + + fetcher = DATASET_FETCHERS["EiaTotalEnergy"]() + result = fetcher.test(params, credentials) + assert result is None diff --git a/openbb_platform/providers/eia/tests/test_eia_mcp.py b/openbb_platform/providers/eia/tests/test_eia_mcp.py new file mode 100644 index 00000000000..ecbb3873196 --- /dev/null +++ b/openbb_platform/providers/eia/tests/test_eia_mcp.py @@ -0,0 +1,883 @@ +import runpy +import socket +import sys +import types +from copy import deepcopy +from inspect import signature +from typing import get_args + +import pytest +from fastapi.params import Depends as DependsParam +from starlette.requests import Request + +from openbb_us_eia import eia_mcp +from openbb_us_eia.utils import rss as eia_mcp_rss + + +@pytest.fixture(autouse=True) +def reset_process(): + prev = eia_mcp._mcp_process + eia_mcp._mcp_process = None + yield + eia_mcp._mcp_process = prev + + +def _request(method="GET", query="", body=b"", headers=None): + headers = headers or [] + + async def receive(): + return {"type": "http.request", "body": body, "more_body": False} + + return Request( + scope={ + "type": "http", + "method": method, + "scheme": "http", + "server": ("test", 80), + "path": "/api/v1/eia/eia_mcp", + "query_string": query.encode(), + "headers": headers, + }, + receive=receive, + ) + + +async def _proxy(request=None): + """Call ``mcp_reverse_proxy`` the way FastAPI does, with its dependency resolved. + + The endpoint takes the extracted dict, never the ``Request`` itself - see + ``test_mcp_reverse_proxy_takes_extracted_dict_not_request`` for why. + """ + return await eia_mcp.mcp_reverse_proxy( + await eia_mcp._extract_mcp_request( + request if request is not None else _request() + ) + ) + + +def test_mcp_port_from_env(monkeypatch): + monkeypatch.setenv("OPENBB_EIA_MCP_PORT", "7777") + assert eia_mcp.mcp_port() == 7777 + + +def test_mcp_port_invalid_env(monkeypatch): + monkeypatch.setenv("OPENBB_EIA_MCP_PORT", "bad") + assert eia_mcp.mcp_port() == eia_mcp._DEFAULT_MCP_PORT + + +def test_mcp_server_url(monkeypatch): + monkeypatch.setenv("OPENBB_EIA_MCP_PORT", "7001") + assert eia_mcp.mcp_server_url() == "http://127.0.0.1:7001/mcp" + + +def test_port_open_true_and_false(): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.bind(("127.0.0.1", 0)) + s.listen(1) + host, port = s.getsockname() + assert eia_mcp._port_open(host, port) is True + assert eia_mcp._port_open(host, port) is False + + +def test_api_state_url(monkeypatch): + monkeypatch.setenv("OPENBB_API_HOST", "127.0.0.9") + monkeypatch.setenv("OPENBB_API_PORT", "7770") + assert eia_mcp._api_state_url("electricity", "u9").startswith( + "http://127.0.0.9:7770/api/v1/eia/eia_mcp_state?browser=electricity&user=u9" + ) + + +def test_ensure_mcp_subprocess_skips_when_running(): + class Proc: + def poll(self): + return None + + eia_mcp._mcp_process = Proc() + eia_mcp.ensure_mcp_subprocess() + assert isinstance(eia_mcp._mcp_process, Proc) + + +def test_ensure_mcp_subprocess_skips_when_port_open(monkeypatch): + called = {"popen": False} + + def fake_open(_h, _p): + return True + + def fake_popen(*_a, **_k): + called["popen"] = True + raise AssertionError("should not run") + + monkeypatch.setattr(eia_mcp, "_port_open", fake_open) + monkeypatch.setattr("subprocess.Popen", fake_popen) + eia_mcp.ensure_mcp_subprocess() + assert called["popen"] is False + + +def test_ensure_mcp_subprocess_launches(monkeypatch): + reg = {"called": False} + + class Proc: + def poll(self): + return None + + def fake_open(_h, _p): + return False + + def fake_popen(*_a, **_k): + return Proc() + + def fake_register(_fn): + reg["called"] = True + + monkeypatch.setattr(eia_mcp, "_port_open", fake_open) + monkeypatch.setattr("subprocess.Popen", fake_popen) + monkeypatch.setattr("atexit.register", fake_register) + eia_mcp.ensure_mcp_subprocess() + assert eia_mcp._mcp_process is not None + assert reg["called"] is True + + +def test_ensure_mcp_subprocess_handles_launch_error(monkeypatch): + def fake_open(_h, _p): + return False + + def fake_popen(*_a, **_k): + raise RuntimeError("boom") + + monkeypatch.setattr(eia_mcp, "_port_open", fake_open) + monkeypatch.setattr("subprocess.Popen", fake_popen) + eia_mcp.ensure_mcp_subprocess() + assert eia_mcp._mcp_process is None + + +def test_stop_mcp_subprocess_terminates(): + class Proc: + def __init__(self): + self.terminated = False + + def poll(self): + return None + + def terminate(self): + self.terminated = True + + proc = Proc() + eia_mcp._mcp_process = proc + eia_mcp.stop_mcp_subprocess() + assert proc.terminated is True + assert eia_mcp._mcp_process is None + + +@pytest.mark.asyncio +async def test_await_ready_true(monkeypatch): + seq = iter([False, False, True]) + + def fake_open(_h, _p): + return next(seq) + + async def fake_sleep(_t): + return None + + monkeypatch.setattr(eia_mcp, "_port_open", fake_open) + monkeypatch.setattr("asyncio.sleep", fake_sleep) + assert await eia_mcp._await_ready(timeout=1.0) is True + + +@pytest.mark.asyncio +async def test_await_ready_false(monkeypatch): + def fake_open(_h, _p): + return False + + async def fake_sleep(_t): + return None + + monkeypatch.setattr(eia_mcp, "_port_open", fake_open) + monkeypatch.setattr("asyncio.sleep", fake_sleep) + assert await eia_mcp._await_ready(timeout=0.4) is False + + +@pytest.mark.asyncio +async def test_extract_mcp_request_filters_headers(): + req = _request( + method="POST", + query="a=1", + body=b"{}", + headers=[ + (b"accept", b"application/json"), + (b"x-openbb-user", b"alice@example.com"), + (b"authorization", b"secret"), + ], + ) + out = await eia_mcp._extract_mcp_request(req) + assert out["method"] == "POST" + assert out["body"] == b"{}" + assert out["query"] == {"a": "1"} + assert "accept" in out["headers"] + assert "x-openbb-user" in out["headers"] + assert "authorization" not in out["headers"] + + +def test_mcp_reverse_proxy_takes_extracted_dict_not_request(): + """The endpoint must take the extracted dict via ``Depends``, never a ``Request``. + + ``add_command_map`` rewraps every extension route with ``build_api_wrapper``, + which hands the endpoint's resolved kwargs to ``CommandRunner``; that does + ``deepcopy(kwargs)`` (command_runner.py). Deep-copying a ``Request`` recurses + through ``starlette.datastructures.State.__getattr__`` until it raises + ``RecursionError``, so declaring one here 500s the route on every single call. + Keeping the ``Request`` inside ``_extract_mcp_request`` is what makes the + route work at all. + """ + params = list(signature(eia_mcp.mcp_reverse_proxy).parameters.values()) + assert len(params) == 1 + param = params[0] + assert param.annotation is not Request + depends = [m for m in get_args(param.annotation)[1:] if isinstance(m, DependsParam)] + assert len(depends) == 1 + assert depends[0].dependency is eia_mcp._extract_mcp_request + + +@pytest.mark.asyncio +async def test_extracted_request_survives_deepcopy(): + """Whatever the endpoint receives has to survive the wrapper's ``deepcopy``.""" + data = await eia_mcp._extract_mcp_request( + _request( + method="POST", + query="a=1", + body=b'{"jsonrpc":"2.0"}', + headers=[(b"accept", b"application/json")], + ) + ) + assert deepcopy(data) == data + + +@pytest.mark.asyncio +async def test_mcp_reverse_proxy_startup_failure(monkeypatch): + monkeypatch.setattr(eia_mcp, "ensure_mcp_subprocess", lambda: None) + + async def not_ready(): + return False + + monkeypatch.setattr(eia_mcp, "_await_ready", not_ready) + resp = await _proxy() + assert resp.status_code == 503 + + +@pytest.mark.asyncio +async def test_mcp_reverse_proxy_client_error(monkeypatch): + import aiohttp + + monkeypatch.setattr(eia_mcp, "ensure_mcp_subprocess", lambda: None) + + async def ready(): + return True + + monkeypatch.setattr(eia_mcp, "_await_ready", ready) + + class Session: + def __init__(self, **_k): + self.closed = False + + async def request(self, *_a, **_k): + raise aiohttp.ClientError("x") + + async def close(self): + self.closed = True + + monkeypatch.setattr("aiohttp.ClientSession", Session) + resp = await _proxy() + assert resp.status_code == 502 + + +@pytest.mark.asyncio +async def test_mcp_reverse_proxy_stream_success(monkeypatch): + monkeypatch.setattr(eia_mcp, "ensure_mcp_subprocess", lambda: None) + + async def ready(): + return True + + monkeypatch.setattr(eia_mcp, "_await_ready", ready) + + state = {"released": False, "closed": False} + + class Content: + async def iter_any(self): + yield b"a" + yield b"b" + + class Upstream: + status = 207 + headers = { + "content-type": "application/json", + "x-test": "ok", + "content-length": "2", + } + content = Content() + + def release(self): + state["released"] = True + + class Session: + def __init__(self, **_k): + pass + + async def request(self, *_a, **_k): + return Upstream() + + async def close(self): + state["closed"] = True + + monkeypatch.setattr("aiohttp.ClientSession", Session) + resp = await _proxy() + body = b"" + async for chunk in resp.body_iterator: + body += chunk + assert resp.status_code == 207 + assert resp.headers.get("x-test") == "ok" + assert "content-length" not in resp.headers + assert body == b"ab" + assert state["released"] is True + assert state["closed"] is True + + +@pytest.mark.asyncio +async def test_mcp_reverse_proxy_stream_iter_error(monkeypatch): + import aiohttp + + monkeypatch.setattr(eia_mcp, "ensure_mcp_subprocess", lambda: None) + + async def ready(): + return True + + monkeypatch.setattr(eia_mcp, "_await_ready", ready) + + state = {"released": False, "closed": False} + + class Content: + async def iter_any(self): + raise aiohttp.ClientError("x") + yield b"x" + + class Upstream: + status = 200 + headers = {"content-type": "application/json"} + content = Content() + + def release(self): + state["released"] = True + + class Session: + def __init__(self, **_k): + pass + + async def request(self, *_a, **_k): + return Upstream() + + async def close(self): + state["closed"] = True + + monkeypatch.setattr("aiohttp.ClientSession", Session) + resp = await _proxy() + body = b"" + async for chunk in resp.body_iterator: + body += chunk + assert body == b"" + assert state["released"] is True + assert state["closed"] is True + + +def test_serve_wires_and_runs(monkeypatch): + calls = {"middleware": False, "exit": False, "run": False} + + class App: + def add_middleware(self, *_a, **_k): + calls["middleware"] = True + + class M: + def http_app(self, **_k): + return App() + + def fake_build(): + return M() + + def fake_exit_when_orphaned(): + calls["exit"] = True + + monkeypatch.setattr(eia_mcp, "_build_mcp_server", fake_build) + monkeypatch.setattr(eia_mcp, "_exit_when_orphaned", fake_exit_when_orphaned) + + def fake_run(_app, host, port, log_level): + calls["run"] = host == "127.0.0.1" and port == 7000 and log_level == "warning" + + monkeypatch.setattr("uvicorn.run", fake_run) + eia_mcp._serve("127.0.0.1", 7000) + assert calls == {"middleware": True, "exit": True, "run": True} + + +def test_exit_when_orphaned_starts_watcher(monkeypatch): + calls = {"thread": False, "target": None, "daemon": None} + + class T: + def __init__(self, target=None, daemon=None): + calls["target"] = target + calls["daemon"] = daemon + + def start(self): + calls["thread"] = True + + monkeypatch.setattr("os.getppid", lambda: 123) + monkeypatch.setattr("threading.Thread", T) + eia_mcp._exit_when_orphaned() + assert calls["thread"] is True + assert calls["daemon"] is True + assert callable(calls["target"]) + + +def test_exit_when_orphaned_watch_exits(monkeypatch): + calls = {"target": None, "sleep": 0, "exit": None} + + class ExitNow(Exception): + pass + + seq = iter([300, 301]) + + class T: + def __init__(self, target=None, daemon=None): + calls["target"] = target + + def start(self): + return None + + def fake_sleep(_t): + calls["sleep"] += 1 + + def fake_exit(code): + calls["exit"] = code + raise ExitNow + + monkeypatch.setattr("os.getppid", lambda: next(seq)) + monkeypatch.setattr("threading.Thread", T) + monkeypatch.setattr("time.sleep", fake_sleep) + monkeypatch.setattr("os._exit", fake_exit) + eia_mcp._exit_when_orphaned() + with pytest.raises(ExitNow): + calls["target"]() + assert calls["sleep"] == 1 + assert calls["exit"] == 0 + + +@pytest.mark.asyncio +async def test_build_mcp_server_tool_returns_rows(monkeypatch): + seen = {} + + class FMCP: + def __init__(self, **_k): + self.tools = {} + + def tool(self, fn): + # Key by name: the server registers several tools, and keying by + # name keeps these tests pinned to the one they mean. + self.tools[fn.__name__] = fn + return fn + + monkeypatch.setitem( + __import__("sys").modules, "fastmcp", types.SimpleNamespace(FastMCP=FMCP) + ) + + class Resp: + status = 200 + + async def read(self): + return b'[{"x":1}]' + + class Ctx: + async def __aenter__(self): + return Resp() + + async def __aexit__(self, *_a): + return False + + class Session: + def __init__(self, **_k): + pass + + async def __aenter__(self): + return self + + async def __aexit__(self, *_a): + return False + + def get(self, url): + seen["url"] = url + return Ctx() + + monkeypatch.setattr("aiohttp.ClientSession", Session) + monkeypatch.setitem( + __import__("sys").modules, + "fastmcp.server.dependencies", + types.SimpleNamespace( + get_http_headers=lambda include=None: {"x-openbb-user": "x@x.com"} + ), + ) + monkeypatch.setattr(eia_mcp, "_api_state_url", lambda b, u: f"http://x/{b}/{u}") + mcp = eia_mcp._build_mcp_server() + rows = await mcp.tools["get_current_browser_data"]("electricity") + assert rows == [{"x": 1}] + assert seen["url"].startswith("http://x/electricity/") + + +@pytest.mark.asyncio +async def test_build_mcp_server_tool_non_200(monkeypatch): + class FMCP: + def __init__(self, **_k): + self.tools = {} + + def tool(self, fn): + # Key by name: the server registers several tools, and keying by + # name keeps these tests pinned to the one they mean. + self.tools[fn.__name__] = fn + return fn + + monkeypatch.setitem( + __import__("sys").modules, "fastmcp", types.SimpleNamespace(FastMCP=FMCP) + ) + + class Resp: + status = 500 + + async def read(self): + return b"[]" + + class Ctx: + async def __aenter__(self): + return Resp() + + async def __aexit__(self, *_a): + return False + + class Session: + def __init__(self, **_k): + pass + + async def __aenter__(self): + return self + + async def __aexit__(self, *_a): + return False + + def get(self, _url): + return Ctx() + + monkeypatch.setattr("aiohttp.ClientSession", Session) + monkeypatch.setitem( + __import__("sys").modules, + "fastmcp.server.dependencies", + types.SimpleNamespace(get_http_headers=lambda include=None: {}), + ) + mcp = eia_mcp._build_mcp_server() + assert await mcp.tools["get_current_browser_data"]("coal") == [] + + +@pytest.mark.asyncio +async def test_build_mcp_server_tool_non_list_payload(monkeypatch): + class FMCP: + def __init__(self, **_k): + self.tools = {} + + def tool(self, fn): + # Key by name: the server registers several tools, and keying by + # name keeps these tests pinned to the one they mean. + self.tools[fn.__name__] = fn + return fn + + monkeypatch.setitem( + __import__("sys").modules, "fastmcp", types.SimpleNamespace(FastMCP=FMCP) + ) + + class Resp: + status = 200 + + async def read(self): + return b'{"x":1}' + + class Ctx: + async def __aenter__(self): + return Resp() + + async def __aexit__(self, *_a): + return False + + class Session: + def __init__(self, **_k): + pass + + async def __aenter__(self): + return self + + async def __aexit__(self, *_a): + return False + + def get(self, _url): + return Ctx() + + monkeypatch.setattr("aiohttp.ClientSession", Session) + monkeypatch.setitem( + __import__("sys").modules, + "fastmcp.server.dependencies", + types.SimpleNamespace(get_http_headers=lambda include=None: {}), + ) + mcp = eia_mcp._build_mcp_server() + assert await mcp.tools["get_current_browser_data"]("coal") == [] + + +@pytest.mark.asyncio +async def test_build_mcp_server_tool_invalid_json(monkeypatch): + class FMCP: + def __init__(self, **_k): + self.tools = {} + + def tool(self, fn): + # Key by name: the server registers several tools, and keying by + # name keeps these tests pinned to the one they mean. + self.tools[fn.__name__] = fn + return fn + + monkeypatch.setitem( + __import__("sys").modules, "fastmcp", types.SimpleNamespace(FastMCP=FMCP) + ) + + class Resp: + status = 200 + + async def read(self): + return b"{" + + class Ctx: + async def __aenter__(self): + return Resp() + + async def __aexit__(self, *_a): + return False + + class Session: + def __init__(self, **_k): + pass + + async def __aenter__(self): + return self + + async def __aexit__(self, *_a): + return False + + def get(self, _url): + return Ctx() + + monkeypatch.setattr("aiohttp.ClientSession", Session) + monkeypatch.setitem( + __import__("sys").modules, + "fastmcp.server.dependencies", + types.SimpleNamespace(get_http_headers=lambda include=None: {}), + ) + mcp = eia_mcp._build_mcp_server() + assert await mcp.tools["get_current_browser_data"]("coal") == [] + + +def test_module_main_invokes_serve(monkeypatch): + calls = {"run": False} + + class App: + def add_middleware(self, *_a, **_k): + return None + + class FMCP: + def __init__(self, **_k): + self.tools = {} + + def tool(self, fn): + # Key by name: the server registers several tools, and keying by + # name keeps these tests pinned to the one they mean. + self.tools[fn.__name__] = fn + return fn + + def http_app(self, **_k): + return App() + + monkeypatch.setitem(sys.modules, "fastmcp", types.SimpleNamespace(FastMCP=FMCP)) + monkeypatch.setitem( + sys.modules, + "starlette.middleware.cors", + types.SimpleNamespace(CORSMiddleware=object), + ) + monkeypatch.setitem( + sys.modules, + "uvicorn", + types.SimpleNamespace(run=lambda *_a, **_k: calls.__setitem__("run", True)), + ) + monkeypatch.setattr(sys, "argv", ["eia_mcp.py"]) + monkeypatch.setattr("threading.Thread.start", lambda self: None) + source = eia_mcp.__file__ + runpy.run_path(source, run_name="__main__") + assert calls["run"] is True + + +def _fake_fastmcp(monkeypatch): + """Install a fake ``fastmcp`` and return the built server's tools by name.""" + + class FMCP: + def __init__(self, **_k): + self.tools = {} + + def tool(self, fn): + self.tools[fn.__name__] = fn + return fn + + monkeypatch.setitem(sys.modules, "fastmcp", types.SimpleNamespace(FastMCP=FMCP)) + monkeypatch.setitem( + sys.modules, + "fastmcp.server.dependencies", + types.SimpleNamespace(get_http_headers=lambda include=None: {}), + ) + return eia_mcp._build_mcp_server().tools + + +class _Body: + """Minimal aiohttp response stand-in.""" + + def __init__(self, status=200, text="", payload=b""): + self.status = status + self._text = text + self._payload = payload + + async def text(self): + return self._text + + async def read(self): + return self._payload + + async def __aenter__(self): + return self + + async def __aexit__(self, *_a): + return False + + +def _session_factory(monkeypatch, response, on_get=None): + class Session: + def __init__(self, **_k): + pass + + async def __aenter__(self): + return self + + async def __aexit__(self, *_a): + return False + + def get(self, url, **_k): + if on_get is not None: + on_get(url) + if isinstance(response, Exception): + raise response + return response + + monkeypatch.setattr("aiohttp.ClientSession", Session) + + +@pytest.mark.asyncio +async def test_get_feed_articles_returns_records(monkeypatch): + tools = _fake_fastmcp(monkeypatch) + + async def fake_fetch(_session, url): + assert url == eia_mcp_rss.EIA_RSS_FEEDS["today_in_energy"]["url"] + return types.SimpleNamespace( + feed={"title": "Today in Energy"}, + entries=[ + { + "title": "Solar output rose", + "link": "todayinenergy/detail.php?id=1", + "summary": "<p>Some <b>summary</b>.</p>", + "author": "EIA", + "published_parsed": (2026, 9, 1, 0, 0, 0, 0, 1, 0), + } + ], + ) + + monkeypatch.setattr(eia_mcp_rss, "fetch_feed", fake_fetch) + _session_factory(monkeypatch, _Body()) + + rows = await tools["get_feed_articles"]("today_in_energy") + assert len(rows) == 1 + assert set(rows[0]) == {"title", "date", "author", "url", "excerpt"} + assert rows[0]["title"] == "Solar output rose" + assert rows[0]["url"].endswith("todayinenergy/detail.php?id=1") + + +@pytest.mark.asyncio +async def test_get_feed_articles_unknown_feed_falls_back(monkeypatch): + tools = _fake_fastmcp(monkeypatch) + seen = {} + + async def fake_fetch(_session, url): + seen["url"] = url + return types.SimpleNamespace(feed={}, entries=[]) + + monkeypatch.setattr(eia_mcp_rss, "fetch_feed", fake_fetch) + _session_factory(monkeypatch, _Body()) + + assert await tools["get_feed_articles"]("not_a_feed") == [] + assert seen["url"] == eia_mcp_rss.EIA_RSS_FEEDS["today_in_energy"]["url"] + + +@pytest.mark.asyncio +async def test_get_feed_articles_client_error(monkeypatch): + import aiohttp + + tools = _fake_fastmcp(monkeypatch) + + async def boom(_session, _url): + raise aiohttp.ClientError("down") + + monkeypatch.setattr(eia_mcp_rss, "fetch_feed", boom) + _session_factory(monkeypatch, _Body()) + + assert await tools["get_feed_articles"]("today_in_energy") == [] + + +@pytest.mark.asyncio +async def test_get_article_content_returns_text(monkeypatch): + tools = _fake_fastmcp(monkeypatch) + _session_factory( + monkeypatch, + _Body(text="<html><style>p{}</style><body><p>Real prose.</p></body></html>"), + ) + out = await tools["get_article_content"]("https://www.eia.gov/todayinenergy/x.php") + assert out == "Real prose." + + +@pytest.mark.asyncio +async def test_get_article_content_rejects_non_eia_host(monkeypatch): + tools = _fake_fastmcp(monkeypatch) + called = {"n": 0} + + def on_get(_url): + called["n"] += 1 + + _session_factory(monkeypatch, _Body(text="secret"), on_get=on_get) + out = await tools["get_article_content"]("https://evil.example.com/x") + assert out == "Only eia.gov article URLs can be fetched." + assert called["n"] == 0 + + +@pytest.mark.asyncio +async def test_get_article_content_non_200(monkeypatch): + tools = _fake_fastmcp(monkeypatch) + _session_factory(monkeypatch, _Body(status=404, text="nope")) + assert await tools["get_article_content"]("https://www.eia.gov/a.php") == "" + + +@pytest.mark.asyncio +async def test_get_article_content_client_error(monkeypatch): + import aiohttp + + tools = _fake_fastmcp(monkeypatch) + _session_factory(monkeypatch, aiohttp.ClientError("boom")) + assert await tools["get_article_content"]("https://www.eia.gov/a.php") == "" diff --git a/openbb_platform/providers/eia/tests/test_eia_router.py b/openbb_platform/providers/eia/tests/test_eia_router.py new file mode 100644 index 00000000000..9e45a7319ff --- /dev/null +++ b/openbb_platform/providers/eia/tests/test_eia_router.py @@ -0,0 +1,290 @@ +"""Tests for the EIA provider router.""" + +from inspect import Parameter +from unittest.mock import AsyncMock, MagicMock, patch + +import pytest +from openbb_core.app.model.abstract.error import OpenBBError + +from openbb_us_eia import eia_provider +from openbb_us_eia.eia_router import datasets, facet_options, router +from openbb_us_eia.utils import catalog +from openbb_us_eia.utils.catalog import DATASET_GROUPS, model_name + +FLAT_MODEL_COMMANDS = { + "/aeo": "EiaAeo", + "/crude_oil_imports": "EiaCrudeOilImports", + "/data_browser": "EiaDataBrowser", + "/ieo": "EiaIeo", + "/international": "EiaInternational", + "/seds": "EiaSeds", + "/total_energy": "EiaTotalEnergy", +} + +GROUP_PREFIXES = { + "coal": "/coal", + "petroleum": "/petroleum", + "natural_gas": "/natural_gas", + "electricity": "/electricity", + "electricity_grid": "/electricity_grid", + "state_electricity_profiles": "/state_electricity_profiles", + "densified_biomass": "/densified_biomass", + "nuclear_outages": "/nuclear_outages", +} + +CATEGORIZED_GROUPS = {"petroleum", "natural_gas"} + + +def _dataset_path(group: str, dataset: str, spec: dict) -> str: + prefix = GROUP_PREFIXES[group] + if group in CATEGORIZED_GROUPS: + return f"{prefix}/{spec['category_slug']}/{dataset}" + return f"{prefix}/{dataset}" + + +def _routes_by_path(): + """Map every registered path to its route. + + ``include_router`` is lazy in newer FastAPI, so the group sub-routers show + up as ``_IncludedRouter`` placeholders rather than ``APIRoute``. Core's + ``iter_api_routes`` resolves them to prefixed route descriptors. + """ + from openbb_core.app.route_iter import iter_api_routes + + return {route.path: route for route in iter_api_routes(router.api_router)} + + +class TestStaticPackageBuild: + """Every route must survive ``openbb-build``. + + The package builder writes ``reference.json`` with ``json.dumps``, so no + parameter default may be a non-serialisable object. A FastAPI dependency + must therefore be declared as ``Annotated[T, Depends(...)]`` -- which the + builder drops -- and never as a ``= Depends(...)`` default value, which it + carries straight into the reference and fails to serialise. + """ + + def _formatted(self, path, route): + from inspect import signature + + from openbb_core.app.static.package_builder.method_definition import ( + MethodDefinition, + ) + + endpoint = route.endpoint + return MethodDefinition.format_params( + path=path, + parameter_map=dict(signature(endpoint).parameters), + func=endpoint, + ) + + def test_no_dependency_leaks_into_a_parameter_default(self): + leaked = [ + (path, name) + for path, route in _routes_by_path().items() + for name, param in self._formatted(path, route).items() + if "Depends" in str(param.default) + ] + assert leaked == [] + + def test_every_parameter_default_is_json_serialisable(self): + from json import dumps + + for path, route in _routes_by_path().items(): + for name, param in self._formatted(path, route).items(): + default = param.default + if default is Parameter.empty: + continue + try: + dumps(default) + except TypeError as exc: # pragma: no cover - guard only + raise AssertionError( + f"{path} parameter '{name}' has a default that" + f" openbb-build cannot serialise: {default!r}" + ) from exc + + def test_the_injected_request_context_is_not_a_public_parameter(self): + for path, route in _routes_by_path().items(): + assert "info" not in self._formatted(path, route) + + +class TestRouterRegistration: + """Every dataset and flat command is registered at its expected path.""" + + def test_flat_model_commands_registered(self): + routes = _routes_by_path() + for path, model in FLAT_MODEL_COMMANDS.items(): + assert path in routes + assert routes[path].openapi_extra["model"] == model + assert model in eia_provider.fetcher_dict + + def test_every_dataset_command_registered(self): + routes = _routes_by_path() + for group in DATASET_GROUPS: + for dataset, spec in catalog.get_group(group)["datasets"].items(): + path = _dataset_path(group, dataset, spec) + assert path in routes, path + assert routes[path].openapi_extra["model"] == model_name(group, dataset) + + def test_dataset_summaries_have_clean_first_sentence(self): + routes = _routes_by_path() + for group in DATASET_GROUPS: + for dataset, spec in catalog.get_group(group)["datasets"].items(): + description = routes[_dataset_path(group, dataset, spec)].description + first = description.split(".")[0] + assert len(first) > 3, description + + def test_discovery_commands_registered(self): + routes = _routes_by_path() + assert "/datasets" in routes + assert "/facet_options" in routes + + def test_report_commands_registered_without_commodity(self): + import openbb_us_eia + + routes = _routes_by_path() + expected = not openbb_us_eia.COMMODITY_INSTALLED + assert ("/petroleum_status_report" in routes) is expected + assert ("/short_term_energy_outlook" in routes) is expected + + +class TestDatasetsCommand: + """The dataset catalog command.""" + + @pytest.mark.asyncio + async def test_all_groups(self): + result = await datasets() + assert len(result.results) == 218 + + @pytest.mark.asyncio + async def test_filtered_group(self): + result = await datasets(group="coal") + assert len(result.results) == 13 + record = next( + row + for row in result.results + if row["dataset"] == "exports_imports_quantity_price" + ) + assert record["route"] == "coal/exports-imports-quantity-price" + assert "coal_rank" in record["filters"] + assert "quantity" in record["data_columns"] + + +class TestFacetOptionsCommand: + """The live facet options command.""" + + @pytest.mark.asyncio + async def test_unknown_facet_raises(self): + with pytest.raises(OpenBBError, match="not a filter"): + await facet_options(group="coal", facet="balancing_authority") + + @pytest.mark.asyncio + async def test_catalogued_facet_served_with_param_slugs(self): + result = await facet_options( + group="coal", facet="coal_rank", dataset="exports_imports_quantity_price" + ) + record = next(item for item in result.results if item["code"] == "MET") + assert record == { + "value": "metallurgical", + "label": "Metallurgical", + "code": "MET", + } + + @pytest.mark.asyncio + async def test_uncatalogued_facet_fetched_live(self, monkeypatch): + from openbb_core.provider.utils import helpers as core_helpers + + captured: dict = {} + + async def fake_amake_request(url, response_callback=None, **kwargs): + captured["url"] = url + return { + "response": { + "facets": [ + {"id": "NUS", "name": "U.S."}, + {"id": "SCA", "name": "California"}, + ] + } + } + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + result = await facet_options( + group="petroleum", + facet="series", + dataset="pad_district_exports_by_destination", + ) + assert "/petroleum/move/expcp/facet/series" in captured["url"] + assert result.results == [ + {"value": "SCA", "label": "California", "code": "SCA"}, + {"value": "NUS", "label": "U.S.", "code": "NUS"}, + ] + + @pytest.mark.asyncio + async def test_default_dataset_is_first_of_group(self, monkeypatch): + from openbb_core.provider.utils import helpers as core_helpers + + captured: dict = {} + + async def fake_amake_request(url, response_callback=None, **kwargs): + captured["url"] = url + return {"response": {"facets": []}} + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + await facet_options(group="petroleum", facet="series") + first = catalog.dataset_choices("petroleum")[0] + assert catalog.get_dataset("petroleum", first)["path"] in captured["url"] + + +class TestModelCommandBodies: + """Model command bodies delegate to ``OBBject.from_query``.""" + + @pytest.mark.asyncio + @pytest.mark.parametrize( + "path", + sorted( + path + for path, route in _routes_by_path().items() + if (route.openapi_extra or {}).get("model") + ), + ) + async def test_body_calls_from_query(self, path): + endpoint = _routes_by_path()[path].endpoint + with ( + patch("openbb_us_eia.eia_router.OBBQuery", new=MagicMock()), + patch( + "openbb_us_eia.eia_router.OBBject.from_query", + new=AsyncMock(return_value="OBBJECT"), + ) as mock_from_query, + ): + result = await endpoint( + cc=MagicMock(), + provider_choices=MagicMock(), + standard_params=MagicMock(), + extra_params=MagicMock(), + ) + assert result == "OBBJECT" + mock_from_query.assert_awaited_once() + + +class TestAppsJson: + """The Workspace app definition endpoint.""" + + @pytest.mark.asyncio + async def test_serves_app_definition(self): + from openbb_us_eia.eia_router import get_eia_apps_json + + apps = await get_eia_apps_json() + assert isinstance(apps, list) + assert apps + + @pytest.mark.asyncio + async def test_unreadable_file_returns_empty(self, monkeypatch): + import json + + from openbb_us_eia.eia_router import get_eia_apps_json + + def broken(_file): + raise ValueError("bad json") + + monkeypatch.setattr(json, "load", broken) + assert await get_eia_apps_json() == [] diff --git a/openbb_platform/providers/eia/tests/test_generate_catalog.py b/openbb_platform/providers/eia/tests/test_generate_catalog.py new file mode 100644 index 00000000000..5048bdf10bd --- /dev/null +++ b/openbb_platform/providers/eia/tests/test_generate_catalog.py @@ -0,0 +1,800 @@ +"""Tests for the EIA catalog generator.""" + +import json + +import pytest + +from openbb_us_eia.utils import generate_catalog + + +def _leaf_node(name, facets=("coalRankId",), freq="annual"): + return { + "name": name, + "description": "A test\r\n dataset.", + "frequency": [ + {"id": freq, "format": "YYYY", "description": "Yearly."}, + ], + "defaultFrequency": freq, + "startPeriod": "2000", + "endPeriod": "2024", + "data": {"heat-content": {"units": "Btu"}, "value": []}, + "facets": [{"id": facet, "description": facet} for facet in facets], + } + + +def _mini_tree(): + nodes = { + "coal": { + "name": "Coal", + "routes": [ + {"id": "receipts", "name": "Receipts"}, + {"id": "price-by-rank", "name": "Price by Rank"}, + ], + }, + "coal/receipts": _leaf_node("Receipts", facets=("coalRankId", "plantId")), + "coal/price-by-rank": _leaf_node("Price by Rank"), + } + facet_values = { + "coal/receipts": { + "coalRankId": { + "total": 2, + "values": [ + {"id": "BIT", "name": "Bituminous"}, + {"id": "SUB", "name": "Subbituminous"}, + {"id": "(NA)", "name": "Not Applicable"}, + ], + }, + "plantId": { + "total": 1, + "values": [{"id": "1", "name": "Plant One"}], + }, + }, + "coal/price-by-rank": { + "coalRankId": { + "total": 1, + "values": [{"id": "LIG", "name": "Lignite"}], + }, + }, + } + root = {"routes": [{"id": "coal", "name": "Coal", "description": "Coal data."}]} + return {"root": root, "nodes": nodes, "facet_values": facet_values} + + +class TestSlugHelpers: + """Slug and snake-case helpers.""" + + def test_slugify_cleans_names(self): + assert generate_catalog.slugify("F.O.B. Costs (per unit)") == "fob_costs" + assert generate_catalog.slugify("No. 2 Distillate - discontinued") == ( + "no2_distillate" + ) + assert ( + generate_catalog.slugify("Total CO2 - deprecated: see SEDS") == "total_co2" + ) + + def test_snake_case(self): + assert generate_catalog.snake_case("plantCode") == "plant_code" + assert generate_catalog.snake_case("heat-content") == "heat_content" + + +class TestNamedGroup: + """Group assembly from a crawled tree.""" + + def test_builds_datasets_and_choices(self): + tree = _mini_tree() + child_meta = generate_catalog._child_meta(tree) + group = generate_catalog._named_group( + "coal", tree, child_meta, ["coal/receipts", "coal/price-by-rank"] + ) + assert sorted(group["datasets"]) == ["price_by_rank", "receipts"] + spec = group["datasets"]["receipts"] + assert spec["path"] == "coal/receipts" + assert spec["description"] == "A test dataset." + assert spec["category"] == "Coal" + assert spec["data_columns"]["heat_content"]["id"] == "heat-content" + assert spec["data_columns"]["value"]["units"] is None + assert spec["facets"]["coal_rank"]["id"] == "coalRankId" + assert {"BIT", "SUB"} == { + choice["value"] for choice in spec["facets"]["coal_rank"]["choices"] + } + assert {"BIT", "LIG", "SUB"} == { + value for value in group["choices"]["coal_rank"] + } + + def test_duplicate_slug_raises(self): + tree = _mini_tree() + tree["nodes"]["coal"]["routes"][1]["name"] = "Receipts" + tree["nodes"]["coal/price-by-rank"]["name"] = "Receipts" + child_meta = generate_catalog._child_meta(tree) + with pytest.raises(ValueError, match="Duplicate dataset slug"): + generate_catalog._named_group( + "coal", tree, child_meta, ["coal/receipts", "coal/price-by-rank"] + ) + + def test_long_slug_without_override_raises(self): + tree = _mini_tree() + tree["nodes"]["coal/price-by-rank"]["name"] = "word " * 20 + child_meta = generate_catalog._child_meta(tree) + with pytest.raises(ValueError, match="add a SLUG_OVERRIDES entry"): + generate_catalog._named_group( + "coal", tree, child_meta, ["coal/price-by-rank"] + ) + + def test_unmapped_facet_raises(self): + tree = _mini_tree() + tree["nodes"]["coal/receipts"]["facets"].append({"id": "newFacetId"}) + child_meta = generate_catalog._child_meta(tree) + with pytest.raises(KeyError, match="Unmapped facet id"): + generate_catalog._named_group("coal", tree, child_meta, ["coal/receipts"]) + + +def _receipt_spec(): + return { + "path": "coal/shipments/receipts", + "name": "Receipts", + "description": "Coal shipment receipts.", + "category": "Coal Shipments", + "category_slug": "coal_shipments", + "frequencies": { + "quarterly": {"format": 'YYYY-"Q"Q', "path": "coal/shipments/receipts"}, + "annual": {"format": "YYYY", "path": "coal/shipments/receipts"}, + }, + "default_frequency": "annual", + "start_period": "2008-Q1", + "end_period": "2025-Q1", + "data_columns": { + "quantity": {"id": "quantity", "alias": None, "units": "tons"}, + "price": {"id": "price", "alias": None, "units": "dollars per ton"}, + }, + "facets": { + "coal_rank": { + "id": "coalRankId", + "description": "Coal Rank", + "n_values": 2, + "choices": [ + {"value": "BIT", "label": "Bituminous", "param": "bituminous"}, + { + "value": "SUB", + "label": "Subbituminous", + "param": "subbituminous", + }, + ], + }, + "mine_type": { + "id": "mineTypeId", + "description": "Mine Type", + "n_values": 2, + "choices": [ + {"value": "S", "label": "Surface", "param": "surface"}, + {"value": "U", "label": "Underground", "param": "underground"}, + ], + }, + "mine": { + "id": "mineMSHAId", + "description": "Mine", + "n_values": 1267, + }, + }, + } + + +class TestFacetQueryField: + """A facet field documents the choices and any frequency restriction.""" + + def test_frequency_restricted_facet_says_so(self): + source = generate_catalog._facet_query_field( + "electricity", + "timezone", + { + "id": "timezone", + "description": "Timezone", + "choices": [ + {"value": "Eastern", "param": "eastern"}, + {"value": "Central", "param": "central"}, + ], + "frequencies": ["hourly", "local-hourly"], + }, + ) + assert "Only applies to frequency: hourly, local-hourly." in source + + def test_unrestricted_facet_omits_the_note(self): + source = generate_catalog._facet_query_field( + "coal", + "coal_rank", + { + "id": "coalRankId", + "description": "Coal rank", + "choices": [{"value": "MET"}, {"value": "BIT"}], + }, + ) + assert "Only applies to frequency" not in source + + +class TestRenderDatasetModule: + """Complete model module rendering.""" + + def test_module_compiles_and_declares_everything(self): + source = generate_catalog.render_dataset_module( + "coal", "receipts", _receipt_spec() + ) + compile(source, "receipts.py", "exec") + assert "class EiaCoalReceiptsQueryParams(EiaApiQueryParams):" in source + assert "class EiaCoalReceiptsData(EiaApiData):" in source + assert "class EiaCoalReceiptsFetcher" in source + assert "@staticmethod" in source + assert "def transform_query" in source + assert "async def aextract_data" in source + assert "def transform_data" in source + assert '__group__ = "coal"' in source + assert '__dataset__ = "receipts"' in source + assert 'mine_type: Literal["surface", "underground"] | None = Field(' in source + assert "coal_rank: str | None = Field(" in source + assert "facet_options" in source + assert "coal_rank_name: str | None = Field(" in source + assert "quantity: float | None = Field(" in source + assert ( + "Quantity (tons). Withheld or unavailable values return as null." in source + ) + + def test_release_module_declares_release_field(self): + spec = _receipt_spec() + spec["category"] = "Annual Energy Outlook" + source = generate_catalog.render_dataset_module( + "aeo", "2025", spec, release_datasets=["2024", "2025"] + ) + compile(source, "aeo.py", "exec") + assert 'release: Literal["2024", "2025"] = Field(' in source + assert 'default="2025"' in source + assert "__dataset__" not in source + + def test_large_vocabulary_points_to_facet_options(self): + spec = _receipt_spec() + spec["facets"]["coal_rank"]["choices"] = [ + {"value": f"V{i}", "label": f"Label {i}", "param": f"label_{i}"} + for i in range(150) + ] + spec["facets"]["coal_rank"]["n_values"] = 150 + source = generate_catalog.render_dataset_module("coal", "receipts", spec) + assert "There are 150 valid values" in source + + def test_catalog_helpers_loader_guard(self, monkeypatch): + import importlib.util + + monkeypatch.setitem(generate_catalog.__dict__, "_CATALOG_HELPERS", None) + monkeypatch.setattr( + importlib.util, "spec_from_file_location", lambda *args, **kwargs: None + ) + with pytest.raises(ImportError, match="Unable to load"): + generate_catalog._catalog_helpers() + + def test_data_column_facet_collision_raises(self): + spec = _receipt_spec() + spec["data_columns"]["coal_rank"] = { + "id": "coal-rank", + "alias": None, + "units": None, + } + with pytest.raises(ValueError, match="collides"): + generate_catalog.render_dataset_module("coal", "receipts", spec) + + +class TestReleaseTemplate: + """Release-group template assembly.""" + + def test_uses_union_choices_and_drops_uncatalogued(self): + spec = _receipt_spec() + group_doc = { + "datasets": {"2024": dict(spec), "2025": dict(spec)}, + "choices": { + "coal_rank": [ + {"value": "BIT", "label": "Bituminous", "param": "bituminous"}, + {"value": "LIG", "label": "Lignite", "param": "lignite"}, + ] + }, + } + template = generate_catalog._release_template("aeo", group_doc) + assert template["name"] == "Coal Shipments" + assert template["path"] == "aeo" + assert "release" in template["description"] + assert [c["param"] for c in template["facets"]["coal_rank"]["choices"]] == [ + "bituminous", + "lignite", + ] + assert "choices" not in template["facets"]["mine_type"] + + +class TestRenderRegistry: + """Registry module rendering.""" + + def test_registry_lists_every_model(self): + catalog_doc = generate_catalog.build_catalog(_full_tree()) + source = generate_catalog.render_registry(catalog_doc) + compile(source, "registry.py", "exec") + assert ( + "from openbb_us_eia.models.coal.receipts import EiaCoalReceiptsFetcher" + in source + ) + assert '"EiaCoalReceipts": EiaCoalReceiptsFetcher,' in source + assert '"EiaAeo": EiaAeoFetcher,' in source + assert '"EiaCrudeOilImports": EiaCrudeOilImportsFetcher,' in source + + +class TestWriteModels: + """Model module writing.""" + + def test_writes_modules_and_registry(self, tmp_path, monkeypatch): + monkeypatch.setattr(generate_catalog, "MODELS_ROOT", tmp_path) + catalog_doc = generate_catalog.build_catalog(_full_tree()) + written = generate_catalog.write_models(catalog_doc) + assert written == sum( + 1 + if group in generate_catalog.FLAT_GROUPS + generate_catalog.RELEASE_GROUPS + else len(catalog_doc["groups"][group]["datasets"]) + for group in generate_catalog.DATASET_GROUPS_EMIT + ) + assert (tmp_path / "coal" / "receipts.py").exists() + assert (tmp_path / "coal" / "__init__.py").exists() + assert (tmp_path / "aeo.py").exists() + assert (tmp_path / "seds.py").exists() + assert (tmp_path / "registry.py").exists() + + +def _full_tree(): + """Build a synthetic crawl covering every catalog group.""" + + def leaf(name, facets, freqs=(("annual", "YYYY"),)): + return { + "name": name, + "description": f"{name} description.", + "frequency": [ + {"id": fid, "format": fmt, "description": fid} for fid, fmt in freqs + ], + "defaultFrequency": freqs[0][0], + "startPeriod": "2000", + "endPeriod": "2024", + "data": {"value": {"units": "units"}}, + "facets": [{"id": facet, "description": facet} for facet in facets], + } + + def category(name, children): + return { + "name": name, + "routes": [{"id": child, "name": f"{name} {child}"} for child in children], + } + + hourly = (("hourly", 'YYYY-MM-DD"T"HH24'), ("local-hourly", 'YYYY-MM-DD"T"HH24TZH')) + daily = (("daily", "YYYY-MM-DD"),) + + nodes = { + "coal": category("Coal", ["receipts"]), + "coal/receipts": leaf("Receipts", ["coalRankId", "plantId"]), + "petroleum": category("Petroleum", ["pri", "move"]), + "petroleum/pri": category("Prices", ["spt", "imc1"]), + "petroleum/pri/spt": leaf( + "Spot Prices", ["duoarea", "product", "process", "series"] + ), + "petroleum/pri/imc1": leaf( + "F.O.B. Costs of Imported Crude Oil by Area", ["duoarea"] + ), + "petroleum/move": category("Movements", ["imc1"]), + "petroleum/move/imc1": leaf( + "F.O.B. Costs of Imported Crude Oil by Area", ["duoarea"] + ), + "natural-gas": category("Natural Gas", ["pri"]), + "natural-gas/pri": category("Prices", ["sum"]), + "natural-gas/pri/sum": leaf( + "Natural Gas Prices", ["duoarea", "product", "process", "series"] + ), + "electricity": category( + "Electricity", + [ + "electric-power-operational-data", + "facility-fuel", + "operating-generator-capacity", + "retail-sales", + "rto", + "state-electricity-profiles", + ], + ), + "electricity/electric-power-operational-data": leaf( + "Electric Power Operations", ["location", "sectorid", "fueltypeid"] + ), + "electricity/facility-fuel": leaf( + "Facility Fuel", + ["plantCode", "fuel2002", "fuelType", "state", "primeMover"], + ), + "electricity/operating-generator-capacity": leaf( + "Inventory of Operable Generators", + [ + "stateid", + "sector", + "entityid", + "plantid", + "generatorid", + "unit", + "technology", + "energy_source_code", + "prime_mover_code", + "balancing_authority_code", + "status", + ], + ), + "electricity/retail-sales": leaf("Retail Sales", ["stateid", "sectorid"]), + "electricity/rto": category( + "Grid Monitor", + [ + "region-data", + "daily-region-data", + "fuel-type-data", + "daily-fuel-type-data", + "interchange-data", + "daily-interchange-data", + "region-sub-ba-data", + "daily-region-sub-ba-data", + ], + ), + "electricity/rto/region-data": leaf( + "Hourly Demand", ["respondent", "type"], freqs=hourly + ), + "electricity/rto/daily-region-data": leaf( + "Daily Demand", ["respondent", "type", "timezone"], freqs=daily + ), + "electricity/rto/fuel-type-data": leaf( + "Hourly Generation", ["respondent", "fueltype"], freqs=hourly + ), + "electricity/rto/daily-fuel-type-data": leaf( + "Daily Generation", ["respondent", "fueltype", "timezone"], freqs=daily + ), + "electricity/rto/interchange-data": leaf( + "Hourly Interchange", ["fromba", "toba"], freqs=hourly + ), + "electricity/rto/daily-interchange-data": leaf( + "Daily Interchange", ["fromba", "toba", "timezone"], freqs=daily + ), + "electricity/rto/region-sub-ba-data": leaf( + "Hourly Subregion Demand", ["subba", "parent"], freqs=hourly + ), + "electricity/rto/daily-region-sub-ba-data": leaf( + "Daily Subregion Demand", ["subba", "parent", "timezone"], freqs=daily + ), + "electricity/state-electricity-profiles": category( + "State Profiles", ["summary"] + ), + "electricity/state-electricity-profiles/summary": leaf( + "State Rankings", ["stateID"] + ), + "crude-oil-imports": leaf( + "Crude Oil Imports", + ["originId", "originType", "destinationId", "destinationType", "gradeId"], + ), + "international": leaf( + "International", + [ + "productId", + "activityId", + "countryRegionId", + "countryRegionTypeId", + "dataFlagId", + "unit", + ], + ), + "seds": leaf("SEDS", ["seriesId", "stateId"]), + "total-energy": leaf("Total Energy", ["msn"]), + "densified-biomass": category("Biomass", ["production-by-region"]), + "densified-biomass/production-by-region": leaf( + "Production by Region", ["fuelTypeId", "region"] + ), + "nuclear-outages": category("Nuclear", ["us-nuclear-outages"]), + "nuclear-outages/us-nuclear-outages": leaf( + "U.S. Nuclear Outages", ["facility"] + ), + "aeo": category("AEO", ["2025"]), + "aeo/2025": leaf( + "AEO 2025", ["history", "scenario", "tableId", "seriesId", "regionId"] + ), + "ieo": category("IEO", ["2023"]), + "ieo/2023": leaf( + "IEO 2023", ["history", "scenario", "tableId", "seriesId", "regionId"] + ), + } + literal_targets = { + "coal": "coal/receipts", + "electricity": "electricity/operating-generator-capacity", + "electricity_grid": "electricity/rto/daily-region-data", + "state_electricity_profiles": "electricity/state-electricity-profiles/summary", + "crude_oil_imports": "crude-oil-imports", + "international": "international", + "densified_biomass": "densified-biomass/production-by-region", + "nuclear_outages": "nuclear-outages/us-nuclear-outages", + "aeo": "aeo/2025", + "ieo": "ieo/2023", + } + for group, path in literal_targets.items(): + canonical_map = generate_catalog.FACET_CANONICAL[group] + declared = {canonical_map[f["id"]] for f in nodes[path]["facets"]} + for canonical in generate_catalog.LITERAL_FACETS.get(group, set()) - declared: + facet_id = next( + key for key, value in canonical_map.items() if value == canonical + ) + nodes[path]["facets"].append({"id": facet_id, "description": facet_id}) + + facet_values: dict = {} + for path, node in nodes.items(): + if node.get("routes"): + continue + for facet in node["facets"]: + facet_values.setdefault(path, {})[facet["id"]] = { + "total": 1, + "values": [{"id": "X", "name": "Value X"}], + } + facet_values["seds"]["seriesId"] = { + "total": 3, + "values": [{"id": f"S{i}", "name": f"Series {i}"} for i in range(3)], + } + root = { + "routes": [ + {"id": top, "name": top, "description": f"{top} route."} + for top in ( + "coal", + "petroleum", + "natural-gas", + "electricity", + "crude-oil-imports", + "international", + "seds", + "total-energy", + "densified-biomass", + "nuclear-outages", + "aeo", + "ieo", + ) + ] + } + return {"root": root, "nodes": nodes, "facet_values": facet_values} + + +class TestBuildCatalog: + """Full catalog assembly over a synthetic all-groups tree.""" + + def test_builds_every_group(self, monkeypatch): + monkeypatch.setattr(generate_catalog, "CHOICES_LIMIT", 2) + catalog = generate_catalog.build_catalog(_full_tree()) + groups = catalog["groups"] + assert sorted(groups) == [ + "aeo", + "coal", + "crude_oil_imports", + "densified_biomass", + "electricity", + "electricity_grid", + "ieo", + "international", + "natural_gas", + "nuclear_outages", + "petroleum", + "seds", + "state_electricity_profiles", + "total_energy", + ] + petroleum_paths = { + spec["path"] for spec in groups["petroleum"]["datasets"].values() + } + assert "petroleum/move/imc1" not in petroleum_paths + assert "petroleum/pri/imc1" in petroleum_paths + demand = groups["electricity_grid"]["datasets"]["demand"] + assert set(demand["frequencies"]) == {"hourly", "local-hourly", "daily"} + assert demand["facets"]["timezone"]["frequencies"] == ["daily"] + assert list(groups["aeo"]["datasets"]) == ["2025"] + assert list(groups["ieo"]["datasets"]) == ["2023"] + assert "series" not in groups["seds"]["choices"] + assert groups["seds"]["choices"]["state"][0]["value"] == "X" + + +class TestFetchTree: + """The live crawl against a stubbed HTTP session.""" + + def test_crawls_routes_and_facets(self, monkeypatch): + tree = _mini_tree() + + class FakeResponse: + def __init__(self, payload, status=200): + self.status_code = status + self._payload = payload + + def json(self): + return {"response": self._payload} + + class FakeSession: + def __init__(self): + self.flaky_hits = 0 + + def get(self, url, params=None, timeout=None): + assert params["api_key"] == "KEY" + path = url.removeprefix(generate_catalog.API_BASE).strip("/") + if not path: + return FakeResponse(tree["root"]) + if "/facet/" in path: + node_path, facet_id = path.split("/facet/") + if facet_id == "plantId": + return FakeResponse({}, status=500) + entry = tree["facet_values"][node_path][facet_id] + return FakeResponse( + {"totalFacets": entry["total"], "facets": entry["values"]} + ) + if path == "coal/receipts": + self.flaky_hits += 1 + if self.flaky_hits == 1: + import requests + + raise requests.RequestException("reset by peer") + if self.flaky_hits == 2: + return FakeResponse({}, status=429) + return FakeResponse(tree["nodes"][path]) + + import time + + import requests + + monkeypatch.setattr(time, "sleep", lambda seconds: None) + monkeypatch.setattr(requests, "Session", FakeSession) + crawled = generate_catalog.fetch_tree("KEY") + assert set(crawled["nodes"]) == set(tree["nodes"]) + assert crawled["facet_values"]["coal/receipts"]["coalRankId"]["total"] == 2 + assert "plantId" not in crawled["facet_values"]["coal/receipts"] + + def test_non_retryable_status_raises(self, monkeypatch): + class FakeResponse: + status_code = 404 + + def json(self): + return {} + + class FakeSession: + def get(self, url, params=None, timeout=None): + return FakeResponse() + + import requests + + monkeypatch.setattr(requests, "Session", FakeSession) + with pytest.raises(RuntimeError, match="HTTP 404"): + generate_catalog.fetch_tree("KEY") + + def test_retries_exhausted_raises(self, monkeypatch): + class FakeResponse: + status_code = 503 + + def json(self): + return {} + + class FakeSession: + def get(self, url, params=None, timeout=None): + return FakeResponse() + + import time + + import requests + + monkeypatch.setattr(time, "sleep", lambda seconds: None) + monkeypatch.setattr(requests, "Session", FakeSession) + with pytest.raises(RuntimeError, match="Retries exhausted"): + generate_catalog.fetch_tree("KEY") + + +class TestLintGenerated: + """The ruff gate on generated modules.""" + + def test_raises_when_ruff_fails(self, tmp_path, monkeypatch): + class FakeCompleted: + returncode = 1 + + monkeypatch.setattr( + generate_catalog.subprocess, "run", lambda argv, **kwargs: FakeCompleted() + ) + with pytest.raises(RuntimeError, match="failed for the generated modules"): + generate_catalog.lint_generated(tmp_path) + + +class TestMain: + """The command-line entry point.""" + + def test_main_writes_outputs_from_tree_file(self, tmp_path, monkeypatch): + tree_file = tmp_path / "tree.json" + tree_file.write_text(json.dumps(_full_tree())) + asset = tmp_path / "eia_catalog.json.xz" + models_root = tmp_path / "models" + monkeypatch.setattr(generate_catalog, "ASSET_PATH", asset) + monkeypatch.setattr(generate_catalog, "MODELS_ROOT", models_root) + monkeypatch.setattr( + "sys.argv", ["generate-eia-catalog", "--tree", str(tree_file)] + ) + assert generate_catalog.main() == 0 + assert asset.exists() + assert (models_root / "coal" / "receipts.py").exists() + assert (models_root / "registry.py").exists() + + def test_main_returns_ty_exit_code(self, tmp_path, monkeypatch, capsys): + tree_file = tmp_path / "tree.json" + tree_file.write_text(json.dumps(_full_tree())) + asset = tmp_path / "eia_catalog.json.xz" + models_root = tmp_path / "models" + monkeypatch.setattr(generate_catalog, "ASSET_PATH", asset) + monkeypatch.setattr(generate_catalog, "MODELS_ROOT", models_root) + monkeypatch.setattr( + "sys.argv", ["generate-eia-catalog", "--tree", str(tree_file)] + ) + + class FakeCompleted: + def __init__(self, returncode): + self.returncode = returncode + + def fake_run(argv, **kwargs): + return FakeCompleted(2 if "ty" in argv else 0) + + monkeypatch.setattr(generate_catalog.subprocess, "run", fake_run) + assert generate_catalog.main() == 2 + assert "ty check failed" in capsys.readouterr().err + + def test_main_asset_only_leaves_models_untouched(self, tmp_path, monkeypatch): + tree_file = tmp_path / "tree.json" + tree_file.write_text(json.dumps(_full_tree())) + asset = tmp_path / "eia_catalog.json.xz" + models_root = tmp_path / "models" + monkeypatch.setattr(generate_catalog, "ASSET_PATH", asset) + monkeypatch.setattr(generate_catalog, "MODELS_ROOT", models_root) + monkeypatch.setattr( + "sys.argv", + ["generate-eia-catalog", "--tree", str(tree_file), "--asset-only"], + ) + assert generate_catalog.main() == 0 + assert asset.exists() + assert not models_root.exists() + + def test_main_requires_api_key_for_live_crawl(self, tmp_path, monkeypatch, capsys): + from openbb_core.app.service.user_service import UserService + + monkeypatch.setattr("sys.argv", ["generate-eia-catalog"]) + + class FakeCredentials: + def model_dump(self): + return {"eia_api_key": None} + + class FakeSettings: + credentials = FakeCredentials() + + monkeypatch.setattr( + UserService, "default_user_settings", FakeSettings(), raising=False + ) + assert generate_catalog.main() == 1 + assert "API key is required" in capsys.readouterr().err + + def test_main_live_crawl_uses_credential(self, tmp_path, monkeypatch): + from openbb_core.app.service.user_service import UserService + from pydantic import SecretStr + + monkeypatch.setattr("sys.argv", ["generate-eia-catalog"]) + monkeypatch.setattr( + generate_catalog, "ASSET_PATH", tmp_path / "eia_catalog.json.xz" + ) + monkeypatch.setattr(generate_catalog, "MODELS_ROOT", tmp_path / "models") + + class FakeCredentials: + def model_dump(self): + return {"eia_api_key": SecretStr("KEY")} + + class FakeSettings: + credentials = FakeCredentials() + + monkeypatch.setattr( + UserService, "default_user_settings", FakeSettings(), raising=False + ) + crawled: dict = {} + + def fake_fetch_tree(api_key): + crawled["api_key"] = api_key + return _full_tree() + + monkeypatch.setattr(generate_catalog, "fetch_tree", fake_fetch_tree) + assert generate_catalog.main() == 0 + assert crawled["api_key"] == "KEY" + assert (tmp_path / "eia_catalog.json.xz").exists() + assert (tmp_path / "models" / "registry.py").exists() diff --git a/openbb_platform/providers/eia/tests/test_helpers.py b/openbb_platform/providers/eia/tests/test_helpers.py new file mode 100644 index 00000000000..f23b642f162 --- /dev/null +++ b/openbb_platform/providers/eia/tests/test_helpers.py @@ -0,0 +1,90 @@ +"""Tests for the EIA provider helpers.""" + +import pytest +from openbb_core.app.model.abstract.error import OpenBBError + +from openbb_us_eia.utils import helpers + + +class FakeResponse: + """Minimal aiohttp-like response.""" + + def __init__(self, payload, status=200): + self.status = status + self._payload = payload + + async def json(self): + return self._payload + + +class TestResponseCallback: + """API error surfacing in the response callback.""" + + @pytest.mark.asyncio + async def test_returns_payload(self): + payload = {"response": {"data": []}} + assert await helpers.response_callback(FakeResponse(payload), None) == payload + + @pytest.mark.asyncio + async def test_403_raises(self): + payload = {"error": {"code": "API_KEY_INVALID", "message": "bad key"}} + with pytest.raises(OpenBBError, match="API_KEY_INVALID -> bad key"): + await helpers.response_callback(FakeResponse(payload, status=403), None) + + @pytest.mark.asyncio + async def test_error_payload_raises(self): + payload = {"error": {"message": "invalid frequency"}} + with pytest.raises(OpenBBError, match="invalid frequency"): + await helpers.response_callback(FakeResponse(payload), None) + + @pytest.mark.asyncio + async def test_plain_error_string_raises(self): + with pytest.raises(OpenBBError, match="nope"): + await helpers.response_callback(FakeResponse({"error": "nope"}), None) + + +class TestDownloadExcelFile: + """Session caching and error wrapping for Excel downloads.""" + + @pytest.mark.asyncio + async def test_downloads_and_caches(self, monkeypatch): + from io import BytesIO + + from openbb_core.provider.utils import helpers as core_helpers + from pandas import DataFrame, ExcelFile + + buffer = BytesIO() + DataFrame({"a": [1]}).to_excel(buffer, index=False) + content = buffer.getvalue() + calls = {"n": 0} + + class RawResponse: + async def read(self): + calls["n"] += 1 + return content + + async def fake_amake_request(url, response_callback=None, **kwargs): + return await response_callback(RawResponse(), None) + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + helpers.download_excel_file.cache_clear() + first = await helpers.download_excel_file("https://ir.eia.gov/x.xls") + second = await helpers.download_excel_file("https://ir.eia.gov/x.xls") + assert isinstance(first, ExcelFile) + assert second is first + assert calls["n"] == 1 + third = await helpers.download_excel_file("https://ir.eia.gov/x.xls", False) + assert calls["n"] == 2 + assert isinstance(third, ExcelFile) + + @pytest.mark.asyncio + async def test_wraps_download_errors(self, monkeypatch): + from openbb_core.provider.utils import helpers as core_helpers + + async def fake_amake_request(url, response_callback=None, **kwargs): + raise ValueError("boom") + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + helpers.download_excel_file.cache_clear() + with pytest.raises(OpenBBError, match="Error downloading the file"): + await helpers.download_excel_file("https://ir.eia.gov/y.xls") diff --git a/openbb_platform/providers/eia/tests/test_proxy_transport.py b/openbb_platform/providers/eia/tests/test_proxy_transport.py new file mode 100644 index 00000000000..83637917385 --- /dev/null +++ b/openbb_platform/providers/eia/tests/test_proxy_transport.py @@ -0,0 +1,303 @@ +"""Tests for the proxy transport: curl session, retries, disk cache, warmup. + +eia.gov TLS-fingerprints its clients, so every fetch goes through a per-thread +curl_cffi session impersonating Chrome. These tests drive that layer through a +fake ``curl_cffi`` rather than a fake of our own code, so the retry, session +recycling, and caching logic all execute for real. +""" + +import asyncio +import time + +import pytest + +from openbb_us_eia import browsers + + +class FakeResponse: + def __init__(self, content=b"", content_type="text/html", status=200, history=()): + self.content = content + self.headers = {"Content-Type": content_type} if content_type else {} + self.status_code = status + self.history = list(history) + self.url = "https://www.eia.gov/landed" + + +class FakeCurlSession: + """Stand in for ``curl_cffi.requests.Session``.""" + + instances: list = [] + + def __init__(self, **kwargs): + self.kwargs = kwargs + self.gets: list = [] + self.posts: list = [] + FakeCurlSession.instances.append(self) + + def get(self, target, **kwargs): + self.gets.append(target) + result = FakeCurlSession.get_results.pop(0) + if isinstance(result, BaseException): + raise result + return result + + def post(self, target, data=None, headers=None, **kwargs): + self.posts.append((target, data, headers)) + result = FakeCurlSession.post_results.pop(0) + if isinstance(result, BaseException): + raise result + return result + + +@pytest.fixture(autouse=True) +def fake_curl(monkeypatch): + """Route the curl session at a fake, and make retry backoff instant.""" + FakeCurlSession.instances = [] + FakeCurlSession.get_results = [] + FakeCurlSession.post_results = [] + monkeypatch.setattr("curl_cffi.requests.Session", FakeCurlSession) + monkeypatch.setattr(browsers._CURL_LOCAL, "session", None, raising=False) + monkeypatch.setattr(time, "sleep", lambda _seconds: None) + browsers._PROXY_CACHE.clear() + browsers._REDIRECTS.clear() + yield + browsers._CURL_LOCAL.session = None + browsers._PROXY_CACHE.clear() + browsers._REDIRECTS.clear() + + +class TestCurlSession: + """One Chrome-impersonating session per thread, reused across fetches.""" + + def test_session_impersonates_chrome_and_is_reused(self): + first = browsers._curl_session() + second = browsers._curl_session() + assert first is second + assert first.kwargs["impersonate"] == "chrome" + assert first.kwargs["headers"]["Referer"] == browsers._EIA_ORIGIN + + def test_each_thread_gets_its_own_session(self): + seen: list = [] + + def grab(): + seen.append(browsers._curl_session()) + + import threading + + main = browsers._curl_session() + thread = threading.Thread(target=grab) + thread.start() + thread.join() + assert seen[0] is not main + + +class TestFetchSync: + """Transient upstream failures are retried on a fresh session.""" + + def test_returns_body_content_type_and_status(self): + FakeCurlSession.get_results = [FakeResponse(b"ok", "text/plain", 200)] + assert browsers._fetch_sync("https://t/x") == (b"ok", "text/plain", 200, "") + + def test_missing_content_type_defaults_to_octet_stream(self): + FakeCurlSession.get_results = [FakeResponse(b"x", None)] + assert browsers._fetch_sync("https://t/x")[1] == "application/octet-stream" + + def test_redirect_history_reports_where_it_landed(self): + FakeCurlSession.get_results = [ + FakeResponse(b"x", "text/html", 200, history=[object()]) + ] + assert browsers._fetch_sync("https://t/x")[3] == "https://www.eia.gov/landed" + + def test_retries_then_succeeds_on_a_new_session(self): + FakeCurlSession.get_results = [ + RuntimeError("reset"), + FakeResponse(b"ok", "text/plain"), + ] + assert browsers._fetch_sync("https://t/x")[0] == b"ok" + assert len(FakeCurlSession.instances) == 2 + + def test_raises_after_exhausting_retries(self): + FakeCurlSession.get_results = [RuntimeError("down")] * 3 + with pytest.raises(RuntimeError, match="down"): + browsers._fetch_sync("https://t/x") + assert len(FakeCurlSession.instances) == 3 + + +class TestPostSync: + """POST carries the body and content type, and retries the same way.""" + + def test_posts_body_and_header(self): + FakeCurlSession.post_results = [FakeResponse(b"{}", "application/json")] + result = browsers._post_sync("https://t/x", b"payload", "application/json") + assert result == (b"{}", "application/json", 200) + target, data, headers = FakeCurlSession.instances[0].posts[0] + assert data == b"payload" + assert headers == {"Content-Type": "application/json"} + + def test_no_content_type_sends_no_header(self): + FakeCurlSession.post_results = [FakeResponse(b"{}", "application/json")] + browsers._post_sync("https://t/x", b"p", "") + assert FakeCurlSession.instances[0].posts[0][2] == {} + + def test_missing_content_type_defaults_to_octet_stream(self): + FakeCurlSession.post_results = [FakeResponse(b"x", None)] + assert browsers._post_sync("https://t/x", b"p", "")[1] == ( + "application/octet-stream" + ) + + def test_retries_then_succeeds(self): + FakeCurlSession.post_results = [ + RuntimeError("reset"), + FakeResponse(b"{}", "application/json"), + ] + assert browsers._post_sync("https://t/x", b"p", "")[0] == b"{}" + + def test_raises_after_exhausting_retries(self): + FakeCurlSession.post_results = [RuntimeError("down")] * 3 + with pytest.raises(RuntimeError, match="down"): + browsers._post_sync("https://t/x", b"p", "") + + @pytest.mark.asyncio + async def test_post_upstream_is_never_cached(self): + FakeCurlSession.post_results = [ + FakeResponse(b"{}", "application/json"), + FakeResponse(b"{}", "application/json"), + ] + target = "https://t/x" + await browsers.post_upstream(target, b"p", "") + await browsers.post_upstream(target, b"p", "") + assert target not in browsers._PROXY_CACHE + assert len(FakeCurlSession.instances[0].posts) == 2 + + +class TestDiskCache: + """Immutable assets are cached to disk; everything else is not.""" + + @pytest.mark.parametrize( + "target", + [ + "https://t/a.js", + "https://t/a.css", + "https://t/a.PNG", + "https://t/a.woff2?v=1", + "https://t/m.pdf", + ], + ) + def test_static_assets_recognised(self, target): + assert browsers._is_static(target) is True + + @pytest.mark.parametrize( + "target", ["https://t/page.html", "https://t/api/data", "https://t/x.json"] + ) + def test_dynamic_targets_are_not_static(self, target): + assert browsers._is_static(target) is False + + def test_cache_paths_are_derived_from_the_url(self, monkeypatch, tmp_path): + monkeypatch.setattr(browsers, "_cache_dir", lambda: tmp_path) + body, type_path = browsers._cache_paths("https://t/a.js") + assert body.parent == tmp_path + assert type_path.name == f"{body.name}.type" + assert browsers._cache_paths("https://t/b.js")[0] != body + + @pytest.mark.asyncio + async def test_unwritable_cache_dir_does_not_break_the_fetch( + self, monkeypatch, tmp_path + ): + blocker = tmp_path / "blocked" + blocker.write_text("not a directory") + monkeypatch.setattr(browsers, "_cache_dir", lambda: blocker / "cache") + FakeCurlSession.get_results = [FakeResponse(b"code", "application/javascript")] + assert await browsers._fetch_upstream("https://t/a.js") == ( + b"code", + "application/javascript", + ) + + +class TestWarmup: + """The proxy pre-fetches the browser's assets so the first load is warm.""" + + ELECTRICITY = browsers.EIA_DATA_BROWSERS["electricity"]["path"] + + @pytest.mark.asyncio + async def test_page_assets_collects_scripts_styles_and_modules(self, monkeypatch): + html = ( + '<link href="/global/styles/screen.css" rel="stylesheet">' + '<script src="app.js"></script>' + '<script src="https://cdn/x.js"></script>' + "<script>require['urlArgs'] = 'v=9';" + 'var m = "/coal/data/browser/node_modules/thing";</script>' + ) + + async def fake_fetch(target): + assert target == f"{browsers._EIA_ORIGIN}/{self.ELECTRICITY}" + return html.encode(), "text/html" + + monkeypatch.setattr(browsers, "_fetch_upstream", fake_fetch) + assets = await browsers._page_assets(self.ELECTRICITY) + assert f"{browsers._EIA_ORIGIN}/global/styles/screen.css" in assets + assert f"{browsers._EIA_ORIGIN}/{self.ELECTRICITY}app.js" in assets + assert not any("cdn" in asset for asset in assets) + assert ( + f"{browsers._EIA_ORIGIN}/coal/data/browser/node_modules/thing.js?v=9" + in assets + ) + + @pytest.mark.asyncio + async def test_warm_fetches_shared_assets_and_survives_page_failure( + self, monkeypatch + ): + fetched: list = [] + + async def fake_fetch(target): + fetched.append(target) + if target.endswith(self.ELECTRICITY): + raise RuntimeError("page down") + return b"", "text/plain" + + monkeypatch.setattr(browsers, "_fetch_upstream", fake_fetch) + await browsers._warm_proxy_cache() + for asset in browsers._WARM_ASSETS: + assert f"{browsers._EIA_ORIGIN}/{asset}" in fetched + + @pytest.mark.asyncio + async def test_warm_swallows_individual_asset_failures(self, monkeypatch): + async def fake_fetch(_target): + raise RuntimeError("boom") + + monkeypatch.setattr(browsers, "_fetch_upstream", fake_fetch) + await browsers._warm_proxy_cache() + + def test_schedule_without_a_running_loop_is_a_no_op(self): + browsers._WARM_TASKS.clear() + browsers._schedule_warm() + assert not browsers._WARM_TASKS + + @pytest.mark.asyncio + async def test_schedule_tracks_and_discards_the_task(self, monkeypatch): + async def fake_warm(): + return None + + monkeypatch.setattr(browsers, "_warm_proxy_cache", fake_warm) + browsers._WARM_TASKS.clear() + browsers._schedule_warm() + assert len(browsers._WARM_TASKS) == 1 + await asyncio.gather(*browsers._WARM_TASKS) + await asyncio.sleep(0) + assert not browsers._WARM_TASKS + + @pytest.mark.asyncio + async def test_lifespan_warms_on_startup_and_cancels_on_shutdown(self, monkeypatch): + started = asyncio.Event() + + async def fake_warm(): + started.set() + await asyncio.sleep(3600) + + monkeypatch.setattr(browsers, "_warm_proxy_cache", fake_warm) + browsers._WARM_TASKS.clear() + async with browsers.lifespan(None): + await started.wait() + tasks = list(browsers._WARM_TASKS) + assert tasks + await asyncio.sleep(0) + assert all(task.cancelled() or task.done() for task in tasks) diff --git a/openbb_platform/providers/eia/tests/test_raw_tables.py b/openbb_platform/providers/eia/tests/test_raw_tables.py new file mode 100644 index 00000000000..47c49ea6c01 --- /dev/null +++ b/openbb_platform/providers/eia/tests/test_raw_tables.py @@ -0,0 +1,877 @@ +"""Tests for the ``raw`` pivot: every EIA browser payload shape becomes rows. + +The ``raw`` button must answer for whatever view is on screen, so each shape the +browsers return -- classic tables, series lists, rankings, state maps, the +International series and overview payloads -- has to pivot into the same +``category / units / source_key / <periods>`` row form. +""" + +import json + +import pytest + +from openbb_us_eia import browsers + +TABLEDATA = { + "UNITS": "million kilowatthours", + "ROWS": [ + { + "SERIES_ID": "ELEC.GEN.ALL-US-99.M", + "CHART_NAME": "All fuels", + "DATA": {"202401": "1000.5", "202402": "900"}, + }, + { + "SERIES_ID": "ELEC.GEN.COW-US-99.M", + "DESCRIPTION": "Coal", + "UNITS": "thousand tons", + "DATA": {"202401": "500", "202402": ""}, + }, + ], +} + +SERIES_PAYLOAD = { + "series": [ + { + "series_id": "SEDS.TETCB.CA.A", + "name": "Total energy consumed", + "units": "billion Btu", + "data": [["2022", 7000.0], ["2023", 7100.0]], + } + ] +} + +RANKING_PAYLOAD = { + "series": [ + { + "stateName": "Texas", + "stateId": "TX", + "seriesId": "SEDS.TETCB.TX.A", + "displayName": "Total energy consumed", + "rank": 1, + "period": "2023", + "value": "12000.5", + }, + { + "stateName": "California", + "seriesId": "SEDS.TETCB.CA.A", + "displayName": "Total energy consumed", + "rank": "2", + "period": "2023", + "value": 7100.0, + }, + ] +} + +STATE_MAP_PAYLOAD = { + "year": 2023, + "series": { + "TETCB": {"TX": "12000", "CA": "7100"}, + "PATCB": {"TX": "4000", "CA": "2000"}, + }, +} + +INTL_SERIES_PAYLOAD = { + "data": { + "INTL.44-1-USA-QBTU.A": {"2022": [95.0, 95.12], "2023": [96.0, 96.34]}, + "INTL.44-1-CHN-QBTU.A": {"2022": [130.0, 130.5], "2023": [131.0, 131.7]}, + } +} + +INTL_OVERVIEW_PAYLOAD = { + "data": [ + { + "series_id": "INTL.44-1-USA-QBTU.A", + "name": "United States", + "iso": "USA", + "unit": "QBTU", + "frequency": "A", + "data": [ + {"date": 1672531200000, "value": 96.34}, + {"date": 1704067200000, "value": 97.5}, + ], + } + ] +} + +BIOFUELS_PAYLOAD = { + "data": { + "INTL.79-1-ABW-TBPD.A": {"2024": ["--"]}, + "INTL.80-1-ABW-TBPD.A": {"2024": [0.0, 0.0]}, + "INTL.81-1-ABW-TBPD.A": {"2024": [0.0, 0.0]}, + } +} + +LABELS = { + "region": {"USA": "United States", "CHN": "China", "ABW": "Aruba"}, + "unit": {"QBTU": "quad Btu", "TBPD": "Mb/d"}, + "product": { + "44": "primary energy", + "79": "biofuels", + "80": "fuel ethanol", + "81": "biomass-based diesel", + }, + "activity": {"1": "production", "2": "consumption"}, + "parent": {"44": None, "79": None, "80": 79, "81": 79}, +} + + +class TestNum: + """A measurement cell is a number or it is missing -- never text. + + EIA marks withheld or negligible values with text inside an otherwise + numeric column. Those markers must not survive into the table, or the + column stops being numeric and cannot be sorted or charted. + """ + + @pytest.mark.parametrize("value", [None, ""]) + def test_missing_becomes_none(self, value): + assert browsers._num(value) is None + + @pytest.mark.parametrize( + ("value", "expected"), [("1.5", 1.5), (2, 2.0), ("-3", -3.0), (4.25, 4.25)] + ) + def test_numeric_becomes_float(self, value, expected): + assert browsers._num(value) == expected + + @pytest.mark.parametrize("marker", ["(s)", "--", "NA", "W", "(*)", "NM"]) + def test_eia_suppression_markers_become_none(self, marker): + assert browsers._num(marker) is None + + def test_non_scalar_becomes_none(self): + assert browsers._num(["a"]) is None + + +class TestSuppressionMarkers: + """Every International pivot drops EIA's text markers. + + ``series_data/data`` returns ``["(s)", 0.000102]`` and ``["--"]``; + ``series_data/infographic`` returns the marker as a bare ``value``. Both + must land as null, not as the string ``(s)`` in a numeric column. + """ + + def test_series_marker_with_an_underlying_value_keeps_the_value(self): + rows = browsers._intl_series_rows( + {"INTL.44-1-ABW-QBTU.A": {"2009": ["(s)", 0.0001023642489938382]}} + ) + assert rows[0]["2009 "] == 0.0001023642489938382 + + def test_series_marker_without_a_value_is_null(self): + rows = browsers._intl_series_rows({"INTL.44-1-ABW-QBTU.A": {"1980": ["--"]}}) + assert rows[0]["1980 "] is None + + @pytest.mark.parametrize("marker", ["(s)", "--"]) + def test_infographic_marker_is_null(self, marker): + rows = browsers._intl_infographic_rows( + [ + { + "series_id": "INTL.44-1-ASM-QBTU.A", + "iso": "ASM", + "unit": "QBTU", + "frequency": "A", + "data": [{"date": 1704067200000, "value": marker}], + } + ] + ) + assert rows[0]["2024 "] is None + + def test_classic_table_marker_is_null(self): + rows = browsers._table_rows( + {"ROWS": [{"SERIES_ID": "S", "CHART_NAME": "C", "DATA": {"2024": "(s)"}}]} + ) + assert rows[0]["2024 "] is None + + def test_no_period_column_holds_text(self): + payload = { + "data": { + "INTL.44-1-ASM-QBTU.A": {"2023": ["(s)"], "2024": ["(s)", 1.7e-05]}, + "INTL.44-1-CSK-QBTU.A": {"2023": ["--"], "2024": ["--"]}, + } + } + for row in browsers.rows_from_payload(payload): + for key, value in row.items(): + if key in ("category", "country", "units", "source_key"): + continue + assert value is None or isinstance(value, float) + + +class TestFormatPeriod: + """EIA period codes render as ISO-style strings.""" + + def test_six_digits_is_year_month(self): + assert browsers._format_period("202401") == "2024-01" + + def test_eight_digits_is_a_date(self): + assert browsers._format_period("20240105") == "2024-01-05" + + def test_bare_year_unchanged(self): + assert browsers._format_period("2024") == "2024" + + def test_non_numeric_unchanged(self): + assert browsers._format_period("2024-Q1") == "2024-Q1" + + +class TestPeriodColumns: + """Identifiers first, then periods ascending -- matching EIA's CSV export. + + JS ``Object.keys`` floats canonical integer-string keys ahead of text keys, + so a bare year must not be a canonical integer key or the year columns jump + in front of the identifier columns in the rendered table. + """ + + def test_bare_years_are_not_canonical_integer_keys(self): + columns = browsers._period_columns({"2024", "2023"}) + assert columns == [("2023 ", "2023"), ("2024 ", "2024")] + for label, _ in columns: + assert str(int(label)) != label + + def test_periods_are_ascending(self): + columns = browsers._period_columns({"2024", "2022", "2023"}) + assert [raw for _, raw in columns] == ["2022", "2023", "2024"] + + def test_month_and_day_periods_are_not_integer_keys(self): + assert browsers._period_columns({"202401"}) == [("2024-01", "202401")] + assert browsers._period_columns({"20240105"}) == [("2024-01-05", "20240105")] + + def test_empty_period_set(self): + assert browsers._period_columns(set()) == [] + + +class TestFlattenCases: + """STEO/AEO payloads nest periods under a case id.""" + + def test_case_keyed_series_are_merged(self): + flat = browsers._flatten_cases( + {"REF2025": {"2024": 1.0}, "HIGH": {"2025": 2.0}} + ) + assert flat == {"2024": 1.0, "2025": 2.0} + + def test_plain_period_map_passes_through(self): + assert browsers._flatten_cases({"2024": 1.0}) == {"2024": 1.0} + + def test_empty_passes_through(self): + assert browsers._flatten_cases({}) == {} + + +class TestTableRows: + """The classic TABLEDATA shape used by electricity, coal, STEO and imports.""" + + def test_identifier_columns_then_periods(self): + rows = browsers._table_rows(TABLEDATA) + assert list(rows[0]) == [ + "category", + "units", + "source_key", + "2024-01", + "2024-02", + ] + + def test_labels_units_and_values(self): + first, second = browsers._table_rows(TABLEDATA) + assert first["category"] == "All fuels" + assert first["units"] == "million kilowatthours" + assert first["source_key"] == "ELEC.GEN.ALL-US-99.M" + assert first["2024-01"] == 1000.5 + assert second["category"] == "Coal" + assert second["units"] == "thousand tons" + assert second["2024-02"] is None + + def test_lowercase_keys_are_accepted(self): + rows = browsers._table_rows( + { + "units": "u", + "rows": [ + {"rowId": "R1", "chart_name": "Low", "data": {"2024": "1"}}, + ], + } + ) + assert rows == [ + {"category": "Low", "units": "u", "source_key": "R1", "2024 ": 1.0} + ] + + def test_rows_given_as_a_mapping(self): + rows = browsers._table_rows( + {"ROWS": {"a": {"MSN": "TETCB", "DESCRIPTION": "T", "DATA": {"2024": 1}}}} + ) + assert rows[0]["source_key"] == "TETCB" + + def test_case_nested_data_is_flattened(self): + rows = browsers._table_rows( + { + "ROWS": [ + { + "SERIES_ID": "S", + "CHART_NAME": "C", + "DATA": {"REF": {"2024": 1.0}}, + } + ] + } + ) + assert rows[0]["2024 "] == 1.0 + + def test_non_dict_entries_skipped(self): + assert browsers._table_rows({"ROWS": ["junk", None]}) == [] + + def test_missing_data_yields_no_period_columns(self): + rows = browsers._table_rows({"ROWS": [{"SERIES_ID": "S", "CHART_NAME": "C"}]}) + assert rows == [{"category": "C", "units": "", "source_key": "S"}] + + def test_pinned_name_used_as_a_last_resort_label(self): + rows = browsers._table_rows( + {"ROWS": [{"SERIES_ID": "S", "PINNED_NAME": "Pinned", "DATA": {}}]} + ) + assert rows[0]["category"] == "Pinned" + + +class TestSeriesRows: + """The ``{series_id, data}`` shape used by SEDS and the state profiles.""" + + def test_pairs_data_becomes_period_columns(self): + rows = browsers._series_rows(SERIES_PAYLOAD["series"]) + assert rows == [ + { + "category": "Total energy consumed", + "units": "billion Btu", + "source_key": "SEDS.TETCB.CA.A", + "2022 ": 7000.0, + "2023 ": 7100.0, + } + ] + + def test_mapping_data_is_accepted(self): + rows = browsers._series_rows( + [{"seriesID": "S", "description": "D", "unit": "u", "data": {"2024": "3"}}] + ) + assert rows[0]["2024 "] == 3.0 + assert rows[0]["units"] == "u" + + def test_series_id_is_the_fallback_label(self): + rows = browsers._series_rows([{"id": "S1", "data": {"2024": 1}}]) + assert rows[0]["category"] == "S1" + + def test_series_without_data_is_skipped(self): + assert browsers._series_rows([{"series_id": "S"}]) == [] + + def test_malformed_points_are_skipped(self): + rows = browsers._series_rows([{"series_id": "S", "data": [["2024"], 5]}]) + assert rows == [{"category": "S", "units": "", "source_key": "S"}] + + def test_non_dict_entries_skipped(self): + assert browsers._series_rows(["junk"]) == [] + + +class TestRankingRows: + """State Energy Profiles rankings are one row per state.""" + + def test_rank_period_and_value(self): + rows = browsers._ranking_rows(RANKING_PAYLOAD["series"]) + assert rows[0] == { + "category": "Texas", + "units": "Total energy consumed", + "source_key": "SEDS.TETCB.TX.A", + "rank": 1.0, + "period": "2023", + "value": 12000.5, + } + assert rows[1]["rank"] == 2.0 + + def test_state_id_is_the_fallback_label(self): + rows = browsers._ranking_rows([{"stateId": "TX"}]) + assert rows[0]["category"] == "TX" + + def test_non_dict_entries_skipped(self): + assert browsers._ranking_rows([None]) == [] + + +class TestStateMapRows: + """A US map payload is ``{code: {state: value}}`` and pivots to one row per state.""" + + def test_state_and_series_codes_are_named_from_the_catalog(self): + rows = browsers._state_map_rows(STATE_MAP_PAYLOAD["series"]) + assert rows == [ + { + "category": "Texas", + "state": "TX", + "Total energy consumption": 12000.0, + "All petroleum products total consumption": 4000.0, + }, + { + "category": "California", + "state": "CA", + "Total energy consumption": 7100.0, + "All petroleum products total consumption": 2000.0, + }, + ] + + def test_unknown_codes_fall_back_to_themselves(self): + rows = browsers._state_map_rows({"A": {"TX": 1}, "B": {"ZZ": 2}}) + assert rows == [ + {"category": "Texas", "state": "TX", "A": 1.0, "B": None}, + {"category": "ZZ", "state": "ZZ", "A": None, "B": 2.0}, + ] + + def test_non_mapping_codes_ignored(self): + assert browsers._state_map_rows({"year": 2023}) == [] + + +class TestInternationalHelpers: + """International encodes region and unit in the series id, values in pairs.""" + + def test_value_takes_the_unrounded_element(self): + assert browsers._intl_value([96.0, 96.34]) == 96.34 + + def test_string_marker_is_missing(self): + assert browsers._intl_value([96.0, "--"]) is None + + def test_scalar_passes_through(self): + assert browsers._intl_value(5) == 5 + + def test_empty_point_is_missing(self): + assert browsers._intl_value([]) is None + + def test_series_id_splits_into_product_activity_region_and_unit(self): + assert browsers._parse_intl_id("INTL.44-1-USA-QBTU.A") == ( + "44", + "1", + "USA", + "QBTU", + ) + + def test_series_id_without_the_prefix(self): + assert browsers._parse_intl_id("44-1-CHN-QBTU.A") == ("44", "1", "CHN", "QBTU") + + def test_series_id_without_a_product(self): + assert browsers._parse_intl_id("USA-QBTU.A") == ("", "", "USA", "QBTU") + + def test_unparseable_series_id(self): + assert browsers._parse_intl_id("INTL.X") == ("", "", "", "") + + @pytest.mark.parametrize( + ("frequency", "expected"), + [("A", "2023"), ("M", "202301"), ("D", "20230101"), ("Q", "2023-Q1")], + ) + def test_epoch_renders_per_frequency(self, frequency, expected): + assert browsers._epoch_period(1672531200000, frequency) == expected + + @pytest.mark.parametrize("stamp", [None, "abc", 10**20]) + def test_bad_epoch_yields_no_period(self, stamp): + assert browsers._epoch_period(stamp, "A") == "" + + def test_infographic_shape_detected(self): + assert browsers._is_intl_infographic(INTL_OVERVIEW_PAYLOAD["data"]) is True + + @pytest.mark.parametrize( + "data", [[], [{"series_id": "S"}], [{"data": []}], {"a": 1}, None] + ) + def test_other_shapes_are_not_infographic(self, data): + assert browsers._is_intl_infographic(data) is False + + +class TestInternationalRows: + """International rows must read like the table: one row per product per country. + + The table lists three rows under each country -- ``Production`` for the + top-level product, then each child product by name -- so the row label is + the product (or the activity it totals) and the country is its own column. + """ + + def test_row_label_is_the_product_and_country_is_its_own_column(self): + rows = browsers._intl_series_rows(BIOFUELS_PAYLOAD["data"], LABELS) + assert [(row["category"], row["country"]) for row in rows] == [ + ("Production", "Aruba"), + ("Fuel ethanol", "Aruba"), + ("Biomass-based diesel", "Aruba"), + ] + assert {row["units"] for row in rows} == {"Mb/d"} + + def test_top_level_product_is_labelled_by_its_activity(self): + rows = browsers._intl_series_rows( + {"INTL.44-2-USA-QBTU.A": {"2023": [96.0, 96.34]}}, LABELS + ) + assert rows[0]["category"] == "Consumption" + + def test_series_rows_are_labelled_with_country_and_unit_names(self): + rows = browsers._intl_series_rows(INTL_SERIES_PAYLOAD["data"], LABELS) + row = next(r for r in rows if r["country"] == "United States") + assert row == { + "category": "Production", + "country": "United States", + "units": "quad Btu", + "source_key": "INTL.44-1-USA-QBTU.A", + "2022 ": 95.12, + "2023 ": 96.34, + } + + def test_series_rows_are_grouped_by_country_the_way_the_grid_shows_them(self): + """The payload is keyed product-first; the grid groups by country.""" + rows = browsers._intl_series_rows(INTL_SERIES_PAYLOAD["data"], LABELS) + assert [row["country"] for row in rows] == ["China", "United States"] + + def test_world_leads_the_table(self): + labels = {**LABELS, "region": {**LABELS["region"], "WORL": "World"}} + data = { + "INTL.44-1-USA-QBTU.A": {"2023": [96.0, 96.34]}, + "INTL.44-1-WORL-QBTU.A": {"2023": [600.0, 600.5]}, + } + rows = browsers._intl_series_rows(data, labels) + assert [row["country"] for row in rows] == ["World", "United States"] + + def test_products_keep_the_order_eia_publishes_them_in(self): + labels = {**LABELS, "product_order": {"7": 0, "11": 1}} + data = { + "INTL.11-1-USA-TST.A": {"2023": [1.0, 1.0]}, + "INTL.7-1-USA-TST.A": {"2023": [2.0, 2.0]}, + } + rows = browsers._intl_series_rows(data, labels) + assert [row["source_key"] for row in rows] == [ + "INTL.7-1-USA-TST.A", + "INTL.11-1-USA-TST.A", + ] + + def test_series_rows_fall_back_to_codes_without_label_maps(self): + rows = browsers._intl_series_rows(INTL_SERIES_PAYLOAD["data"]) + row = next(r for r in rows if r["country"] == "USA") + assert row["units"] == "QBTU" + assert row["category"] == "INTL.44-1-USA-QBTU.A" + + def test_series_rows_skip_non_mapping_entries(self): + assert browsers._intl_series_rows({"INTL.X": "junk"}) == [] + + def test_overview_rows_are_labelled_and_keyed_by_period(self): + rows = browsers._intl_infographic_rows(INTL_OVERVIEW_PAYLOAD["data"], LABELS) + assert rows == [ + { + "category": "Production", + "country": "United States", + "units": "quad Btu", + "source_key": "INTL.44-1-USA-QBTU.A", + "2023 ": 96.34, + "2024 ": 97.5, + } + ] + + def test_overview_rows_fall_back_to_the_entry_name(self): + rows = browsers._intl_infographic_rows( + [{"series_id": "S", "name": "Kuwait", "data": [], "frequency": "A"}] + ) + assert rows[0]["country"] == "Kuwait" + assert rows[0]["category"] == "S" + + def test_overview_rows_skip_malformed_entries(self): + rows = browsers._intl_infographic_rows( + ["junk", {"series_id": "S", "data": [1]}] + ) + assert rows == [ + {"category": "S", "country": "", "units": "", "source_key": "S"} + ] + + +class TestRowsFromPayload: + """Every browser payload shape dispatches to the right pivot.""" + + def test_tabledata(self): + rows = browsers.rows_from_payload({"TABLEDATA": TABLEDATA}) + assert rows[0]["category"] == "All fuels" + + def test_lowercase_tabledata(self): + rows = browsers.rows_from_payload({"tabledata": TABLEDATA}) + assert rows[0]["category"] == "All fuels" + + def test_seriesdata(self): + rows = browsers.rows_from_payload({"SERIESDATA": TABLEDATA}) + assert rows[0]["category"] == "All fuels" + + def test_viewsdata(self): + rows = browsers.rows_from_payload({"VIEWSDATA": TABLEDATA}) + assert rows[0]["category"] == "All fuels" + + def test_seriesdata_without_rows_is_ignored(self): + assert browsers.rows_from_payload({"SERIESDATA": {"ROWS": []}}) == [] + + def test_table_data_list(self): + rows = browsers.rows_from_payload( + {"TABLE_DATA": [{"seriesID": "S", "data": {"2024": 1}}]} + ) + assert rows[0]["source_key"] == "S" + + def test_series_list_of_series(self): + rows = browsers.rows_from_payload(SERIES_PAYLOAD) + assert rows[0]["category"] == "Total energy consumed" + + def test_series_list_of_rankings(self): + rows = browsers.rows_from_payload(RANKING_PAYLOAD) + assert rows[0]["rank"] == 1.0 + + def test_series_mapping_is_a_state_map(self): + rows = browsers.rows_from_payload(STATE_MAP_PAYLOAD) + assert rows[0]["category"] == "Texas" + assert rows[0]["state"] == "TX" + + def test_international_series(self): + rows = browsers.rows_from_payload(INTL_SERIES_PAYLOAD) + assert {row["source_key"] for row in rows} == { + "INTL.44-1-USA-QBTU.A", + "INTL.44-1-CHN-QBTU.A", + } + + def test_international_overview(self): + rows = browsers.rows_from_payload(INTL_OVERVIEW_PAYLOAD) + assert rows[0]["country"] == "USA" + assert rows[0]["source_key"] == "INTL.44-1-USA-QBTU.A" + + def test_plain_list_of_records(self): + assert browsers.rows_from_payload({"data": [{"a": 1}, "junk"]}) == [{"a": 1}] + + def test_bare_list_of_records(self): + assert browsers.rows_from_payload([{"a": 1}]) == [{"a": 1}] + + def test_list_of_payloads_is_flattened(self): + rows = browsers.rows_from_payload([{"TABLEDATA": TABLEDATA}]) + assert rows[0]["category"] == "All fuels" + + def test_unrecognised_payload_is_empty(self): + assert browsers.rows_from_payload("nope") == [] + assert browsers.rows_from_payload({}) == [] + assert browsers.rows_from_payload({"data": None}) == [] + + +class TestSteoTable: + """STEO has no TABLEDATA: its table is VIEWSDATA, not the pinned SERIESDATA.""" + + PAYLOAD = { + "VIEWSDATA": { + "ROWS": [ + {"CHART_NAME": "Energy Production", "HAS_DATA": 0, "LEVEL": 1}, + { + "CHART_NAME": "U.S. Crude Oil Production", + "SERIES_ID": "COPRPUS", + "UNITS": "million barrels per day", + "DATA": {"2025": "13.6"}, + }, + ] + }, + "SERIESDATA": { + "ROWS": [ + { + "CHART_NAME": "Biodiesel Net Imports", + "SERIES_ID": "BDNIPUS", + "UNITS": "million barrels per day", + "DATA": {"2025": "0.1"}, + } + ] + }, + } + + def test_the_view_is_the_table_not_the_pinned_series(self): + rows = browsers.rows_from_payload(self.PAYLOAD) + assert [row["source_key"] for row in rows] == ["", "COPRPUS"] + + def test_pinned_series_are_the_table_when_no_view_is_selected(self): + payload = {"VIEWSDATA": {"ROWS": []}, "SERIESDATA": self.PAYLOAD["SERIESDATA"]} + rows = browsers.rows_from_payload(payload) + assert [row["source_key"] for row in rows] == ["BDNIPUS"] + + +class TestImportsRows: + """Imports ships only series ids; the browser builds every label from config.""" + + LABELS = { + "origin": { + "REG": {"WORLD": "World"}, + "OPN": {"Y": "OPEC", "N": "Non-OPEC"}, + "CTY": {}, + }, + "destination": {"RP": {"3": "PADD3 (Gulf Coast)"}, "RS": {"US": "Total U.S."}}, + "grade": {"LSO": "Light Sour", "LSW": "Light Sweet"}, + } + RECORDS = [ + {"seriesID": "PET_IMPORTS.WORLD-RP_3-LSO.M", "data": {"200901": 9091}}, + {"seriesID": "PET_IMPORTS.OPN_Y-RP_3-LSW.M", "data": {"200901": 20089}}, + ] + + def test_rows_are_named_the_way_the_table_names_them(self): + rows = browsers._imports_rows(self.RECORDS, self.LABELS) + assert rows[0]["category"] == ( + "Imports of Light Sour from World to PADD3 (Gulf Coast), monthly" + ) + assert rows[0]["origin"] == "World" + assert rows[0]["destination"] == "PADD3 (Gulf Coast)" + assert rows[0]["grade"] == "Light Sour" + assert rows[0]["units"] == "thousand barrels" + assert rows[0]["2009-01"] == 9091.0 + + def test_typed_origin_prefix_is_resolved(self): + rows = browsers._imports_rows(self.RECORDS, self.LABELS) + assert rows[1]["origin"] == "OPEC" + assert rows[1]["grade"] == "Light Sweet" + + def test_annual_series_says_annual(self): + rows = browsers._imports_rows( + [{"seriesID": "PET_IMPORTS.WORLD-RS_US-ALL.A", "data": {"2024": 1}}], + self.LABELS, + ) + assert rows[0]["category"] == ( + "Imports of all grades from World to Total U.S., annual" + ) + + def test_unknown_codes_fall_back_to_themselves(self): + rows = browsers._imports_rows( + [{"seriesID": "PET_IMPORTS.ZZ-YY_9-QQ.M", "data": {}}], self.LABELS + ) + assert rows[0]["origin"] == "ZZ" + assert rows[0]["destination"] == "YY_9" + assert rows[0]["grade"] == "QQ" + + def test_unparseable_series_id_still_yields_a_row(self): + rows = browsers._imports_rows([{"seriesID": "BROKEN"}], self.LABELS) + assert rows[0]["category"] == "BROKEN" + assert rows[0]["source_key"] == "BROKEN" + + def test_non_dict_entries_skipped(self): + assert browsers._imports_rows(["junk"], self.LABELS) == [] + + +class TestNgqsRows: + """NGQS records are keyed by short grid field ids; the payload names them.""" + + PAYLOAD = { + "columns": [ + {"headerName": "Area", "field": "a"}, + {"headerName": "Company", "field": "b"}, + {"headerName": "Item", "field": "c"}, + {"headerName": 2023, "field": "y2023", "numeric": True}, + {"width": 10}, + ], + "data": [ + { + "a": " U.S. Total", + "b": " Total of All Companies", + "c": "Production Volume", + "y2023": 2389716115, + }, + "junk", + ], + } + + def test_grid_headers_become_the_columns(self): + rows = browsers._ngqs_rows(self.PAYLOAD) + assert rows == [ + { + "Area": " U.S. Total", + "Company": " Total of All Companies", + "Item": "Production Volume", + "2023 ": 2389716115.0, + } + ] + + def test_year_headers_are_not_canonical_integer_keys(self): + assert "2023 " in browsers._ngqs_rows(self.PAYLOAD)[0] + + def test_missing_columns_yield_nothing(self): + assert browsers._ngqs_rows({"data": []}) == [] + assert browsers._ngqs_rows({"columns": []}) == [] + + +class TestStatesTableRows: + """The State Profiles table keeps its values outside the series metadata.""" + + PAYLOAD = { + "request": "SEDS.TETCB.TX.A", + "series": [ + { + "series_id": "SEDS.TETCB.TX.A", + "name": "SEDS.TETCB.TX.A, annual", + "units": "Billion Btu", + "column_index": "column_0", + } + ], + "data": [ + {"time": "2024", "column_0": 14536890}, + {"time": "2023", "column_0": 14149656}, + {"time": "", "column_0": 1}, + ], + } + + def test_values_are_joined_to_their_series_by_column_index(self): + rows = browsers.rows_from_payload(self.PAYLOAD) + assert rows == [ + { + "category": "SEDS.TETCB.TX.A, annual", + "units": "Billion Btu", + "source_key": "SEDS.TETCB.TX.A", + "2023 ": 14149656.0, + "2024 ": 14536890.0, + } + ] + + def test_series_without_values_is_not_mistaken_for_a_ranking(self): + rows = browsers.rows_from_payload(self.PAYLOAD) + assert "rank" not in rows[0] + + def test_series_metadata_without_a_column_index_is_skipped(self): + payload = dict(self.PAYLOAD, series=[{"column_index": "column_0"}, "junk"]) + rows = browsers._states_table_rows(payload["series"], payload["data"]) + assert len(rows) == 1 + assert rows[0]["category"] == "" + + def test_non_dict_records_are_skipped(self): + rows = browsers._states_table_rows( + self.PAYLOAD["series"], ["junk", {"time": "2024", "column_0": 1}] + ) + assert rows[0]["2024 "] == 1.0 + + +class TestParseInlineTable: + """Total Energy ships its table inline as ``sampleData``.""" + + def test_extracts_and_pivots(self): + html = f"<script>var sampleData = {json.dumps(TABLEDATA)};</script>" + rows = browsers.parse_inline_table(html) + assert rows[0]["category"] == "All fuels" + + def test_absent_marker_yields_nothing(self): + assert browsers.parse_inline_table("<html></html>") == [] + + def test_malformed_json_yields_nothing(self): + assert browsers.parse_inline_table("sampleData = {not json") == [] + + def test_non_object_payload_yields_nothing(self): + assert browsers.parse_inline_table('sampleData = "x" {}') == [] + + +class TestTableParamsFromHash: + """Classic browsers encode the current view in the URL fragment.""" + + def test_builds_aggregate_params(self): + params = browsers.table_params_from_hash( + "#/topic/0?agg=0,1&geo=g&freq=A&ctype=linechart&linechart=ELEC.X&rtype=s" + ) + assert params["method"] == browsers._TABLE_METHOD + assert params["topic"] == "0" + assert params["agg"] == "0,1" + assert params["geo"] == "g" + assert params["freq"] == "A" + assert params["rtype"] == "s" + assert params["ids"] == "ELEC.X" + + def test_pin_wins_over_the_chart_selection(self): + params = browsers.table_params_from_hash( + "#/topic/0?pin=PINNED&ctype=linechart&linechart=OTHER" + ) + assert params["ids"] == "PINNED" + + def test_defaults_applied_when_absent(self): + params = browsers.table_params_from_hash("#/topic/2?geo=g") + assert params["freq"] == "M" + assert params["rtype"] == "s" + assert params["ids"] == "" + + def test_chart_keys_are_not_forwarded_as_filters(self): + params = browsers.table_params_from_hash("#/topic/0?ctype=map&map=X") + assert "map" not in params + assert "ctype" not in params + + @pytest.mark.parametrize( + "fragment", ["", "no-hash", "#/nowhere?x=1", "#/topic/0", "#/topic/0?"] + ) + def test_unusable_fragments_yield_none(self, fragment): + assert browsers.table_params_from_hash(fragment) is None diff --git a/openbb_platform/providers/eia/tests/test_report_models.py b/openbb_platform/providers/eia/tests/test_report_models.py new file mode 100644 index 00000000000..3cfc61aa564 --- /dev/null +++ b/openbb_platform/providers/eia/tests/test_report_models.py @@ -0,0 +1,298 @@ +"""Tests for the Weekly Petroleum Status Report and Short Term Energy Outlook models.""" + +from datetime import date, datetime +from io import BytesIO + +import pytest +from openbb_core.app.model.abstract.error import OpenBBError +from pandas import DataFrame, ExcelFile, ExcelWriter + +from openbb_us_eia.models.petroleum_status_report import ( + EiaPetroleumStatusReportFetcher, +) +from openbb_us_eia.models.short_term_energy_outlook import ( + EiaShortTermEnergyOutlookFetcher, +) + + +def _wpsr_sheet(dates): + """Build one WPSR-style sheet: banner row, symbol/title headers, data rows.""" + rows = [ + ["Back to Contents", "Data 1: Test Table"], + ["Sourcekey", "WTOTUSA"], + ["Date", "U.S. Ending Stocks of Crude Oil (Thousand Barrels)"], + ] + rows += [[datetime(d.year, d.month, d.day), 100.0 + i] for i, d in enumerate(dates)] + return DataFrame(rows) + + +def _wpsr_file(sheets): + """Write sheets into an in-memory workbook and open it as an ExcelFile.""" + buffer = BytesIO() + with ExcelWriter(buffer) as writer: + for name, frame in sheets.items(): + frame.to_excel(writer, sheet_name=name, header=False, index=False) + return ExcelFile(BytesIO(buffer.getvalue())) + + +class TestPetroleumStatusReportQuery: + """Category and table validation.""" + + def test_all_invalid_for_weekly_estimates(self): + with pytest.raises(OpenBBError, match="not a supported choice"): + EiaPetroleumStatusReportFetcher.transform_query( + {"category": "weekly_estimates", "table": "all"} + ) + + def test_all_with_other_tables_warns_and_drops_all(self): + with pytest.warns(UserWarning, match="Ignoring 'all'"): + query = EiaPetroleumStatusReportFetcher.transform_query( + {"category": "balance_sheet", "table": "all,stocks"} + ) + assert query.table == "stocks" + + def test_invalid_table_raises(self): + with pytest.raises(OpenBBError, match="Invalid table choice"): + EiaPetroleumStatusReportFetcher.transform_query( + {"category": "balance_sheet", "table": "imports"} + ) + + def test_weekly_estimates_defaults_to_stocks(self): + query = EiaPetroleumStatusReportFetcher.transform_query( + {"category": "weekly_estimates"} + ) + assert query.table == "stocks" + + +class TestPetroleumStatusReportPipeline: + """Extraction error wrapping and workbook transformation.""" + + @pytest.mark.asyncio + async def test_extract_wraps_download_errors(self, monkeypatch): + from openbb_us_eia.utils import helpers + + async def failing_download(url, use_cache=True): + raise OpenBBError("download failed") + + monkeypatch.setattr(helpers, "download_excel_file", failing_download) + query = EiaPetroleumStatusReportFetcher.transform_query({}) + with pytest.raises(OpenBBError, match="Error extracting data"): + await EiaPetroleumStatusReportFetcher.aextract_data(query, None) + + def test_transform_requires_excel_file(self): + query = EiaPetroleumStatusReportFetcher.transform_query({}) + with pytest.raises(OpenBBError, match="Expected an ExcelFile"): + EiaPetroleumStatusReportFetcher.transform_data(query, {"file": None}) + + def test_transform_flattens_and_filters_dates(self): + file = _wpsr_file( + { + "Data 1": _wpsr_sheet([date(2024, 1, 5), date(2024, 1, 12)]), + "Data 2": _wpsr_sheet([date(2020, 1, 3)]), + } + ) + query = EiaPetroleumStatusReportFetcher.transform_query( + { + "category": "retail_prices", + "table": "weekly,monthly", + "start_date": date(2024, 1, 1), + "end_date": date(2024, 1, 31), + } + ) + with pytest.warns(UserWarning, match="No data for table: monthly"): + rows = EiaPetroleumStatusReportFetcher.transform_data(query, {"file": file}) + assert [row.date for row in rows] == [date(2024, 1, 5), date(2024, 1, 12)] + record = rows[0].model_dump() + assert record["symbol"] == "WTOTUSA" + assert record["title"] == "U.S. Ending Stocks of Crude Oil" + assert record["unit"] == "Thousand Barrels" + assert record["table"] == "Data 01: Test Table" + + def test_transform_all_tables_empty_raises(self): + file = _wpsr_file( + { + "Data 1": _wpsr_sheet([date(2020, 1, 3)]), + "Data 2": _wpsr_sheet([date(2020, 1, 3)]), + } + ) + query = EiaPetroleumStatusReportFetcher.transform_query( + {"category": "retail_prices", "start_date": date(2024, 1, 1)} + ) + with ( + pytest.warns(UserWarning, match="No data for table"), + pytest.raises(OpenBBError, match="Error transforming the data"), + ): + EiaPetroleumStatusReportFetcher.transform_data(query, {"file": file}) + + +def _steo_response(rows, total=None): + return { + "response": { + "data": rows, + "total": str(total if total is not None else len(rows)), + } + } + + +def _steo_rows(period, symbols): + return [ + { + "period": period, + "seriesId": symbol, + "seriesDescription": symbol, + "value": "1", + } + for symbol in symbols + ] + + +class TestShortTermEnergyOutlookExtract: + """Date formatting, chunking, pagination, and message handling.""" + + @pytest.mark.parametrize( + ("frequency", "start", "end"), + [ + ("month", "start=2024-01", "end=2024-04"), + ("quarter", "start=2024-Q1", "end=2024-Q2"), + ("annual", "start=2024", "end=2024"), + ], + ) + @pytest.mark.asyncio + async def test_date_params_formatted_per_frequency( + self, monkeypatch, frequency, start, end + ): + from openbb_core.provider.utils import helpers as core_helpers + + urls: list[str] = [] + + async def fake_amake_request(url, response_callback=None, **kwargs): + urls.append(url) + return _steo_response(_steo_rows("2024-01", ["WTIPUUS"])) + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + query = EiaShortTermEnergyOutlookFetcher.transform_query( + { + "symbol": "WTIPUUS", + "frequency": frequency, + "start_date": date(2024, 1, 1), + "end_date": date(2024, 4, 1), + } + ) + await EiaShortTermEnergyOutlookFetcher.aextract_data( + query, {"eia_api_key": "MOCK_KEY"} + ) + assert start in urls[0] + assert end in urls[0] + + @pytest.mark.asyncio + async def test_paginates_when_total_exceeds_page(self, monkeypatch): + from openbb_core.provider.utils import helpers as core_helpers + + first_page = _steo_rows("2024-01", [f"S{i}" for i in range(5000)]) + second_page = _steo_rows("2024-02", ["S0"]) + calls = {"n": 0} + + async def fake_amake_request(url, response_callback=None, **kwargs): + calls["n"] += 1 + if "offset=0" in url: + return _steo_response(first_page, total=5001) + return _steo_response(second_page, total=5001) + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + query = EiaShortTermEnergyOutlookFetcher.transform_query({"symbol": "WTIPUUS"}) + rows = await EiaShortTermEnergyOutlookFetcher.aextract_data( + query, {"eia_api_key": "MOCK_KEY"} + ) + assert len(rows) == 5001 + assert calls["n"] == 2 + + @pytest.mark.asyncio + async def test_pagination_stops_on_empty_page_with_warning(self, monkeypatch): + from openbb_core.provider.utils import helpers as core_helpers + + first_page = _steo_rows("2024-01", [f"S{i}" for i in range(5000)]) + + async def fake_amake_request(url, response_callback=None, **kwargs): + if "offset=0" in url: + return _steo_response(first_page, total=5001) + return _steo_response([], total=5001) + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + query = EiaShortTermEnergyOutlookFetcher.transform_query({"symbol": "WTIPUUS"}) + with pytest.warns(UserWarning, match="No additional data returned"): + rows = await EiaShortTermEnergyOutlookFetcher.aextract_data( + query, {"eia_api_key": "MOCK_KEY"} + ) + assert len(rows) == 5000 + + @pytest.mark.asyncio + async def test_all_empty_raises_messages(self, monkeypatch): + from openbb_core.provider.utils import helpers as core_helpers + + async def fake_amake_request(url, response_callback=None, **kwargs): + return _steo_response([]) + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + query = EiaShortTermEnergyOutlookFetcher.transform_query({"symbol": "WTIPUUS"}) + with pytest.raises(OpenBBError, match="No data returned"): + await EiaShortTermEnergyOutlookFetcher.aextract_data( + query, {"eia_api_key": "MOCK_KEY"} + ) + + @pytest.mark.asyncio + async def test_request_error_wrapped(self, monkeypatch): + from openbb_core.provider.utils import helpers as core_helpers + + async def fake_amake_request(url, response_callback=None, **kwargs): + raise ValueError("socket closed") + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + query = EiaShortTermEnergyOutlookFetcher.transform_query({"symbol": "WTIPUUS"}) + with pytest.raises(OpenBBError, match="Error fetching data"): + await EiaShortTermEnergyOutlookFetcher.aextract_data( + query, {"eia_api_key": "MOCK_KEY"} + ) + + @pytest.mark.asyncio + async def test_partial_results_warn(self, monkeypatch): + from openbb_core.provider.utils import helpers as core_helpers + + async def fake_amake_request(url, response_callback=None, **kwargs): + if "WTIPUUS" in url: + return _steo_response(_steo_rows("2024-01", ["WTIPUUS"])) + return _steo_response([]) + + monkeypatch.setattr(core_helpers, "amake_request", fake_amake_request) + symbols = ",".join(["WTIPUUS"] + [f"S{i}" for i in range(10)]) + query = EiaShortTermEnergyOutlookFetcher.transform_query({"symbol": symbols}) + with pytest.warns(UserWarning, match="No data returned"): + rows = await EiaShortTermEnergyOutlookFetcher.aextract_data( + query, {"eia_api_key": "MOCK_KEY"} + ) + assert len(rows) == 1 + + +class TestShortTermEnergyOutlookTransform: + """Period parsing and missing-symbol warnings.""" + + def test_missing_symbols_warn(self): + query = EiaShortTermEnergyOutlookFetcher.transform_query( + {"symbol": "WTIPUUS,BREPUUS"} + ) + rows = _steo_rows("2024-Q1", ["WTIPUUS"]) + for row in rows: + row["value"] = 80.0 + query = query.model_copy(update={"frequency": "quarter"}) + with pytest.warns(UserWarning, match="No data was returned for: BREPUUS"): + out = EiaShortTermEnergyOutlookFetcher.transform_data(query, rows) + assert out[0].date == date(2024, 1, 1) + + def test_table_mode_orders_and_labels(self): + query = EiaShortTermEnergyOutlookFetcher.transform_query({"table": "01"}) + rows = _steo_rows("2024-01", ["WTIPUUS", "COPRPUS"]) + for row in rows: + row["value"] = 1.0 + out = EiaShortTermEnergyOutlookFetcher.transform_data(query, rows) + record = out[0].model_dump() + assert record["table"].startswith("STEO - 1:") + assert record["order"] == 1 diff --git a/openbb_platform/providers/eia/tests/test_rss.py b/openbb_platform/providers/eia/tests/test_rss.py new file mode 100644 index 00000000000..b37176a8e5e --- /dev/null +++ b/openbb_platform/providers/eia/tests/test_rss.py @@ -0,0 +1,381 @@ +"""Tests for the EIA RSS feed widget and helpers.""" + +import time + +import aiohttp +import feedparser +import pytest + +from openbb_us_eia import rss as rss_widget +from openbb_us_eia.utils import rss + +SAMPLE_RSS = b"""<?xml version="1.0" encoding="UTF-8"?> +<rss version="2.0" xmlns:eia="https://www.eia.gov/rss/"> + <channel> + <title>Sample Feed + + First Article + https://www.eia.gov/todayinenergy/detail.php?id=1 + <p>A short summary.</p> + Mon, 19 May 2026 13:00:00 GMT + Jane Doe + + + Second Article + detail.php?id=2 + Plain text summary. + Mon, 19 May 2026 12:00:00 GMT + + + +""" + +PRESENTATION_RSS = b""" + + + Presentations + + Deck + https://www.eia.gov/pressroom/index.php + A talk. + Wed, 04 Mar 2026 13:00:00 GMT + /pressroom/presentations/deck.pdf + /pressroom/presentations/deck.pptx + Energy + A. Person + + + Video Talk + https://www.youtube.com/watch?v=abc123 + Recorded. + Tue, 03 Mar 2026 13:00:00 GMT + + + Landing Page Only + https://www.eia.gov/pressroom/other.php + No document. + Mon, 02 Mar 2026 13:00:00 GMT + + + +""" + +PRICE_RSS = b""" + + + Gasoline + + Prices + https://www.eia.gov/petroleum/gasdiesel/ + Summary excerpt here<br/>Regular Gasoline<br/>3.081 .. U.S.<br/>2.855 .. Gulf Coast<br/>Diesel<br/>3.624 .. U.S. + Mon, 06 Jul 2026 13:00:00 GMT + + + +""" + + +class _FakeResponse: + def __init__(self, body=b"", status=200): + self._body = body + self.status = status + + async def read(self): + return self._body + + def raise_for_status(self): + if self.status >= 400: + raise aiohttp.ClientError(f"HTTP {self.status}") + + async def __aenter__(self): + return self + + async def __aexit__(self, *_args): + return None + + +class _FakeSession: + def __init__(self, results): + self.results = list(results) + self.calls = 0 + self.closed = False + + async def get(self, _url, **_kwargs): + self.calls += 1 + result = self.results.pop(0) + if isinstance(result, BaseException): + raise result + return result + + async def __aenter__(self): + return self + + async def __aexit__(self, *_args): + self.closed = True + + +class TestRegistry: + def test_feed_specs_complete(self): + assert set(rss.EIA_RSS_FEEDS) == { + "today_in_energy", + "whats_new", + "press_releases", + "congressional_testimony", + "presentations", + "gasoline_diesel", + "heating_oil_propane", + } + for spec in rss.EIA_RSS_FEEDS.values(): + assert set(spec) == {"label", "description", "url", "base", "viewer"} + assert spec["viewer"] in ("page", "pdf", "table") + + def test_feed_choices(self): + choices = rss.feed_choices() + assert choices[0] == {"label": "Today in Energy", "value": "today_in_energy"} + assert len(choices) == len(rss.EIA_RSS_FEEDS) + + +class TestTextHelpers: + def test_strip_html(self): + assert rss.strip_html("

    A B\n C

    ") == "A B C" + + def test_strip_html_empty(self): + assert rss.strip_html("") == "" + + def test_article_text_drops_script_and_style(self): + html = ( + "" + "" + "

    Real prose.

    " + ) + assert rss.article_text(html) == "Real prose." + + def test_article_text_empty(self): + assert rss.article_text("") == "" + + def test_article_text_truncates_to_limit(self): + assert rss.article_text("

    " + "ab " * 100 + "

    ", limit=5) == "ab ab" + + def test_excerpt_short_text_unchanged(self): + assert rss.clean_excerpt("short") == "short" + + def test_excerpt_cuts_at_word_boundary(self): + assert rss.clean_excerpt("word " * 100, limit=22) == "word word word word…" + + def test_excerpt_keeps_whitelisted_inline_markup(self): + out = rss.clean_excerpt("

    Crude rose 4%

    ") + assert out == "Crude rose 4%" + + def test_excerpt_drops_unlisted_tags_but_keeps_their_text(self): + out = rss.clean_excerpt('
    link and emphasis') + assert out == "link and emphasis" + + def test_excerpt_discards_script_source(self): + assert ( + rss.clean_excerpt("Prices fell") == "Prices fell" + ) + + def test_excerpt_discards_style_source(self): + assert rss.clean_excerpt("Prices fell") == ( + "Prices fell" + ) + + def test_excerpt_decodes_entities_into_markup(self): + out = rss.clean_excerpt("CO<sub>2</sub> & NG") + assert out == "CO2 & NG" + + def test_excerpt_closes_tags_left_open_by_truncation(self): + out = rss.clean_excerpt("very long bold text to cut", limit=20) + assert out == "very long bold text…" + + def test_excerpt_of_empty_summary(self): + assert rss.clean_excerpt("") == "" + assert rss.clean_excerpt(None) == "" + + def test_excerpt_stops_once_the_budget_is_exhausted(self): + assert rss.clean_excerpt("abcdefgh", limit=4) == "abcd" + + def test_struct_time_to_iso(self): + value = time.gmtime(0) + assert rss.struct_time_to_iso(value) == "1970-01-01T00:00:00+00:00" + + def test_struct_time_none_returns_now(self): + assert rss.struct_time_to_iso(None).endswith("+00:00") + + def test_escape(self): + assert rss._escape("&") == "<a>&" + assert rss._escape("") == "" + + def test_youtube_embed(self): + assert ( + rss._youtube_embed("https://www.youtube.com/watch?v=abc_1-2") + == "https://www.youtube.com/embed/abc_1-2" + ) + assert ( + rss._youtube_embed("https://youtu.be/xyz") + == "https://www.youtube.com/embed/xyz" + ) + assert rss._youtube_embed("https://www.eia.gov/page") is None + + +class TestFetchFeed: + @pytest.mark.asyncio + async def test_parses_first_success(self): + session = _FakeSession([_FakeResponse(SAMPLE_RSS)]) + parsed = await rss.fetch_feed(session, "http://feed") + assert len(parsed.entries) == 2 + assert session.calls == 1 + + @pytest.mark.asyncio + async def test_retries_transient_failure(self): + session = _FakeSession([aiohttp.ClientError("boom"), _FakeResponse(SAMPLE_RSS)]) + parsed = await rss.fetch_feed(session, "http://feed") + assert len(parsed.entries) == 2 + assert session.calls == 2 + + @pytest.mark.asyncio + async def test_exhausted_retries_return_empty(self): + session = _FakeSession([TimeoutError(), TimeoutError(), TimeoutError()]) + parsed = await rss.fetch_feed(session, "http://feed") + assert parsed.entries == [] + assert session.calls == 3 + + @pytest.mark.asyncio + async def test_http_error_counts_as_failure(self): + session = _FakeSession( + [_FakeResponse(b"", status=503), _FakeResponse(SAMPLE_RSS)] + ) + parsed = await rss.fetch_feed(session, "http://feed") + assert len(parsed.entries) == 2 + + +class TestRenderPriceTable: + def test_sections_and_rows(self): + description = ( + "Summary excerpt ignored
    Regular Gasoline
    " + "3.081 .. U.S.
    2.855 .. Gulf Coast
    Diesel
    3.624 .. U.S." + ) + out = rss.render_price_table(description) + assert out.count("

    ") == 2 + assert out.count("U.S.3.081" in out + + def test_empty_description(self): + assert rss.render_price_table("") == "" + + def test_plain_text_without_markup(self): + out = rss.render_price_table("Header\n1.23 .. Item") + assert "

    Header

    " in out + assert "1.23" in out + + +class TestBuildFeed: + def test_page_feed_rewrites_src_through_proxy(self): + parsed = feedparser.parse(SAMPLE_RSS) + data = rss.build_feed("today_in_energy", parsed, 50, "http://t/eia_proxy") + assert data["label"] == "Today in Energy" + first, second = data["items"] + assert first["title"] == "First Article" + assert first["src"] == "http://t/eia_proxy/todayinenergy/detail.php?id=1" + assert first["url"] == "https://www.eia.gov/todayinenergy/detail.php?id=1" + assert first["excerpt"] == "A short summary." + assert second["author"] == "Sample Feed" + assert second["url"] == "https://www.eia.gov/todayinenergy/detail.php?id=2" + + def test_without_proxy_keeps_original_src(self): + parsed = feedparser.parse(SAMPLE_RSS) + data = rss.build_feed("today_in_energy", parsed, 50, "") + assert data["items"][0]["src"].startswith("https://www.eia.gov/") + + def test_limit_and_sort_desc(self): + parsed = feedparser.parse(SAMPLE_RSS) + data = rss.build_feed("today_in_energy", parsed, 1, "") + assert len(data["items"]) == 1 + assert data["items"][0]["title"] == "First Article" + + def test_presentation_variants(self): + parsed = feedparser.parse(PRESENTATION_RSS) + data = rss.build_feed("presentations", parsed, 50, "http://t/eia_proxy") + deck, video, page = data["items"] + assert deck["viewer"] == "pdf" + assert deck["src"] == "http://t/eia_proxy/pressroom/presentations/deck.pdf" + assert ( + deck["ppt_url"] == "https://www.eia.gov/pressroom/presentations/deck.pptx" + ) + assert {"label": "Subject", "value": "Energy"} in deck["meta"] + assert video["viewer"] == "embed" + assert video["src"] == "https://www.youtube.com/embed/abc123" + assert page["viewer"] == "page" + assert page["src"] == "http://t/eia_proxy/pressroom/other.php" + + def test_table_feed_renders_body_html(self): + parsed = feedparser.parse(PRICE_RSS) + data = rss.build_feed("gasoline_diesel", parsed, 50, "http://t/eia_proxy") + item = data["items"][0] + assert item["viewer"] == "table" + assert "") + data = rss.build_feed("today_in_energy", parsed, 50, "") + assert data["items"] == [] + assert data["label"] == "Today in Energy" + + +class TestRenderRssHtml: + def test_escapes_blob_and_sets_theme(self): + html = rss.render_rss_html({"feed": "x", "label": "&", "items": []}, "light") + assert "__EIA_RSS_DATA__" not in html + assert "\\u003cL\\u003e\\u0026" in html + assert '"theme": "light"' in html or '"light"' in html + + def test_dark_default(self): + html = rss.render_rss_html({"feed": "x", "items": []}, "anything") + assert '"dark"' in html + + +class TestRssFeedEndpoint: + @pytest.fixture + def stubbed(self, monkeypatch): + session = _FakeSession([_FakeResponse(SAMPLE_RSS)]) + + async def fake_get_session(): + return session + + monkeypatch.setattr( + "openbb_core.provider.utils.helpers.get_async_requests_session", + fake_get_session, + ) + return session + + INFO = {"url": "http://t/api/v1/eia/rss_feed", "query": "", "path": ""} + + @pytest.mark.asyncio + async def test_renders_feed_with_proxy_base(self, stubbed): + response = await rss_widget.rss_feed( + info=self.INFO, feed="today_in_energy", theme="dark" + ) + text = response.body.decode() + assert "First Article" in text + assert "eia_proxy/todayinenergy" in text + assert '"endpoint": "http://t/api/v1/eia/rss_feed"' in text + assert stubbed.closed is True + + @pytest.mark.asyncio + async def test_unknown_feed_falls_back(self, stubbed): + response = await rss_widget.rss_feed( + info=self.INFO, feed="bogus", theme="light" + ) + assert '"today_in_energy"' in response.body.decode() + + +class TestRouterRegistration: + def test_route_and_widget_config(self): + routes = {route.path: route for route in rss_widget.router._api_router.routes} + widget = routes["/rss_feed"] + config = widget.openapi_extra["widget_config"] + params = {p["paramName"]: p for p in config["params"]} + assert params["theme"]["show"] is False + assert [o["value"] for o in params["feed"]["options"]] == list( + rss.EIA_RSS_FEEDS + ) diff --git a/openbb_platform/providers/eia/uv.lock b/openbb_platform/providers/eia/uv.lock new file mode 100644 index 00000000000..542923cf63d --- /dev/null +++ b/openbb_platform/providers/eia/uv.lock @@ -0,0 +1,4775 @@ +version = 1 +revision = 3 +requires-python = ">=3.10, <4" +resolution-markers = [ + "python_full_version >= '3.15' and sys_platform == 'win32'", + "python_full_version == '3.14.*' and sys_platform == 'win32'", + "python_full_version >= '3.15' and sys_platform == 'emscripten'", + "python_full_version == '3.14.*' and sys_platform == 'emscripten'", + "python_full_version >= '3.15' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.14.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version < '3.11'", +] + +[[package]] +name = "aiofile" +version = "3.9.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +dependencies = [ + { name = "caio", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/67/e2/d7cb819de8df6b5c1968a2756c3cb4122d4fa2b8fc768b53b7c9e5edb646/aiofile-3.9.0.tar.gz", hash = "sha256:e5ad718bb148b265b6df1b3752c4d1d83024b93da9bd599df74b9d9ffcf7919b", size = 17943, upload-time = "2024-10-08T10:39:35.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/50/25/da1f0b4dd970e52bf5a36c204c107e11a0c6d3ed195eba0bfbc664c312b2/aiofile-3.9.0-py3-none-any.whl", hash = "sha256:ce2f6c1571538cbdfa0143b04e16b208ecb0e9cb4148e528af8a640ed51cc8aa", size = 19539, upload-time = "2024-10-08T10:39:32.955Z" }, +] + +[[package]] +name = "aiofile" +version = "3.11.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.15' and sys_platform == 'win32'", + "python_full_version == '3.14.*' and sys_platform == 'win32'", + "python_full_version >= '3.15' and sys_platform == 'emscripten'", + "python_full_version == '3.14.*' and sys_platform == 'emscripten'", + "python_full_version >= '3.15' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.14.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", +] +dependencies = [ + { name = "caio", marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/48/41/2fea7e193e061ce54eacc3b7bc0e6a99e4fcff43c78cf0a76dd781ed8334/aiofile-3.11.1.tar.gz", hash = "sha256:1f91912c6643d2a4e49ca4ae3514f0bf3867ce948a36d99a6411b8f4755f4cf9", size = 19342, upload-time = "2026-05-16T08:18:33.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/cd/0d76dfc5de72bde52f55f53e925c7d152d9c7906634ec1e0cbc7e8d4ad93/aiofile-3.11.1-py3-none-any.whl", hash = "sha256:ce77d14ac07f77bc2b757834a5c129321f3f705c474593deed5ab209079a52c9", size = 20446, upload-time = "2026-05-16T08:18:32.051Z" }, +] + +[[package]] +name = "aiohappyeyeballs" +version = "2.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/f4/eec0465c2f67b2664688d0240b3212d5196fd89e741df67ddb81f8d35658/aiohappyeyeballs-2.7.1.tar.gz", hash = "sha256:065665c041c42a5938ed220bdcd7230f22527fbec085e1853d2402c8a3615d9d", size = 24757, upload-time = "2026-07-01T17:11:55.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/43/1947f06babed6b3f1d7f38b0c767f52df66bfb2bc10b468c4a7de9eceff2/aiohappyeyeballs-2.7.1-py3-none-any.whl", hash = "sha256:9243213661e29250eb41368e5daa826fc017156c3b8a11440826b2e3ed376472", size = 15038, upload-time = "2026-07-01T17:11:54.055Z" }, +] + +[[package]] +name = "aiohttp" +version = "3.13.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohappyeyeballs" }, + { name = "aiosignal" }, + { name = "async-timeout", marker = "python_full_version < '3.11'" }, + { name = "attrs" }, + { name = "frozenlist" }, + { name = "multidict" }, + { name = "propcache" }, + { name = "yarl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/77/9a/152096d4808df8e4268befa55fba462f440f14beab85e8ad9bf990516918/aiohttp-3.13.5.tar.gz", hash = "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1", size = 7858271, upload-time = "2026-03-31T22:01:03.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/85/cebc47ee74d8b408749073a1a46c6fcba13d170dc8af7e61996c6c9394ac/aiohttp-3.13.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b", size = 750547, upload-time = "2026-03-31T21:56:30.024Z" }, + { url = "https://files.pythonhosted.org/packages/05/98/afd308e35b9d3d8c9ec54c0918f1d722c86dc17ddfec272fcdbcce5a3124/aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5", size = 503535, upload-time = "2026-03-31T21:56:31.935Z" }, + { url = "https://files.pythonhosted.org/packages/6f/4d/926c183e06b09d5270a309eb50fbde7b09782bfd305dec1e800f329834fb/aiohttp-3.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670", size = 497830, upload-time = "2026-03-31T21:56:33.654Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d6/f47d1c690f115a5c2a5e8938cce4a232a5be9aac5c5fb2647efcbbbda333/aiohttp-3.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274", size = 1682474, upload-time = "2026-03-31T21:56:35.513Z" }, + { url = "https://files.pythonhosted.org/packages/01/44/056fd37b1bb52eac760303e5196acc74d9d546631b035704ae5927f7b4ac/aiohttp-3.13.5-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a", size = 1655259, upload-time = "2026-03-31T21:56:37.843Z" }, + { url = "https://files.pythonhosted.org/packages/91/9f/78eb1a20c1c28ae02f6a3c0f4d7b0dcc66abce5290cadd53d78ce3084175/aiohttp-3.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d", size = 1736204, upload-time = "2026-03-31T21:56:39.822Z" }, + { url = "https://files.pythonhosted.org/packages/de/6c/d20d7de23f0b52b8c1d9e2033b2db1ac4dacbb470bb74c56de0f5f86bb4f/aiohttp-3.13.5-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796", size = 1826198, upload-time = "2026-03-31T21:56:41.378Z" }, + { url = "https://files.pythonhosted.org/packages/2f/86/a6f3ff1fd795f49545a7c74b2c92f62729135d73e7e4055bf74da5a26c82/aiohttp-3.13.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95", size = 1681329, upload-time = "2026-03-31T21:56:43.374Z" }, + { url = "https://files.pythonhosted.org/packages/fb/68/84cd3dab6b7b4f3e6fe9459a961acb142aaab846417f6e8905110d7027e5/aiohttp-3.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5", size = 1560023, upload-time = "2026-03-31T21:56:45.031Z" }, + { url = "https://files.pythonhosted.org/packages/41/2c/db61b64b0249e30f954a65ab4cb4970ced57544b1de2e3c98ee5dc24165f/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a", size = 1652372, upload-time = "2026-03-31T21:56:47.075Z" }, + { url = "https://files.pythonhosted.org/packages/25/6f/e96988a6c982d047810c772e28c43c64c300c943b0ed5c1c0c4ce1e1027c/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73", size = 1662031, upload-time = "2026-03-31T21:56:48.835Z" }, + { url = "https://files.pythonhosted.org/packages/b7/26/a56feace81f3d347b4052403a9d03754a0ab23f7940780dada0849a38c92/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297", size = 1708118, upload-time = "2026-03-31T21:56:50.833Z" }, + { url = "https://files.pythonhosted.org/packages/78/6e/b6173a8ff03d01d5e1a694bc06764b5dad1df2d4ed8f0ceec12bb3277936/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074", size = 1548667, upload-time = "2026-03-31T21:56:52.81Z" }, + { url = "https://files.pythonhosted.org/packages/16/13/13296ffe2c132d888b3fe2c195c8b9c0c24c89c3fa5cc2c44464dc23b22e/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e", size = 1724490, upload-time = "2026-03-31T21:56:54.541Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/1f1c287f4a79782ef36e5a6e62954c85343bc30470d862d30bd5f26c9fa2/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7", size = 1667109, upload-time = "2026-03-31T21:56:56.21Z" }, + { url = "https://files.pythonhosted.org/packages/ef/42/8461a2aaf60a8f4ea4549a4056be36b904b0eb03d97ca9a8a2604681a500/aiohttp-3.13.5-cp310-cp310-win32.whl", hash = "sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9", size = 439478, upload-time = "2026-03-31T21:56:58.292Z" }, + { url = "https://files.pythonhosted.org/packages/e5/71/06956304cb5ee439dfe8d86e1b2e70088bd88ed1ced1f42fb29e5d855f0e/aiohttp-3.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76", size = 462047, upload-time = "2026-03-31T21:57:00.257Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f5/a20c4ac64aeaef1679e25c9983573618ff765d7aa829fa2b84ae7573169e/aiohttp-3.13.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6", size = 757513, upload-time = "2026-03-31T21:57:02.146Z" }, + { url = "https://files.pythonhosted.org/packages/75/0a/39fa6c6b179b53fcb3e4b3d2b6d6cad0180854eda17060c7218540102bef/aiohttp-3.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d", size = 506748, upload-time = "2026-03-31T21:57:04.275Z" }, + { url = "https://files.pythonhosted.org/packages/87/ec/e38ce072e724fd7add6243613f8d1810da084f54175353d25ccf9f9c7e5a/aiohttp-3.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c", size = 501673, upload-time = "2026-03-31T21:57:06.208Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ba/3bc7525d7e2beaa11b309a70d48b0d3cfc3c2089ec6a7d0820d59c657053/aiohttp-3.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb", size = 1763757, upload-time = "2026-03-31T21:57:07.882Z" }, + { url = "https://files.pythonhosted.org/packages/5e/ab/e87744cf18f1bd78263aba24924d4953b41086bd3a31d22452378e9028a0/aiohttp-3.13.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6", size = 1720152, upload-time = "2026-03-31T21:57:09.946Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f3/ed17a6f2d742af17b50bae2d152315ed1b164b07a5fd5cc1754d99e4dfa5/aiohttp-3.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13", size = 1818010, upload-time = "2026-03-31T21:57:12.157Z" }, + { url = "https://files.pythonhosted.org/packages/53/06/ecbc63dc937192e2a5cb46df4d3edb21deb8225535818802f210a6ea5816/aiohttp-3.13.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174", size = 1907251, upload-time = "2026-03-31T21:57:14.023Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a5/0521aa32c1ddf3aa1e71dcc466be0b7db2771907a13f18cddaa45967d97b/aiohttp-3.13.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc", size = 1759969, upload-time = "2026-03-31T21:57:16.146Z" }, + { url = "https://files.pythonhosted.org/packages/f6/78/a38f8c9105199dd3b9706745865a8a59d0041b6be0ca0cc4b2ccf1bab374/aiohttp-3.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6", size = 1616871, upload-time = "2026-03-31T21:57:17.856Z" }, + { url = "https://files.pythonhosted.org/packages/6f/41/27392a61ead8ab38072105c71aa44ff891e71653fe53d576a7067da2b4e8/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49", size = 1739844, upload-time = "2026-03-31T21:57:19.679Z" }, + { url = "https://files.pythonhosted.org/packages/6e/55/5564e7ae26d94f3214250009a0b1c65a0c6af4bf88924ccb6fdab901de28/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8", size = 1731969, upload-time = "2026-03-31T21:57:22.006Z" }, + { url = "https://files.pythonhosted.org/packages/6d/c5/705a3929149865fc941bcbdd1047b238e4a72bcb215a9b16b9d7a2e8d992/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d", size = 1795193, upload-time = "2026-03-31T21:57:24.256Z" }, + { url = "https://files.pythonhosted.org/packages/a6/19/edabed62f718d02cff7231ca0db4ef1c72504235bc467f7b67adb1679f48/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c", size = 1606477, upload-time = "2026-03-31T21:57:26.364Z" }, + { url = "https://files.pythonhosted.org/packages/de/fc/76f80ef008675637d88d0b21584596dc27410a990b0918cb1e5776545b5b/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac", size = 1813198, upload-time = "2026-03-31T21:57:28.316Z" }, + { url = "https://files.pythonhosted.org/packages/e5/67/5b3ac26b80adb20ea541c487f73730dc8fa107d632c998f25bbbab98fcda/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3", size = 1752321, upload-time = "2026-03-31T21:57:30.549Z" }, + { url = "https://files.pythonhosted.org/packages/88/06/e4a2e49255ea23fa4feeb5ab092d90240d927c15e47b5b5c48dff5a9ce29/aiohttp-3.13.5-cp311-cp311-win32.whl", hash = "sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06", size = 439069, upload-time = "2026-03-31T21:57:32.388Z" }, + { url = "https://files.pythonhosted.org/packages/c0/43/8c7163a596dab4f8be12c190cf467a1e07e4734cf90eebb39f7f5d53fc6a/aiohttp-3.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8", size = 462859, upload-time = "2026-03-31T21:57:34.455Z" }, + { url = "https://files.pythonhosted.org/packages/be/6f/353954c29e7dcce7cf00280a02c75f30e133c00793c7a2ed3776d7b2f426/aiohttp-3.13.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9", size = 748876, upload-time = "2026-03-31T21:57:36.319Z" }, + { url = "https://files.pythonhosted.org/packages/f5/1b/428a7c64687b3b2e9cd293186695affc0e1e54a445d0361743b231f11066/aiohttp-3.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416", size = 499557, upload-time = "2026-03-31T21:57:38.236Z" }, + { url = "https://files.pythonhosted.org/packages/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2", size = 500258, upload-time = "2026-03-31T21:57:39.923Z" }, + { url = "https://files.pythonhosted.org/packages/67/84/c9ecc5828cb0b3695856c07c0a6817a99d51e2473400f705275a2b3d9239/aiohttp-3.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4", size = 1749199, upload-time = "2026-03-31T21:57:41.938Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d3/3c6d610e66b495657622edb6ae7c7fd31b2e9086b4ec50b47897ad6042a9/aiohttp-3.13.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9", size = 1721013, upload-time = "2026-03-31T21:57:43.904Z" }, + { url = "https://files.pythonhosted.org/packages/49/a0/24409c12217456df0bae7babe3b014e460b0b38a8e60753d6cb339f6556d/aiohttp-3.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5", size = 1781501, upload-time = "2026-03-31T21:57:46.285Z" }, + { url = "https://files.pythonhosted.org/packages/98/9d/b65ec649adc5bccc008b0957a9a9c691070aeac4e41cea18559fef49958b/aiohttp-3.13.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e", size = 1878981, upload-time = "2026-03-31T21:57:48.734Z" }, + { url = "https://files.pythonhosted.org/packages/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1", size = 1767934, upload-time = "2026-03-31T21:57:51.171Z" }, + { url = "https://files.pythonhosted.org/packages/31/04/d3f8211f273356f158e3464e9e45484d3fb8c4ce5eb2f6fe9405c3273983/aiohttp-3.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286", size = 1566671, upload-time = "2026-03-31T21:57:53.326Z" }, + { url = "https://files.pythonhosted.org/packages/41/db/073e4ebe00b78e2dfcacff734291651729a62953b48933d765dc513bf798/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9", size = 1705219, upload-time = "2026-03-31T21:57:55.385Z" }, + { url = "https://files.pythonhosted.org/packages/48/45/7dfba71a2f9fd97b15c95c06819de7eb38113d2cdb6319669195a7d64270/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88", size = 1743049, upload-time = "2026-03-31T21:57:57.341Z" }, + { url = "https://files.pythonhosted.org/packages/18/71/901db0061e0f717d226386a7f471bb59b19566f2cae5f0d93874b017271f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3", size = 1749557, upload-time = "2026-03-31T21:57:59.626Z" }, + { url = "https://files.pythonhosted.org/packages/08/d5/41eebd16066e59cd43728fe74bce953d7402f2b4ddfdfef2c0e9f17ca274/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b", size = 1558931, upload-time = "2026-03-31T21:58:01.972Z" }, + { url = "https://files.pythonhosted.org/packages/30/e6/4a799798bf05740e66c3a1161079bda7a3dd8e22ca392481d7a7f9af82a6/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe", size = 1774125, upload-time = "2026-03-31T21:58:04.007Z" }, + { url = "https://files.pythonhosted.org/packages/84/63/7749337c90f92bc2cb18f9560d67aa6258c7060d1397d21529b8004fcf6f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14", size = 1732427, upload-time = "2026-03-31T21:58:06.337Z" }, + { url = "https://files.pythonhosted.org/packages/98/de/cf2f44ff98d307e72fb97d5f5bbae3bfcb442f0ea9790c0bf5c5c2331404/aiohttp-3.13.5-cp312-cp312-win32.whl", hash = "sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3", size = 433534, upload-time = "2026-03-31T21:58:08.712Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1", size = 460446, upload-time = "2026-03-31T21:58:10.945Z" }, + { url = "https://files.pythonhosted.org/packages/78/e9/d76bf503005709e390122d34e15256b88f7008e246c4bdbe915cd4f1adce/aiohttp-3.13.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61", size = 742930, upload-time = "2026-03-31T21:58:13.155Z" }, + { url = "https://files.pythonhosted.org/packages/57/00/4b7b70223deaebd9bb85984d01a764b0d7bd6526fcdc73cca83bcbe7243e/aiohttp-3.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832", size = 496927, upload-time = "2026-03-31T21:58:15.073Z" }, + { url = "https://files.pythonhosted.org/packages/9c/f5/0fb20fb49f8efdcdce6cd8127604ad2c503e754a8f139f5e02b01626523f/aiohttp-3.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9", size = 497141, upload-time = "2026-03-31T21:58:17.009Z" }, + { url = "https://files.pythonhosted.org/packages/3b/86/b7c870053e36a94e8951b803cb5b909bfbc9b90ca941527f5fcafbf6b0fa/aiohttp-3.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090", size = 1732476, upload-time = "2026-03-31T21:58:18.925Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e5/4e161f84f98d80c03a238671b4136e6530453d65262867d989bbe78244d0/aiohttp-3.13.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b", size = 1706507, upload-time = "2026-03-31T21:58:21.094Z" }, + { url = "https://files.pythonhosted.org/packages/d4/56/ea11a9f01518bd5a2a2fcee869d248c4b8a0cfa0bb13401574fa31adf4d4/aiohttp-3.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a", size = 1773465, upload-time = "2026-03-31T21:58:23.159Z" }, + { url = "https://files.pythonhosted.org/packages/eb/40/333ca27fb74b0383f17c90570c748f7582501507307350a79d9f9f3c6eb1/aiohttp-3.13.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8", size = 1873523, upload-time = "2026-03-31T21:58:25.59Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d2/e2f77eef1acb7111405433c707dc735e63f67a56e176e72e9e7a2cd3f493/aiohttp-3.13.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665", size = 1754113, upload-time = "2026-03-31T21:58:27.624Z" }, + { url = "https://files.pythonhosted.org/packages/fb/56/3f653d7f53c89669301ec9e42c95233e2a0c0a6dd051269e6e678db4fdb0/aiohttp-3.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540", size = 1562351, upload-time = "2026-03-31T21:58:29.918Z" }, + { url = "https://files.pythonhosted.org/packages/ec/a6/9b3e91eb8ae791cce4ee736da02211c85c6f835f1bdfac0594a8a3b7018c/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb", size = 1693205, upload-time = "2026-03-31T21:58:32.214Z" }, + { url = "https://files.pythonhosted.org/packages/98/fc/bfb437a99a2fcebd6b6eaec609571954de2ed424f01c352f4b5504371dd3/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46", size = 1730618, upload-time = "2026-03-31T21:58:34.728Z" }, + { url = "https://files.pythonhosted.org/packages/e4/b6/c8534862126191a034f68153194c389addc285a0f1347d85096d349bbc15/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8", size = 1745185, upload-time = "2026-03-31T21:58:36.909Z" }, + { url = "https://files.pythonhosted.org/packages/0b/93/4ca8ee2ef5236e2707e0fd5fecb10ce214aee1ff4ab307af9c558bda3b37/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d", size = 1557311, upload-time = "2026-03-31T21:58:39.38Z" }, + { url = "https://files.pythonhosted.org/packages/57/ae/76177b15f18c5f5d094f19901d284025db28eccc5ae374d1d254181d33f4/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6", size = 1773147, upload-time = "2026-03-31T21:58:41.476Z" }, + { url = "https://files.pythonhosted.org/packages/01/a4/62f05a0a98d88af59d93b7fcac564e5f18f513cb7471696ac286db970d6a/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c", size = 1730356, upload-time = "2026-03-31T21:58:44.049Z" }, + { url = "https://files.pythonhosted.org/packages/e4/85/fc8601f59dfa8c9523808281f2da571f8b4699685f9809a228adcc90838d/aiohttp-3.13.5-cp313-cp313-win32.whl", hash = "sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc", size = 432637, upload-time = "2026-03-31T21:58:46.167Z" }, + { url = "https://files.pythonhosted.org/packages/c0/1b/ac685a8882896acf0f6b31d689e3792199cfe7aba37969fa91da63a7fa27/aiohttp-3.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83", size = 458896, upload-time = "2026-03-31T21:58:48.119Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ce/46572759afc859e867a5bc8ec3487315869013f59281ce61764f76d879de/aiohttp-3.13.5-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c", size = 745721, upload-time = "2026-03-31T21:58:50.229Z" }, + { url = "https://files.pythonhosted.org/packages/13/fe/8a2efd7626dbe6049b2ef8ace18ffda8a4dfcbe1bcff3ac30c0c7575c20b/aiohttp-3.13.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be", size = 497663, upload-time = "2026-03-31T21:58:52.232Z" }, + { url = "https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25", size = 499094, upload-time = "2026-03-31T21:58:54.566Z" }, + { url = "https://files.pythonhosted.org/packages/0a/33/a8362cb15cf16a3af7e86ed11962d5cd7d59b449202dc576cdc731310bde/aiohttp-3.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56", size = 1726701, upload-time = "2026-03-31T21:58:56.864Z" }, + { url = "https://files.pythonhosted.org/packages/45/0c/c091ac5c3a17114bd76cbf85d674650969ddf93387876cf67f754204bd77/aiohttp-3.13.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2", size = 1683360, upload-time = "2026-03-31T21:58:59.072Z" }, + { url = "https://files.pythonhosted.org/packages/23/73/bcee1c2b79bc275e964d1446c55c54441a461938e70267c86afaae6fba27/aiohttp-3.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a", size = 1773023, upload-time = "2026-03-31T21:59:01.776Z" }, + { url = "https://files.pythonhosted.org/packages/c7/ef/720e639df03004fee2d869f771799d8c23046dec47d5b81e396c7cda583a/aiohttp-3.13.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be", size = 1853795, upload-time = "2026-03-31T21:59:04.568Z" }, + { url = "https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b", size = 1730405, upload-time = "2026-03-31T21:59:07.221Z" }, + { url = "https://files.pythonhosted.org/packages/ce/75/ee1fd286ca7dc599d824b5651dad7b3be7ff8d9a7e7b3fe9820d9180f7db/aiohttp-3.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94", size = 1558082, upload-time = "2026-03-31T21:59:09.484Z" }, + { url = "https://files.pythonhosted.org/packages/c3/20/1e9e6650dfc436340116b7aa89ff8cb2bbdf0abc11dfaceaad8f74273a10/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d", size = 1692346, upload-time = "2026-03-31T21:59:12.068Z" }, + { url = "https://files.pythonhosted.org/packages/d8/40/8ebc6658d48ea630ac7903912fe0dd4e262f0e16825aa4c833c56c9f1f56/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7", size = 1698891, upload-time = "2026-03-31T21:59:14.552Z" }, + { url = "https://files.pythonhosted.org/packages/d8/78/ea0ae5ec8ba7a5c10bdd6e318f1ba5e76fcde17db8275188772afc7917a4/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772", size = 1742113, upload-time = "2026-03-31T21:59:17.068Z" }, + { url = "https://files.pythonhosted.org/packages/8a/66/9d308ed71e3f2491be1acb8769d96c6f0c47d92099f3bc9119cada27b357/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5", size = 1553088, upload-time = "2026-03-31T21:59:19.541Z" }, + { url = "https://files.pythonhosted.org/packages/da/a6/6cc25ed8dfc6e00c90f5c6d126a98e2cf28957ad06fa1036bd34b6f24a2c/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1", size = 1757976, upload-time = "2026-03-31T21:59:22.311Z" }, + { url = "https://files.pythonhosted.org/packages/c1/2b/cce5b0ffe0de99c83e5e36d8f828e4161e415660a9f3e58339d07cce3006/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b", size = 1712444, upload-time = "2026-03-31T21:59:24.635Z" }, + { url = "https://files.pythonhosted.org/packages/6c/cf/9e1795b4160c58d29421eafd1a69c6ce351e2f7c8d3c6b7e4ca44aea1a5b/aiohttp-3.13.5-cp314-cp314-win32.whl", hash = "sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3", size = 438128, upload-time = "2026-03-31T21:59:27.291Z" }, + { url = "https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162", size = 464029, upload-time = "2026-03-31T21:59:29.429Z" }, + { url = "https://files.pythonhosted.org/packages/79/11/c27d9332ee20d68dd164dc12a6ecdef2e2e35ecc97ed6cf0d2442844624b/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a", size = 778758, upload-time = "2026-03-31T21:59:31.547Z" }, + { url = "https://files.pythonhosted.org/packages/04/fb/377aead2e0a3ba5f09b7624f702a964bdf4f08b5b6728a9799830c80041e/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254", size = 512883, upload-time = "2026-03-31T21:59:34.098Z" }, + { url = "https://files.pythonhosted.org/packages/bb/a6/aa109a33671f7a5d3bd78b46da9d852797c5e665bfda7d6b373f56bff2ec/aiohttp-3.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36", size = 516668, upload-time = "2026-03-31T21:59:36.497Z" }, + { url = "https://files.pythonhosted.org/packages/79/b3/ca078f9f2fa9563c36fb8ef89053ea2bb146d6f792c5104574d49d8acb63/aiohttp-3.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f", size = 1883461, upload-time = "2026-03-31T21:59:38.723Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e3/a7ad633ca1ca497b852233a3cce6906a56c3225fb6d9217b5e5e60b7419d/aiohttp-3.13.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800", size = 1747661, upload-time = "2026-03-31T21:59:41.187Z" }, + { url = "https://files.pythonhosted.org/packages/33/b9/cd6fe579bed34a906d3d783fe60f2fa297ef55b27bb4538438ee49d4dc41/aiohttp-3.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf", size = 1863800, upload-time = "2026-03-31T21:59:43.84Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3f/2c1e2f5144cefa889c8afd5cf431994c32f3b29da9961698ff4e3811b79a/aiohttp-3.13.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b", size = 1958382, upload-time = "2026-03-31T21:59:46.187Z" }, + { url = "https://files.pythonhosted.org/packages/66/1d/f31ec3f1013723b3babe3609e7f119c2c2fb6ef33da90061a705ef3e1bc8/aiohttp-3.13.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a", size = 1803724, upload-time = "2026-03-31T21:59:48.656Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b4/57712dfc6f1542f067daa81eb61da282fab3e6f1966fca25db06c4fc62d5/aiohttp-3.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8", size = 1640027, upload-time = "2026-03-31T21:59:51.284Z" }, + { url = "https://files.pythonhosted.org/packages/25/3c/734c878fb43ec083d8e31bf029daae1beafeae582d1b35da234739e82ee7/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be", size = 1806644, upload-time = "2026-03-31T21:59:53.753Z" }, + { url = "https://files.pythonhosted.org/packages/20/a5/f671e5cbec1c21d044ff3078223f949748f3a7f86b14e34a365d74a5d21f/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b", size = 1791630, upload-time = "2026-03-31T21:59:56.239Z" }, + { url = "https://files.pythonhosted.org/packages/0b/63/fb8d0ad63a0b8a99be97deac8c04dacf0785721c158bdf23d679a87aa99e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6", size = 1809403, upload-time = "2026-03-31T21:59:59.103Z" }, + { url = "https://files.pythonhosted.org/packages/59/0c/bfed7f30662fcf12206481c2aac57dedee43fe1c49275e85b3a1e1742294/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037", size = 1634924, upload-time = "2026-03-31T22:00:02.116Z" }, + { url = "https://files.pythonhosted.org/packages/17/d6/fd518d668a09fd5a3319ae5e984d4d80b9a4b3df4e21c52f02251ef5a32e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500", size = 1836119, upload-time = "2026-03-31T22:00:04.756Z" }, + { url = "https://files.pythonhosted.org/packages/78/b7/15fb7a9d52e112a25b621c67b69c167805cb1f2ab8f1708a5c490d1b52fe/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9", size = 1772072, upload-time = "2026-03-31T22:00:07.494Z" }, + { url = "https://files.pythonhosted.org/packages/7e/df/57ba7f0c4a553fc2bd8b6321df236870ec6fd64a2a473a8a13d4f733214e/aiohttp-3.13.5-cp314-cp314t-win32.whl", hash = "sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8", size = 471819, upload-time = "2026-03-31T22:00:10.277Z" }, + { url = "https://files.pythonhosted.org/packages/62/29/2f8418269e46454a26171bfdd6a055d74febf32234e474930f2f60a17145/aiohttp-3.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9", size = 505441, upload-time = "2026-03-31T22:00:12.791Z" }, +] + +[[package]] +name = "aiosignal" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "frozenlist" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, +] + +[[package]] +name = "annotated-doc" +version = "0.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "anyio" +version = "4.14.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "idna" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3b/72/5562aabb8dd7181e8e860622a38bea08d17842b99ecd4c91f84ac95251b0/anyio-4.14.1.tar.gz", hash = "sha256:8d648a3544c1a700e3ff78615cd679e4c5c3f149904287e73687b2596963629e", size = 254831, upload-time = "2026-06-24T20:56:06.017Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/7b/90df4a0a816d98d6ea26f559d87836d494a2cf1fcf063be67df50a7bcc30/anyio-4.14.1-py3-none-any.whl", hash = "sha256:4e5533c5b8ff0a24f5d7a176cbe6877129cd183893f66b537f8f227d10527d72", size = 124875, upload-time = "2026-06-24T20:56:04.413Z" }, +] + +[[package]] +name = "appnope" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170, upload-time = "2024-02-06T09:43:11.258Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" }, +] + +[[package]] +name = "astroid" +version = "3.3.11" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/18/74/dfb75f9ccd592bbedb175d4a32fc643cf569d7c218508bfbd6ea7ef9c091/astroid-3.3.11.tar.gz", hash = "sha256:1e5a5011af2920c7c67a53f65d536d65bfa7116feeaf2354d8b94f29573bb0ce", size = 400439, upload-time = "2025-07-13T18:04:23.177Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/0f/3b8fdc946b4d9cc8cc1e8af42c4e409468c84441b933d037e101b3d72d86/astroid-3.3.11-py3-none-any.whl", hash = "sha256:54c760ae8322ece1abd213057c4b5bba7c49818853fc901ef09719a60dbf9dec", size = 275612, upload-time = "2025-07-13T18:04:21.07Z" }, +] + +[[package]] +name = "asttokens" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, +] + +[[package]] +name = "async-lru" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e8/1f/989ecfef8e64109a489fff357450cb73fa73a865a92bd8c272170a6922c2/async_lru-2.3.0.tar.gz", hash = "sha256:89bdb258a0140d7313cf8f4031d816a042202faa61d0ab310a0a538baa1c24b6", size = 16332, upload-time = "2026-03-19T01:04:32.413Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl", hash = "sha256:eea27b01841909316f2cc739807acea1c623df2be8c5cfad7583286397bb8315", size = 8403, upload-time = "2026-03-19T01:04:30.883Z" }, +] + +[[package]] +name = "async-timeout" +version = "5.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a5/ae/136395dfbfe00dfc94da3f3e136d0b13f394cba8f4841120e34226265780/async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3", size = 9274, upload-time = "2024-11-06T16:41:39.6Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c", size = 6233, upload-time = "2024-11-06T16:41:37.9Z" }, +] + +[[package]] +name = "attrs" +version = "26.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, +] + +[[package]] +name = "authlib" +version = "1.7.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, + { name = "joserfc" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/36/98/7d93f30d029643c0275dbc0bd6d5a6f670661ee6c9a94d93af7ab4887600/authlib-1.7.2.tar.gz", hash = "sha256:2cea25fefcd4e7173bdf1372c0afc265c8034b23a8cd5dcb6a9164b826c64231", size = 176511, upload-time = "2026-05-06T08:10:23.116Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/95/adcb68e20c34162e9135f370d6e31737719c2b6f94bc953fe7ed1f10fe21/authlib-1.7.2-py2.py3-none-any.whl", hash = "sha256:3e1faedc9d87e7d56a164eca3ccb6ace0d61b94abe83e92242f8dc8bba9b4a9f", size = 259548, upload-time = "2026-05-06T08:10:21.436Z" }, +] + +[[package]] +name = "backports-asyncio-runner" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8e/ff/70dca7d7cb1cbc0edb2c6cc0c38b65cba36cccc491eca64cabd5fe7f8670/backports_asyncio_runner-1.2.0.tar.gz", hash = "sha256:a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162", size = 69893, upload-time = "2025-07-02T02:27:15.685Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/59/76ab57e3fe74484f48a53f8e337171b4a2349e506eabe136d7e01d059086/backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5", size = 12313, upload-time = "2025-07-02T02:27:14.263Z" }, +] + +[[package]] +name = "backports-tarfile" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz", hash = "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991", size = 86406, upload-time = "2024-05-28T17:01:54.731Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", size = 30181, upload-time = "2024-05-28T17:01:53.112Z" }, +] + +[[package]] +name = "beartype" +version = "0.22.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/94/1009e248bbfbab11397abca7193bea6626806be9a327d399810d523a07cb/beartype-0.22.9.tar.gz", hash = "sha256:8f82b54aa723a2848a56008d18875f91c1db02c32ef6a62319a002e3e25a975f", size = 1608866, upload-time = "2025-12-13T06:50:30.72Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/cc/18245721fa7747065ab478316c7fea7c74777d07f37ae60db2e84f8172e8/beartype-0.22.9-py3-none-any.whl", hash = "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2", size = 1333658, upload-time = "2025-12-13T06:50:28.266Z" }, +] + +[[package]] +name = "black" +version = "26.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + { name = "pytokens" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/37/5628dd55bf2b34257fc7603f0fe97c40e3aaf24265f416a9c85c95ca1436/black-26.5.1.tar.gz", hash = "sha256:dd321f668053961824bcc1be1cc1df748b2d7e4fa28086b08331e577b0100a73", size = 679439, upload-time = "2026-05-18T16:53:36.107Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/84/b3f55026206a9e8820a91503308075ca48eadc515e436731ca01dbe043b3/black-26.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9942db8888e06943c5dde66ca0037dcff82a2a4ec1ad0ada9e0d2ee9d9823893", size = 1987719, upload-time = "2026-05-18T17:05:02.757Z" }, + { url = "https://files.pythonhosted.org/packages/c6/34/7db312c5e5783d6e76cffd9d5ac8972a32badae4c6e3288dac0eed8d3bed/black-26.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:89c93167a74d3a75dfaa38a5c7cca015537d5820dd7f17d63267d674a61cae90", size = 1810083, upload-time = "2026-05-18T17:05:04.302Z" }, + { url = "https://files.pythonhosted.org/packages/33/e2/e0101e73c2c8727634e2efcb35e2b34bd23ad70dfa673789f5773a591b21/black-26.5.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22f2cd76d069cc54c71f10360744ba8983fbb616903b4304a85b734915c8e1b4", size = 1860633, upload-time = "2026-05-18T17:05:06.391Z" }, + { url = "https://files.pythonhosted.org/packages/b0/4c/e15c0c5b23cf3651035fe5addcce90e283af3548a3f91bb03d81b83106ab/black-26.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:87ed5c6f450580a2f6790bc7cbfb016dfc73bc750249762268a3695361315eef", size = 1477886, upload-time = "2026-05-18T17:05:07.96Z" }, + { url = "https://files.pythonhosted.org/packages/9f/3f/59d43ade98d2ce5c8dc34a4e46cbecd177e6d55d7d4092969c6003ccc655/black-26.5.1-cp310-cp310-win_arm64.whl", hash = "sha256:58b4bd92cf88aacf83d88479c8f9caee044b1ec55f2451a337354a7ea2590a22", size = 1277111, upload-time = "2026-05-18T17:05:09.473Z" }, + { url = "https://files.pythonhosted.org/packages/4b/96/3c3e09f09f44a37aac36b178a279cd19aa7001bd796187a7b162a294c81f/black-26.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:96ae2c733b2aabdd9986e2c5df628ff3473676cd1c5faded1ff496cf6d74083c", size = 1970639, upload-time = "2026-05-18T17:05:11.461Z" }, + { url = "https://files.pythonhosted.org/packages/83/ea/5ad117b9ee3ecd933c712bcbae610006e5b7cc9f41c526cd7ed3b6c4124c/black-26.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0e48b87e03bf109288e55cfceadcfa15ff5470aca2851a851950ed2926f450d7", size = 1792130, upload-time = "2026-05-18T17:05:12.983Z" }, + { url = "https://files.pythonhosted.org/packages/06/3a/7c448bc623fcdfa96672531beb5a616ea5e64f6975955254d7731ffb0ad9/black-26.5.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5119fa92ae61f786e8c3662fd60aece1d0a2dd5cca5d0c79417a95e7a4272a59", size = 1846134, upload-time = "2026-05-18T17:05:14.506Z" }, + { url = "https://files.pythonhosted.org/packages/a1/5b/0b39b3a5917f0657ac014ad2edb58c139553a478adfe7f817abf1622ff6e/black-26.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:30d3c14661f2792e9142cce3eeeb1cbc175b3eb5f733be0c8eeb99651e52b0c3", size = 1478883, upload-time = "2026-05-18T17:05:16.542Z" }, + { url = "https://files.pythonhosted.org/packages/4c/48/dc222692e0f95030db1bbfb6c857e76858bad09058221ea7aae815255327/black-26.5.1-cp311-cp311-win_arm64.whl", hash = "sha256:1ef92b76f7733f282fd096ea406200b5a286c42947412b0eaff3a74e3616cefe", size = 1277776, upload-time = "2026-05-18T17:05:18.029Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/7744b906703228264ef73bdd534df88ec1ef3de45c4e78f6d31b9e32d0c9/black-26.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4ad6fa01f941920f54f2bbb35f3df7673428a0ef98a0b0840c2eaef3b110efa8", size = 2012518, upload-time = "2026-05-18T17:05:20.108Z" }, + { url = "https://files.pythonhosted.org/packages/b7/c0/c5a3b1636dfd09c42534f2b3cf33506814f6d3e066fb0879ffa16c1ae860/black-26.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3915f256e75a2d7cf88d8953d37f780455dc586cc72dee059c528fe77f581217", size = 1816016, upload-time = "2026-05-18T17:05:21.84Z" }, + { url = "https://files.pythonhosted.org/packages/1f/0e/36044316b65ca471d3bb6d3703fd06fb50c6b727c3562f6a5a3153634f88/black-26.5.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d98d4137277c75dfb898ec8d846c4fd68ba1e9cf77f95e2865c203dc18f4c3d", size = 1884150, upload-time = "2026-05-18T17:05:23.546Z" }, + { url = "https://files.pythonhosted.org/packages/b3/33/dafc5808c2af43672912111d7c3354af1615f7e2be3bed7a878461abbe4d/black-26.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:a1dca32d9f1784af512a13410ec204c6f7f0aa9797a111c42e1c03449821c264", size = 1486825, upload-time = "2026-05-18T17:05:25.004Z" }, + { url = "https://files.pythonhosted.org/packages/82/14/b965ee6ad2a311f28bdbf692def3ee9848d2ae289dab28b27657fcee3e78/black-26.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:1037d5ac7b7b310b2632ad867ec8d0e4c4819dcdb0b820f63135da746a24e418", size = 1288646, upload-time = "2026-05-18T17:05:26.477Z" }, + { url = "https://files.pythonhosted.org/packages/3f/5c/c384363980e11e25ca6b93205949bb331fbf35f4e0dbec376dfa6326cec8/black-26.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2b36cf2ddf5566e205f6535f782a62194a184d33e175b64ae8c40b1737522be3", size = 2009020, upload-time = "2026-05-18T17:05:28.132Z" }, + { url = "https://files.pythonhosted.org/packages/0b/df/9f31c5e0babbfed77d505fc5d120beb98b21b33feaeded3924ea941fe360/black-26.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f7ea64ebfa01b50f693508fc39f875e264446d3b097088f84f203b9d09618a0", size = 1813335, upload-time = "2026-05-18T17:05:31.266Z" }, + { url = "https://files.pythonhosted.org/packages/fb/24/8e7b9a2fa61b0afd82209efe937557d180a1fa055bd7f6161eb9defc3719/black-26.5.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecb3e624844c798144e9bd986954e0adc81d8911a1f30f375e1252fe26e8c294", size = 1881614, upload-time = "2026-05-18T17:05:32.718Z" }, + { url = "https://files.pythonhosted.org/packages/49/ad/b4e0d9365ba8ac34f6bbab62a4b1b2dd5d618fac3fa1b8db968c844201b5/black-26.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:e1a26503279b6b310669fb0b219c39e4820b77e8189fe80f522bb511f247db0a", size = 1488925, upload-time = "2026-05-18T17:05:34.259Z" }, + { url = "https://files.pythonhosted.org/packages/a1/4b/652b859bf5df88a751c30451b09338f7fd26a77d1271c666992f836b7711/black-26.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:5c34b25da232ead53a6f335b76dbea124f4d152ad568b9080d6f944bc2b34b52", size = 1289883, upload-time = "2026-05-18T17:05:36.019Z" }, + { url = "https://files.pythonhosted.org/packages/a6/16/a8da8eb208c51c7f4ce74609a45d0dcc6d8a2141e45e81ee5289d1bb0d59/black-26.5.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e88976690a64b0af98312ca958415849cb42423423c5f2ee74af4b49a97a2168", size = 2004800, upload-time = "2026-05-18T17:05:38.182Z" }, + { url = "https://files.pythonhosted.org/packages/11/8a/a479296a19e383b70a725882a6cf3d786540601ff03cabbaaf1cce864c5a/black-26.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32d5ea7f6c8bdfa6e648326ebca1f02b0764e2a029edc6f8dce2627e19d468c3", size = 1815576, upload-time = "2026-05-18T17:05:40.309Z" }, + { url = "https://files.pythonhosted.org/packages/81/6b/cfaf3d39f25132c156a068f6b805576c9103a84086019507c70e1911ee7d/black-26.5.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ea8d16dc41655aa113cd64665e7219446cd7e4ff2248d7178eaa905190c86b18", size = 1877927, upload-time = "2026-05-18T17:05:42.463Z" }, + { url = "https://files.pythonhosted.org/packages/66/76/302e313964bcff7e28df329d39f84f5270095730d85ff0acc260610a0d82/black-26.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:577f21094ea469ef92ec1adaf2c9441a226d2144d01a5be2fa823cecf6543e50", size = 1511860, upload-time = "2026-05-18T17:05:43.943Z" }, + { url = "https://files.pythonhosted.org/packages/27/4e/a3827e35e0e567f9f9ee59e2a0ab979267dca98718f25547ca8c6733afd4/black-26.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:ed1a20af114c301a0269bf01163d51dbef72737fd65f850001e7cbe7f3c7abae", size = 1316632, upload-time = "2026-05-18T17:05:45.521Z" }, + { url = "https://files.pythonhosted.org/packages/94/51/f975cae76d44274cc2868dc9040ac5d58d464784610234455b4e7b19c6ef/black-26.5.1-py3-none-any.whl", hash = "sha256:4ed7f7da04046d2e488437170797d3b4a4ad83906683bcb7dfc68b673bbce5e2", size = 213693, upload-time = "2026-05-18T16:53:33.964Z" }, +] + +[[package]] +name = "cachebox" +version = "5.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/36/f6/85f176d2518cf1d1be5f981fc2dadf6b131e33fefd721f36b330e3434d6c/cachebox-5.2.3.tar.gz", hash = "sha256:b1f68246685aa739bbbd2734befb1465363a1e1042407c154feadb065f17a099", size = 63686, upload-time = "2026-04-10T12:21:35.028Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/9e/88193fcb7a2a43fe8ed9d9888374d43fa5c7176aa802651e68b28f1aee4a/cachebox-5.2.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c2c89720547271d36e10cad2c7302bbe11f46eb39eead0a2c321c2d371b8f8b6", size = 374393, upload-time = "2026-04-10T12:20:20.424Z" }, + { url = "https://files.pythonhosted.org/packages/98/8d/e0b13d9bfd43f295cce7824ebaac1970f818a7027c16f290de404934cafe/cachebox-5.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e7f33d24e90dc8aa26762e25898c91a1223b66685420a28a3628fa2e006924f5", size = 356318, upload-time = "2026-04-10T12:20:07.518Z" }, + { url = "https://files.pythonhosted.org/packages/bc/02/8ae1b63dbdebb2ebf600523f48b54e9bfb10db5a28551c3432346f49e1dd/cachebox-5.2.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56cb03ec6289a2ac5daf7422d755683324f02d821bfa796087100df2a7ebd5de", size = 395782, upload-time = "2026-04-10T12:18:50.054Z" }, + { url = "https://files.pythonhosted.org/packages/e4/2f/79a8a0057f354581c25a1a00ddabbd5db4b8631d192670d7a0cc4271dbb7/cachebox-5.2.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a71a71df463ba4c86bc843fa01c3a2a721033adefad888af28c6b65e1915a75c", size = 353194, upload-time = "2026-04-10T12:19:03.083Z" }, + { url = "https://files.pythonhosted.org/packages/3b/57/a1fead35cf481432bd87def0653cd4a069b1ea5847589255795e49ae74b8/cachebox-5.2.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbe4655371d19fc9f4f5874312bcb6e5b5b6182989979ac33d93c34c8d10c012", size = 371090, upload-time = "2026-04-10T12:19:16.019Z" }, + { url = "https://files.pythonhosted.org/packages/8c/58/53f1fab8bcc3238fd6c533ef3ab146097986a8acb722863c688a2410c1b2/cachebox-5.2.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4974476d1779961df89d6e6f79e6103a1659289d3ee11c92adcb52e236a8aaeb", size = 390902, upload-time = "2026-04-10T12:19:28.258Z" }, + { url = "https://files.pythonhosted.org/packages/11/2f/5abff74666f8388d2c9516c265f99c33484c827f7fcb3cd703c2f3cbb17e/cachebox-5.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad16d733219f4cab3eec6533af30ab7b9c919c6e3e22ad1ef4eb82629a62edef", size = 395855, upload-time = "2026-04-10T12:19:54.207Z" }, + { url = "https://files.pythonhosted.org/packages/dd/11/30b429db12ab5df663aa108bcfac42805f733da65b0bf452f60bfaf4a530/cachebox-5.2.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:12a9e0a93774ca2b3a9fe8a2a0d0812e399fac4af0fce6246a5bca1e7009b8fc", size = 425760, upload-time = "2026-04-10T12:19:41.138Z" }, + { url = "https://files.pythonhosted.org/packages/cd/b4/fdac1bb902b954c03d23eb301d645a328c9664caff5898930fdbd92fde80/cachebox-5.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:be89497a011eb7a638d13cc520244d77579c0f515b95bf759b3de0b90a015203", size = 564988, upload-time = "2026-04-10T12:20:34.673Z" }, + { url = "https://files.pythonhosted.org/packages/4e/63/76cd5405b0339f15bf86593258bf9bc5608f10a5e0fa6f37a282b42a6caa/cachebox-5.2.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:dd01fc0c1934cccb76493eb4b149a9232d299e5e0275f557adf875c3d25cec81", size = 669110, upload-time = "2026-04-10T12:20:49.039Z" }, + { url = "https://files.pythonhosted.org/packages/d9/bc/52d154aa0407bafce94d1d8d3ff27ca5e842f8311be43cfabdefcbb0f6b7/cachebox-5.2.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a0dfd97b0968f8bd48c33098a03d10f797964559c3a437c84bf97a9973545714", size = 643768, upload-time = "2026-04-10T12:21:04.095Z" }, + { url = "https://files.pythonhosted.org/packages/51/d9/82627eb8cecaf5e7e601bbc65d474a1c3053a2fbc21618ddc6aac19c47dc/cachebox-5.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:223ccf7ac60f595def258e7bc74c0b1d6f43991c9cae6d06749c803d22786d99", size = 610047, upload-time = "2026-04-10T12:21:19.469Z" }, + { url = "https://files.pythonhosted.org/packages/6e/2e/cc5b303746418fde00c93ddbc295733b4e2d131d2e8f5afbc6f45f50454e/cachebox-5.2.3-cp310-cp310-win32.whl", hash = "sha256:745b805fdd99931c3ce1d87d2ee21ca3fb62cba6b4e1f674907af87aad73dce4", size = 275529, upload-time = "2026-04-10T12:21:49.84Z" }, + { url = "https://files.pythonhosted.org/packages/31/72/fb10d6f779d041f701b89f0b7830329f51d1846fbc600869f9f7d635b7b5/cachebox-5.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:a87b19c0a3d8d665a9805b5b4afd64b40082395b70ebe2756131ed1edb0c8f02", size = 287988, upload-time = "2026-04-10T12:21:36.41Z" }, + { url = "https://files.pythonhosted.org/packages/81/88/154179d492f2c000fe6efab3c3ff6b8eb94fbfaa09efe47999bce6b1e29f/cachebox-5.2.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:996f49d04b234082530afcc650bdd00556afbebc19c6c0daaafb85950340cb3c", size = 374245, upload-time = "2026-04-10T12:20:22.042Z" }, + { url = "https://files.pythonhosted.org/packages/7d/9d/3b03f2e063161bcb1a5e0969d521b5c622c2da02252a5c8bd4ef0e4f9914/cachebox-5.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23a3300ebbb526fa12ce6fa53699002f5fba6da23b4bbbaf8ba8b18a3f03e6b3", size = 356308, upload-time = "2026-04-10T12:20:09.149Z" }, + { url = "https://files.pythonhosted.org/packages/bb/9b/8da38af731e3832e9f987548e4bfb610d7f3054019e12c44a94ba9272b37/cachebox-5.2.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79c63ee1589364caa04c018405e625d2e44e0bf9994f2715b2f322075d8c45b6", size = 395666, upload-time = "2026-04-10T12:18:51.89Z" }, + { url = "https://files.pythonhosted.org/packages/01/dd/1522aa808f94c904c5eb3640991799fed14dd43c1dd99a9f7b71bd95b1e3/cachebox-5.2.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ebd0f8d4ebc3943c1ddcbbdc54f1a8ddf95505c862ed5731319cebd1eb98ae41", size = 353362, upload-time = "2026-04-10T12:19:04.536Z" }, + { url = "https://files.pythonhosted.org/packages/dd/52/95bf883ec9b69a76f3a7d9fb14d015d9a4bdab0143a3eff62ceebc8b1419/cachebox-5.2.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:569966efcc6309aa7d774443e3513cdbb8671efae0158138ba2ebb7d8cc9d8ed", size = 371007, upload-time = "2026-04-10T12:19:17.484Z" }, + { url = "https://files.pythonhosted.org/packages/4b/3d/cc02066d5ccfcb8b35adbaf867977fdb54572cda56ace56da396f0caa3bf/cachebox-5.2.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5774d06f0da37dd566239a4376d6ca8cf983d3e4c3228712ec22b4130f662f21", size = 390670, upload-time = "2026-04-10T12:19:29.685Z" }, + { url = "https://files.pythonhosted.org/packages/b3/50/8e4d59b3e344405d8393d6cc5cc92754d3cc1d81134041ebffd3f5ab73e6/cachebox-5.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae5bf8755bc66bcf42e7ca5c42d703a041a7aaad58f9a0c3be54d5b1cefd2641", size = 395765, upload-time = "2026-04-10T12:19:56.169Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d4/d731cff1c4cec22404bd3ddda05b233c5efaa5f13d7abf4e2728905b7cdd/cachebox-5.2.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:63f061cc6a5ca70bbce2e6be0588fe2fee00a93a1b0581b1086d54b10288cdb6", size = 425707, upload-time = "2026-04-10T12:19:42.714Z" }, + { url = "https://files.pythonhosted.org/packages/36/01/3ec8aadceb0dcc66dbd0b9b32966cf7b6928ed84471424c24d21b0af62d0/cachebox-5.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:577c781f18b559f4dc9eea176c6aed008843ef4b8e045cf61bb519e09dccc9ef", size = 564759, upload-time = "2026-04-10T12:20:36.268Z" }, + { url = "https://files.pythonhosted.org/packages/db/23/31cbc8623ecc2e25900f7e8f20f11bfb84786989a59a8046e70b27cbea6d/cachebox-5.2.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:7f691e25572a3ddbb018e19d796f774713bd6b0f7ce9be2e71f6e18572de264a", size = 669309, upload-time = "2026-04-10T12:20:51.117Z" }, + { url = "https://files.pythonhosted.org/packages/34/29/5a9e92bdc7b32dc865e73dd776638244f900136daee5bb0591a67e1530fa/cachebox-5.2.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:33368adf86669c29b936fbae5d6219cf90aacd4b1db71dae2e23d584a8219cd6", size = 643705, upload-time = "2026-04-10T12:21:05.882Z" }, + { url = "https://files.pythonhosted.org/packages/04/90/5273a412855fdc11f674e4749aee6d5ec0a91f5c1a9f6e922f7fa0cb7a83/cachebox-5.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:38ce67b7b45713e49459a09411d07f82de04022c04aecde6202cd32f934c2b1f", size = 609751, upload-time = "2026-04-10T12:21:21.331Z" }, + { url = "https://files.pythonhosted.org/packages/a1/a4/0fadb5e6a00f373cc3fe56b4415cdea2fc0147f6ec475611762d16eb4b05/cachebox-5.2.3-cp311-cp311-win32.whl", hash = "sha256:a7cd2c81347063ab6c512d0f569aeb5f75fc2dfe686c8486258ffd08052324f4", size = 275485, upload-time = "2026-04-10T12:21:51.563Z" }, + { url = "https://files.pythonhosted.org/packages/03/83/67c1bf83f815294d2c3acd7631f25b5cbe6067e1d56495f76829dd60057b/cachebox-5.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:7e45798d6b969794840bb302857946d710ecb32af78dfcb3ab40f4e68ee7fdaf", size = 288024, upload-time = "2026-04-10T12:21:37.999Z" }, + { url = "https://files.pythonhosted.org/packages/e4/e7/6fa6abfc9c4c07b88f09a88466fa93c7081fd679d8e06f8f558bb4ac845c/cachebox-5.2.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:09c0340e9daa7b4530801e5a570cb0c1a1ad941a85d245d360020d3986d0e787", size = 377791, upload-time = "2026-04-10T12:20:23.87Z" }, + { url = "https://files.pythonhosted.org/packages/3a/79/89e4423352d0ca33bbf80fc1b4b665e654a93de8b16cf41e96fcac81801a/cachebox-5.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3162758792626685ec34950eedd565d015b115d0ff0d751d2716031fc32d51b", size = 359562, upload-time = "2026-04-10T12:20:10.626Z" }, + { url = "https://files.pythonhosted.org/packages/d2/ab/e533c2751e6a3411ebe369277aaed03199b9e4586a48f0a3712a1f4b418b/cachebox-5.2.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a189a780c3ccd7b9d157074ba6bf3e191e522b39abbdb590075111851f02d50d", size = 397910, upload-time = "2026-04-10T12:18:53.336Z" }, + { url = "https://files.pythonhosted.org/packages/7a/0d/b8492d6ca53278499a37c9f9d51afd4ad77bfbe813d6281944d45b97a1e7/cachebox-5.2.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:410b67baa99d433644199b11289627f7ebba4ee5786f95ca9858f238afcee157", size = 353699, upload-time = "2026-04-10T12:19:06.248Z" }, + { url = "https://files.pythonhosted.org/packages/78/d4/fd20b3a5362651303fa12d3ee62f56af2bd396e4a7303d7014a1a1e5b392/cachebox-5.2.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f81474dc19d3865fa5e57263f834bc6bbc00e471a594fb9d934ed552732c02fd", size = 372510, upload-time = "2026-04-10T12:19:18.997Z" }, + { url = "https://files.pythonhosted.org/packages/71/94/3ec55c946d300cc4eaed3a0f79740051ac6e11ef4032421332c6ca15f5d5/cachebox-5.2.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:85ccd827193b3e3e887a88a16b88ef7ed174e7e65be515b5253322aa75e665c3", size = 392802, upload-time = "2026-04-10T12:19:31.196Z" }, + { url = "https://files.pythonhosted.org/packages/01/b1/1a3c4e436ad8a4c4ba3e70f4c62e1f927cbbb3c943a9bba5813b8b815bde/cachebox-5.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a1e7d3cb8a5e7e68996a8619e3ef8771a124d14568c251f9e586eba88d759c1", size = 398223, upload-time = "2026-04-10T12:19:57.583Z" }, + { url = "https://files.pythonhosted.org/packages/0a/ea/d36ad3976c4396b350b96a1582411b7a00e56c144eec0bb5ba5f36ce7d86/cachebox-5.2.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:adcedfcfcb933b21e7fdcfe560c79887bc8287abceab0586aa3730417dd0277d", size = 427696, upload-time = "2026-04-10T12:19:44.361Z" }, + { url = "https://files.pythonhosted.org/packages/a8/36/71845b5c7a9ffbd85e6fdb470c11a174f499bd5238fa37b1214157c2454d/cachebox-5.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c7f0c72c51a3a9e7049ea6ff2a43cd3877ab7fee966eb65771a59621563b75e3", size = 567854, upload-time = "2026-04-10T12:20:38.357Z" }, + { url = "https://files.pythonhosted.org/packages/e8/a2/baf0e5a8392e64e352b137ccd7356b3d98068c842fd19f510a7790c05d34/cachebox-5.2.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c48c10e498d573511aafbd545570e7f43b40a7428dc282183bf5adc334d9e1a8", size = 670306, upload-time = "2026-04-10T12:20:52.903Z" }, + { url = "https://files.pythonhosted.org/packages/a5/22/cd4e4c1d624b8ef9fb4b8bebf0bf5d2d74a399cf1ac46b667bb79d15359a/cachebox-5.2.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2f1e086ab5ffd082a68bb63699d517655a59b06414927bfc84e01df91b81e34d", size = 645943, upload-time = "2026-04-10T12:21:08.238Z" }, + { url = "https://files.pythonhosted.org/packages/0a/d6/55859981f5ec6a9e412baaa4db6aa5973a00008750b3f054cdefcb6491fc/cachebox-5.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:649d18399f13735bb82daa33800196f815529c49e967767c40ca221723e68afa", size = 612309, upload-time = "2026-04-10T12:21:23.404Z" }, + { url = "https://files.pythonhosted.org/packages/d7/1e/313f650467ac85824c4199188f8f1ee3386cd12eb665dbf7c88d372e4956/cachebox-5.2.3-cp312-cp312-win32.whl", hash = "sha256:0a17aeb4e5b1c6ef1c3db8fc5186f9986e215ba5ea5a5d08baa45bcf55f261b2", size = 279789, upload-time = "2026-04-10T12:21:53.215Z" }, + { url = "https://files.pythonhosted.org/packages/c5/50/3b334f887accfa811cf5c7533b8ce22c523eb009363a86401198899dadd2/cachebox-5.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:cfd69114141ab362acaa2099e425a1b965cf7b021a539a4e953143d593930b74", size = 290917, upload-time = "2026-04-10T12:21:39.696Z" }, + { url = "https://files.pythonhosted.org/packages/31/3b/16d5c295f6ec2913ef595b39986dc7b7cc179fdd2e73f5ebd1814c38fd51/cachebox-5.2.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:9527c5c70f8735f2d696331d8bcf77254f03b4dc8542046807823bd36ed4e8ba", size = 377408, upload-time = "2026-04-10T12:20:25.444Z" }, + { url = "https://files.pythonhosted.org/packages/cd/87/45f834154f79721e5b64a80ffab4f9710834c4f9c01fa977f94a9116c32a/cachebox-5.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:40ac878af00d5969862c1f6bc076de1e34ca248662fce6aecca1761f52e33e32", size = 359274, upload-time = "2026-04-10T12:20:12.127Z" }, + { url = "https://files.pythonhosted.org/packages/46/17/794e5f93e0a172aa14ecd692f6d89bdf094f71eb35fa923d0a0af25cef1c/cachebox-5.2.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5ff26bfd8f7e95b3becf6d5f65c25edaca50fa68078868648b70d79bcccc260", size = 397520, upload-time = "2026-04-10T12:18:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/23/19/9470b1a96de6e480192b1a92b2fafa72aa052efc2509a5418a5652205b33/cachebox-5.2.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:82e7002dd343afeeba2fcf0e483131b342a27ec3bc34b2214dc617691bda40d6", size = 353183, upload-time = "2026-04-10T12:19:07.797Z" }, + { url = "https://files.pythonhosted.org/packages/6c/2b/72813f80397ed4640e337cbd1a14ab7eaafe33e479291d3623b6a6a55fec/cachebox-5.2.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ccbdc54a6c4b5758408c1083bdfa217bd382894a8331c7d0a54b84ba0cf51e5b", size = 372239, upload-time = "2026-04-10T12:19:20.44Z" }, + { url = "https://files.pythonhosted.org/packages/05/17/47dc9687288fa55486573627089ecd9aae124de5924a4bce008af96d80b6/cachebox-5.2.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df5135a168f143d186b1cc3be0ca16b66446897ab5cedc03bd80bcc926fcd403", size = 392568, upload-time = "2026-04-10T12:19:32.73Z" }, + { url = "https://files.pythonhosted.org/packages/13/95/450765b971a3bed9d7cf003c3833c1976482eb83b0241b6dbb840a25b43b/cachebox-5.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10bedf96db8f9766cc956f9adcc623e604264e5d6fa2e255432f8c2ed7519143", size = 397920, upload-time = "2026-04-10T12:19:59.314Z" }, + { url = "https://files.pythonhosted.org/packages/5f/3e/dd8f4c1f92e58d479913ce9cbaa3227c911128e6046c82f4fd44309f685a/cachebox-5.2.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f22732d0d69bb84ad2dca7480bffdfd0430c647152d488936e152ecbbfee52fb", size = 427332, upload-time = "2026-04-10T12:19:45.888Z" }, + { url = "https://files.pythonhosted.org/packages/7e/20/80d8c26ce63e78da3874a5bb07a3a78de53a2b0356ba80583a4927f0a074/cachebox-5.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:26ae0b68979204d360327f4c0725cfdc95cfc34ab73ab1a8f528e3bd2f6d023c", size = 567494, upload-time = "2026-04-10T12:20:40.373Z" }, + { url = "https://files.pythonhosted.org/packages/10/35/7249885dfed3602b3b48c1e67781197dcdc536c50f72caeabe3944348af8/cachebox-5.2.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:f3d628b816e28a6e7661d460e02dd5b421247cc2cd275814f80ea79621245fc4", size = 669968, upload-time = "2026-04-10T12:20:55.155Z" }, + { url = "https://files.pythonhosted.org/packages/2d/8a/e5b58f0bbd6fef74da5d8e5ab49e67898ce7e6df28c16280a0f2b78461f7/cachebox-5.2.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:64057caa6b741320655cd3c5997fe642dae5dbff571eb530e6f53e58272bb43b", size = 645547, upload-time = "2026-04-10T12:21:09.948Z" }, + { url = "https://files.pythonhosted.org/packages/d8/25/51783a4c6f25ca87ef1b4b762ff0364bd98053a02d597b30d26ff4cf13c5/cachebox-5.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa325306084aa2dc0b21e07723d7700f4d43dece3732c7fdaf7a269dc5e35aa7", size = 611844, upload-time = "2026-04-10T12:21:25.286Z" }, + { url = "https://files.pythonhosted.org/packages/c5/c5/b26c4b046e296d0e249448fe297626b3caca2e851837712f03c358662cb7/cachebox-5.2.3-cp313-cp313-win32.whl", hash = "sha256:55003089d21c2f5515089c307be063b45558e884a4a1cc9593944374c89975c4", size = 279421, upload-time = "2026-04-10T12:21:54.921Z" }, + { url = "https://files.pythonhosted.org/packages/e0/7f/a49420670393bfea618de7a893d45cae9294cf3293d7b158e7af20e8f39e/cachebox-5.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:dcc5edb6ecf2b516e90b773d232360c5e4ed8fdcda038b19441da2ed9cf208ab", size = 290702, upload-time = "2026-04-10T12:21:41.458Z" }, + { url = "https://files.pythonhosted.org/packages/c9/0b/bf83bda13ef6fc490d208a1d4dd712034624526a88f61713cca0edc9884f/cachebox-5.2.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:a4b7559fa4994c4032dd07466c2041d57e055feb814762e1f73f4e8beef188d0", size = 371704, upload-time = "2026-04-10T12:20:27.253Z" }, + { url = "https://files.pythonhosted.org/packages/8e/ea/aa5162273238e84f9e41b33600c69299572dc1c8f0f768d07660b71be07d/cachebox-5.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f57afada3d9327adf87f3b5cf0094348c6fd49354ab2e9bd20b044648eb094ae", size = 353385, upload-time = "2026-04-10T12:20:13.668Z" }, + { url = "https://files.pythonhosted.org/packages/47/96/3ca013e2e48df5c1d7855669b208f4bf8014ccb842ccf7a3a0eaac07bee0/cachebox-5.2.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8342ff350ce86f062492752d612e9f056ac5dc56375713d75c3bf6e83b4d18db", size = 392181, upload-time = "2026-04-10T12:18:56.385Z" }, + { url = "https://files.pythonhosted.org/packages/63/ca/1bacb4efa0b0ce8065d1fb7c8dc7c382ec4e1cc3f007eb08417732be2725/cachebox-5.2.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:405f9cc8492fc9d953b5a6b9e2b661e99583755c6639ab8d09a287fdf336503c", size = 349494, upload-time = "2026-04-10T12:19:09.505Z" }, + { url = "https://files.pythonhosted.org/packages/d7/2e/75db4bda3768658f5baa5a54f6a4f643bc2de1a16788e40581a080e803c7/cachebox-5.2.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:94aae393ec1d9b26565d346445bb6afa3963d2a0d3eb5e4188d0e510fab871a0", size = 369216, upload-time = "2026-04-10T12:19:22.224Z" }, + { url = "https://files.pythonhosted.org/packages/f5/82/e1f833be0d57e29a8c5eb0a0275cd34b962f3c7f5b9e0517ec4bf75e7cc3/cachebox-5.2.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8b0b575066fc09f6fae0d4bd30d6ff56584a6870cbe7d202916c5e0d725cfd4", size = 385922, upload-time = "2026-04-10T12:19:34.198Z" }, + { url = "https://files.pythonhosted.org/packages/53/d6/615a3c16c1d63839f2c67644eb414c4dc9769ab2e169d935110fd8e268d5/cachebox-5.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41e99c1240106d39b63ce7868a6cd8c9da9243fef08848b85d428164e0769fd2", size = 393276, upload-time = "2026-04-10T12:20:00.925Z" }, + { url = "https://files.pythonhosted.org/packages/2f/a6/7844c9c84b170dae1005b22da174639968e64c8055d66a209a1598663771/cachebox-5.2.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:432ca62b99f7eafc21af669d76c88c1b7377db179b89fb6fca3ea93b8f9fff19", size = 421355, upload-time = "2026-04-10T12:19:47.691Z" }, + { url = "https://files.pythonhosted.org/packages/c9/0f/43f62355846cae3dc41cb4daccac0a4bb2b7b8b3c7d77d1b6a220bae6d54/cachebox-5.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e51d9c59006b53447f806145406eb37a7fc3c25553d4fd24c3887f3b268d214e", size = 561656, upload-time = "2026-04-10T12:20:42.161Z" }, + { url = "https://files.pythonhosted.org/packages/9b/fc/a453813c6d000d69a41a06c6a3143a6c4d0d0e41f23c155db2f82ea0edfa/cachebox-5.2.3-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:5e48a405f699fb001b8af120a6e0b4a981277f84eb5dd66a1faa21e4b6fe9485", size = 665791, upload-time = "2026-04-10T12:20:56.842Z" }, + { url = "https://files.pythonhosted.org/packages/aa/a3/f6a9e75f1e602b67b6d67088a9a766adfc4e0a740a9c4b68e4e6207c1006/cachebox-5.2.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8cbfc007ea78af61d75d7d26e5854df53dc5da6877d074afd4b4696c074f4ee7", size = 640975, upload-time = "2026-04-10T12:21:11.641Z" }, + { url = "https://files.pythonhosted.org/packages/a3/15/4ac98277f7fd9d855c8ed337e8e2a3386d17997cce2dd3eadb23dedc08e3/cachebox-5.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6a94d0da8133b3a0707ae11c9ea321f8fc37e3b5a14517019a05d632218b0f56", size = 607242, upload-time = "2026-04-10T12:21:27.27Z" }, + { url = "https://files.pythonhosted.org/packages/9c/0b/ce61907a803f75854e0cc91b84c16e14dce0e4e939efbda26293eb4c8784/cachebox-5.2.3-cp313-cp313t-win32.whl", hash = "sha256:5fee33549877c03c2494ec5359a57a7667f872fe8e296a7f39d3dfe08dd3914c", size = 271619, upload-time = "2026-04-10T12:21:56.768Z" }, + { url = "https://files.pythonhosted.org/packages/b0/06/fece190ad5173d06b2779494aaad5528907f2e55c809618e5b67c2e3dbb5/cachebox-5.2.3-cp313-cp313t-win_amd64.whl", hash = "sha256:67548a05cd41fcc4f7af80a2f97f742fef3d436537ac2e1a1dce0fcba5d41190", size = 283133, upload-time = "2026-04-10T12:21:43.037Z" }, + { url = "https://files.pythonhosted.org/packages/b8/8b/72c0e80aad08e09867ce14a621bce689a733552f20cdf2ef96d4b052da10/cachebox-5.2.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:37fa0891f0defee053c09f5f43f802f731e36e6e6ca055d7d174af07f77232ca", size = 380523, upload-time = "2026-04-10T12:20:29.345Z" }, + { url = "https://files.pythonhosted.org/packages/fc/62/33aaade81b181d5191cc39c867c297aa7c65f3191aa9749bf99b77496b88/cachebox-5.2.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dc6315902f2ef4afbf10bc8e08c54ff34de5ce124546b8e0016c9b0d327be21e", size = 362424, upload-time = "2026-04-10T12:20:15.215Z" }, + { url = "https://files.pythonhosted.org/packages/9e/0b/3eedaf9ea4b41c931f4340bfa42056efe2bb5fe3a79649d6c8a1dce585a5/cachebox-5.2.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7df1735ca778480d51b8232fed397ffe3935158f20d34fb1c5ed171b53d5a6e2", size = 399572, upload-time = "2026-04-10T12:18:58.331Z" }, + { url = "https://files.pythonhosted.org/packages/be/69/c79b8a6a5b889ac4a60800bacea3553cb3b86f6fd13b2262bade1cb962c6/cachebox-5.2.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e22451cde8f884051e941b21870e4fc91fcf58d0d8c285bb8964107e1f02445c", size = 353803, upload-time = "2026-04-10T12:19:11.21Z" }, + { url = "https://files.pythonhosted.org/packages/d4/c3/bc7838de51039f8c50506d8dc82f22ff9a652794339a223b12af595e1d2f/cachebox-5.2.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dcbccf3015d9a42bcf41260fa5cc048a5bdb75aa10997d514d6c976117f30ee2", size = 374474, upload-time = "2026-04-10T12:19:23.658Z" }, + { url = "https://files.pythonhosted.org/packages/65/61/e5231ad2ae952ca482f9b9df55df4b96add1a80de28de537c5f574605987/cachebox-5.2.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:311eae5079e256cbbfafdc3dcff1714b6598a767f9c1ef8c3709e74ea0cc12b0", size = 393045, upload-time = "2026-04-10T12:19:35.651Z" }, + { url = "https://files.pythonhosted.org/packages/78/c4/c9b3fa764ac5420a9e079ad53fa8840d4a26b74c4ccda56acbef49cf76ff/cachebox-5.2.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f4d2a80a5cd3380739c67f7d89e596634f5897b8d5a4a3dc1598312cb077535", size = 398700, upload-time = "2026-04-10T12:20:02.513Z" }, + { url = "https://files.pythonhosted.org/packages/9b/3e/c4e3acd4cb04e01c5fb7cc7a4de16059b9594d90672fff85af8670275267/cachebox-5.2.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3977515b727a5203f494c44c4566fb936c4b940351c01d3d8e7b5d104dff4f53", size = 426725, upload-time = "2026-04-10T12:19:49.385Z" }, + { url = "https://files.pythonhosted.org/packages/25/5d/610b79479719951581109d985244d34c97f86a308c3d7c83443e2b1dac46/cachebox-5.2.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c5be17dd5c4fabcfecd5bcf6d54f9c6fb719daed3ef01ac1c03a14af0e2b26c1", size = 570042, upload-time = "2026-04-10T12:20:43.793Z" }, + { url = "https://files.pythonhosted.org/packages/8c/63/cad8a05db4d0c0f5ba6bccb32e57d15c472276de9476f56004445b40711f/cachebox-5.2.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:6d37334fc218fdaee31db8a4f938938716e7c3b1b4059e25de27c8447fc95fde", size = 670974, upload-time = "2026-04-10T12:20:58.528Z" }, + { url = "https://files.pythonhosted.org/packages/54/d1/9cff7c2b9048d1c38b7ad8199ce856596d09720b3bea74043f3bad71970b/cachebox-5.2.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:1e5f1b7e23411b748d919348c3b65db1f9f8927ab8f6f3acae19bd617543df2d", size = 646213, upload-time = "2026-04-10T12:21:13.619Z" }, + { url = "https://files.pythonhosted.org/packages/27/ae/2e1ad162ec13903e84469c8a753baf385f1bc324279d6c7cb6365e7099df/cachebox-5.2.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e7b06a75a898b31fd73c4d8bf727a9b9f8b5b7738cccd0ab5e6fd2a9cf659d3c", size = 612787, upload-time = "2026-04-10T12:21:29.271Z" }, + { url = "https://files.pythonhosted.org/packages/c8/8a/07b5ffd841e1ff534bb6e8721c39fdfe0d7cdaac1398e1783b2a0c37bd22/cachebox-5.2.3-cp314-cp314-win32.whl", hash = "sha256:3b798052719f09a2ce7bf9fa9452dc0a7d4dc53b50a2d3aba6ce6ebc12d39df7", size = 278559, upload-time = "2026-04-10T12:21:58.482Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f8/b88a82ce9ec7a2fa0f09ed1cdd031692c8664c41f9ab71831e177c7ce2df/cachebox-5.2.3-cp314-cp314-win_amd64.whl", hash = "sha256:4afc8b8575e3228a42ad8d819de5fbbecc6bd0b521295966b00244be37ae3b9b", size = 291928, upload-time = "2026-04-10T12:21:44.621Z" }, + { url = "https://files.pythonhosted.org/packages/4a/01/8c79c07c8c6517fb2fe7d479dd87044e38aac5b9af0245b33fcd695eae37/cachebox-5.2.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:0e8a34b82be30d3d9fb7dfaf9a86ec2b3ab9bc264715909ef27fc3d3587324d2", size = 374325, upload-time = "2026-04-10T12:20:30.923Z" }, + { url = "https://files.pythonhosted.org/packages/7f/51/0fc26b923e80ab857ac99d5f7f3784dc941e7b4de361c204835233176ddf/cachebox-5.2.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:4d4e336aebf866463878ccd28a4d0ef4003ea216708cf4a02a7f198481b3af81", size = 355444, upload-time = "2026-04-10T12:20:16.879Z" }, + { url = "https://files.pythonhosted.org/packages/c1/6d/a6b399221f8dc4b3e01b37d3240ef5b8a7eb78cd9bfbb99b0e655dd01649/cachebox-5.2.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b102fcdd97b0602bf5d6ba1a571bba3e3d6fa912b89fd768b0da5427408eab8", size = 393978, upload-time = "2026-04-10T12:18:59.753Z" }, + { url = "https://files.pythonhosted.org/packages/bd/f1/4c8f998c117c1941a82bd824d6687280c50167f21fea6392e41531d641e2/cachebox-5.2.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:245a79fb2c5d3bff252f4263f76210ef3ad7c2ff9b0234859b26974830a80491", size = 349298, upload-time = "2026-04-10T12:19:12.843Z" }, + { url = "https://files.pythonhosted.org/packages/d1/dd/683bc5a32a0da660d02fa248b880b71a2b834e9b54b8d272b5801282f402/cachebox-5.2.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd0e8dbd8fd4cf664c645c08f9e10508e133353756705c4a738e90a5406224b5", size = 370619, upload-time = "2026-04-10T12:19:25.298Z" }, + { url = "https://files.pythonhosted.org/packages/81/49/d6c47c78a7769b355076c5b635c2b538c8b88e8ceeb408e104d0f269b515/cachebox-5.2.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdb74294bdc33e39e26606919a9b2229038d5fac0edb80c9056683c08584d4a9", size = 385988, upload-time = "2026-04-10T12:19:37.638Z" }, + { url = "https://files.pythonhosted.org/packages/70/e2/b669555ada7fa1392e4cdb8a19f3367db5c6abef0fde8ab034a9747760df/cachebox-5.2.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bba3e9a7f52fa196b434522f39675f3b32a076976ef2373ded6f1065e99f4d20", size = 394090, upload-time = "2026-04-10T12:20:03.978Z" }, + { url = "https://files.pythonhosted.org/packages/8f/01/42916249e53fe4fcbdf0419fb55dbc09b9f377475376e1d7f4ae9c9bd6cd/cachebox-5.2.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abb21f0f937fb66528f1b9f1a04874d6aa503e78bbb26f4cf33bf67faddbdd68", size = 421632, upload-time = "2026-04-10T12:19:51.048Z" }, + { url = "https://files.pythonhosted.org/packages/a1/54/34eebe18c6ed8ba27b1331b5e3d08bd8bb62f03ba81fbf47a2db0fa646f7/cachebox-5.2.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:dab6fd3189b0c746fb03e1915fd947aaca9112cedf26ef3a0c39383acf87d2e5", size = 563871, upload-time = "2026-04-10T12:20:45.417Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b2/f92da0d54e4f18609588709090de8c81dd7c8b20ed6ac30f9b91bedbedf5/cachebox-5.2.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:b4e7d2935b9df11d3717f99c7237b6780f1f8c70e6a99b69b8430d89929ec825", size = 665677, upload-time = "2026-04-10T12:21:00.512Z" }, + { url = "https://files.pythonhosted.org/packages/43/9d/bf2d3dc949afe4d21fc7eb15b7524255e834b9252df6bba111e6686d1c6f/cachebox-5.2.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:611aa260fe1b2506330ff72f415e2cb4053c9c4e3776ac68fe2eedee0e1b91b1", size = 642067, upload-time = "2026-04-10T12:21:15.727Z" }, + { url = "https://files.pythonhosted.org/packages/6e/4f/a789eda189550d239fbaf165b9810f148e733e97a2a4eda7c4192295c7f8/cachebox-5.2.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a424ffb8514a9cb49bacff7995b7c767625cb2239692bd6524245e8579e375cc", size = 608048, upload-time = "2026-04-10T12:21:31.156Z" }, + { url = "https://files.pythonhosted.org/packages/41/c3/590e161c04ffbd36e33933e6dcca5ffa40b5548e3121a21d77aad42af138/cachebox-5.2.3-cp314-cp314t-win32.whl", hash = "sha256:83988dd8e9075ee837e8407e26db49a9944ae74924d5db57b477444d7d98622c", size = 271694, upload-time = "2026-04-10T12:22:00.589Z" }, + { url = "https://files.pythonhosted.org/packages/66/f4/f60b8506df467261178afe918801df37c02c46ec2b8ce019760a14e2abe7/cachebox-5.2.3-cp314-cp314t-win_amd64.whl", hash = "sha256:dbda6390fa5070a19157ae35ab8066d3fe468634e0e9e21452c68ce7999c7d0c", size = 284212, upload-time = "2026-04-10T12:21:46.241Z" }, + { url = "https://files.pythonhosted.org/packages/ce/7b/5eead1ca0d437b1993a742c6571079ae58ae4db50d94d42e87b514aed6c3/cachebox-5.2.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c798cddfb780156db09d3d96ed5da4c2d5fc01dad4bc7b54db5b20c34f221926", size = 376199, upload-time = "2026-04-10T12:20:32.674Z" }, + { url = "https://files.pythonhosted.org/packages/77/e3/5e45042f9b552a5087cafc2e0fed834e632531fca17818201d72e78593ce/cachebox-5.2.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:c8f3de4afeb3fd721620be3d02f2338bcbc3fdbd464ca14e1c474088c9669db0", size = 357109, upload-time = "2026-04-10T12:20:18.554Z" }, + { url = "https://files.pythonhosted.org/packages/d4/51/3c4743b718b42e4b80166fa61f8722b603eba7bf206768a7892c4699dce7/cachebox-5.2.3-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b39022c258872185327acffa9ad42d6bdf42f37d006d35c825a684eb5fa98d40", size = 396433, upload-time = "2026-04-10T12:19:01.463Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9b/678da91187bdb2836db2b8da62519da75359b46bc28697799a7caa314519/cachebox-5.2.3-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a0599fb85dcb6df9a86502435643fe90c793bbcd50b5d85217c70f2bc2e38fc", size = 354287, upload-time = "2026-04-10T12:19:14.55Z" }, + { url = "https://files.pythonhosted.org/packages/df/06/769446da6c9f2855499aaa19e2d7260aa47934bc2e15a931e5b737f8685a/cachebox-5.2.3-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3cdbe8f1b7716a44dc82ef3a6830a612260c7379478cfa80804632e2e6252b8e", size = 372507, upload-time = "2026-04-10T12:19:26.763Z" }, + { url = "https://files.pythonhosted.org/packages/79/cf/86c60994a7be734abef0395e440dc11714f84ffcd369cbcd8e61c3d58126/cachebox-5.2.3-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:783d1b9a0b3c77c43e7ae331b9d6561ad75827e16b2484e2a6cc289ec4d392ee", size = 390831, upload-time = "2026-04-10T12:19:39.591Z" }, + { url = "https://files.pythonhosted.org/packages/9d/db/acfb55f8d5ee4ea1c5f2d32ede25d4d04e944ba09d2832c27c085022490d/cachebox-5.2.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c6476a2a842906fee782d92f8fbcb03ecfd22eecc39adb7fb5b047d7e1cf020", size = 396277, upload-time = "2026-04-10T12:20:05.735Z" }, + { url = "https://files.pythonhosted.org/packages/dc/4f/35e27e85a48e15671c5863addcabde910eb311800a621c3e47c04bd36d17/cachebox-5.2.3-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:184bbcfa1370415b6d1f09e4fb74ab697dac8df09f522aa217a2fac65f973744", size = 426980, upload-time = "2026-04-10T12:19:52.622Z" }, + { url = "https://files.pythonhosted.org/packages/09/4b/50f2cadf20c02db9e449f2e9fee95f3eb5768ab1804dd0a5eba6c98119ad/cachebox-5.2.3-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:f89df36b46f8f5e11c0c49701ec3cebddf51191f96afb7bb75c394faf3c1cbc8", size = 565539, upload-time = "2026-04-10T12:20:47.051Z" }, + { url = "https://files.pythonhosted.org/packages/43/53/b8e948cadb48b8bcf1d13c2aa4a788ff0e95b50ddb808c18e998499b4680/cachebox-5.2.3-pp311-pypy311_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:fb0bdcd9e28686e3b91d5210c843542858f0f10de151181aee27a7978fe4992e", size = 670870, upload-time = "2026-04-10T12:21:02.141Z" }, + { url = "https://files.pythonhosted.org/packages/29/7b/d68ca3f59a9d6963c2f6b19bc4b1926a37db2e4a4f6c9891d12788e49ce2/cachebox-5.2.3-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:5196f0d2c2f99c92ddf0d2c37803ff90509d14a5df211b7754feb8b61ffd8740", size = 644542, upload-time = "2026-04-10T12:21:17.541Z" }, + { url = "https://files.pythonhosted.org/packages/f8/c8/44ae6d5dff09f044d61a92591e6a8db17f3b2ee51a54d375cce90271527b/cachebox-5.2.3-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:73671850d8c3634ab217398c83715d3feb52589ec97bd8e2f4d22e472741ea48", size = 610235, upload-time = "2026-04-10T12:21:32.93Z" }, + { url = "https://files.pythonhosted.org/packages/9a/1b/31cf2449da9a296f6c6c0002c7ae91a25c3a4bfef071763bbeb85300b402/cachebox-5.2.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:70c718f6bb77e6ba142b9a055b81ce85412a0c0e5e82a154489b45e6f91d09ec", size = 287614, upload-time = "2026-04-10T12:21:47.909Z" }, +] + +[[package]] +name = "cachetools" +version = "7.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f4/8b/0d3945a13955303b81272f759a0331e54c5c793da455e6f5706b89d2639c/cachetools-7.1.4.tar.gz", hash = "sha256:437f55a4e0c1b01a4f3077cc470e6991d47430970e36fbcb77e2be0df4fc1cd6", size = 40085, upload-time = "2026-05-21T22:40:43.376Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/7b/1fc1c09cc0756cf25861a3be10565915953876da48bb228fb9a672b20a42/cachetools-7.1.4-py3-none-any.whl", hash = "sha256:323dc4127934744db5b54eb4924482d7edafbf9554e820d1531c2e08c0e4ef54", size = 16761, upload-time = "2026-05-21T22:40:41.845Z" }, +] + +[[package]] +name = "caio" +version = "0.9.25" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/88/b8527e1b00c1811db339a1df8bd1ae49d146fcea9d6a5c40e3a80aaeb38d/caio-0.9.25.tar.gz", hash = "sha256:16498e7f81d1d0f5a4c0ad3f2540e65fe25691376e0a5bd367f558067113ed10", size = 26781, upload-time = "2025-12-26T15:21:36.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/80/ea4ead0c5d52a9828692e7df20f0eafe8d26e671ce4883a0a146bb91049e/caio-0.9.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ca6c8ecda611478b6016cb94d23fd3eb7124852b985bdec7ecaad9f3116b9619", size = 36836, upload-time = "2025-12-26T15:22:04.662Z" }, + { url = "https://files.pythonhosted.org/packages/17/b9/36715c97c873649d1029001578f901b50250916295e3dddf20c865438865/caio-0.9.25-cp310-cp310-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:db9b5681e4af8176159f0d6598e73b2279bb661e718c7ac23342c550bd78c241", size = 79695, upload-time = "2025-12-26T15:22:18.818Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ab/07080ecb1adb55a02cbd8ec0126aa8e43af343ffabb6a71125b42670e9a1/caio-0.9.25-cp310-cp310-manylinux_2_34_aarch64.whl", hash = "sha256:bf61d7d0c4fd10ffdd98ca47f7e8db4d7408e74649ffaf4bef40b029ada3c21b", size = 79457, upload-time = "2026-03-04T22:08:16.024Z" }, + { url = "https://files.pythonhosted.org/packages/88/95/dd55757bb671eb4c376e006c04e83beb413486821f517792ea603ef216e9/caio-0.9.25-cp310-cp310-manylinux_2_34_x86_64.whl", hash = "sha256:ab52e5b643f8bbd64a0605d9412796cd3464cb8ca88593b13e95a0f0b10508ae", size = 77705, upload-time = "2026-03-04T22:08:17.202Z" }, + { url = "https://files.pythonhosted.org/packages/ec/90/543f556fcfcfa270713eef906b6352ab048e1e557afec12925c991dc93c2/caio-0.9.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d6956d9e4a27021c8bd6c9677f3a59eb1d820cc32d0343cea7961a03b1371965", size = 36839, upload-time = "2025-12-26T15:21:40.267Z" }, + { url = "https://files.pythonhosted.org/packages/51/3b/36f3e8ec38dafe8de4831decd2e44c69303d2a3892d16ceda42afed44e1b/caio-0.9.25-cp311-cp311-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bf84bfa039f25ad91f4f52944452a5f6f405e8afab4d445450978cd6241d1478", size = 80255, upload-time = "2025-12-26T15:22:20.271Z" }, + { url = "https://files.pythonhosted.org/packages/df/ce/65e64867d928e6aff1b4f0e12dba0ef6d5bf412c240dc1df9d421ac10573/caio-0.9.25-cp311-cp311-manylinux_2_34_aarch64.whl", hash = "sha256:ae3d62587332bce600f861a8de6256b1014d6485cfd25d68c15caf1611dd1f7c", size = 80052, upload-time = "2026-03-04T22:08:20.402Z" }, + { url = "https://files.pythonhosted.org/packages/46/90/e278863c47e14ec58309aa2e38a45882fbe67b4cc29ec9bc8f65852d3e45/caio-0.9.25-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:fc220b8533dcf0f238a6b1a4a937f92024c71e7b10b5a2dfc1c73604a25709bc", size = 78273, upload-time = "2026-03-04T22:08:21.368Z" }, + { url = "https://files.pythonhosted.org/packages/d3/25/79c98ebe12df31548ba4eaf44db11b7cad6b3e7b4203718335620939083c/caio-0.9.25-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fb7ff95af4c31ad3f03179149aab61097a71fd85e05f89b4786de0359dffd044", size = 36983, upload-time = "2025-12-26T15:21:36.075Z" }, + { url = "https://files.pythonhosted.org/packages/a3/2b/21288691f16d479945968a0a4f2856818c1c5be56881d51d4dac9b255d26/caio-0.9.25-cp312-cp312-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:97084e4e30dfa598449d874c4d8e0c8d5ea17d2f752ef5e48e150ff9d240cd64", size = 82012, upload-time = "2025-12-26T15:22:20.983Z" }, + { url = "https://files.pythonhosted.org/packages/03/c4/8a1b580875303500a9c12b9e0af58cb82e47f5bcf888c2457742a138273c/caio-0.9.25-cp312-cp312-manylinux_2_34_aarch64.whl", hash = "sha256:4fa69eba47e0f041b9d4f336e2ad40740681c43e686b18b191b6c5f4c5544bfb", size = 81502, upload-time = "2026-03-04T22:08:22.381Z" }, + { url = "https://files.pythonhosted.org/packages/d1/1c/0fe770b8ffc8362c48134d1592d653a81a3d8748d764bec33864db36319d/caio-0.9.25-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:6bebf6f079f1341d19f7386db9b8b1f07e8cc15ae13bfdaff573371ba0575d69", size = 80200, upload-time = "2026-03-04T22:08:23.382Z" }, + { url = "https://files.pythonhosted.org/packages/31/57/5e6ff127e6f62c9f15d989560435c642144aa4210882f9494204bc892305/caio-0.9.25-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d6c2a3411af97762a2b03840c3cec2f7f728921ff8adda53d7ea2315a8563451", size = 36979, upload-time = "2025-12-26T15:21:35.484Z" }, + { url = "https://files.pythonhosted.org/packages/a3/9f/f21af50e72117eb528c422d4276cbac11fb941b1b812b182e0a9c70d19c5/caio-0.9.25-cp313-cp313-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0998210a4d5cd5cb565b32ccfe4e53d67303f868a76f212e002a8554692870e6", size = 81900, upload-time = "2025-12-26T15:22:21.919Z" }, + { url = "https://files.pythonhosted.org/packages/9c/12/c39ae2a4037cb10ad5eb3578eb4d5f8c1a2575c62bba675f3406b7ef0824/caio-0.9.25-cp313-cp313-manylinux_2_34_aarch64.whl", hash = "sha256:1a177d4777141b96f175fe2c37a3d96dec7911ed9ad5f02bac38aaa1c936611f", size = 81523, upload-time = "2026-03-04T22:08:25.187Z" }, + { url = "https://files.pythonhosted.org/packages/22/59/f8f2e950eb4f1a5a3883e198dca514b9d475415cb6cd7b78b9213a0dd45a/caio-0.9.25-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:9ed3cfb28c0e99fec5e208c934e5c157d0866aa9c32aa4dc5e9b6034af6286b7", size = 80243, upload-time = "2026-03-04T22:08:26.449Z" }, + { url = "https://files.pythonhosted.org/packages/69/ca/a08fdc7efdcc24e6a6131a93c85be1f204d41c58f474c42b0670af8c016b/caio-0.9.25-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fab6078b9348e883c80a5e14b382e6ad6aabbc4429ca034e76e730cf464269db", size = 36978, upload-time = "2025-12-26T15:21:41.055Z" }, + { url = "https://files.pythonhosted.org/packages/5e/6c/d4d24f65e690213c097174d26eda6831f45f4734d9d036d81790a27e7b78/caio-0.9.25-cp314-cp314-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:44a6b58e52d488c75cfaa5ecaa404b2b41cc965e6c417e03251e868ecd5b6d77", size = 81832, upload-time = "2025-12-26T15:22:22.757Z" }, + { url = "https://files.pythonhosted.org/packages/87/a4/e534cf7d2d0e8d880e25dd61e8d921ffcfe15bd696734589826f5a2df727/caio-0.9.25-cp314-cp314-manylinux_2_34_aarch64.whl", hash = "sha256:628a630eb7fb22381dd8e3c8ab7f59e854b9c806639811fc3f4310c6bd711d79", size = 81565, upload-time = "2026-03-04T22:08:27.483Z" }, + { url = "https://files.pythonhosted.org/packages/3f/ed/bf81aeac1d290017e5e5ac3e880fd56ee15e50a6d0353986799d1bc5cfd5/caio-0.9.25-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:0ba16aa605ccb174665357fc729cf500679c2d94d5f1458a6f0d5ca48f2060a7", size = 80071, upload-time = "2026-03-04T22:08:28.751Z" }, + { url = "https://files.pythonhosted.org/packages/86/93/1f76c8d1bafe3b0614e06b2195784a3765bbf7b0a067661af9e2dd47fc33/caio-0.9.25-py3-none-any.whl", hash = "sha256:06c0bb02d6b929119b1cfbe1ca403c768b2013a369e2db46bfa2a5761cf82e40", size = 19087, upload-time = "2025-12-26T15:22:00.221Z" }, +] + +[[package]] +name = "certifi" +version = "2026.6.17" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/c7/424b75da314c1045981bd9777432fad05a9e0c69daa4ed7e308bbaffe405/certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432", size = 134594, upload-time = "2026-06-17T10:31:07.894Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/2f/c5464532e965badff2f4c4c1a3a83f5697f0d7c407ed0cda44aaa99bb451/certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db", size = 133289, upload-time = "2026-06-17T10:31:06.348Z" }, +] + +[[package]] +name = "cffi" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/57/5f/ff100cae70ebe9d8df1c01a00e510e45d9adb5c1fdda84791b199141de97/cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9", size = 531036, upload-time = "2026-07-06T21:34:30.382Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/e9/6d7724983b3d5a0908dbf74f64038ade77c18646ff6636ec7894fd392ce1/cffi-2.1.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:b65f590ef2a44640f9a05dbb548a429b4ade77913ce683ac8b1480777658a6c0", size = 183837, upload-time = "2026-07-06T21:32:09.655Z" }, + { url = "https://files.pythonhosted.org/packages/69/aa/24580a278de21fd7322635556334d9b535f1cbc00b0a3919447cdf464c65/cffi-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164bff1657b2a74f0b6d54e11c9b375bc97b931f2ca9c43fcf875838da1570dd", size = 184226, upload-time = "2026-07-06T21:32:11.196Z" }, + { url = "https://files.pythonhosted.org/packages/88/a9/02cae418ec4beb282ace11958d9d4737793439d561fadc7e6d56f2e2b354/cffi-2.1.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:c941bb58d5a6e1c3892d86e42927ed6c180302f07e6d395d08c416e594b98b46", size = 211107, upload-time = "2026-07-06T21:32:12.328Z" }, + { url = "https://files.pythonhosted.org/packages/3b/30/c806937ed5e4c2c7ac30d9d6b76b5dc57ff8b75d83800d9bb11a8253cf2a/cffi-2.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a016194dbe13d14ee9556e734b772d8d67b947092b268d757fd4290e3ba2dfc2", size = 218733, upload-time = "2026-07-06T21:32:13.67Z" }, + { url = "https://files.pythonhosted.org/packages/f9/cf/398272b8bbfd58aa314fda5a7f1cdbb26d1d78ae324a11211521315dd1f0/cffi-2.1.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:03e9810d18c646077e501f661b682fbf5dee4676048527ca3cffe66faa9960dd", size = 205543, upload-time = "2026-07-06T21:32:15.148Z" }, + { url = "https://files.pythonhosted.org/packages/45/ca/f91641185cdd90c36d317a9dc7f85e88ef8682d8b300977baff5e23c35d8/cffi-2.1.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:19c54ac121cad98450b4896fa9a43ee0180d57bc4bc911a33db6cab1efab6cd3", size = 205460, upload-time = "2026-07-06T21:32:16.479Z" }, + { url = "https://files.pythonhosted.org/packages/38/66/04781a77b411f0bb5b234d62c1814754ab75ebe455ccff1b08e8d7aae98f/cffi-2.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d433a51f1870e43a13b6732f92aaf540ff77c2015097c78556f75a2d6c030e0", size = 218760, upload-time = "2026-07-06T21:32:17.98Z" }, + { url = "https://files.pythonhosted.org/packages/d0/9a/bb1d5ed9c3fcae158e9f6391bf309c95d98c2ac37ed56573228471d0af5e/cffi-2.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3d7f118b5adbfdfead90c25822690b02bc8074fba949bb7858bec4ebd55adb43", size = 221230, upload-time = "2026-07-06T21:32:19.407Z" }, + { url = "https://files.pythonhosted.org/packages/41/aa/3c1409cdd26094efacd1c36c66e0a6eb9d4296e4fd4f9901b8b2042f4323/cffi-2.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c5f5df567f6eb216de69be06ce55c8b714090fae02b18a3b40da8163b8c5fa9c", size = 213524, upload-time = "2026-07-06T21:32:20.828Z" }, + { url = "https://files.pythonhosted.org/packages/fa/75/74dfb7c3fc6ebbd408038476bd4c1d7e925c62614e7b9c534ecc34218288/cffi-2.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:11b3fb55f4f8ad92274ed26705f65d8f91457de71f5380061eb6d125a768fecd", size = 220341, upload-time = "2026-07-06T21:32:21.9Z" }, + { url = "https://files.pythonhosted.org/packages/70/b6/9003c33a3e7d2c1306f5962e646457dcfe5a8cd8fce6bbe02d7af25db783/cffi-2.1.0-cp310-cp310-win32.whl", hash = "sha256:9d72af0cf10a76a600a9690078fe31c63b9588c8e86bf9fd353f713c84b5db0f", size = 174578, upload-time = "2026-07-06T21:32:23.073Z" }, + { url = "https://files.pythonhosted.org/packages/8a/26/710688310447531c7a22f857c7f79d9855ec18b03e04494ced723fb37e2f/cffi-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb62edb5bb52cca65fab91a63afa7561607120d26090a7e8fda6fb9f064726da", size = 185071, upload-time = "2026-07-06T21:32:24.671Z" }, + { url = "https://files.pythonhosted.org/packages/d3/67/85c89a59ba36a671e79638f44d466749f08179266a57e4f2ffdf92174072/cffi-2.1.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:02cb7ff33ded4f1532476731f89ede53e2e488a8e6205515a82144246ffa7dcc", size = 183845, upload-time = "2026-07-06T21:32:26.32Z" }, + { url = "https://files.pythonhosted.org/packages/ea/dd/e3b0baa2d3d6a857ac72b7efbf18e32e487c9cdafcc13049ad765495b15e/cffi-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f5bce581e6b8c235e566a14768a943b172ada3ed73537bb0c0be1edee312d4e7", size = 184186, upload-time = "2026-07-06T21:32:28.025Z" }, + { url = "https://files.pythonhosted.org/packages/65/68/9f3ef890cf3c6ab97bd531c5677f67613d302165d16f8142b2811782a614/cffi-2.1.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:30b65779d598c370374fefabf138d456fd6f3216bfa7bedfab1ba82025b0cd93", size = 211892, upload-time = "2026-07-06T21:32:29.565Z" }, + { url = "https://files.pythonhosted.org/packages/22/d7/1a74539db16d8bfd839ff1515948948efbb162e574650fd3d846896eea95/cffi-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88023dfe18799507b73f1dbb0d14326a17465de1bc9c9c7655c22845e9ddc3a2", size = 218793, upload-time = "2026-07-06T21:32:30.951Z" }, + { url = "https://files.pythonhosted.org/packages/ec/d1/9a5b7169499e8e8d8e636de70b97ac7c9447104d2ff1a2cd94790cea5162/cffi-2.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:0a96b74cda968eebbad56d973efe5098974f0a9fb323865bf99ea1fd24e3e64c", size = 205737, upload-time = "2026-07-06T21:32:32.216Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b0/e131a9c41f10607926278453d9596163594fe1c4ebc46efe3b5e5b34eb84/cffi-2.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a5781494d4d400a3f47f8f1da94b324f6e6b440a53387774002890a2a2f4b50f", size = 204909, upload-time = "2026-07-06T21:32:33.655Z" }, + { url = "https://files.pythonhosted.org/packages/fb/d2/4398416cd699b35167947c6e22aca52c47e69ad5695073c9f1f2c52e04aa/cffi-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aa7a1b53a2a4452ada2d1b5dade9960b2522f1e61293a811a077439e39029565", size = 217883, upload-time = "2026-07-06T21:32:35.173Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a5/d4fe77b589e5e82d43ebc809bf2e6474afe8e48e32ea050b9357645b6471/cffi-2.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d8272c0e483b024e1b9ad029821470ed8ec65631dbd90217469da0e7cd89f1c", size = 221251, upload-time = "2026-07-06T21:32:36.527Z" }, + { url = "https://files.pythonhosted.org/packages/22/f0/a2fc43084c0433caf7f461bccc013e28f848d04ee1c5ed7fce71423cf4d9/cffi-2.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7762faa47e8ff7eb80bd261d9a7d8eea2d8baa69de5e95b70c1f338bbe712f02", size = 214250, upload-time = "2026-07-06T21:32:37.852Z" }, + { url = "https://files.pythonhosted.org/packages/04/8c/b925975448cf20634a9fbd5efceb807219db452653648d2897c0989cab2d/cffi-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:89095c1968b4ba8285840e131bf2891b09ae137fe2146905acae0354fbce1b5e", size = 219441, upload-time = "2026-07-06T21:32:39.146Z" }, + { url = "https://files.pythonhosted.org/packages/eb/da/5c4918a2d61d86fa927d716cb3d8e4626ef8dc8f605a599d32f33897f59a/cffi-2.1.0-cp311-cp311-win32.whl", hash = "sha256:64c753a0f87a256020004f37a1c8c02c480e725f910f0b2a0f3f07debd1b2479", size = 174496, upload-time = "2026-07-06T21:32:40.467Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c8/6c2de1d55cf35ef8b92885d5ef280790f0fb9634d87ea1cc315176aecd61/cffi-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:4f26194e3d95e06501b942642855aed4f953d55e95d7d01b7c4483db3ecff458", size = 185113, upload-time = "2026-07-06T21:32:41.761Z" }, + { url = "https://files.pythonhosted.org/packages/9e/4e/e8d7cb5783f1841a3c8fb3a7735838d7484d08ec08c9f984b14cac1ac0e9/cffi-2.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:35aaea0c7ee0e58a5cd8c2fd1a48fdf7ece0d2699b7ecdda08194e9ce5dd9b3d", size = 179927, upload-time = "2026-07-06T21:32:42.961Z" }, + { url = "https://files.pythonhosted.org/packages/1e/85/990925db5df586ec90beb97529c853497e7f85ba0234830447faf41c3057/cffi-2.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:df2b82571a1b30f58a87bf4e5a9e78d2b1eff6c6ce8fd3aa3757221f93f0863f", size = 184829, upload-time = "2026-07-06T21:32:44.324Z" }, + { url = "https://files.pythonhosted.org/packages/4b/92/e7bb136ad6b5352603732cf907ef862ca103f20f2031c1735a46300c20c9/cffi-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78474632761faa0fb96f30b1c928c84ebcf68713cbb80d15bab09dfe61640fde", size = 184728, upload-time = "2026-07-06T21:32:45.683Z" }, + { url = "https://files.pythonhosted.org/packages/c3/c0/d1ec30ffb370f748f2fb54425972bfef9871e0132e82fb589c46b6676049/cffi-2.1.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:5972433ad71a9e46516584ef60a0fda12d9dc459938d1539c3ddecf9bdc1368d", size = 214815, upload-time = "2026-07-06T21:32:48.557Z" }, + { url = "https://files.pythonhosted.org/packages/1b/dc/5620cf930688be01f2d673804291de757a934c90b946dbdc3d84130c2ea4/cffi-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b6422532152adf4e59b110cb2808cee7a033800952f5c036b4af047ee43199e7", size = 222429, upload-time = "2026-07-06T21:32:49.848Z" }, + { url = "https://files.pythonhosted.org/packages/4b/a4/77b53abbf7a1e0beb9637edbef2a94d15f9c822f591e85d439ffd91519a6/cffi-2.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:46b1c8db8f6122420f32d02fffb924c2fe9bc772d228c7c711748fff56aabb2b", size = 210315, upload-time = "2026-07-06T21:32:51.221Z" }, + { url = "https://files.pythonhosted.org/packages/58/0c/f528df19cc94b675087324d4760d9e6d5bfae97d6217aa4fac43de4f5fcc/cffi-2.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9fafc5aa2e2a39aaf7f8cc0c1f044a9b07fca12e558dca53a3cc5c654ad67a7", size = 208859, upload-time = "2026-07-06T21:32:52.512Z" }, + { url = "https://files.pythonhosted.org/packages/62/f2/c9522a81c32132799a1972c39f5c5f8b4c8b9f00488a23feaa6c06f07741/cffi-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e9f50d192a3e525b15a75ab5114e442d83d657b7ec29182a991bc9a88fd3a66", size = 221844, upload-time = "2026-07-06T21:32:53.704Z" }, + { url = "https://files.pythonhosted.org/packages/6e/28/bd53988b9833e8f8ad539d26f4c07a6b3f6bcb1e9e02e7ca038250b3428d/cffi-2.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98fff996e983a36d3aa2eca83af40c5821202e7e6f32d13ae94e3d2286f10cfe", size = 225287, upload-time = "2026-07-06T21:32:54.907Z" }, + { url = "https://files.pythonhosted.org/packages/79/99/0d0fd37f055224085f42bbb2c022d002e17dde4a97972822327b07d84101/cffi-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:379de10ce1ba048b1448599d1b37b24caee16309d1ac98d3982fc997f768700b", size = 223681, upload-time = "2026-07-06T21:32:56.329Z" }, + { url = "https://files.pythonhosted.org/packages/b0/80/c138990aa2a70b1a269f6e06348729836d733d6f970867943f61d367f8cc/cffi-2.1.0-cp312-cp312-win32.whl", hash = "sha256:9b8f0f26ca4e7513c534d351eca551947d053fac438f2a04ac96d882909b0d3a", size = 175269, upload-time = "2026-07-06T21:32:57.777Z" }, + { url = "https://files.pythonhosted.org/packages/a8/eb/f636456ff21a83fc13c032b58cc5dde061691546ac79efa284b2989b7982/cffi-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:c97f080ea627e2863524c5af3836e2270b5f5dfff1f104392b959f8df0c5d384", size = 185881, upload-time = "2026-07-06T21:32:59.253Z" }, + { url = "https://files.pythonhosted.org/packages/dd/2c/400ea43e721727dca8a65c4521390e9196757caba4a45643acb2b63271b8/cffi-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:6d194185eabd279f1c05ebe3504265ddfc5ad2b58d0714f7db9f01da592e9eb6", size = 180088, upload-time = "2026-07-06T21:33:02.278Z" }, + { url = "https://files.pythonhosted.org/packages/96/88/a996879e2eeccb815f6e3a5967b12a308257412acec882039d386bd2aa7b/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:10537b1df4967ca26d21e5072d7d54188354483b91dc75058968d3f0cf13fbda", size = 194331, upload-time = "2026-07-06T21:33:03.697Z" }, + { url = "https://files.pythonhosted.org/packages/58/85/7ae00d5c8dd6266f4e944c3db630f3c5c9a98b61d469c714d848b1d8138a/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a95b05f9baf29b91171b3a8bd2020b028835243e7b0ff6bb23e2a3c228518b1b", size = 196966, upload-time = "2026-07-06T21:33:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/8c/e9/45c3a76ad8d43ad9261f4c95436da61128d3ca545d72b9612c0ab5be0b1c/cffi-2.1.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:15faec4adfff450819f3aee0e2e02c812de6edb88203aa58807955db2003472a", size = 184795, upload-time = "2026-07-06T21:33:06.699Z" }, + { url = "https://files.pythonhosted.org/packages/84/4c/82f132cb4418ee6d953d982b19191e87e2a6372c8a4ce36e50b69d6ade4a/cffi-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:716ff8ec22f20b4d988b12884086bcef0fc99737043e503f7a3935a6be99b1ea", size = 184746, upload-time = "2026-07-06T21:33:08.071Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1c/4ed5a0e5bdca6cbc275556de3328dd1b76fd0c11cc13c88fe66d1d8715f2/cffi-2.1.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:63960549e4f8dc41e31accb97b975abaecfc44c03e396c093a6436763c2ea7db", size = 214747, upload-time = "2026-07-06T21:33:09.671Z" }, + { url = "https://files.pythonhosted.org/packages/3a/a6/e879bb68cc23a2bc9ba8f4b7d8019f0c2694bad2ab6c4a3701d429439f58/cffi-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff067a8d8d880e7809e4ac88eb009bb848870115317b306666502ccad30b147f", size = 222392, upload-time = "2026-07-06T21:33:10.896Z" }, + { url = "https://files.pythonhosted.org/packages/88/f6/01890cfd63c08f8eb96a8319b0443690197d240a8bd6346048cf7bde9190/cffi-2.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3b926723c13eba9f81d2ef3820d63aeceec3b2d4639906047bf675cb8a7a500d", size = 210285, upload-time = "2026-07-06T21:33:12.251Z" }, + { url = "https://files.pythonhosted.org/packages/a6/cf/2b684132056f438567b61e19d690dd31cd0921ace051e0a458be6074369e/cffi-2.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:47ff3a8bfd8cb9da1af7524b965127095055654c177fcfc7578debcb015eecd0", size = 208801, upload-time = "2026-07-06T21:33:13.617Z" }, + { url = "https://files.pythonhosted.org/packages/6f/08/f2e7d62c460faae0926f2d6e423694aa409ced3bc1fe2927a0a6e5f05416/cffi-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:799416bae98336e400981ff6e532d67d5c709cfb30afb79865a1315f94b0e224", size = 221808, upload-time = "2026-07-06T21:33:15.466Z" }, + { url = "https://files.pythonhosted.org/packages/38/37/04f54b8e63a02f3d908332c9effbf8c366167c6f733ed8a3d4f79b7e2a1e/cffi-2.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:961be50688f7fba2fa65f63712d3b9b341a22311f5253460ce933f52f0de1c8c", size = 225241, upload-time = "2026-07-06T21:33:16.869Z" }, + { url = "https://files.pythonhosted.org/packages/a9/d6/c72eecca433cd3e681c65ed313ab4835d9d4a379704d0f628a6a05f51c2e/cffi-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf5c6cf48238b0eb4c086978c492ad1cbc22373fc5b2d7353b3a598ce6db887a", size = 223588, upload-time = "2026-07-06T21:33:18.239Z" }, + { url = "https://files.pythonhosted.org/packages/c6/4b/e706f67279140f92939da3475ad610df18bfd52d50f14953a8e5fede71d5/cffi-2.1.0-cp313-cp313-win32.whl", hash = "sha256:db3eb7d46527159a878ec3460e9d40615bc25ba337d477db681aea6e4f05c5d2", size = 175248, upload-time = "2026-07-06T21:33:19.799Z" }, + { url = "https://files.pythonhosted.org/packages/5a/47/59eb7975cb0e4ef0afa764ea945b29a5bb4537a9f771cb7d6c8a5dd74c95/cffi-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:8e74a6135550c4748af665b1b1118b6aab33b1fc6a16f9aff630af107c3b4512", size = 185717, upload-time = "2026-07-06T21:33:21.47Z" }, + { url = "https://files.pythonhosted.org/packages/5a/af/34fee85c48f8d94efc8597bc09470c9dd274c145f1c12e0fbc6ab6d38d74/cffi-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:2282cd5e38aa8accd03e99d1256af8411c84cdbee6a89d841b563fdbd1f3e50f", size = 180114, upload-time = "2026-07-06T21:33:22.515Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f0/81478e482afa03f6d18dc8f2afb5edc45b3080853b634b5ed91961be0998/cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d2117334c3af3bdcb9a88522b844a2bdb5efdc4f71c6c822df55486ae1c3347a", size = 194142, upload-time = "2026-07-06T21:33:23.657Z" }, + { url = "https://files.pythonhosted.org/packages/7d/95/8de304305cd9204974b0ca051b86d307cafca13aa575a0ef1b44d92c0d8c/cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:702c436735fbe99d59ada02a1f65cfc0d31c0ee8b7290912f8fbc5cd1e4b16c3", size = 196819, upload-time = "2026-07-06T21:33:25.007Z" }, + { url = "https://files.pythonhosted.org/packages/20/71/7c8372d30e42415602ed9f268f7cfd66f1b855fed881ecd168bcb45dbc0b/cffi-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1ff3456eab0d889592d1936d6125bbfbc7ae4d3354a700f8bd80450a66445d4d", size = 184965, upload-time = "2026-07-06T21:33:26.605Z" }, + { url = "https://files.pythonhosted.org/packages/d6/5c/584e626835f0375c928176c04137c96927165cb8733cdb3150ec04e5ee5e/cffi-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c4165821e131d6d4ca444347c2b694e2311bcfa3fe5a861cc72968f28867beac", size = 184952, upload-time = "2026-07-06T21:33:27.823Z" }, + { url = "https://files.pythonhosted.org/packages/2e/d2/065fcae1c73979fac8e054462478d0ff8a29c40cdc2ed7ea5676a061df53/cffi-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:276f20fffd7b396e12516ba8edf9509210ac248cbbc5acbc39cd512f9f59ebe6", size = 222353, upload-time = "2026-07-06T21:33:29.178Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a5/e8bbb1ce5b3ac2f53ad6a10bde44318a5a8d99d4f4a000d44a6e39aeb3e4/cffi-2.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7d5980a3433d4b71a5e120f9dd551403d7824e31e2e67124fe2769c404c06913", size = 210051, upload-time = "2026-07-06T21:33:30.534Z" }, + { url = "https://files.pythonhosted.org/packages/28/ed/c127d3ac36e899c965e3361357c3befacd6578c03f40125183e41c3b219e/cffi-2.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6ca4919c6e4f89aa99c42510b42cf54596892c00b3f9077f6bdd1505e24b9c8d", size = 208630, upload-time = "2026-07-06T21:33:31.753Z" }, + { url = "https://files.pythonhosted.org/packages/cc/d7/97d3136f81db489ec8d1d67748c110d6c994268fd7528014aa9f2b085e4e/cffi-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d53d10f7da99ae46f7373b9150393e9c5eab9b224909982b43832668de4779f5", size = 221593, upload-time = "2026-07-06T21:33:33.044Z" }, + { url = "https://files.pythonhosted.org/packages/d3/27/93195977168ee63aed233a1a0993a2178798654d1f4bddcdd321d6fd3b21/cffi-2.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c351efb95e832a853a29361675f33a7ce53de1a109cd73fd47af0712213aa4ce", size = 225146, upload-time = "2026-07-06T21:33:34.224Z" }, + { url = "https://files.pythonhosted.org/packages/b3/c1/6dbd291ee2ae5a50a034aa057207081f545923bbf15dad4511e985aafff5/cffi-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:dbf7c7a88e2bac086f06d14577332760bdeecc42bdec8ac4077f6260557d9326", size = 223240, upload-time = "2026-07-06T21:33:35.57Z" }, + { url = "https://files.pythonhosted.org/packages/0f/6f/ade5ce9863a57992a6ea3d0d10d7e29b8749fc127204b3d493d667b2815f/cffi-2.1.0-cp314-cp314-win32.whl", hash = "sha256:1854b724d00f6654c742097d5387569021be12d3a0f770eae1df8f8acfcc6acd", size = 177723, upload-time = "2026-07-06T21:33:51.626Z" }, + { url = "https://files.pythonhosted.org/packages/41/de/92b9eeed4ae4a21d6fd9b2a2c8505cbed573299902ea73981cc13f7ff62c/cffi-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:1b96bfe2c4bd825681b7d311ad6d9b7280a091f43e8f63da5729638083cd3bfb", size = 187937, upload-time = "2026-07-06T21:33:53.403Z" }, + { url = "https://files.pythonhosted.org/packages/2e/1a/cc6ae6c2913a03aab8898eee57963cf1035b8df5872ed8b9115fcc7e2be8/cffi-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:7d28dff1db6764108bc30788d85d61c876beff416d9a49cb9dd7c5a9f34f5804", size = 183001, upload-time = "2026-07-06T21:33:54.74Z" }, + { url = "https://files.pythonhosted.org/packages/14/f0/134c00ce0779ec86dea2aa1aac69339c2741a8045072676763512363a2ea/cffi-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7ea6b3e2c4250ff1de21c630fe72d0f63eb95c2c32ffbf64a358cf4a8836d714", size = 188538, upload-time = "2026-07-06T21:33:36.792Z" }, + { url = "https://files.pythonhosted.org/packages/50/d8/3b86aba791cb610d24e8a3e1b2cd529e71fa15096b04e4d4e360049d4a4c/cffi-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6af371f3767faeffc6ac1ef57cdfd25844403e9d3f476c5537caee499de96376", size = 188230, upload-time = "2026-07-06T21:33:38.011Z" }, + { url = "https://files.pythonhosted.org/packages/14/d0/117dcd9209255ad8571fbc8c92ef32593a1d294dcec91ddc4e4db50606f2/cffi-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb4e8997a49aa2c08a3e43c9045d224448b8941d88e7ac163c7d383e560cbf98", size = 223899, upload-time = "2026-07-06T21:33:39.514Z" }, + { url = "https://files.pythonhosted.org/packages/b6/3d/f20f8b886b254e3ad10e15cd4186d3aed49f3e6a35ab37aab9f8f25f7c03/cffi-2.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bf01d8c84cbea96b944c73b22182e6c7c432b3475632b8111dbfdc95ddad6e13", size = 211652, upload-time = "2026-07-06T21:33:40.851Z" }, + { url = "https://files.pythonhosted.org/packages/28/3b/fad54de07260b93ddeef4b96d0131d57ea900675df1d410ae1deee52d7a6/cffi-2.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:33eb1ad83ebe8f313e0df035c406227d55a79456704a863fad9842136af5ad7d", size = 210755, upload-time = "2026-07-06T21:33:42.183Z" }, + { url = "https://files.pythonhosted.org/packages/cc/82/3d5c705acb7abbba9bbd7d79b8e62e0f25b6120eb7ae6ac49f1b721722fe/cffi-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ac0f1a2d0cfa7eea3f2aaf006ab6e70e8feeb16b75d65b7e5939982ca2f11056", size = 223933, upload-time = "2026-07-06T21:33:43.603Z" }, + { url = "https://files.pythonhosted.org/packages/6c/d0/47e338384ab6b1004241002fa616301020cea4fc95f283506565d252f276/cffi-2.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c16914df9fb7f500e440e6875fa23ff5e0b31db01fa9c06af98d59a91f0dc2e4", size = 226749, upload-time = "2026-07-06T21:33:45.046Z" }, + { url = "https://files.pythonhosted.org/packages/70/25/65bd5b58ea4bfdfc15cde02cb5365f89ef8ab8b2adfb8fe5c4bd4233382f/cffi-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5ecbd0499275d57506d397eebe1981cee87b47fcd9ef5c22cab7ed7644a39a94", size = 225703, upload-time = "2026-07-06T21:33:46.374Z" }, + { url = "https://files.pythonhosted.org/packages/dc/78/aa01ac599a8a4322533d45a1f9bc93b338276d2d59dabbe7c6d92a775c81/cffi-2.1.0-cp314-cp314t-win32.whl", hash = "sha256:7d034dcffa09e9a46c93fa3a3be402096cb5354ac6e41ab8e5cc9cd8b642ad76", size = 182857, upload-time = "2026-07-06T21:33:47.696Z" }, + { url = "https://files.pythonhosted.org/packages/b9/26/d00496b22de4d4228f32dde94ad996f350c8aad676d63bcca0743c8dea4d/cffi-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0582a58f3051372229ca8e7f5f589f9e5632678208d8636fea3676711fdf7fe5", size = 194065, upload-time = "2026-07-06T21:33:48.953Z" }, + { url = "https://files.pythonhosted.org/packages/d5/dd/0c7dbf815a579ff005008a2d815a55d6bb047c349eef536d9dc53d3f0a8d/cffi-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:510aeeeac94811b138077451da1fb18b308a5feab47dd2b603af55804155e1c8", size = 186404, upload-time = "2026-07-06T21:33:50.309Z" }, + { url = "https://files.pythonhosted.org/packages/55/c7/8c8c50cb11c6750051daf12164098a9a6f027ac4356967fd4d800a07f242/cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:2e9dabb9abcb7ad15938c7196ad5c1718a4e6d33cc79b4c0209bdb64c4a54a5c", size = 194121, upload-time = "2026-07-06T21:33:56.109Z" }, + { url = "https://files.pythonhosted.org/packages/99/e2/67680bf19a6b60d2bb7ff83baefa2a4c3d2d7dc0f3277034b802e1fc504c/cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:37f525a7e7e50c017fdebe58b787be310ad59357ae43a053943a6e1a6c526001", size = 196820, upload-time = "2026-07-06T21:33:57.288Z" }, + { url = "https://files.pythonhosted.org/packages/ed/da/4bbe583a3b3a5c8c60892124fe17f3fa3656523faf0d3484eae90f091853/cffi-2.1.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:95f2954c2c9473d892eca6e0409f3568b37ab62a8eedb122461f73cc273476e3", size = 184936, upload-time = "2026-07-06T21:33:58.765Z" }, + { url = "https://files.pythonhosted.org/packages/e5/4b/1f4c36ab273980d7aa75bb126ea4f8971f24a96108acad3a0a084028c57b/cffi-2.1.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:cdf2448aab5f661c9315308ec8b93f4e8a1a67a3c733f8631067a2b67d5913dc", size = 185045, upload-time = "2026-07-06T21:34:00.085Z" }, + { url = "https://files.pythonhosted.org/packages/ef/c3/ad299dc38f3583f8d916b299f028af418a9ec98bc695fcbebeae7420691c/cffi-2.1.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:90bec57cf82089383bd06a605b3eb8daebf7e5a668520beaf6e327a83a947699", size = 222342, upload-time = "2026-07-06T21:34:01.814Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d8/df4543cc087245044ed02ef3ad8e0a26619d0075ac7a77a12dc81177851b/cffi-2.1.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6274dcb2d15cef48daa73ed1be5a40d501d74dccd0cd6db364776d12cb6ba022", size = 210073, upload-time = "2026-07-06T21:34:03.255Z" }, + { url = "https://files.pythonhosted.org/packages/2c/0e/fac738d73728c6cea2a88a2883dca54892496cbba88a1dc1f2909cb8a6f5/cffi-2.1.0-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:2b71d409cccee78310ab5dec549aed052aaea483346e282c7b02362596e01bb0", size = 208551, upload-time = "2026-07-06T21:34:04.433Z" }, + { url = "https://files.pythonhosted.org/packages/e6/3f/0b04a700dd64f465c93020253a793a82c9b4dff9961f48facd0df945d9b8/cffi-2.1.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7d3538f9c0e50670f4deb93dbb696576e60590369cae2faf7de681e597a8a1f1", size = 221649, upload-time = "2026-07-06T21:34:06.157Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7c/b7379a5704c79eda57ce075869ba70a0368d1c850f803b3c0d078d39dcaf/cffi-2.1.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:8f9ec95b8a043d3dfbc74d9abc6f7baf524dd27a8dc160b0a32ff9cdab650c28", size = 225203, upload-time = "2026-07-06T21:34:07.489Z" }, + { url = "https://files.pythonhosted.org/packages/5a/02/d5e6c43ea85c41bda2a184a3418f195fe7cf602967a8d2b94e085b83deef/cffi-2.1.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:af5e2915d41fe6c961694d7bfdc8562942638200f3ce2765dfb8b745cf997629", size = 223263, upload-time = "2026-07-06T21:34:08.712Z" }, + { url = "https://files.pythonhosted.org/packages/2c/d8/772b8259bf75749adffb1c546828978381fb516f60cf701f6c83daf60c85/cffi-2.1.0-cp315-cp315-win32.whl", hash = "sha256:0a42c688d19fca6e095a53c6a6e2295a5b050a8b289f109adab02a9e61a25de6", size = 177696, upload-time = "2026-07-06T21:34:26.355Z" }, + { url = "https://files.pythonhosted.org/packages/2f/dd/afa2191fc6d57fedd26e5844a2fe2fcc0bbfa00961bbaa5a41e4921e7cca/cffi-2.1.0-cp315-cp315-win_amd64.whl", hash = "sha256:bccbbb5ee76a61f9d99b5bf3846a51d7fca4b6a732fe46f89295610edaf41853", size = 187914, upload-time = "2026-07-06T21:34:27.58Z" }, + { url = "https://files.pythonhosted.org/packages/05/ef/6cd4f8c671517162379dc79cfae5aea9106bc38abb89628d5c16adf6a838/cffi-2.1.0-cp315-cp315-win_arm64.whl", hash = "sha256:8d35c139744adb3e727cd51b1a18324bbe44b8bd41bf8322bca4d41289f48eda", size = 183004, upload-time = "2026-07-06T21:34:28.905Z" }, + { url = "https://files.pythonhosted.org/packages/11/b6/12fc55092817a5faa26fb8c40c7f9d662e11a46ee248c137aafc42517d92/cffi-2.1.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:f9912624a0c0b834b7520d7769b3644453aabc0a7e1c839da7359f050750e9bc", size = 188378, upload-time = "2026-07-06T21:34:09.926Z" }, + { url = "https://files.pythonhosted.org/packages/8d/2e/cdac88979f295fde5daa69622c7d2111e56e7ceb94f211357fbe452339e4/cffi-2.1.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:df92f2aba50eb4d96718b68ef76f2e57a57b54f2fa62333496d16c6d585a85ca", size = 188319, upload-time = "2026-07-06T21:34:11.101Z" }, + { url = "https://files.pythonhosted.org/packages/e0/27/1d0b408497e41a74795af122d7b603c418c5fed0171450f899afd04e594f/cffi-2.1.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0520e1f4c35f44e209cbbb421b67eec42e6a157f59444dfb6058874ff3610e5d", size = 223904, upload-time = "2026-07-06T21:34:12.606Z" }, + { url = "https://files.pythonhosted.org/packages/8b/31/e115c985105dd7ffb32444505f18ceb874bb42d992af05d5dced7ecf1980/cffi-2.1.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3681e031db29958a7502f5c0c9d6bbc4c36cb20f7b104086fa642d1799631ff8", size = 211554, upload-time = "2026-07-06T21:34:13.987Z" }, + { url = "https://files.pythonhosted.org/packages/5a/67/9e6e09409336d9e515c58367e7cfcf4f89df06ad25252675595a58eb59d5/cffi-2.1.0-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:762f99479dcb369f60ab9017ad4ab97a36a1dd7c1ee5a3b15db0f4b8659120cd", size = 210795, upload-time = "2026-07-06T21:34:15.972Z" }, + { url = "https://files.pythonhosted.org/packages/19/e5/d3cc82a4a0be7902af279c04181ad038449c096734464a5ae1de3e1401bd/cffi-2.1.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0611e7ebf90573a535ebdc33ae9da222d037853983e13359f580fab781ca017f", size = 223843, upload-time = "2026-07-06T21:34:17.509Z" }, + { url = "https://files.pythonhosted.org/packages/b9/65/b434abc97ce7cecc2c640fde160507c0ecc7e21544b483ba3325d2e2ea17/cffi-2.1.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:86cf8755a791f72c85dc287128cc62d4f24d392e3f1e15837245623f4a33cccc", size = 226773, upload-time = "2026-07-06T21:34:19.05Z" }, + { url = "https://files.pythonhosted.org/packages/b5/9f/d4dc66ca651eb1145a133314cda721abf13cfac3d28c4a0402263ae6ad75/cffi-2.1.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:ba00f661f8ba35d075c937174e27c2c421cec3942fd2e0ea3e66996757c0fdd9", size = 225719, upload-time = "2026-07-06T21:34:20.576Z" }, + { url = "https://files.pythonhosted.org/packages/68/5a/e536c528bc8057496c360c0978559a2dc45653f89dd6151078aa7d8fca1a/cffi-2.1.0-cp315-cp315t-win32.whl", hash = "sha256:cb96698e3c7413d906ce83f8ffd245ec1bd94707541f299d0ce4d6b0193e982b", size = 182760, upload-time = "2026-07-06T21:34:22.059Z" }, + { url = "https://files.pythonhosted.org/packages/d3/0b/0ffe8b82d3875bced5fa1e7986a7a46b748262a40ab7f60b475eb9fb1bb3/cffi-2.1.0-cp315-cp315t-win_amd64.whl", hash = "sha256:f146d154428a2523f9cc7936c02353c2459b8f6cf07d3cd1ee1c0a611109c5d5", size = 193769, upload-time = "2026-07-06T21:34:23.589Z" }, + { url = "https://files.pythonhosted.org/packages/a0/17/1073b53b68c9b5ca6914adf5f8bf55aacc2d3be102418c90700160ea8605/cffi-2.1.0-cp315-cp315t-win_arm64.whl", hash = "sha256:cbb7640ce37159548d2147b5b8c241f962143d4c71231431820783f4dc78f210", size = 186405, upload-time = "2026-07-06T21:34:24.857Z" }, +] + +[[package]] +name = "cfgv" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/2a/23f34ec9d04624958e137efdc394888716353190e75f25dd22c7a2c7a8aa/charset_normalizer-3.4.9.tar.gz", hash = "sha256:673611bbd43f0810bec0b0f028ddeaaa501190339cac411f347ac76917c3ae7b", size = 152439, upload-time = "2026-07-07T14:34:58.454Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/81/8e983840c6e5b93b33c2ba81aa3d52c2e42f0e9a690ce7607a2e61da4a5c/charset_normalizer-3.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd6280cf040f233bd7d3407b743b4b4c74f70e8e1c4199cb112a62c941c0772a", size = 322240, upload-time = "2026-07-07T14:32:36.236Z" }, + { url = "https://files.pythonhosted.org/packages/de/d1/b4319dc3229d8272fba305e206fc0a148e2de8d4087917ce62ae6382f359/charset_normalizer-3.4.9-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa99adc8f081b475a12843953db36831eaf83ec33eb46a90629ca6a5de45a616", size = 216475, upload-time = "2026-07-07T14:32:38.142Z" }, + { url = "https://files.pythonhosted.org/packages/80/33/6c99c1b3e6b8bf730e1bc809b9a2608f224145069114c479a2e9e1494346/charset_normalizer-3.4.9-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c1225416b463483160e4af85d5fc3a9690ccb53fd4b1865a6437825f5ede3209", size = 238670, upload-time = "2026-07-07T14:32:39.658Z" }, + { url = "https://files.pythonhosted.org/packages/7f/f4/ffbb83546e1f198ecc70ecd372b65cf2b50f9068b380abd67640f17a8e18/charset_normalizer-3.4.9-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:16d10d789dd9bcca1173c95af82c58433122564b7bc39385124be735a35cbe99", size = 233476, upload-time = "2026-07-07T14:32:41.155Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5f/b98b8da398637b551e427e7be922bdec19177dc54d6811dcdaa503f23aac/charset_normalizer-3.4.9-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9bb41182d93ea91f60b4bc8fbf4c820c69ef8a12ab2d917f3f1834f1acad07e8", size = 223817, upload-time = "2026-07-07T14:32:42.592Z" }, + { url = "https://files.pythonhosted.org/packages/36/31/a276bb2e66243072a3fd06fdcab9cbb61a305b02143d70d2bda21d888fa8/charset_normalizer-3.4.9-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:bcf74c1df76758a395bf0af608c04c82257523f55c9868b334f06270d0f2112b", size = 207974, upload-time = "2026-07-07T14:32:44.258Z" }, + { url = "https://files.pythonhosted.org/packages/5e/be/7ee4453d7e88dfbc4104ccd34900b9f2c7c17dac22881865fe0e82424a25/charset_normalizer-3.4.9-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b5314963fce9b0b12743891de876e724997864ee22aa496f903f426c7e2fa5b2", size = 221655, upload-time = "2026-07-07T14:32:45.64Z" }, + { url = "https://files.pythonhosted.org/packages/1d/85/181c652953eb5276d198f375b1dd641047392050098100a3a02d6534f657/charset_normalizer-3.4.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e9701d0049d92c16703a42771b98d560b95248949f23f8cf7b4eddd201814fb9", size = 219229, upload-time = "2026-07-07T14:32:47.376Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e7/aaf6da33fc9f4691cda8f7efbc9f69179d3d39ec8a4799baf273ee1d8db0/charset_normalizer-3.4.9-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:65a7ff3f705e57d392f7261b6d0550fe137c3019477431f1c355e0db0a7d3e15", size = 209704, upload-time = "2026-07-07T14:32:48.855Z" }, + { url = "https://files.pythonhosted.org/packages/63/01/f2fb3bd3a73be48b173ee0c6aa8d2497af97d5663a8c4c4b491de4c62f7a/charset_normalizer-3.4.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79580094b00d1789d1f93ea55bc43cb2f611910c72235b7657f3482ddcc1b22d", size = 226243, upload-time = "2026-07-07T14:32:50.239Z" }, + { url = "https://files.pythonhosted.org/packages/c4/02/c57a22739fe05246b0b5783b3bfb6afaac4eebb46f3ececdfb2f048f780e/charset_normalizer-3.4.9-cp310-cp310-win32.whl", hash = "sha256:432786d3561e69aeeae6c7e8648964ce0ad05736120135601f87ac26b9c83381", size = 150935, upload-time = "2026-07-07T14:32:51.676Z" }, + { url = "https://files.pythonhosted.org/packages/37/8d/ca39a7559a4797505530d084fd3a49a2c959efbbbff146302fb7be4e3b35/charset_normalizer-3.4.9-cp310-cp310-win_amd64.whl", hash = "sha256:8c041122946b7ba21bb32c45b1aa57b1be35527690aeb3c5c234521085632eee", size = 162314, upload-time = "2026-07-07T14:32:53.193Z" }, + { url = "https://files.pythonhosted.org/packages/01/da/a44bd7a13d426e69e4894557106cd58669097bfad4a8681123b618fbfc5d/charset_normalizer-3.4.9-cp310-cp310-win_arm64.whl", hash = "sha256:375b83ed0aecfce76c16d198fbc21f3b11b337d68662bea0a995046682a11419", size = 153075, upload-time = "2026-07-07T14:32:54.554Z" }, + { url = "https://files.pythonhosted.org/packages/0b/e3/85ec501f206fb049259288c1f3506e53876937fb00edb47009348e66756b/charset_normalizer-3.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0e94703ec9684807f20cfb5eed95c70f67f2a8f21ad620146d7b5a13677b93e5", size = 317075, upload-time = "2026-07-07T14:32:56.021Z" }, + { url = "https://files.pythonhosted.org/packages/c3/69/2a5385192e67175f7d8bd5ce4f57c24bc956439adeae5c13a99aa28a53d1/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a441ea71902098ffe78c5abe6c494f44160b4af614ed16c3d9a3b1d17fd8ee2", size = 213837, upload-time = "2026-07-07T14:32:57.78Z" }, + { url = "https://files.pythonhosted.org/packages/b3/46/03ddc7da576d814fe0a36dd1f0fd3258e95404b4b2e3c026b7923d7e133f/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:304b13570067b2547562e308af560b3963857b1fa90bd6afd978130130fe2d6a", size = 235503, upload-time = "2026-07-07T14:32:59.205Z" }, + { url = "https://files.pythonhosted.org/packages/4e/6e/de0229a7ef40f6f9d28a837eebf4ec47bdca5dab4e900c84f22919af636a/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4773092f8019072343a7447203308b176e10199920eb02d6195e81bbb3274c29", size = 229944, upload-time = "2026-07-07T14:33:00.803Z" }, + { url = "https://files.pythonhosted.org/packages/a5/34/49b9060e8418b14fb5cba9cf6bfb383111e2538a03a1fb18e66a95aeb3d5/charset_normalizer-3.4.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:04ce310cb89c15df659582aee80a0603788732a5e017d5bd5c81158106ce249c", size = 221276, upload-time = "2026-07-07T14:33:02.199Z" }, + { url = "https://files.pythonhosted.org/packages/44/95/80282cce0fae9c3061203d723ee87da996aed79679e65d8935050ee7ca1f/charset_normalizer-3.4.9-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:c0323c9daef75ef2e5083624b4585018a0c9d5e3b40f607eed81a311270b934b", size = 205260, upload-time = "2026-07-07T14:33:03.698Z" }, + { url = "https://files.pythonhosted.org/packages/0c/74/2f62c8821b969ea3bd67cc2e6976834f48ca5d12664d2559ebcd9bcfbed7/charset_normalizer-3.4.9-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:871ff67ea1aad4dfd91736464934d56b32dac49f9fbe16cddba36198a7b3a0db", size = 217786, upload-time = "2026-07-07T14:33:05.12Z" }, + { url = "https://files.pythonhosted.org/packages/d9/8d/feabb82cb49fcad14515b1d7d1ca4787b0da7fc723a212bf89bc9e0fac52/charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:67830fc78e67501f47bb950471b2dcb9b35b140084429318e862895a8e89c993", size = 216798, upload-time = "2026-07-07T14:33:06.629Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ff/c946d63bc3786d5b84d960b0f7ab7e25b828486a946b5aa997625bcaf6a6/charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:3d92613ec25e43b05f042302531ec0f00b8445190e43325880cbd6ab7c2581da", size = 206429, upload-time = "2026-07-07T14:33:08.006Z" }, + { url = "https://files.pythonhosted.org/packages/af/ba/5e5007c370702f85d2ef75791fac7943ed41e080364a673b20142e430e3e/charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:280081916dc341820640489a66e4696049401ef1cf6dd672f672e70ad915aca3", size = 223066, upload-time = "2026-07-07T14:33:09.783Z" }, + { url = "https://files.pythonhosted.org/packages/83/d5/9096aa3cf532dfad237861544eb47a0f20d5adbf1039760fed8eaae935d9/charset_normalizer-3.4.9-cp311-cp311-win32.whl", hash = "sha256:ac351b3b8014eead140e77e9717e2992c6bbe30b63bc3422422eb84865412e3d", size = 150456, upload-time = "2026-07-07T14:33:11.217Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a1/e29995109e455dc8eff8d0fac6ae509be39561318a7cfeac5d33ad029213/charset_normalizer-3.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:6366a16e1a25018694d6a5d784d09b046edc9eac40ea2b54065c3052672516a1", size = 161410, upload-time = "2026-07-07T14:33:12.743Z" }, + { url = "https://files.pythonhosted.org/packages/4f/8d/1569f4d0032d6ba2a4fe4591c35bf87868c600c41a71eb5c2e1ffa8464c2/charset_normalizer-3.4.9-cp311-cp311-win_arm64.whl", hash = "sha256:1d22856ffbe153a602df38e4a5464f0b748a54002e0d69ac6d2ad0a197cc99ec", size = 152649, upload-time = "2026-07-07T14:33:14.173Z" }, + { url = "https://files.pythonhosted.org/packages/70/4a/ecbd131485c07fcdfad54e28946d513e3da22ef3b4bd854dcafae54ec739/charset_normalizer-3.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:45b0cc4e3556cd875e09102988d1ab8356c998b596c9fced84547c8138b487a0", size = 319300, upload-time = "2026-07-07T14:33:15.666Z" }, + { url = "https://files.pythonhosted.org/packages/ec/96/5d9364e3342d69f3a045e1777bc47c85c383e6e9466d561b33fdb419d1f9/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9b2aff1c7b3884512b9512c3eaadd9bab39fb45042ffaaa1dd08ff2b9f8109d9", size = 215802, upload-time = "2026-07-07T14:33:17.031Z" }, + { url = "https://files.pythonhosted.org/packages/4b/4c/5361f9aa7f2cb58d94f2ab831b3d493f69efb1d239654b4744e3c09527cb/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9104ed0bd76a429d46f9ec0dbc9b08ad1d2dcdf2b00a5a0daa1c145329b35b44", size = 237171, upload-time = "2026-07-07T14:33:18.576Z" }, + { url = "https://files.pythonhosted.org/packages/50/78/ce342ca4ff30b2eb49fe6d9578df85974f90c67d294113e94efdd9664cbd/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7b86a2b16095d250c6f58b3d9b2eee6f4147754344f3dab0922f7c9bf7d226c9", size = 233075, upload-time = "2026-07-07T14:33:20.084Z" }, + { url = "https://files.pythonhosted.org/packages/01/c4/4fa4c8b3097a11f3c5f09a35b72ed6855fb1d332469504962ab7bafcc702/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e226f6218febc71f6c1fc2fafb91c226f75bdc1d8fb12d66823716e891608fd", size = 224256, upload-time = "2026-07-07T14:33:21.747Z" }, + { url = "https://files.pythonhosted.org/packages/87/3a/ad914516df7e358a81aae018caa5e0470ba827fa6d763b1d2e87d920a5f6/charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:90c44bc373b7687f6948b693cceaea1348ae0975d7474746559494468e3c1d84", size = 208784, upload-time = "2026-07-07T14:33:23.313Z" }, + { url = "https://files.pythonhosted.org/packages/d7/74/3c12f9755717dfe5c5c87da63f35d765fa0c00382ec26bf23f7fae34f2ba/charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cdef90ae47919cae358d8ab15797a800ed41da7aba5d72419fb510729e2ed4b", size = 219928, upload-time = "2026-07-07T14:33:24.814Z" }, + { url = "https://files.pythonhosted.org/packages/33/9a/895095b83e7907abd6d3d99aad3a38ad0d9686cc186cb0c94c24320fe63e/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:60f44ade2cf573dad7a277e6f8ca9a51a21dda572b13bd7d8539bb3cd5dbedde", size = 218489, upload-time = "2026-07-07T14:33:26.42Z" }, + { url = "https://files.pythonhosted.org/packages/a1/34/ef5c05f412f42520d7709b7d3784d19640839eb7366ded1755511585429f/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a1786910334ed46ab1dd73222f2cd1e05c2c3bb39f6dddb4f8b36fc382058a39", size = 210267, upload-time = "2026-07-07T14:33:27.952Z" }, + { url = "https://files.pythonhosted.org/packages/83/dc/9b29fa4412b318bf3bfea985c35d67eb55e04b59a7c3f2237168b0e0be6f/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03d07803992c6c7bbc976327f34b18b6160327fc81cb82c9d504720ac0be3b62", size = 226030, upload-time = "2026-07-07T14:33:29.397Z" }, + { url = "https://files.pythonhosted.org/packages/0e/42/6dbc00b8cd16011691203e33570fa42ed5746599a2e878112d16eab403a3/charset_normalizer-3.4.9-cp312-cp312-win32.whl", hash = "sha256:78841cccf1af7b40f6f716338d50c0902dbe88d9f800b3c973b7a9a0a693a642", size = 151185, upload-time = "2026-07-07T14:33:30.781Z" }, + { url = "https://files.pythonhosted.org/packages/80/cc/f920afd1a23c58ccd53c1d36085a71893a4737ff5e66e0371efab6809850/charset_normalizer-3.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:4b3dac63058cc36820b0dd072f89898604e2d39686fe05321729d00d8ac185a0", size = 162557, upload-time = "2026-07-07T14:33:32.176Z" }, + { url = "https://files.pythonhosted.org/packages/f0/e6/0386d43a261ff4e4b30c5857af7df877254b46bec7b9d1b74b6bf969a90b/charset_normalizer-3.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:78fa18e436a1a0e58dbd7e02fc4473f3f32cceb12df9dfca542d075961c307d2", size = 152665, upload-time = "2026-07-07T14:33:33.711Z" }, + { url = "https://files.pythonhosted.org/packages/b2/06/97ec2aeae780b31d742b6352218b43841a6871e2564578ca522dce4a45c3/charset_normalizer-3.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:440eede837960000d74978f0eba527be106b5b9aee0daf779d395276ed0b0614", size = 317688, upload-time = "2026-07-07T14:33:35.408Z" }, + { url = "https://files.pythonhosted.org/packages/d0/39/8ff066c672434225f8d25f8b739f992af250944392173dcc88362681c9bf/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21e764fd1e70b6a3e205a0e46f3051701f98a8cb3fad66eeb80e48bb502f8698", size = 214982, upload-time = "2026-07-07T14:33:36.996Z" }, + { url = "https://files.pythonhosted.org/packages/92/8f/3a47a3667c83c2df9483d91644c6c107de3bf8874aa1793da9d3012eb986/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e4fd89cc178bced6ad29cb3e6dd4aa63fa5017c3524dbd0b25998fb64a87cc8b", size = 236460, upload-time = "2026-07-07T14:33:38.536Z" }, + { url = "https://files.pythonhosted.org/packages/f1/60/b22cdbee7e4013dab8b0d7647fc6181120fbbbc8f7025c226d15bd5a47fc/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bd47ba7fc3ca94896759ea0109775132d3e7ab921fbf54038e1bab2e46c313c9", size = 232003, upload-time = "2026-07-07T14:33:40.059Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f8/72eb13dcabe7257035cea8aefd922caad2f110d252bf9f67c4c2ca763aee/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:84fd18bcc17526fc2b3c1af7d2b9217d32c9c04448c16ec693b9b4f1985c3d33", size = 223149, upload-time = "2026-07-07T14:33:41.631Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3e/faee8f9de92b14ee1198e9163252bb15efee7301b31256a3b6d9ebfdd0dd/charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:5b10cd92fc5c498b35a8635df6d5a100207f88b63a4dc1de7ef9a548e1e2cd63", size = 207901, upload-time = "2026-07-07T14:33:43.209Z" }, + { url = "https://files.pythonhosted.org/packages/3a/25/45f30093ae27dd7b92a793b61882a38685f993700113ca36e0c9c14965e1/charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4fbdde9dd4a9ce5fd52c2b3a347bb50cc89483ef783f1cb00d408c13f7a96c0", size = 219176, upload-time = "2026-07-07T14:33:44.725Z" }, + { url = "https://files.pythonhosted.org/packages/48/18/c8f397329c35e32f6a837e488986f4ae03bd2abebc453b48714991630c2f/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:416c229f77e5ea25b3dfd4b582f8d73d7e43c22320302b9ab128a2d3a0b38efe", size = 217356, upload-time = "2026-07-07T14:33:46.192Z" }, + { url = "https://files.pythonhosted.org/packages/86/7e/5ce0bba863470fd1902d5e5843968951bddf38abe4742fc97116ef4598b3/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:75286256590a6320cf106a0d28970d3560aad9ee09aa7b34fb40524792436d35", size = 209614, upload-time = "2026-07-07T14:33:47.705Z" }, + { url = "https://files.pythonhosted.org/packages/6c/ef/2473d3c4d869155be4af1191111d59c4d5c4e0173026f7e85b176e23bf65/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:69b157c5d3292bcd443faca052f3096f637f1e074b98212a933c074ae23dc3b8", size = 224991, upload-time = "2026-07-07T14:33:49.238Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a3/53ddae3db108a088156aa8ddfafd411ebbc1340f48c5573f697b27f69a39/charset_normalizer-3.4.9-cp313-cp313-win32.whl", hash = "sha256:51307f5c71007673a2bf8232ad973483d281e74cb99c8c5a990af1eefa6277d9", size = 150622, upload-time = "2026-07-07T14:33:50.711Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ef/6953a77c7cf2c2ff9998e6f575ab3e380119f100223381565a4f94c1f836/charset_normalizer-3.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:fe2c7201c642b7c308f1675355ad7ff7b66acfe3541625efe5a3ad38f29d6115", size = 161947, upload-time = "2026-07-07T14:33:52.197Z" }, + { url = "https://files.pythonhosted.org/packages/6e/fb/d560d1d1555debbfe7849d9cac6145c1b537709d79576bf22557ed803b82/charset_normalizer-3.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:611057cc5d5c0afc743ba8be6bd828c17e0aaa8643f9d0a9b9bb7dea80eb8012", size = 152594, upload-time = "2026-07-07T14:33:53.486Z" }, + { url = "https://files.pythonhosted.org/packages/7e/8d/496817fa0944239ecae662dd57ea765cfeaec6a735f9f025d4b7b72e7143/charset_normalizer-3.4.9-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:0327fcd59a935777d83410750c50600ee9571af2846f71ce40f25b13da1ef380", size = 317253, upload-time = "2026-07-07T14:33:54.994Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f9/ef4a69ea338ad3c0deceea0f5f7d2380ae8b52132b06d652cb0d2cd86706/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a79d9f4d8001473a30c163556b3c3bfebec837495a412dde78b51672f6134f9", size = 215898, upload-time = "2026-07-07T14:33:56.334Z" }, + { url = "https://files.pythonhosted.org/packages/8c/e7/5ddfd76fc061eb52de219658a4aa431cbacadf0a0219c8854f00da50d289/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:33bdcc2a32c0a0e861f60841a512c8acc658c87c2ac59d89e3a46dacf7d866e4", size = 236718, upload-time = "2026-07-07T14:33:57.9Z" }, + { url = "https://files.pythonhosted.org/packages/49/ba/768fa3f36048d81c477a0ce61f813bc1454d80917ccfe550abd9f44f5e24/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f840ed6d8ecba8255df8c42b87fadeda98ddfc6eeec05e2dc66e26d46dd6f58a", size = 232519, upload-time = "2026-07-07T14:33:59.811Z" }, + { url = "https://files.pythonhosted.org/packages/f4/c4/b3e049d2aa3766180c78507110543d9d50894cc97f57de543f1be521dcdc/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c25fe15c70c59eb7c5ce8c06a1f3fa1da0ecc5ea1e7a5922c40fd2fa9b0d5046", size = 223143, upload-time = "2026-07-07T14:34:01.517Z" }, + { url = "https://files.pythonhosted.org/packages/19/79/55c32d06d76ae4feafe053f061f3e3ab70bcf19f4007797ce8c3efda7830/charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:f7fb7d750cfa0a070d2c24e831fd3481019a60dd317ea2b39acbcebc08b6ed81", size = 206742, upload-time = "2026-07-07T14:34:03.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/e0/47c079dd82d217c807479cd59ffd30af56307ea31c108b75758970459ad3/charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4d1c96a7a18b9690a4d46df09e3e3382406ae3213727cd1019ebade1c4a81917", size = 219191, upload-time = "2026-07-07T14:34:04.657Z" }, + { url = "https://files.pythonhosted.org/packages/42/ab/b9bc2e77d6b44a7e46ef62ec5cac1c9a6ba7b9135a5d560f002696ec9995/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a4cfde78a9f2880208d16a93b795726a3017d5977e08d1e162a7a31322479c41", size = 218328, upload-time = "2026-07-07T14:34:06.115Z" }, + { url = "https://files.pythonhosted.org/packages/f1/78/c9c71d599f5aa2d42bcdd35cbbd46d7f535351a57e40ff7d8e5a7e219401/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4d6fcde76f94f5cb9e43e9e9a61f16dacefd228cbbf6f1a09bd9b219a92f1a1", size = 207406, upload-time = "2026-07-07T14:34:07.554Z" }, + { url = "https://files.pythonhosted.org/packages/f6/39/c914445c321a845097ce4f6ac7de9a18228a77b766272125a1ce00d851eb/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:898f0e9068ca27d37f8e83a5b962821df851532e6c4a7d615c1c033f9da6eedf", size = 225157, upload-time = "2026-07-07T14:34:09.061Z" }, + { url = "https://files.pythonhosted.org/packages/9b/f2/c0d4b8508565a36bc5c624e88ed297f5b0b1095011034d7f5b83a69908b5/charset_normalizer-3.4.9-cp314-cp314-win32.whl", hash = "sha256:c1c948747b03be832dceed96ca815cef7360de9aa19d37c730f8e3f6101aca48", size = 151095, upload-time = "2026-07-07T14:34:10.901Z" }, + { url = "https://files.pythonhosted.org/packages/49/fd/a1d26144398c67486422a72bf5812cda22cb4ccfcd95a290fb41ceb4b8e2/charset_normalizer-3.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:16b65ea0f2465b6fb52aa22de5eca612aa964ddfec00a912e26f4656cbef890b", size = 162796, upload-time = "2026-07-07T14:34:12.47Z" }, + { url = "https://files.pythonhosted.org/packages/20/95/d75e82f8ce9fd323ebf059c16c9aadefb22a1ecde13b7840b35835e4886c/charset_normalizer-3.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:40a126142a56b2dfc0aacbad1de8310cbf60da7656db0e6b16eebd48e3e93519", size = 153334, upload-time = "2026-07-07T14:34:14.044Z" }, + { url = "https://files.pythonhosted.org/packages/00/5e/17398df3a139985ba9d11ed072531986f408c8fca952835ef1ab1820c02b/charset_normalizer-3.4.9-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:609b3ba8fcc0fb5ab7af00719d0fb6ad0cb518e48e7712d12fd68f1327951198", size = 338848, upload-time = "2026-07-07T14:34:15.688Z" }, + { url = "https://files.pythonhosted.org/packages/cd/91/7253a32e86b7e1d1239b1b36ba6dd0f021a21107ab33054b53119cc083b9/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51447e9aa2684679af07ca5021c3db526e0284347ebf4ffcec1154c3350cfe32", size = 223022, upload-time = "2026-07-07T14:34:17.248Z" }, + { url = "https://files.pythonhosted.org/packages/cb/32/2e64bd2be10e89c61e57ebe6a93fd98ae88eb7ebe414b5121f22c96c69eb/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cc1b0fff8ead343dae06305f954eb8468ba0ec1a97881f42489d198e4ce3c632", size = 241590, upload-time = "2026-07-07T14:34:18.813Z" }, + { url = "https://files.pythonhosted.org/packages/3d/ef/d96ec496cfea0c21db43b0ad03891308b02388d054cc902cf0e5a1ad6a88/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fa36ec09ef71d158186bc79e359ff5fdd6e7996fe8ab638f00d6b93139ba4fcf", size = 239584, upload-time = "2026-07-07T14:34:20.52Z" }, + { url = "https://files.pythonhosted.org/packages/d4/ce/9af95f7876194bd7a14e3dfe4a4de2e0bff02666a3910d72beafd06cc297/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df115d4d83168fdf2cae48ef1ff6d1cb4c466364e30861b37121de0f3bf1b990", size = 230224, upload-time = "2026-07-07T14:34:22.189Z" }, + { url = "https://files.pythonhosted.org/packages/52/94/af74dde74a3996bd959c350709bfe50e297823d70a8c1cbd54b838880863/charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f86c6358749bd4fda175388691e3ba8c46e24c5347d0afd20f9b7edfc9faf07d", size = 212667, upload-time = "2026-07-07T14:34:23.857Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f0/f1c4fe746c395922961b5916ed1d7d6e7d4c84851d19ed43cc89980ec953/charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:32286a2c8d167e897177b673176c1e3e00d4057caf5d2b64eef9a3666b03018e", size = 227179, upload-time = "2026-07-07T14:34:25.586Z" }, + { url = "https://files.pythonhosted.org/packages/e4/56/6c745619ac397e8871e2bcd3cea1eec86b877488f33888b3aef5c3ed506e/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:83aed2c10721ddd90f68140685391b50811a880af20654c59af6b6c66c40513c", size = 225372, upload-time = "2026-07-07T14:34:27.212Z" }, + { url = "https://files.pythonhosted.org/packages/78/ad/98aae8630ac71f16711968e38a5acfecce41b778bf2f0312851020f565a8/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cd6c3d4b783c556fa00bf540854e42f135e2f256abd29669fcd0da0f2dec79c2", size = 215222, upload-time = "2026-07-07T14:34:28.774Z" }, + { url = "https://files.pythonhosted.org/packages/f7/40/9593d54209765207a7f11073c06494c1721e4ca4a0a426c597679bf7f91e/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ee2f2a527e3c1a6e6411eb4209642e138b544a2d72fe5d0d76daf77b24063534", size = 231958, upload-time = "2026-07-07T14:34:30.345Z" }, + { url = "https://files.pythonhosted.org/packages/b1/27/693ee5e8a18191eb38647360c51cd505013e2bd3b366aa43fd5344c21e3c/charset_normalizer-3.4.9-cp314-cp314t-win32.whl", hash = "sha256:0d861473f743244d349b50f850d10eb87aeb22bbdcc8e64f79273c94af5a8226", size = 155580, upload-time = "2026-07-07T14:34:31.884Z" }, + { url = "https://files.pythonhosted.org/packages/80/3f/bd97d3d9c613013d07cb7733d299385b41df37f0471310f5a73dc359f0b8/charset_normalizer-3.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:9b8e0f3107e2200b76f6054de99016eac3ee6762713587b36baaa7e4bd2ae177", size = 167620, upload-time = "2026-07-07T14:34:33.438Z" }, + { url = "https://files.pythonhosted.org/packages/3d/c6/eee9dca4439b1061f76373f06ea855678cc4a64c1c3c90b50e479edbb8eb/charset_normalizer-3.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:19ac87f93086ce37b86e098888555c4b4bc48102279bae3350098c0ed664b501", size = 158037, upload-time = "2026-07-07T14:34:35.018Z" }, + { url = "https://files.pythonhosted.org/packages/98/2b/f97f1c193fb855c345d678f5077d6926034db0722df74c8f057020e05a25/charset_normalizer-3.4.9-py3-none-any.whl", hash = "sha256:68e5f26a1ad57ded6d1cfb85331d1c1a195314756471d97758c48498bb4dcdf5", size = 64538, upload-time = "2026-07-07T14:34:56.993Z" }, +] + +[[package]] +name = "click" +version = "8.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/d4/81420972a676e8ffea40450d8c8c92943e7218a78fe9b64359836cc9876b/click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", size = 338000, upload-time = "2026-06-24T17:45:15.148Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/e2/79c688af8b210d232694e31e59da9f6ec747bae31c3f5946e4e9b98860d5/click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76", size = 119243, upload-time = "2026-06-24T17:45:13.73Z" }, +] + +[[package]] +name = "codespell" +version = "2.4.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2d/9d/1d0903dff693160f893ca6abcabad545088e7a2ee0a6deae7c24e958be69/codespell-2.4.2.tar.gz", hash = "sha256:3c33be9ae34543807f088aeb4832dfad8cb2dae38da61cac0a7045dd376cfdf3", size = 352058, upload-time = "2026-03-05T18:10:42.936Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/a1/52fa05533e95fe45bcc09bcf8a503874b1c08f221a4e35608017e0938f55/codespell-2.4.2-py3-none-any.whl", hash = "sha256:97e0c1060cf46bd1d5db89a936c98db8c2b804e1fdd4b5c645e82a1ec6b1f886", size = 353715, upload-time = "2026-03-05T18:10:41.398Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "comm" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971", size = 6319, upload-time = "2025-07-25T14:02:04.452Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" }, +] + +[[package]] +name = "coverage" +version = "7.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/8b/adeb62ea8951f13c4c7fef2e7a85e1a06b499c8d8237ea589d496029e53f/coverage-7.15.0.tar.gz", hash = "sha256:9ac3fe7a1435986463eaa8ee253ae2f2a268709ba4ae5c7dd1f52a05391ad78f", size = 925362, upload-time = "2026-07-02T13:10:50.535Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/97/c52dc440c390b6cfa87be9432b141a956e2d56d9b9f5fc8bd71c5f471722/coverage-7.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50913d4bf5ddafa6ca3693da5e4dd833dd1b772e0283c99ca7f7d287db67331a", size = 220539, upload-time = "2026-07-02T13:08:19.252Z" }, + { url = "https://files.pythonhosted.org/packages/3f/26/602de8c2aec7e2e3e99ebfb8e04ba65598f746275396eea5f6794ff4673f/coverage-7.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:359e141ccd33893ce3f1ad5525f8b96083003677c82182e5907d62d4ea5799fc", size = 221058, upload-time = "2026-07-02T13:08:21.013Z" }, + { url = "https://files.pythonhosted.org/packages/fc/13/ebab0743138891c1d646d61e247ec29639afcbb6c4e1905e6a0f0c75291a/coverage-7.15.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3200b6204935f928c64b2ca1f923ab8c1acb7c9de45ec61569711b34d25cccaf", size = 247797, upload-time = "2026-07-02T13:08:22.474Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b7/b6ffb9e042aa48dc4144a8a65529affaec8dca0685309353614a2a7386ad/coverage-7.15.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:be616bf61346883b2cfdc5178669647e03531d81ab761a7e378558b7e8bcb628", size = 249626, upload-time = "2026-07-02T13:08:23.803Z" }, + { url = "https://files.pythonhosted.org/packages/9c/06/243ff05b652333d8e3d060c11223efc2723b19cacf6605e433fa686ab5d4/coverage-7.15.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc7bafc3fe1059463a8fdd97ca79972d6e2bf819d775c7d54991b5b1971201d6", size = 251493, upload-time = "2026-07-02T13:08:25.397Z" }, + { url = "https://files.pythonhosted.org/packages/d3/2b/867faa17030a806114dae388b32a3fa929d8cd4bf39226fbc11f6e6bb705/coverage-7.15.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b713aa7fcf325a01d4184d848acb46fd84f78fdb0978470c636b23a06a753d91", size = 253406, upload-time = "2026-07-02T13:08:26.842Z" }, + { url = "https://files.pythonhosted.org/packages/94/c0/d789ce18f6605afc4895db75723424be2ef494282f77f61d8e5832923183/coverage-7.15.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e38e6fba2d56652fdfaf0231f8f78aeb805234a912de25dc291ee5cce5b8faa4", size = 248512, upload-time = "2026-07-02T13:08:28.398Z" }, + { url = "https://files.pythonhosted.org/packages/c9/b6/b2673c30739f4a2e06649a0a38ad8b093c4d865462dc7bab0e9524a2c3b1/coverage-7.15.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:884499f42e382675be80770391983b90e0c0c774d87dbeeebf5f991cf6612b20", size = 249532, upload-time = "2026-07-02T13:08:29.731Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/acd79e9a41beabee92b623afe4f30b549916f48566271475f2907e752828/coverage-7.15.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:840481b12e083dbcbafab14794a8781a958edf327c8d3d70b4eee42f9b8253aa", size = 247537, upload-time = "2026-07-02T13:08:31.173Z" }, + { url = "https://files.pythonhosted.org/packages/12/d4/2d301c4d1b3238d7c88b70ab9d13fd53ed9505662a7ff1b46ba1e2e4e3c3/coverage-7.15.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:276646e9481703d09f854f3b2f018f24e19fd7049ae670a92570043eb97203b1", size = 251348, upload-time = "2026-07-02T13:08:32.63Z" }, + { url = "https://files.pythonhosted.org/packages/35/bb/c67708b2bc00f32e12805ec23d5fa677a0a51652f449341a89f9d6b1b715/coverage-7.15.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4de4b4d3f5545aa6c60dc4efd9c63b5b5dcc3bf00fe83146b2bdfffb8f6613bd", size = 247806, upload-time = "2026-07-02T13:08:33.931Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6c/57c4f653c47a6e917748f8938e389e72fbcae44e3643cd906664f0477a13/coverage-7.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5c504097b2a89b1e85bc6070d920df77daec701337e3aeef2c17775a5dd0ca90", size = 248410, upload-time = "2026-07-02T13:08:35.189Z" }, + { url = "https://files.pythonhosted.org/packages/6c/94/bb083041aef828903668f134273f319f2bd49224962875359c52faa5497f/coverage-7.15.0-cp310-cp310-win32.whl", hash = "sha256:f6e80ed91f98316e86b9c137206b04b2bcfbffccbdff49bd2eb09dddb1cf14e0", size = 222588, upload-time = "2026-07-02T13:08:36.486Z" }, + { url = "https://files.pythonhosted.org/packages/ef/94/a09d8ee618956f626741b0734854bac4425a00e10c0565f5abca64e7e751/coverage-7.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:b3b3e22030f3f6f5e01a5ce69936552a5c0f6992b7698777377b99041961031f", size = 223214, upload-time = "2026-07-02T13:08:37.885Z" }, + { url = "https://files.pythonhosted.org/packages/ae/23/82e910835ef4b8391047025e1d53aa48d66029f444eb8b25373c849bf503/coverage-7.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:003fff99412ea848c0aaebcc78ed2b6ce7d8a1227ed17e68470672770b78a02a", size = 220662, upload-time = "2026-07-02T13:08:39.205Z" }, + { url = "https://files.pythonhosted.org/packages/6d/0d/c7b213dde2f1579de5231062b386d8413f79c11667eb58c39319b25991da/coverage-7.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5cbd804bf2784ce7b45114516050f346ecd50f960c4bb630a7ee9e1d78fa2118", size = 221168, upload-time = "2026-07-02T13:08:40.471Z" }, + { url = "https://files.pythonhosted.org/packages/33/77/d000aeedfac085088337b3c7becdad328474b1f8a9e4c9368a0c99605d68/coverage-7.15.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8773e15c23305b58882a4611fb9b2755977eae0dc2e515366a1b6c98866cc4c2", size = 251587, upload-time = "2026-07-02T13:08:42.033Z" }, + { url = "https://files.pythonhosted.org/packages/cc/e0/86787c56b9df17afd370d5e293515dd4d9a107a561d13054873eefad8ecc/coverage-7.15.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f50e40081494c1dc4239ebb202014cbcc3306ea96fb6302a34c8cc0967fc5ae8", size = 253497, upload-time = "2026-07-02T13:08:43.387Z" }, + { url = "https://files.pythonhosted.org/packages/3f/02/181bc917359299c07dead6270f94e411151c8b60cec905c33499da69afe6/coverage-7.15.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daf96f37f5fc3a7b6c6da862eb4aee61c426bd63da236ed4a73ef0e503b4bca5", size = 255607, upload-time = "2026-07-02T13:08:44.897Z" }, + { url = "https://files.pythonhosted.org/packages/b9/35/ca5e7427699913da6788c4f910e73ab16c5f4b59ec5d3a999dce2a45112f/coverage-7.15.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:51aa20f6ae2788fd197747766edf4cd8234fd9423309b934257fa6b21a592723", size = 257563, upload-time = "2026-07-02T13:08:46.334Z" }, + { url = "https://files.pythonhosted.org/packages/0b/4d/b8220bacc2fc3c4e9078e27c32e99fb411479a4718a72bdd00036a9891c8/coverage-7.15.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03d1f922757662eb7af586e77834792274cff776bc7b1d1a0b66a49ea9d84735", size = 251726, upload-time = "2026-07-02T13:08:47.941Z" }, + { url = "https://files.pythonhosted.org/packages/c4/e4/2e145da1991d72189b9c3cf7eca05c716ee7080d099aaea6757cfc7df008/coverage-7.15.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a6d6acc9a7666245e6133dd15144ca038a85a9cd5026bb06d6bbae9e77440dc9", size = 253301, upload-time = "2026-07-02T13:08:49.5Z" }, + { url = "https://files.pythonhosted.org/packages/72/28/d2c841d698bf762e481f08bd4839d370246b6d9b61dab085a7b20b201a08/coverage-7.15.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1ac2c4c27c7df851dc9a017c2d7de00b69147e84ba3d96f37a530b0b6fb51035", size = 251361, upload-time = "2026-07-02T13:08:51.304Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ed/55d9ffde994fba3897c0c783f77a7d053b0c18787f6892ed5b0aed73f469/coverage-7.15.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b761a1d504fd4bd1f20f418753964dca9f5862a511fc854dac58296b3b223671", size = 255129, upload-time = "2026-07-02T13:08:52.661Z" }, + { url = "https://files.pythonhosted.org/packages/1d/c0/ecbf33b8c460ea2718aeb813e2df8140d0370e5f67261c31524ceb0a2a8d/coverage-7.15.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e43b045e11c16e897895758ae90e4a90cf99e93d58549e2f90c0e2272e155695", size = 251081, upload-time = "2026-07-02T13:08:54.188Z" }, + { url = "https://files.pythonhosted.org/packages/a9/de/fb87b4261f54448dd2b9504ef19a58be42cef0d9520595fbfe1219b15234/coverage-7.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:589b54513e901739f4b4582c705ce96b80c96f57641b1464607e2367a270e540", size = 251988, upload-time = "2026-07-02T13:08:55.726Z" }, + { url = "https://files.pythonhosted.org/packages/df/27/3494d5f291b9a4cb868f73c11221a8bd2d5bd761a8f9acea61ff57128dd1/coverage-7.15.0-cp311-cp311-win32.whl", hash = "sha256:106781b8482749162d0b47056937ba0933508e5d9447f65a5e7d5c422f0d6bb4", size = 222754, upload-time = "2026-07-02T13:08:57.091Z" }, + { url = "https://files.pythonhosted.org/packages/2a/ee/cd4847ebc9be6a9c0123d763645a6f1f3be6b8c58c962706368b79cbac07/coverage-7.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:821e92b3631d762a339695824cadbbc73020354eba2a23a551a99ad34938fbe6", size = 223225, upload-time = "2026-07-02T13:08:58.594Z" }, + { url = "https://files.pythonhosted.org/packages/57/37/5011581aa7f2be498b97dcc7c9902192442a42f4f9a748aeadb3d6506b42/coverage-7.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:309990eb5fb8014b9f67cb211f7fd41876ec8a88a88d3ae76de0ed1d611e3640", size = 222774, upload-time = "2026-07-02T13:09:00.074Z" }, + { url = "https://files.pythonhosted.org/packages/2a/74/fd4c0901137c4f8d81a76ada99e43c65163b4c94a02ece107a4ec0c6b615/coverage-7.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b75ee5e8cb7575636ac598719b4307ac529ec8fcd79608a35c3cd4d4dada812d", size = 220838, upload-time = "2026-07-02T13:09:02.084Z" }, + { url = "https://files.pythonhosted.org/packages/0f/2e/2347583467bd7f0402635101a916961915cc68fce652cd0db5f173ea04fc/coverage-7.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffb31267816b93b075302248cc1737506081b4f163df4401e9df1a6424aafabe", size = 221197, upload-time = "2026-07-02T13:09:03.617Z" }, + { url = "https://files.pythonhosted.org/packages/f0/17/99fa688541ae1d6e84543a0e544f83de0c944815b63e9e7b1ed411d15036/coverage-7.15.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e4d0bb73455bf97ab243a8f12c37c686ccf1c13bb614b7b85f1d062f06f42b2c", size = 252705, upload-time = "2026-07-02T13:09:05.059Z" }, + { url = "https://files.pythonhosted.org/packages/fb/02/6a95a5cd83b74839017ef9cf48d2d8c9ae60af919e17a3f336e6f9f1b7bd/coverage-7.15.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:20d9ccc4ebd0edc434d86dfd2a1dd2a8efa6b6b3073d0485a394fee86459ebb4", size = 255441, upload-time = "2026-07-02T13:09:06.559Z" }, + { url = "https://files.pythonhosted.org/packages/67/f2/406f6c57d600f68185942422c4c00f1a3255d60aee6e5fd961425cd9987e/coverage-7.15.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20c8a976c365c8cb12f0cbd099508772ea41fb5fa80657a8506df0e11bd278c5", size = 256556, upload-time = "2026-07-02T13:09:08.197Z" }, + { url = "https://files.pythonhosted.org/packages/74/8e/d3fa48489c15ecdec1ba48fd61f68798555dddd2f6716f9ad42adeb1a2a9/coverage-7.15.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f948fd5ba1b9cbca91f0ae08b4c1ce2b139509149a435e2585d056d57d70bf01", size = 258815, upload-time = "2026-07-02T13:09:09.691Z" }, + { url = "https://files.pythonhosted.org/packages/47/2e/2d40ddd110462c6a2769677cf7f1c119a52b45f568978fc6c98e4cc0dd0f/coverage-7.15.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f58185f06edf6ad68ec9fb155d63ef650c82f3fbd7e1770e2867751fb13158f4", size = 253117, upload-time = "2026-07-02T13:09:11.212Z" }, + { url = "https://files.pythonhosted.org/packages/51/c0/310782f0d7c3cb2b5ac05ba8d205fe91f24a36f6bf3256098f1782181c38/coverage-7.15.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02adc79a920c73c647c5d117f55747df7f2de94571884758ce8bc58e04f0a796", size = 254475, upload-time = "2026-07-02T13:09:13.029Z" }, + { url = "https://files.pythonhosted.org/packages/86/f7/702da6c275f8ae6ade423d2877243122932c9b27f5403003b9ef8c927d12/coverage-7.15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6eb7c300fbed667fd6e3588eba71c1904cdb06110ca6fdf908c26bdd88b8e382", size = 252619, upload-time = "2026-07-02T13:09:14.699Z" }, + { url = "https://files.pythonhosted.org/packages/fb/84/c5b15a7e5ecba4e56218d772d99fe80a63e63f8d11f12783723a6005ab45/coverage-7.15.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b5fb23fa2de9dce1f5c36c09066d8fcda16cd96e8e26686caa2d7cb9b567d65c", size = 256689, upload-time = "2026-07-02T13:09:16.103Z" }, + { url = "https://files.pythonhosted.org/packages/95/2f/c8b07559b57701230c61b23a953858c052890c12ef568d81780c6c46e92e/coverage-7.15.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:cec79341dbe6281484024979976d0c7f22beae08b4a254655decd25d42cbe766", size = 252189, upload-time = "2026-07-02T13:09:17.828Z" }, + { url = "https://files.pythonhosted.org/packages/6b/80/6d2f049dd3fd3dbfd60b62ba6b2162a04009e2c002ce70b24cf3878dec7a/coverage-7.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c664c5444b1d970b1b2a450e21fb19ee5c9cfdf151ded2dda37260031cca0da", size = 254059, upload-time = "2026-07-02T13:09:19.304Z" }, + { url = "https://files.pythonhosted.org/packages/ce/92/b0287a2c42031d25c628f815f89a3cd9f8268ee78bb1252c9356cda1c689/coverage-7.15.0-cp312-cp312-win32.whl", hash = "sha256:5f764a3fa339bde6b3aa97657f5a6a3a9451e4a5b4ea98a2892c773a43525f77", size = 222893, upload-time = "2026-07-02T13:09:20.812Z" }, + { url = "https://files.pythonhosted.org/packages/a9/69/e34c481915fecb499b3146975061dac528752e37706edc1804f32c822469/coverage-7.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:52f9a4d2c4c56c8848bc2f524916698354b0211488b38c49ad9ae54f6cafbff6", size = 223429, upload-time = "2026-07-02T13:09:22.315Z" }, + { url = "https://files.pythonhosted.org/packages/fe/98/6e878f0b571d32684ef3f38d7c03db241ca5b82a5da8a5391596a8f209c4/coverage-7.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:31e5c3e70c85307ea35a12964e2e40f56ca2ee4b1c8c721ccf4609d17071080b", size = 222810, upload-time = "2026-07-02T13:09:23.812Z" }, + { url = "https://files.pythonhosted.org/packages/76/04/145a3748098bcc86b631a85408d2c3dc5c104e0bd86d605468239b25b6c4/coverage-7.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5be4caf3b28836f078abe700f8944dac4a65d78f16d6c600c89cb624e5535782", size = 220863, upload-time = "2026-07-02T13:09:25.371Z" }, + { url = "https://files.pythonhosted.org/packages/a4/5c/4ed55708fed2c64b63c9bc5715daef670872202101938869b7fe5d5fbb8f/coverage-7.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dd58ad1404704303ca8d4f4b8a1095e7cbc7040ef17a66df1e6619aa10176430", size = 221230, upload-time = "2026-07-02T13:09:26.897Z" }, + { url = "https://files.pythonhosted.org/packages/7b/19/3a80b97d3b2a5c77a01ae359c6bed20c13738fe3d9380f08616d4fec0281/coverage-7.15.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bbcbb317c2e5ded5b21104af81c29f391be2af98d065693ffbe8d23949b948e5", size = 252227, upload-time = "2026-07-02T13:09:28.543Z" }, + { url = "https://files.pythonhosted.org/packages/a1/fa/b70062750686bd7da454da27927622f48bbac6990ac7a4c4a4653e7b0036/coverage-7.15.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:27f31ecb458da3f859aab3f15ada871eb7a7768807d88df4a9f186bb17737970", size = 254823, upload-time = "2026-07-02T13:09:30.177Z" }, + { url = "https://files.pythonhosted.org/packages/a9/09/dad6a75a2e561b9dc5086a8c5257a7591d584246f67e23e70d2995b89ab6/coverage-7.15.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fb759be317fdc62e0f56bffdf61cfcb45c7761ad6b71e3e583e71a67ae753c", size = 256059, upload-time = "2026-07-02T13:09:31.979Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e7/b5d2941fa9564573d44b693a871ff3156f0c42cbefe977a09fa7fdc59971/coverage-7.15.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d5cf007add5ab4bb8fa9f4c77e3732127c9e6cad501d7db43355fbfafca0be84", size = 258190, upload-time = "2026-07-02T13:09:34.035Z" }, + { url = "https://files.pythonhosted.org/packages/7c/1d/8e895bcde3c57ccd46d896dda5f2b3d5df761a1b0c6c9d450d175dedc632/coverage-7.15.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cc78d9843bd576fbe2118248258d485e968dc535f95ed504a7b0867ba9b51389", size = 252456, upload-time = "2026-07-02T13:09:35.765Z" }, + { url = "https://files.pythonhosted.org/packages/14/4c/f6997da343ddeb959be82c3b05322793f92c071ad45f7cb8a96336e2dd5f/coverage-7.15.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a263060f1de0b4b74b4e089c2a70b8003b3781c733329a9c8fd54995328f9950", size = 254192, upload-time = "2026-07-02T13:09:37.445Z" }, + { url = "https://files.pythonhosted.org/packages/17/27/a0bc09d032267b9da89d95a2d874cfbef2a5aebbf0e87cf7aba221d79a99/coverage-7.15.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c48decf16e0dfd5b049c7d5e82200c23c08126719142998d4f172444e3d0529e", size = 252153, upload-time = "2026-07-02T13:09:39.422Z" }, + { url = "https://files.pythonhosted.org/packages/54/c0/77fc233d9fba07b244c40948c53fe27308b8f21732fb3417f87fbd6fd992/coverage-7.15.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:08fb028000ed0aaa0a4cbdfbb98be7cb42f370db973fbbb469733505ab20e13e", size = 256310, upload-time = "2026-07-02T13:09:41.006Z" }, + { url = "https://files.pythonhosted.org/packages/d5/24/601cecfb5825becacb8d45219a018a3b55b9dbaec624efdb0ea249d08be2/coverage-7.15.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fb7dc0c3b7d8a1077abea0b8546ebc5e26d6ef6ecefc2f0f5ad2b8a53bdad837", size = 251974, upload-time = "2026-07-02T13:09:42.733Z" }, + { url = "https://files.pythonhosted.org/packages/47/1e/6f45e5a5b3d5484318d368702af6716b5ab8913b0428bec981a562fcf296/coverage-7.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6cb3602054ccbe9f0d8c2dc04bbeba90d5719236e2cd06e042ddd6d3fc7b6e37", size = 253745, upload-time = "2026-07-02T13:09:44.376Z" }, + { url = "https://files.pythonhosted.org/packages/8e/db/4df027a77bd11d0e527f44c53557c76e54ad027413d0304252ea3a78d67e/coverage-7.15.0-cp313-cp313-win32.whl", hash = "sha256:0bf781da64326b677be344df505171435b6f58716108606621d5d27d964fff8b", size = 222902, upload-time = "2026-07-02T13:09:46.122Z" }, + { url = "https://files.pythonhosted.org/packages/a0/10/0355894d34e231f2c5449e71287e81a50793a325df2e2b027b7bcd9dfd19/coverage-7.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:2c57a275078ee3fa185f83e400f765bc764a549de66d99b47881645cbd4ea629", size = 223444, upload-time = "2026-07-02T13:09:47.687Z" }, + { url = "https://files.pythonhosted.org/packages/06/ef/bb725f263befaaff851203ab338e68af15e195d7f7b5f323162532d9b6a8/coverage-7.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:3812c61afc6685c7999b39320779ab8f43b7a3081fdb0def39976e56fbdb9a21", size = 222839, upload-time = "2026-07-02T13:09:49.717Z" }, + { url = "https://files.pythonhosted.org/packages/4f/9c/1e3ca54f72a3185ece06c58d871099898c48f0ed6430d17b6ab75f0d180a/coverage-7.15.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:41cb79af843222e11da87127ad0ecbfa878abadd0f770a4a99391a27d3887324", size = 220906, upload-time = "2026-07-02T13:09:51.339Z" }, + { url = "https://files.pythonhosted.org/packages/09/37/f718613d83b274880382f6b67e78f3802549ae39b0b3e65ae5b5974df56e/coverage-7.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7d2008989ef8fe54188d3f3bfa2e3099b025af11e90a6a1b9e7dc433d04263d8", size = 221239, upload-time = "2026-07-02T13:09:53.138Z" }, + { url = "https://files.pythonhosted.org/packages/a7/ce/22bae91e0b75445f68d365c7643ed0aa4880bbf77450ee74ca65bdae53a7/coverage-7.15.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:769e8ece11a596315ebf5aa7ec383aeeed016c091d2bf6363ffb996d41529092", size = 252286, upload-time = "2026-07-02T13:09:54.996Z" }, + { url = "https://files.pythonhosted.org/packages/dd/1e/bec5e32aa508615d9d7a2790effb25fb4dc28606e995816afe400b25ece3/coverage-7.15.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:65a6b6164ee5c39e2f3803f314292d6c61a607ba7fee253d1e03c42dc3903502", size = 254789, upload-time = "2026-07-02T13:09:56.678Z" }, + { url = "https://files.pythonhosted.org/packages/17/29/0e865435b4354e4a7c03b1b7920046d31d0a273d55decefea27e011cb9bf/coverage-7.15.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75128817f95a5c45bb01d65fd2d8b9cb54bbe03d81608fb70e3e14b437ad56c2", size = 256135, upload-time = "2026-07-02T13:09:58.343Z" }, + { url = "https://files.pythonhosted.org/packages/84/ff/33a870b58a13325d62fc0a6c8f01fa0ff667cef60c7498e2382a147dfa18/coverage-7.15.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9887bb428fe2d4cd4bee89bac1a6c9932f484afd5b36fbd4ff6ea5f825bb1f5e", size = 258449, upload-time = "2026-07-02T13:10:00.057Z" }, + { url = "https://files.pythonhosted.org/packages/18/7b/6fffe596bf3ddba8462758d02c5dad730fd91055a6634aa2e4226229181a/coverage-7.15.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0bfc0be1f702042207a93a00523b1065ee1fe951e96edf311581c0bbc2e34888", size = 252313, upload-time = "2026-07-02T13:10:01.946Z" }, + { url = "https://files.pythonhosted.org/packages/58/1b/11468dd6c1676ab831a70cb9a8d4e198e8607fa0b7220ab918b73fe9bfbd/coverage-7.15.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f64627d55def5a43282d70e08396672692f77e4da610a5bb8bb4060b432b6859", size = 254142, upload-time = "2026-07-02T13:10:04.065Z" }, + { url = "https://files.pythonhosted.org/packages/79/41/29328e21d16b1b95092c30dd700e08cf915bd3734f836df8f3bdb0e8fa9f/coverage-7.15.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2c6f0fa473003905c6d5bac328ee4eba9fbea654f15bc24b8a3274b23363fa99", size = 252108, upload-time = "2026-07-02T13:10:06.11Z" }, + { url = "https://files.pythonhosted.org/packages/9b/de/05ccfb990439655b35afbfd8e0d13fe66677565a7d4eb38c3f5ef2635e1c/coverage-7.15.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2bcf9afaf064172c6ec3c58a325a9957ad1178c05dd934e25f253321776e0676", size = 256385, upload-time = "2026-07-02T13:10:08.141Z" }, + { url = "https://files.pythonhosted.org/packages/51/0e/486828a3d2695ea7a2609f17ff572f6b01905e608379440a11da4b8dffbe/coverage-7.15.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:baf06bc987115d6fb938d403f7eab684a057766c490367999a2b71a6883110c6", size = 251923, upload-time = "2026-07-02T13:10:10.179Z" }, + { url = "https://files.pythonhosted.org/packages/18/c7/03582b6715f078e5e558354c87616d945b9894cda2dace8e4009b17035e4/coverage-7.15.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f0405f2ff97b1c4c0e782cb32e02f32369bcf2e6b618b591d67e1ea754575dfe", size = 253580, upload-time = "2026-07-02T13:10:12.052Z" }, + { url = "https://files.pythonhosted.org/packages/db/dc/9e578bbaf2ecb4959a81b7e7601ad8cca772cba2892e8d144cb749b4a71a/coverage-7.15.0-cp314-cp314-win32.whl", hash = "sha256:ab282853ed5fbd64bbb162f19cb8fcb7087187508a6374b4f9c34ec1577c4e8f", size = 223107, upload-time = "2026-07-02T13:10:13.994Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3e/c8c3b75d8dbe0e35f7b0cc3ff5e949fc59500f70b21d0398813f66740664/coverage-7.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:3bb3040e9f4bbe26fcb0cd7cc85ac63e630d3f3a9c74f027abf4caa27e706663", size = 223597, upload-time = "2026-07-02T13:10:15.906Z" }, + { url = "https://files.pythonhosted.org/packages/cd/bc/3cbc9fb036eb388519bccd521f783499c39b64256013fbc362782f196fe1/coverage-7.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:346771144d34f7fa84ec28386f78e0f31653f33cf35e19d253d5b35f9e8201da", size = 223020, upload-time = "2026-07-02T13:10:17.844Z" }, + { url = "https://files.pythonhosted.org/packages/28/00/199c4a8d656dff63102577a056c0fce2ff6a79e40adac092fc986c49cbf1/coverage-7.15.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d34a010905fb6401324ba016b5da03d574967f7b21ce48ea41e66f0f1f95f641", size = 221638, upload-time = "2026-07-02T13:10:19.703Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8e/9d0092c96a3d3a26951ecc7020826aa57bcb1b119ca81acbba996884ab13/coverage-7.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:bb25d825d885ca8036795dacfc3924d33091fc76d71ebc99420c6b79e77d96fa", size = 221903, upload-time = "2026-07-02T13:10:21.514Z" }, + { url = "https://files.pythonhosted.org/packages/6d/b4/c0ca3028f42c9a08e51feb4561ef1192e5de99797cd1db5b04590c215bda/coverage-7.15.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:94c9686bfe8a9a6810297aecbd99beaa3445f9e8dc2f80b1382cca0d86b64461", size = 263267, upload-time = "2026-07-02T13:10:23.261Z" }, + { url = "https://files.pythonhosted.org/packages/5f/aa/a375e3846e5d3c013dc600b2a3231089055c73d77f5393dd2192a8d64da6/coverage-7.15.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9bd671c25f9d85f09d7ec481d0e43d5139f486c06a37139847a7ce569788af72", size = 265390, upload-time = "2026-07-02T13:10:25.152Z" }, + { url = "https://files.pythonhosted.org/packages/92/e1/5783cdabb797305e1c9e4809fea496d31834c51fa772514f73dc148bcfc9/coverage-7.15.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:110cbdf8d2e216577312cf06ccf85539c0e5a5420ef747e4a4719b5e483c88cd", size = 267811, upload-time = "2026-07-02T13:10:27.249Z" }, + { url = "https://files.pythonhosted.org/packages/85/31/96d8bbf58b8e9193bc8389574a91a0db48355ee98feb66aa6bf8d1b32eea/coverage-7.15.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2c5d4619214f1d9993e7b00a8600d14614b7e9d84e89507460b126aa5e6559e5", size = 268928, upload-time = "2026-07-02T13:10:29.242Z" }, + { url = "https://files.pythonhosted.org/packages/5e/7a/5294567e811a1cb7eda93140c628fa050d66189da28da320f93d1d815c73/coverage-7.15.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:781a704516e2d8346fbbd5be6c6f3412dd824785146528b3a01816f26c081007", size = 262378, upload-time = "2026-07-02T13:10:31.107Z" }, + { url = "https://files.pythonhosted.org/packages/69/3f/3f48538421f899f28946f90a3d272136a4686e1abf461cc9249a783ee0f3/coverage-7.15.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd4a1b44bcb65ee29e947ac92bbee04956df3a6bfc6143641bb6cae7ede00fc9", size = 265263, upload-time = "2026-07-02T13:10:32.942Z" }, + { url = "https://files.pythonhosted.org/packages/ce/d3/092df15efcab8a9c1467ee960eb8019bbad3f9300d115d89ea6195f369ff/coverage-7.15.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0e4950c9d6d3e39c64c991814ff315e2d0b9cb8152363594212c9e55208c0a8f", size = 262866, upload-time = "2026-07-02T13:10:35.104Z" }, + { url = "https://files.pythonhosted.org/packages/e5/ab/0254d2b88665efb2c57ad368cc77ab5de3435bd8d5add4729c1b0e79431e/coverage-7.15.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:fe9c87ff42e5472d80d21704972e1f96e104a0a599d77c5e35db5a3c562e2571", size = 266599, upload-time = "2026-07-02T13:10:37.05Z" }, + { url = "https://files.pythonhosted.org/packages/a8/79/1cfa4023e489ce6fbc7be4a5d442dbc375edb4f4fda39a352cedb53263c2/coverage-7.15.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f00d5ae1dd2fe13fb8186e3e7d37bcbd8b25c0d764ff7d1b32cef9be058510a8", size = 261714, upload-time = "2026-07-02T13:10:38.966Z" }, + { url = "https://files.pythonhosted.org/packages/b7/eb/fee5c8665656be63f497418d410484637c438172568688e8ac92e06574e7/coverage-7.15.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:363ab38cc78b615f11c9cac3cf1d7eef950c18b9fdedfb9066f59461dcf84d68", size = 264025, upload-time = "2026-07-02T13:10:40.789Z" }, + { url = "https://files.pythonhosted.org/packages/ab/99/63005db722f91edc81abc16302f9cc2f6228c1679e46e15be9ae144b14d0/coverage-7.15.0-cp314-cp314t-win32.whl", hash = "sha256:54fd9c53a5fafff509195f1b6a3f9be615d8e8362a3629ff1de23d270c03c86b", size = 223413, upload-time = "2026-07-02T13:10:42.597Z" }, + { url = "https://files.pythonhosted.org/packages/c1/e8/2bc6181c4fb06f1a6b981eb85330cc57bfad7e3f710fc9c9d350013ba228/coverage-7.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:87b47553097ba185ed964866078e7e63adea9f5f51b5f39691c34f30afd21080", size = 224245, upload-time = "2026-07-02T13:10:44.47Z" }, + { url = "https://files.pythonhosted.org/packages/79/b8/4d959bf9cc45d0cfed2f4d35cafcab978cdb6ea02eb5100009cd740632a3/coverage-7.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aeefb2dd178fe7eee79f0ad25d75855cb35ee9ed472db2c5ea06f5b4fd00cec5", size = 223558, upload-time = "2026-07-02T13:10:46.368Z" }, + { url = "https://files.pythonhosted.org/packages/52/30/21b2ad45959cd50e909e02ebac1e30b4ceb7162e91c11d4c570223a458b7/coverage-7.15.0-py3-none-any.whl", hash = "sha256:56da6a4cbe8f7e9e80bd072ca9cefe67d7106a440a7ec06519ec6507ac94ad19", size = 212632, upload-time = "2026-07-02T13:10:48.641Z" }, +] + +[package.optional-dependencies] +toml = [ + { name = "tomli", marker = "python_full_version <= '3.11'" }, +] + +[[package]] +name = "cryptography" +version = "49.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1f/99/d1c90d6041656cc6ee229dc99cd67fd0cd5aec3c5f7d72fffc27cc750054/cryptography-49.0.0.tar.gz", hash = "sha256:f89660a348f4f78a92366240a61404e337586ef7f5909a2fef59ca88ef505493", size = 854345, upload-time = "2026-06-12T20:02:30.512Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/22/adf66990e63584a68dfb50c24f48a125c07b1699899381c8151e63ed458c/cryptography-49.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:966fe0e9c67490071f14c0d2b1cb2dfb3023c5ce39457343931415f08382f2db", size = 4032100, upload-time = "2026-06-12T20:02:32.143Z" }, + { url = "https://files.pythonhosted.org/packages/09/41/3797cfaf69cae04a13ee78ebd83f0678d9c02b4779d21ce24445326f1a69/cryptography-49.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:36d1709f992593689b45bda411498d62c6e365f2ca00b84657d4dadd24de16db", size = 4692978, upload-time = "2026-06-12T20:01:21.305Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8b/43011f7ebe515a8aa20d61f290a326cd890c2e738e16e59eaff8d9c3a412/cryptography-49.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0e959b578856a3924bc0cbb710fc12c387b9412a951389f3ca61704a9e25f325", size = 4716422, upload-time = "2026-06-12T20:01:48.566Z" }, + { url = "https://files.pythonhosted.org/packages/4a/91/01ce7303a4579e6d3a6abef01bd322848e9ea7a219adcabc5048b9033571/cryptography-49.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:53ecee2e23f7169b6117e99fc8a944e5e50f79e69758a83b52a00cb98ab2b2d2", size = 4700503, upload-time = "2026-06-12T20:02:47.091Z" }, + { url = "https://files.pythonhosted.org/packages/62/99/a2c95cf8293f07491e9e27c20cc4dcd18176d944e674679adeb1d0173fd6/cryptography-49.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:2eda353d8a27bcbcaa4cbed18994a74ab4d19a2ca897db188ea269ab9b71419b", size = 5309779, upload-time = "2026-06-12T20:02:08.987Z" }, + { url = "https://files.pythonhosted.org/packages/20/2c/0622f20ff02b2ef32558733443805dc82fd4c275be01b2d19d14676f3a1b/cryptography-49.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2afe9051da7ae7bd5905da5a949280c7d2bb75682e188f650a9d0f2756b834c6", size = 4749683, upload-time = "2026-06-12T20:02:03.335Z" }, + { url = "https://files.pythonhosted.org/packages/a3/5b/c5246635d5fd3b64e0d45ae10e99fd32fe9676a79915ccfe5a61ba9af1a5/cryptography-49.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:0b82e28ee398a386f0807bba7884d30f25218855690f45115831bcce5d90822c", size = 4337874, upload-time = "2026-06-12T20:02:54.323Z" }, + { url = "https://files.pythonhosted.org/packages/6d/88/05563c7fe2e914e87d1a536d06fe83e66b4e1d95cb593e05aea375531da8/cryptography-49.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ccac2bfebc306b862133e3bb71f3f6ee8bb525240089b2d952e4144b3a6d5da7", size = 4700283, upload-time = "2026-06-12T20:01:34.822Z" }, + { url = "https://files.pythonhosted.org/packages/c4/b6/d7696e4e890d6ae1469935164c9e5215c557671cb78d6e3f458ccceaa632/cryptography-49.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:d0527ce944105f257f605a827d6ebead966c752038b6e8656abb9c5edee6fc68", size = 5265844, upload-time = "2026-06-12T20:01:24.09Z" }, + { url = "https://files.pythonhosted.org/packages/a9/3c/f3ad17eecc1a57b0ba236dc01f90e783c51f4a2f35f64777cc4f47a184b2/cryptography-49.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:cbc77da8c523d5abd028635ba850a6966fcee2c82e2bf65a41d1d8afe0f98be9", size = 4749290, upload-time = "2026-06-12T20:01:30.848Z" }, + { url = "https://files.pythonhosted.org/packages/4f/01/339573cf1023163a400b0b5d16f6d507de413b9f60be6fd1b77feeaf6737/cryptography-49.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b87e65d263b3e5d3bb92a57e2a6638e2f31110fa7aa890c7b2dbba42248d0a3f", size = 4834612, upload-time = "2026-06-12T20:01:29.246Z" }, + { url = "https://files.pythonhosted.org/packages/71/fd/577302e213a1be9468f92d1afef66fcf1ef83d516819d9992ca547f592bd/cryptography-49.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:66ec79c3904820572d7e987abdf304281f141d37ad9a489b8e97066e7b9b6459", size = 4980804, upload-time = "2026-06-12T20:01:42.853Z" }, + { url = "https://files.pythonhosted.org/packages/1f/09/f42b1d190c5ba75f72062a387f8030d1d75f6ab035788f1d9c4b01de6525/cryptography-49.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:e5dfc1e64de5677cec922ffa8da89c546d0415bf6efdf081842e5d44c84e1f0e", size = 3810026, upload-time = "2026-06-12T20:02:39.262Z" }, + { url = "https://files.pythonhosted.org/packages/ec/9e/db72b3ae7fc9cfad53e630e56c6ae83b9b6ff0bf3718ffb8012d20b3aabf/cryptography-49.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:73a205dce83953d131a4aa1e0fd917a2fd1c5b1eef251e9d7152efefcbf5caf7", size = 4013892, upload-time = "2026-06-12T20:02:10.735Z" }, + { url = "https://files.pythonhosted.org/packages/86/12/c48a424f38db03027be9f7ed5c7dc5de9933dbee992865f98b13727a009d/cryptography-49.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:196ecd6a36e4e9aa10270393bb98d8df88fccee0bf1e5128b91ae4eb4375896d", size = 4678835, upload-time = "2026-06-12T20:02:48.743Z" }, + { url = "https://files.pythonhosted.org/packages/68/28/8a3ad4653662c93fc44dc4e5d8fd374c25c42e07b34bbfbadf49cf57a5a8/cryptography-49.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7abcee80084cda3f7691f3eb1ce480d8df49cec637b429aa35986c1de71738aa", size = 4697239, upload-time = "2026-06-12T20:02:56.03Z" }, + { url = "https://files.pythonhosted.org/packages/a8/b2/2193fc74f81aee4f9b62733133b73b5176718932ed8f2e4b03fa040480a6/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:4ae387c9cb68ea569ca17e490d66d8142b81c3cc814bf179974b7d146e490bbb", size = 4685593, upload-time = "2026-06-12T20:02:50.666Z" }, + { url = "https://files.pythonhosted.org/packages/47/f1/1d3eaa243bfc5de4a187b22aa8c048b3e4980bfbe830ac46e6bac2e66947/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:f37d847238971164fdbc68ade6f6574aecc9c0af714190e2083429ff68f4ce9d", size = 5289961, upload-time = "2026-06-12T20:01:46.468Z" }, + { url = "https://files.pythonhosted.org/packages/58/39/2d51306721330c486495853eda1c567880ff036de15a14c4b74f399934af/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:c2bc30226390d60ea19d9f82b19db005fe0452154a23c1c410c12ea801e43561", size = 4731145, upload-time = "2026-06-12T20:02:16.832Z" }, + { url = "https://files.pythonhosted.org/packages/17/50/983e838c7fd0d87fd8c969bcdd328edaf5f756e38df5281637424c155873/cryptography-49.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:07cab27cc7b7e0fd28e5e26bb9eeedde5c135c868b46de4a27845abe94af6122", size = 4321719, upload-time = "2026-06-12T20:02:52.611Z" }, + { url = "https://files.pythonhosted.org/packages/a7/f5/8f571d7e27c55bce9f76f026143bcb1e040a4233149ecca0bea5fa5dd5f7/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:b20133d204d2bb56ba047642199603876c872026ca53e79c35b83772ab2cc505", size = 4685209, upload-time = "2026-06-12T20:02:07.282Z" }, + { url = "https://files.pythonhosted.org/packages/e7/84/0e27016a6fc5a0886f797018b26aa42f40c09a82332bff77822a451deaaa/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b970c6da94d5bb18629db453d14f2a1300f6bf59b61e9b82377931ef95504866", size = 5246285, upload-time = "2026-06-12T20:01:32.439Z" }, + { url = "https://files.pythonhosted.org/packages/11/2d/5e1fb307cb5931881516b464c98774b3f2c36b5d4bb9a2830253cf553cad/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d8ecde755e2e91bf773fc94e8c9d730cd7f2007004cb492263a794ec3899a1c8", size = 4730441, upload-time = "2026-06-12T20:02:01.469Z" }, + { url = "https://files.pythonhosted.org/packages/e4/c0/bff5a02ee731d207d6a1ed51732549d8c53d2bc8da1d10ec6f2844201d68/cryptography-49.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e3fb64c420688e5319ae25113a354015abbd8dffbfbc41781a1ea66fc7622ac3", size = 4815869, upload-time = "2026-06-12T20:01:36.574Z" }, + { url = "https://files.pythonhosted.org/packages/b9/26/814681d14248d95d73d5c3eea0c39a94eb8302df966f670a2c60de90974b/cryptography-49.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32703d93296f5c1f4b53349ad3a250c2cae0fdecd3a3dd5d47e616d8d616af27", size = 4960948, upload-time = "2026-06-12T20:02:18.688Z" }, + { url = "https://files.pythonhosted.org/packages/4c/fe/93ecac273d3738939d023612ad12cca9a3740a5345d69fda04134c43fd96/cryptography-49.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:33cd0565932807baddb67b96dbee92f2c374b5c89dee09fd74079aeb8c8dba61", size = 3799153, upload-time = "2026-06-12T20:01:39.059Z" }, + { url = "https://files.pythonhosted.org/packages/19/2a/5bb823f5bedcf80718cea7fbc95ec5515cca3769633c4b01a32be7f30e7c/cryptography-49.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ec5e529fb80935c94fe7b729f9972b50e351a0e6b50aa294fd5cabb109fcc29a", size = 4025947, upload-time = "2026-06-12T20:01:25.745Z" }, + { url = "https://files.pythonhosted.org/packages/3d/df/40577043ca124e17012f408ddddaeb213b856336ac82ddb3bc915f39e29f/cryptography-49.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f78ff2c9ed8dc2d036b0f4d640e22522213d047c1b14e61205a7e55c80a494d4", size = 4692429, upload-time = "2026-06-12T20:01:53.628Z" }, + { url = "https://files.pythonhosted.org/packages/2c/99/2d13299eb3dd27b02dcfaafcc91d6b5cb3329f7cbd6d8f51921acd566c1a/cryptography-49.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:35b151772baff2c74cba7fa290ceaff4c3b11c0c881eb93eb5dbc05a7cfbba18", size = 4700968, upload-time = "2026-06-12T20:02:45.383Z" }, + { url = "https://files.pythonhosted.org/packages/a5/4d/9c0cd02f95e2602dd5e563da149ee0830abef3537be8b34dc56281ebe27a/cryptography-49.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0f21641cf4b30fca7aee061ced0ec7ad7b073518088b7c9969a297c0ae796c69", size = 4697758, upload-time = "2026-06-12T20:01:41.13Z" }, + { url = "https://files.pythonhosted.org/packages/24/01/186c825898477d77e2324d5360fefe622ff1d8d1963ec0554e2cada8ec77/cryptography-49.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9e82dcc8e56052715fb18b2429e3bca4823b1629136a2084fc45a9a5cecb9b64", size = 5298863, upload-time = "2026-06-12T20:02:24.579Z" }, + { url = "https://files.pythonhosted.org/packages/b8/7b/62cbbab75d0659865bf0273790031544a0b16c8072d258f9428dcd8190dc/cryptography-49.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6f2debedf9ca60cf1d5bd466475638af5130f89965605cd818484d19987d3a21", size = 4735983, upload-time = "2026-06-12T20:01:50.14Z" }, + { url = "https://files.pythonhosted.org/packages/6c/72/3e798c064bc39e471008075d0f9bc9daf77a80879c092e4a8e170c585ed4/cryptography-49.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:8c25ceb16df5b9435f3f6a9829204985b0e0cbee3b48aacd432c7d2c850b44d9", size = 4334173, upload-time = "2026-06-12T20:01:44.743Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ee/6fca21d1ac73e06f8bef71940abfd4d2f6472b4bca284d770f32bd4086f6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:28d8b15e6275f12c8a207dc309dfa957903c927d08d0cc937ee3f63f200693cc", size = 4697298, upload-time = "2026-06-12T20:02:20.918Z" }, + { url = "https://files.pythonhosted.org/packages/67/d0/a5fcd3515f0bae49a7b6d0413cc1bdccdcc1fc0047037a0d480642cdc5d6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6fc361c34fb6aac015ce19435876635e5c6d21db31998b0920f675f131e043b8", size = 5254338, upload-time = "2026-06-12T20:02:22.737Z" }, + { url = "https://files.pythonhosted.org/packages/a0/84/84fe36f19caf857d61cb7fc9c63035a47ffabd84ea12d1d393148efa3615/cryptography-49.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:2400ef9c9e2299a25614eb1dea3db54a69b1349efd043bfac9c67630d136df36", size = 4735650, upload-time = "2026-06-12T20:02:41.389Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a0/db537264e234f7273a73ec020873d6d6b39dfd8a53db78b550ca8320440e/cryptography-49.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:67e1d20ad9ef3a563c59ef22e7a8a0b8210bd26604369ea4a30a7c66aefe504e", size = 4834820, upload-time = "2026-06-12T20:01:51.847Z" }, + { url = "https://files.pythonhosted.org/packages/93/77/8df9eb486495979bccecd1062e2eaf435250e84437040295b57d09048b0b/cryptography-49.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:42b0684e0e40cf26122427802486f6d93aea593612603a94fbf260c7eb1e9c1b", size = 4967968, upload-time = "2026-06-12T20:02:12.524Z" }, + { url = "https://files.pythonhosted.org/packages/c2/e6/f60198ea8d9dfa15fff9ed4ca02ce362f6eadd9ba757dcc50634c4257b63/cryptography-49.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:026ac7423e6fa66872d3bf889be5974507da3944f866f704fa200eadacd00001", size = 3785547, upload-time = "2026-06-12T20:02:26.847Z" }, + { url = "https://files.pythonhosted.org/packages/63/d3/4a83af35d65e3fad632c926fad684c193ea4398569ccb0bbbc7fe8f5dc9a/cryptography-49.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fc1e275c2f1d97b1a6450b8b0ea3ebfa6e087a611c2b26cb2404d48588abab7b", size = 3993685, upload-time = "2026-06-12T20:02:14.883Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a7/f9dac0ab7f80368c56993a7bf638ef9935f825c91902798481fac0898138/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83782480a4a9da4d0feb51950131ba32e12e70813848b3343f6e18c28a66838", size = 4676239, upload-time = "2026-06-12T20:02:28.793Z" }, + { url = "https://files.pythonhosted.org/packages/d7/70/2ba3769dd0ae167e2f33dfa9592d45db6ff9a61d62ca1a5b3d1bdd09068f/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b39efa323140595abd3ecca8529d321ae50f55f3aa3ba9cc81ea56a6011953d5", size = 4715584, upload-time = "2026-06-12T20:01:27.495Z" }, + { url = "https://files.pythonhosted.org/packages/94/64/2923570ac1c0bd3a737aa366ac3abbbbde273042308b8cde95e2364a6e6a/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:b47db11c2c3525083296069b98ac5221907455e989ae0c2e3008bde851921615", size = 4675885, upload-time = "2026-06-12T20:01:55.49Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f8/614dc7e051418cfe53d55173c1e24c6b0085e89996fe90508c2fdf769aef/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:084ef1af862eb07ec46d25f68689f2102a9fc0e05ce7b80f14f5fe51e4eef0f6", size = 4715449, upload-time = "2026-06-12T20:02:05.469Z" }, + { url = "https://files.pythonhosted.org/packages/aa/50/a9caea39ad19c431c1a3f8a31114df65b260cdfe67786b6c7e7c040c4c44/cryptography-49.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be9fcb48a55f023493482827d4f459bd263cc20efde64f204b97c123201850c6", size = 3783731, upload-time = "2026-06-12T20:02:43.319Z" }, +] + +[[package]] +name = "curl-cffi" +version = "0.15.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "cffi" }, + { name = "rich" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/48/5b/89fcfebd3e5e85134147ac99e9f2b2271165fd4d71984fc65da5f17819b7/curl_cffi-0.15.0.tar.gz", hash = "sha256:ea0c67652bf6893d34ee0f82c944f37e488f6147e9421bef1771cc6545b02ded", size = 196437, upload-time = "2026-04-03T11:12:31.525Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/42/54ddd442c795f30ce5dd4e49f87ce77505958d3777cd96a91567a3975d2a/curl_cffi-0.15.0-cp310-abi3-macosx_10_9_x86_64.whl", hash = "sha256:bda66404010e9ed743b1b83c20c86f24fe21a9a6873e17479d6e67e29d8ded28", size = 2795267, upload-time = "2026-04-03T11:11:46.48Z" }, + { url = "https://files.pythonhosted.org/packages/83/2d/3915e238579b3c5a92cead5c79130c3b8d20caaba7616cc4d894650e1d6b/curl_cffi-0.15.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:a25620d9bf989c9c029a7d1642999c4c265abb0bad811deb2f77b0b5b2b12e5b", size = 2573544, upload-time = "2026-04-03T11:11:47.951Z" }, + { url = "https://files.pythonhosted.org/packages/2a/b3/9d2f1057749a1b07ba1989db3c1503ce8bed998310bae9aea2c43aa64f20/curl_cffi-0.15.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:582e570aa2586b96ed47cf4a17586b9a3c462cbe43f780487c3dc245c6ef1527", size = 10515369, upload-time = "2026-04-03T11:11:50.126Z" }, + { url = "https://files.pythonhosted.org/packages/b5/1d/6d10dded5ce3fd8157e558ebd97d09e551b77a62cdc1c31e93d0a633cee5/curl_cffi-0.15.0-cp310-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:838e48212447d9c81364b04707a5c861daf08f8320f9ecb3406a8919d1d5c3b3", size = 10160045, upload-time = "2026-04-03T11:11:52.664Z" }, + { url = "https://files.pythonhosted.org/packages/5c/12/c70b835487ace3b9ba1502631912e3440082b8ae3a162f60b59cb0b6444d/curl_cffi-0.15.0-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2b6c847d86283b07ae69bb72c82eb8a59242277142aa35b89850f89e792a02fc", size = 11090433, upload-time = "2026-04-03T11:11:55.049Z" }, + { url = "https://files.pythonhosted.org/packages/ea/0d/78edcc4f71934225db99df68197a107386d59080742fc7bf6bb4d007924f/curl_cffi-0.15.0-cp310-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9e5e69eee735f659287e2c84444319d68a1fa68dd37abf228943a4074864283a", size = 10479178, upload-time = "2026-04-03T11:11:57.685Z" }, + { url = "https://files.pythonhosted.org/packages/5b/84/1e101c1acb1ea2f0b4992f5c3024f596d8e21db0d53540b9d583f673c4e7/curl_cffi-0.15.0-cp310-abi3-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa1323950224db24f4c510d010b3affa02196ca853fb424191fa917a513d3f4b", size = 10317051, upload-time = "2026-04-03T11:12:00.295Z" }, + { url = "https://files.pythonhosted.org/packages/28/42/8ef236b22a6c23d096c85a1dc507efe37bfdfc7a2f8a4b34efb590197369/curl_cffi-0.15.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:41f80170ba844009273b2660da1964ec31e99e5719d16b3422ada87177e32e13", size = 11299660, upload-time = "2026-04-03T11:12:02.791Z" }, + { url = "https://files.pythonhosted.org/packages/1d/01/56aeb055d962da87a1be0d74c6c644e251c7e88129b5471dc44ac724e678/curl_cffi-0.15.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1977e1e12cfb5c11352cbb74acef1bed24eb7d226dab61ca57c168c21acd4d61", size = 11945049, upload-time = "2026-04-03T11:12:05.912Z" }, + { url = "https://files.pythonhosted.org/packages/d8/8c/2abf99a38d6340d66cf0557e0c750ef3f8883dfc5d450087e01c85861343/curl_cffi-0.15.0-cp310-abi3-win_amd64.whl", hash = "sha256:5a0c1896a0d5a5ac1eb89cd24b008d2b718dd1df6fd2f75451b59ca66e49e572", size = 1661649, upload-time = "2026-04-03T11:12:07.948Z" }, + { url = "https://files.pythonhosted.org/packages/3d/39/dfd54f2240d3a9b96d77bacc62b97813b35e2aa8ecf5cd5013c683f1ba96/curl_cffi-0.15.0-cp310-abi3-win_arm64.whl", hash = "sha256:a6d57f8389273a3a1f94370473c74897467bcc36af0a17336989780c507fa43d", size = 1410741, upload-time = "2026-04-03T11:12:10.073Z" }, + { url = "https://files.pythonhosted.org/packages/19/6a/c24df8a4fc22fa84070dcd94abeba43c15e08cc09e35869565c0bad196fd/curl_cffi-0.15.0-cp313-abi3-android_24_arm64_v8a.whl", hash = "sha256:4682dc38d4336e0eb0b185374db90a760efde63cbea994b4e63f3521d44c4c92", size = 7190427, upload-time = "2026-04-03T11:12:12.142Z" }, + { url = "https://files.pythonhosted.org/packages/11/56/132225cb3491d07cc6adcce5fe395e059bde87c68cff1ef87a31c88c7819/curl_cffi-0.15.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:967ad7355bd8e9586f8c2d02eaa99953747549e7ea4a9b25cd53353e6b67fe6d", size = 2795723, upload-time = "2026-04-03T11:12:13.668Z" }, + { url = "https://files.pythonhosted.org/packages/07/8f/f4f83cd303bef7e8f1749512e5dd157e7e5d08b0a36c8211f9640a2757bf/curl_cffi-0.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7e63539d0d839d0a8c5eacf86229bc68c57803547f35e0db7ee0986328b478c3", size = 2573739, upload-time = "2026-04-03T11:12:15.08Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5c/643d65c7fc9acd742876aa55c2d7823c438cb7665810acd2e66c9976c4d9/curl_cffi-0.15.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:08c799b89740b9bc49c09fbc3d5907f13ac1f845ca52620507ef9466d4639dd5", size = 10521046, upload-time = "2026-04-03T11:12:17.034Z" }, + { url = "https://files.pythonhosted.org/packages/7f/0b/9b8037113c93f4c5323096163471fa7c35c7676c3f608eeaf1287cd99d58/curl_cffi-0.15.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7b7a92767a888ee90147e18964b396d8435ff42737030d6fb00824ffd6094805", size = 11096115, upload-time = "2026-04-03T11:12:19.694Z" }, + { url = "https://files.pythonhosted.org/packages/5f/96/fff2fcbd924ef4042e0d67379f751a8a4e3186a91e75e35a4cf218b306ee/curl_cffi-0.15.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:829cc357061ecb99cc2d406301f609a039e05665322f5c025ec67c38b0dc49ce", size = 11305346, upload-time = "2026-04-03T11:12:22.151Z" }, + { url = "https://files.pythonhosted.org/packages/53/1b/304b253a45ab28691c8c5e8cca1e6cbb9cf8e46dfceae4648dd536f75e73/curl_cffi-0.15.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:408d6f14e346841cd889c2e0962832bb235ba3b6749ebf609f347f747da5e60f", size = 11949834, upload-time = "2026-04-03T11:12:24.986Z" }, + { url = "https://files.pythonhosted.org/packages/5a/ff/4723d92f08259c707a974aba27a08d0a822b9555e35ca581bf18d055a364/curl_cffi-0.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b624c7ce087bfda967a013ed0a64702a525444e5b6e97d23534d567ccc6525aa", size = 1702771, upload-time = "2026-04-03T11:12:28.201Z" }, + { url = "https://files.pythonhosted.org/packages/59/8c/36bbe06d66fa2b765e4a07199f643a59a9cd1a754207a96335402a9520f4/curl_cffi-0.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0b6c0543b993996670e9e4b78e305a2d60809d5681903ffb5568e21a387434d3", size = 1466312, upload-time = "2026-04-03T11:12:30.054Z" }, +] + +[[package]] +name = "cyclopts" +version = "4.22.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "docstring-parser" }, + { name = "rich" }, + { name = "rich-rst" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/47/32d992e829f63aedea5b93360db23c8882c9bbbde094bcf0fff899ea8a3b/cyclopts-4.22.1.tar.gz", hash = "sha256:49cd3779da7113a96ac5c23b151aa61ac9ae1b4b1fe813594d207ca843c97892", size = 193551, upload-time = "2026-07-20T17:38:59.38Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/89/f2710638cd2f824cb976777e63ef6ed1e83fc56888cf5c9f5a053490b7be/cyclopts-4.22.1-py3-none-any.whl", hash = "sha256:9b614e231075aee9849c0bfd78f7611ab7adf417f16af5b9e42b9ed6e18c17d1", size = 232953, upload-time = "2026-07-20T17:38:58.078Z" }, +] + +[[package]] +name = "debugpy" +version = "1.8.21" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/aa/12037145b7a56eaa5b29b41872f7a21b538e807e13f32c4d3c46e59be084/debugpy-1.8.21.tar.gz", hash = "sha256:a3c53278e84c94e11bd87c53970ec391d1a67396c8b22609fcac576520e611a6", size = 1697577, upload-time = "2026-06-01T19:30:35.156Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/f3/6b1d4c71f4cbb5360009f928934a03b42906f28fc7b3f7f35f04e58acead/debugpy-1.8.21-cp310-cp310-macosx_15_0_x86_64.whl", hash = "sha256:8eeab7b5462f683452c57c0126aaa5ec4e974ddb705f39ba87dff8818c8e08f9", size = 2113873, upload-time = "2026-06-01T19:30:37.148Z" }, + { url = "https://files.pythonhosted.org/packages/1c/f2/17c3bf91cebc173bfbf5734cd2669723d0a35c0cf9d2fd2124546efeae83/debugpy-1.8.21-cp310-cp310-manylinux_2_34_x86_64.whl", hash = "sha256:0fddfdc130ac6d8bfc0415b0409822fa901c8f310e5c945ac5653a0352532344", size = 3004715, upload-time = "2026-06-01T19:30:38.888Z" }, + { url = "https://files.pythonhosted.org/packages/5a/22/1f8efd80c7b5909e760f9cfd0c9e8681d2d35d532f7c0a40760cd4da4a19/debugpy-1.8.21-cp310-cp310-win32.whl", hash = "sha256:72b5d676c4cbfac3bac5bb01c138a4656e843f93f03ce2a5f4e394ad49fbee73", size = 5303455, upload-time = "2026-06-01T19:30:40.52Z" }, + { url = "https://files.pythonhosted.org/packages/da/ce/54c79abd6cccef92fa7b43d97e3acafedf4d645557267ece05e948b5e4b8/debugpy-1.8.21-cp310-cp310-win_amd64.whl", hash = "sha256:a7fe47fd23da57b9e0bec3f4a8ee65a2dc55782455ed7f2141d75ab5d2eaeef5", size = 5331751, upload-time = "2026-06-01T19:30:42.146Z" }, + { url = "https://files.pythonhosted.org/packages/89/fb/cbf306d6e07a313a91e7171a98669054502840931432c227cfd505ee367f/debugpy-1.8.21-cp311-cp311-macosx_15_0_universal2.whl", hash = "sha256:da456226c7b4c69e35dbe35dcee6623d912000a77816db7856a41af1c72a0264", size = 2203120, upload-time = "2026-06-01T19:30:43.964Z" }, + { url = "https://files.pythonhosted.org/packages/aa/57/aa739bd4ad2cbf96aeb1b20b56918ddd5ae4c28b68709bfcd327f02123ee/debugpy-1.8.21-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:f68b891688e61bdc08b8d364d919ff0051e0b94657b39dcd027bc3173edb7cdc", size = 3059958, upload-time = "2026-06-01T19:30:45.622Z" }, + { url = "https://files.pythonhosted.org/packages/a8/31/453d2c9a23d133fe2c8ec7ca1d816ded52a913487fe3ffef7c01b4b706af/debugpy-1.8.21-cp311-cp311-win32.whl", hash = "sha256:f843a8b08c2edeaf9b1582eed4f25441af21a297c22ff16bf76a662557aa9c9e", size = 5236515, upload-time = "2026-06-01T19:30:47.461Z" }, + { url = "https://files.pythonhosted.org/packages/60/94/6660de2f2d7bf388f229335ba4637646eebabdbf38564cb439a95a9193c9/debugpy-1.8.21-cp311-cp311-win_amd64.whl", hash = "sha256:84c564d8cc701d41843b29a92814c1f1bef6798724ca9d675c284ad9f6a547d7", size = 5256138, upload-time = "2026-06-01T19:30:49.113Z" }, + { url = "https://files.pythonhosted.org/packages/a2/df/bf625547431a9cadc9f4cbfeda38866e2b17f6aed147b625377e87834449/debugpy-1.8.21-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:9f96713896f39c3dff0ee841f47320c3f2983d33c341e009361bb0ebc79adc4e", size = 2483609, upload-time = "2026-06-01T19:30:50.794Z" }, + { url = "https://files.pythonhosted.org/packages/bf/09/59324b903599031ff9faaec1758292409f6561a0ec2492fe4b703327705a/debugpy-1.8.21-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:c193d474f0a211191f2b4449d2d06157c689013035bd952f3b617e0ef422b176", size = 3968900, upload-time = "2026-06-01T19:30:52.341Z" }, + { url = "https://files.pythonhosted.org/packages/14/cd/27f65b805d7fe005c44e1a36b9183ecdfbcdbf9d3e721a5115d461ecc7ee/debugpy-1.8.21-cp312-cp312-win32.whl", hash = "sha256:4743373c1cac7f9e74a1b9915bf1dbe0e900eca657ffb170ae07ac8363205ae9", size = 5336340, upload-time = "2026-06-01T19:30:54.047Z" }, + { url = "https://files.pythonhosted.org/packages/77/1d/c84e30c0c674184948b66f076ab271c01d940618a2824c23cd035a27bc20/debugpy-1.8.21-cp312-cp312-win_amd64.whl", hash = "sha256:bd7ba9dd3daa7c2f942c6ca8d4695a16bf9ac16b63615261c7982bc74f7ed20c", size = 5374751, upload-time = "2026-06-01T19:30:55.891Z" }, + { url = "https://files.pythonhosted.org/packages/77/6b/d817e1f8cc77aa055d37fba092e0febfdff40fe652d8d53d4cd7a86ad98d/debugpy-1.8.21-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:13678151fc401e2d68c9880b91e28714f797d40422994572b24560ef80910a88", size = 2477398, upload-time = "2026-06-01T19:30:57.644Z" }, + { url = "https://files.pythonhosted.org/packages/48/57/412421516afc3055fa577516f00beec3d663f9b0ab330639547ae6c57720/debugpy-1.8.21-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:ecbd158386c31ffe71d46f72d44d56e66331ab9b16cad649156d514368f23ab2", size = 3962096, upload-time = "2026-06-01T19:30:59.235Z" }, + { url = "https://files.pythonhosted.org/packages/c1/62/2c616337cf6ba7b07ebbc97f02c6c945a8e2f76b365e33ee809c32ee36d1/debugpy-1.8.21-cp313-cp313-win32.whl", hash = "sha256:2c2ae706dec41d99a9ca1f7ebc987a83e65578363be6f6b3ac9067504917fae1", size = 5336288, upload-time = "2026-06-01T19:31:00.79Z" }, + { url = "https://files.pythonhosted.org/packages/f8/99/9175103392f84c4b1bf7622888cdc68da07f0ff7d9e581266428f6776033/debugpy-1.8.21-cp313-cp313-win_amd64.whl", hash = "sha256:aa648733047443eb1d07682c4ef287d36a54507b643ffdf38b09a3ef002c72a0", size = 5376567, upload-time = "2026-06-01T19:31:02.56Z" }, + { url = "https://files.pythonhosted.org/packages/ce/3d/f4bbb323a548bfab2af3d6b4ffd9bf22636e55956a1285d317a1de643aad/debugpy-1.8.21-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9bb2a685287a2ac9b181cde89edcec64845cb51de7faaa75badb9a698bc24782", size = 2477209, upload-time = "2026-06-01T19:31:04.157Z" }, + { url = "https://files.pythonhosted.org/packages/8c/2d/6e7ec524984a1702777868de49a4c53202bddac2a432a76a093469587750/debugpy-1.8.21-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:3d6922439bf33fd38a3e2c447869ebc7b97da5cd3d329ff1ef9bc06c4903437e", size = 3927115, upload-time = "2026-06-01T19:31:05.863Z" }, + { url = "https://files.pythonhosted.org/packages/97/47/d1aa6d64005a98a9144647d99306b419396f9ad7bf1d73c119e17a81fb4d/debugpy-1.8.21-cp314-cp314-win32.whl", hash = "sha256:15d4963bd5ffa48f0da0947fd06757fa7621945048a14ad7705431566d3c0e7c", size = 5336724, upload-time = "2026-06-01T19:31:07.711Z" }, + { url = "https://files.pythonhosted.org/packages/5f/67/b905b90d163af11878c1af8abafa4a25206335e112e284e413454543a6da/debugpy-1.8.21-cp314-cp314-win_amd64.whl", hash = "sha256:fe0744a12353406de0ae8ccff0d0a4a666f00801a3db8fd04e7a5f761cd520e8", size = 5373803, upload-time = "2026-06-01T19:31:09.469Z" }, + { url = "https://files.pythonhosted.org/packages/95/51/67e7cf11a53e40694f720457d5b3a1cdaaa3d5a9a633e482f225456b93ff/debugpy-1.8.21-py2.py3-none-any.whl", hash = "sha256:b1e37d333663c8851516a47364ef473da127f9caebe4417e6df6f5825a7e9a92", size = 5352888, upload-time = "2026-06-01T19:31:25.186Z" }, +] + +[[package]] +name = "decorator" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/60/8b/32f9823da46cde7df2087faa08cd98d01b908f8dcab982cdba9c84e85355/decorator-5.3.1.tar.gz", hash = "sha256:4cbcdd55a6efadb9dbea26b858f4fb3264567b52d69ca0d25b721b553f60ea82", size = 58084, upload-time = "2026-05-18T06:03:28.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/7f/798705f5296a58ca505d600456748d1be48078eac8a7050d8a98bc9edb89/decorator-5.3.1-py3-none-any.whl", hash = "sha256:f47fe6fdbd2edd623ecfe36875d37aba411624e2670dd395dddae1358689bb3c", size = 10365, upload-time = "2026-05-18T06:03:26.517Z" }, +] + +[[package]] +name = "deepdiff" +version = "9.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cachebox" }, + { name = "orderly-set" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f9/6b/6a4a5aaf38535eb332c2856aa08e73ed7c549d0851b1215401af0a2db1a7/deepdiff-9.1.0.tar.gz", hash = "sha256:07e9e366fab4297755153c4eab795ad4ef3cbd0d51660e847f5751c6bd727687", size = 382149, upload-time = "2026-05-15T20:18:05.751Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/26/4a2bad8eb430d8d805a4642c4bff25103a37548d74ab346f8b1e024abcc5/deepdiff-9.1.0-py3-none-any.whl", hash = "sha256:80c0460e1993b04f6f0ca79abf25548b129fd218478c4ebb08f80560f5d10610", size = 184662, upload-time = "2026-05-15T20:18:03.956Z" }, +] + +[[package]] +name = "dill" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/81/e1/56027a71e31b02ddc53c7d65b01e68edf64dea2932122fe7746a516f75d5/dill-0.4.1.tar.gz", hash = "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa", size = 187315, upload-time = "2026-01-19T02:36:56.85Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d", size = 120019, upload-time = "2026-01-19T02:36:55.663Z" }, +] + +[[package]] +name = "distlib" +version = "0.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/02/bd72be9134d25ed783ecbbc38a539ffaefbf90c78418c7fb7229600dbac7/distlib-0.4.3.tar.gz", hash = "sha256:f152097224a0ae24be5a0f6bae1b9359af82133bce63f98a95f86cae1aede9ed", size = 615141, upload-time = "2026-06-12T08:04:52.847Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/08/9c41fb51ab5b43eb21674aff13df270e8ba6c4b29c8624e328dc7a9482af/distlib-0.4.3-py2.py3-none-any.whl", hash = "sha256:4b0ce306c966eb73bc3a7b6abad017c556dadd92c44701562cd528ac7fde4d5b", size = 470628, upload-time = "2026-06-12T08:04:50.506Z" }, +] + +[[package]] +name = "dnspython" +version = "2.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" }, +] + +[[package]] +name = "docstring-parser" +version = "0.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/4d/f332313098c1de1b2d2ff91cf2674415cc7cddab2ca1b01ae29774bd5fdf/docstring_parser-0.18.0.tar.gz", hash = "sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015", size = 29341, upload-time = "2026-04-14T04:09:19.867Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" }, +] + +[[package]] +name = "email-validator" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dnspython" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f5/22/900cb125c76b7aaa450ce02fd727f452243f2e91a61af068b40adba60ea9/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426", size = 51238, upload-time = "2025-08-26T13:09:06.831Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4", size = 35604, upload-time = "2025-08-26T13:09:05.858Z" }, +] + +[[package]] +name = "et-xmlfile" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/38/af70d7ab1ae9d4da450eeec1fa3918940a5fafb9055e934af8d6eb0c2313/et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54", size = 17234, upload-time = "2024-10-25T17:25:40.039Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa", size = 18059, upload-time = "2024-10-25T17:25:39.051Z" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + +[[package]] +name = "fastapi" +version = "0.139.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-doc" }, + { name = "pydantic" }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d3/af/a5f50ccfa659ec1802cb4ca842c23f06d906a8cc9aef6016a2caeea3d4ed/fastapi-0.139.0.tar.gz", hash = "sha256:99ab7b2d92223c76d6cf10757ab3f89d45b38267fc20b2a136cf02f6beac3145", size = 423016, upload-time = "2026-07-01T16:35:33.436Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/7c/8e3c6ad324ea5cb36604fc3f968554887891c316d9dfde57761611d907ad/fastapi-0.139.0-py3-none-any.whl", hash = "sha256:cf15e1e9e667ddb0ad63811e60bd11390d1aac838ca4a7a23f421807b2308189", size = 130339, upload-time = "2026-07-01T16:35:32.19Z" }, +] + +[[package]] +name = "fastmcp" +version = "3.4.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastmcp-slim", extra = ["client", "server"] }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9c/f7/5188565d1b93ad611cbd80bf473e7ad669d1f3b689c4bedcd304e1ec3472/fastmcp-3.4.4.tar.gz", hash = "sha256:378202e26ec15b23819d9a1c0d1b0ebda096bc712720532010a0b82a45c2b1df", size = 28796458, upload-time = "2026-07-09T00:32:41.352Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/67/3cef84ba38a23dca1e1e776bfda8a35ab3c7a6c94a8ca81d0715de6dd3c5/fastmcp-3.4.4-py3-none-any.whl", hash = "sha256:f86f208713212260068cf55c32936839eee856fefc7808e18a032f31eb0f718e", size = 8019, upload-time = "2026-07-09T00:32:39.411Z" }, +] + +[[package]] +name = "fastmcp-slim" +version = "3.4.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "platformdirs" }, + { name = "pydantic", extra = ["email"] }, + { name = "pydantic-settings" }, + { name = "python-dotenv" }, + { name = "rich" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/45/79/f35661c6a1d76dfbe17a079f912d96fffcfdd40fad5a9144bb9e7dfb1fdf/fastmcp_slim-3.4.4.tar.gz", hash = "sha256:dcaa3e0be2127d7eacdce592c2ef0039204923dc0ec396454615cb4a3275b078", size = 590203, upload-time = "2026-07-09T00:32:20.531Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/16/91/321e0b2e9ed70d0628b17ddaec76fc7b09f3e1d5d290f70bf101a2890142/fastmcp_slim-3.4.4-py3-none-any.whl", hash = "sha256:9d3a6327b9ee835188eb7323fc3b5d4cd061631b48da8ece56794bb538972505", size = 765158, upload-time = "2026-07-09T00:32:19.11Z" }, +] + +[package.optional-dependencies] +client = [ + { name = "authlib" }, + { name = "exceptiongroup" }, + { name = "httpx" }, + { name = "mcp" }, + { name = "opentelemetry-api" }, + { name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] }, + { name = "starlette" }, +] +server = [ + { name = "authlib" }, + { name = "cyclopts" }, + { name = "exceptiongroup" }, + { name = "griffelib" }, + { name = "httpx" }, + { name = "joserfc" }, + { name = "jsonref" }, + { name = "jsonschema-path" }, + { name = "mcp" }, + { name = "openapi-pydantic" }, + { name = "opentelemetry-api" }, + { name = "packaging" }, + { name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] }, + { name = "pyperclip" }, + { name = "python-multipart" }, + { name = "pyyaml" }, + { name = "starlette" }, + { name = "uncalled-for" }, + { name = "uvicorn" }, + { name = "watchfiles" }, + { name = "websockets" }, +] + +[[package]] +name = "feedparser" +version = "6.0.12" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sgmllib3k" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dc/79/db7edb5e77d6dfbc54d7d9df72828be4318275b2e580549ff45a962f6461/feedparser-6.0.12.tar.gz", hash = "sha256:64f76ce90ae3e8ef5d1ede0f8d3b50ce26bcce71dd8ae5e82b1cd2d4a5f94228", size = 286579, upload-time = "2025-09-10T13:33:59.486Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/eb/c96d64137e29ae17d83ad2552470bafe3a7a915e85434d9942077d7fd011/feedparser-6.0.12-py3-none-any.whl", hash = "sha256:6bbff10f5a52662c00a2e3f86a38928c37c48f77b3c511aedcd51de933549324", size = 81480, upload-time = "2025-09-10T13:33:58.022Z" }, +] + +[[package]] +name = "filelock" +version = "3.29.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/94/00f2059e4835eace3ae8fde680b932c496f8ec7bdc99168dfa53fb2e6b79/filelock-3.29.7.tar.gz", hash = "sha256:5b481979797ae69e72f0b389d89a80bdd585c260c5b3f1fb9c0a5ba9bb3f195d", size = 71521, upload-time = "2026-07-08T05:46:58.716Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/02/be4a57b60c7149b55b9e3b3c13f609cd8eb5307c751f22bd8fb8d262e75b/filelock-3.29.7-py3-none-any.whl", hash = "sha256:987db6f789a3a2a59f55081801b2b3697cb97e2a736b5f1a9e99b559285fbc51", size = 46036, upload-time = "2026-07-08T05:46:57.53Z" }, +] + +[[package]] +name = "freezegun" +version = "1.5.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/dd/23e2f4e357f8fd3bdff613c1fe4466d21bfb00a6177f238079b17f7b1c84/freezegun-1.5.5.tar.gz", hash = "sha256:ac7742a6cc6c25a2c35e9292dfd554b897b517d2dec26891a2e8debf205cb94a", size = 35914, upload-time = "2025-08-09T10:39:08.338Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/2e/b41d8a1a917d6581fc27a35d05561037b048e47df50f27f8ac9c7e27a710/freezegun-1.5.5-py3-none-any.whl", hash = "sha256:cd557f4a75cf074e84bc374249b9dd491eaeacd61376b9eb3c423282211619d2", size = 19266, upload-time = "2025-08-09T10:39:06.636Z" }, +] + +[[package]] +name = "frozenlist" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/4a/557715d5047da48d54e659203b9335be7bfaafda2c3f627b7c47e0b3aaf3/frozenlist-1.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011", size = 86230, upload-time = "2025-10-06T05:35:23.699Z" }, + { url = "https://files.pythonhosted.org/packages/a2/fb/c85f9fed3ea8fe8740e5b46a59cc141c23b842eca617da8876cfce5f760e/frozenlist-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565", size = 49621, upload-time = "2025-10-06T05:35:25.341Z" }, + { url = "https://files.pythonhosted.org/packages/63/70/26ca3f06aace16f2352796b08704338d74b6d1a24ca38f2771afbb7ed915/frozenlist-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad", size = 49889, upload-time = "2025-10-06T05:35:26.797Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ed/c7895fd2fde7f3ee70d248175f9b6cdf792fb741ab92dc59cd9ef3bd241b/frozenlist-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2", size = 219464, upload-time = "2025-10-06T05:35:28.254Z" }, + { url = "https://files.pythonhosted.org/packages/6b/83/4d587dccbfca74cb8b810472392ad62bfa100bf8108c7223eb4c4fa2f7b3/frozenlist-1.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186", size = 221649, upload-time = "2025-10-06T05:35:29.454Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c6/fd3b9cd046ec5fff9dab66831083bc2077006a874a2d3d9247dea93ddf7e/frozenlist-1.8.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e", size = 219188, upload-time = "2025-10-06T05:35:30.951Z" }, + { url = "https://files.pythonhosted.org/packages/ce/80/6693f55eb2e085fc8afb28cf611448fb5b90e98e068fa1d1b8d8e66e5c7d/frozenlist-1.8.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450", size = 231748, upload-time = "2025-10-06T05:35:32.101Z" }, + { url = "https://files.pythonhosted.org/packages/97/d6/e9459f7c5183854abd989ba384fe0cc1a0fb795a83c033f0571ec5933ca4/frozenlist-1.8.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef", size = 236351, upload-time = "2025-10-06T05:35:33.834Z" }, + { url = "https://files.pythonhosted.org/packages/97/92/24e97474b65c0262e9ecd076e826bfd1d3074adcc165a256e42e7b8a7249/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4", size = 218767, upload-time = "2025-10-06T05:35:35.205Z" }, + { url = "https://files.pythonhosted.org/packages/ee/bf/dc394a097508f15abff383c5108cb8ad880d1f64a725ed3b90d5c2fbf0bb/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff", size = 235887, upload-time = "2025-10-06T05:35:36.354Z" }, + { url = "https://files.pythonhosted.org/packages/40/90/25b201b9c015dbc999a5baf475a257010471a1fa8c200c843fd4abbee725/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c", size = 228785, upload-time = "2025-10-06T05:35:37.949Z" }, + { url = "https://files.pythonhosted.org/packages/84/f4/b5bc148df03082f05d2dd30c089e269acdbe251ac9a9cf4e727b2dbb8a3d/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f", size = 230312, upload-time = "2025-10-06T05:35:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/db/4b/87e95b5d15097c302430e647136b7d7ab2398a702390cf4c8601975709e7/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7", size = 217650, upload-time = "2025-10-06T05:35:40.377Z" }, + { url = "https://files.pythonhosted.org/packages/e5/70/78a0315d1fea97120591a83e0acd644da638c872f142fd72a6cebee825f3/frozenlist-1.8.0-cp310-cp310-win32.whl", hash = "sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a", size = 39659, upload-time = "2025-10-06T05:35:41.863Z" }, + { url = "https://files.pythonhosted.org/packages/66/aa/3f04523fb189a00e147e60c5b2205126118f216b0aa908035c45336e27e4/frozenlist-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6", size = 43837, upload-time = "2025-10-06T05:35:43.205Z" }, + { url = "https://files.pythonhosted.org/packages/39/75/1135feecdd7c336938bd55b4dc3b0dfc46d85b9be12ef2628574b28de776/frozenlist-1.8.0-cp310-cp310-win_arm64.whl", hash = "sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e", size = 39989, upload-time = "2025-10-06T05:35:44.596Z" }, + { url = "https://files.pythonhosted.org/packages/bc/03/077f869d540370db12165c0aa51640a873fb661d8b315d1d4d67b284d7ac/frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84", size = 86912, upload-time = "2025-10-06T05:35:45.98Z" }, + { url = "https://files.pythonhosted.org/packages/df/b5/7610b6bd13e4ae77b96ba85abea1c8cb249683217ef09ac9e0ae93f25a91/frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9", size = 50046, upload-time = "2025-10-06T05:35:47.009Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ef/0e8f1fe32f8a53dd26bdd1f9347efe0778b0fddf62789ea683f4cc7d787d/frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93", size = 50119, upload-time = "2025-10-06T05:35:48.38Z" }, + { url = "https://files.pythonhosted.org/packages/11/b1/71a477adc7c36e5fb628245dfbdea2166feae310757dea848d02bd0689fd/frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f", size = 231067, upload-time = "2025-10-06T05:35:49.97Z" }, + { url = "https://files.pythonhosted.org/packages/45/7e/afe40eca3a2dc19b9904c0f5d7edfe82b5304cb831391edec0ac04af94c2/frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695", size = 233160, upload-time = "2025-10-06T05:35:51.729Z" }, + { url = "https://files.pythonhosted.org/packages/a6/aa/7416eac95603ce428679d273255ffc7c998d4132cfae200103f164b108aa/frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52", size = 228544, upload-time = "2025-10-06T05:35:53.246Z" }, + { url = "https://files.pythonhosted.org/packages/8b/3d/2a2d1f683d55ac7e3875e4263d28410063e738384d3adc294f5ff3d7105e/frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581", size = 243797, upload-time = "2025-10-06T05:35:54.497Z" }, + { url = "https://files.pythonhosted.org/packages/78/1e/2d5565b589e580c296d3bb54da08d206e797d941a83a6fdea42af23be79c/frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567", size = 247923, upload-time = "2025-10-06T05:35:55.861Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c3/65872fcf1d326a7f101ad4d86285c403c87be7d832b7470b77f6d2ed5ddc/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b", size = 230886, upload-time = "2025-10-06T05:35:57.399Z" }, + { url = "https://files.pythonhosted.org/packages/a0/76/ac9ced601d62f6956f03cc794f9e04c81719509f85255abf96e2510f4265/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92", size = 245731, upload-time = "2025-10-06T05:35:58.563Z" }, + { url = "https://files.pythonhosted.org/packages/b9/49/ecccb5f2598daf0b4a1415497eba4c33c1e8ce07495eb07d2860c731b8d5/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d", size = 241544, upload-time = "2025-10-06T05:35:59.719Z" }, + { url = "https://files.pythonhosted.org/packages/53/4b/ddf24113323c0bbcc54cb38c8b8916f1da7165e07b8e24a717b4a12cbf10/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd", size = 241806, upload-time = "2025-10-06T05:36:00.959Z" }, + { url = "https://files.pythonhosted.org/packages/a7/fb/9b9a084d73c67175484ba2789a59f8eebebd0827d186a8102005ce41e1ba/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967", size = 229382, upload-time = "2025-10-06T05:36:02.22Z" }, + { url = "https://files.pythonhosted.org/packages/95/a3/c8fb25aac55bf5e12dae5c5aa6a98f85d436c1dc658f21c3ac73f9fa95e5/frozenlist-1.8.0-cp311-cp311-win32.whl", hash = "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25", size = 39647, upload-time = "2025-10-06T05:36:03.409Z" }, + { url = "https://files.pythonhosted.org/packages/0a/f5/603d0d6a02cfd4c8f2a095a54672b3cf967ad688a60fb9faf04fc4887f65/frozenlist-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b", size = 44064, upload-time = "2025-10-06T05:36:04.368Z" }, + { url = "https://files.pythonhosted.org/packages/5d/16/c2c9ab44e181f043a86f9a8f84d5124b62dbcb3a02c0977ec72b9ac1d3e0/frozenlist-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a", size = 39937, upload-time = "2025-10-06T05:36:05.669Z" }, + { url = "https://files.pythonhosted.org/packages/69/29/948b9aa87e75820a38650af445d2ef2b6b8a6fab1a23b6bb9e4ef0be2d59/frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", size = 87782, upload-time = "2025-10-06T05:36:06.649Z" }, + { url = "https://files.pythonhosted.org/packages/64/80/4f6e318ee2a7c0750ed724fa33a4bdf1eacdc5a39a7a24e818a773cd91af/frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", size = 50594, upload-time = "2025-10-06T05:36:07.69Z" }, + { url = "https://files.pythonhosted.org/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", size = 50448, upload-time = "2025-10-06T05:36:08.78Z" }, + { url = "https://files.pythonhosted.org/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", size = 242411, upload-time = "2025-10-06T05:36:09.801Z" }, + { url = "https://files.pythonhosted.org/packages/8f/83/f61505a05109ef3293dfb1ff594d13d64a2324ac3482be2cedc2be818256/frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", size = 243014, upload-time = "2025-10-06T05:36:11.394Z" }, + { url = "https://files.pythonhosted.org/packages/d8/cb/cb6c7b0f7d4023ddda30cf56b8b17494eb3a79e3fda666bf735f63118b35/frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", size = 234909, upload-time = "2025-10-06T05:36:12.598Z" }, + { url = "https://files.pythonhosted.org/packages/31/c5/cd7a1f3b8b34af009fb17d4123c5a778b44ae2804e3ad6b86204255f9ec5/frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", size = 250049, upload-time = "2025-10-06T05:36:14.065Z" }, + { url = "https://files.pythonhosted.org/packages/c0/01/2f95d3b416c584a1e7f0e1d6d31998c4a795f7544069ee2e0962a4b60740/frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", size = 256485, upload-time = "2025-10-06T05:36:15.39Z" }, + { url = "https://files.pythonhosted.org/packages/ce/03/024bf7720b3abaebcff6d0793d73c154237b85bdf67b7ed55e5e9596dc9a/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", size = 237619, upload-time = "2025-10-06T05:36:16.558Z" }, + { url = "https://files.pythonhosted.org/packages/69/fa/f8abdfe7d76b731f5d8bd217827cf6764d4f1d9763407e42717b4bed50a0/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", size = 250320, upload-time = "2025-10-06T05:36:17.821Z" }, + { url = "https://files.pythonhosted.org/packages/f5/3c/b051329f718b463b22613e269ad72138cc256c540f78a6de89452803a47d/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", size = 246820, upload-time = "2025-10-06T05:36:19.046Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ae/58282e8f98e444b3f4dd42448ff36fa38bef29e40d40f330b22e7108f565/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", size = 250518, upload-time = "2025-10-06T05:36:20.763Z" }, + { url = "https://files.pythonhosted.org/packages/8f/96/007e5944694d66123183845a106547a15944fbbb7154788cbf7272789536/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", size = 239096, upload-time = "2025-10-06T05:36:22.129Z" }, + { url = "https://files.pythonhosted.org/packages/66/bb/852b9d6db2fa40be96f29c0d1205c306288f0684df8fd26ca1951d461a56/frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", size = 39985, upload-time = "2025-10-06T05:36:23.661Z" }, + { url = "https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", size = 44591, upload-time = "2025-10-06T05:36:24.958Z" }, + { url = "https://files.pythonhosted.org/packages/a7/06/1dc65480ab147339fecc70797e9c2f69d9cea9cf38934ce08df070fdb9cb/frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd", size = 40102, upload-time = "2025-10-06T05:36:26.333Z" }, + { url = "https://files.pythonhosted.org/packages/2d/40/0832c31a37d60f60ed79e9dfb5a92e1e2af4f40a16a29abcc7992af9edff/frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", size = 85717, upload-time = "2025-10-06T05:36:27.341Z" }, + { url = "https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", size = 49651, upload-time = "2025-10-06T05:36:28.855Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", size = 49417, upload-time = "2025-10-06T05:36:29.877Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027", size = 234391, upload-time = "2025-10-06T05:36:31.301Z" }, + { url = "https://files.pythonhosted.org/packages/40/76/c202df58e3acdf12969a7895fd6f3bc016c642e6726aa63bd3025e0fc71c/frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822", size = 233048, upload-time = "2025-10-06T05:36:32.531Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c0/8746afb90f17b73ca5979c7a3958116e105ff796e718575175319b5bb4ce/frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121", size = 226549, upload-time = "2025-10-06T05:36:33.706Z" }, + { url = "https://files.pythonhosted.org/packages/7e/eb/4c7eefc718ff72f9b6c4893291abaae5fbc0c82226a32dcd8ef4f7a5dbef/frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5", size = 239833, upload-time = "2025-10-06T05:36:34.947Z" }, + { url = "https://files.pythonhosted.org/packages/c2/4e/e5c02187cf704224f8b21bee886f3d713ca379535f16893233b9d672ea71/frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e", size = 245363, upload-time = "2025-10-06T05:36:36.534Z" }, + { url = "https://files.pythonhosted.org/packages/1f/96/cb85ec608464472e82ad37a17f844889c36100eed57bea094518bf270692/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11", size = 229314, upload-time = "2025-10-06T05:36:38.582Z" }, + { url = "https://files.pythonhosted.org/packages/5d/6f/4ae69c550e4cee66b57887daeebe006fe985917c01d0fff9caab9883f6d0/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1", size = 243365, upload-time = "2025-10-06T05:36:40.152Z" }, + { url = "https://files.pythonhosted.org/packages/7a/58/afd56de246cf11780a40a2c28dc7cbabbf06337cc8ddb1c780a2d97e88d8/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1", size = 237763, upload-time = "2025-10-06T05:36:41.355Z" }, + { url = "https://files.pythonhosted.org/packages/cb/36/cdfaf6ed42e2644740d4a10452d8e97fa1c062e2a8006e4b09f1b5fd7d63/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8", size = 240110, upload-time = "2025-10-06T05:36:42.716Z" }, + { url = "https://files.pythonhosted.org/packages/03/a8/9ea226fbefad669f11b52e864c55f0bd57d3c8d7eb07e9f2e9a0b39502e1/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed", size = 233717, upload-time = "2025-10-06T05:36:44.251Z" }, + { url = "https://files.pythonhosted.org/packages/1e/0b/1b5531611e83ba7d13ccc9988967ea1b51186af64c42b7a7af465dcc9568/frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496", size = 39628, upload-time = "2025-10-06T05:36:45.423Z" }, + { url = "https://files.pythonhosted.org/packages/d8/cf/174c91dbc9cc49bc7b7aab74d8b734e974d1faa8f191c74af9b7e80848e6/frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231", size = 43882, upload-time = "2025-10-06T05:36:46.796Z" }, + { url = "https://files.pythonhosted.org/packages/c1/17/502cd212cbfa96eb1388614fe39a3fc9ab87dbbe042b66f97acb57474834/frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62", size = 39676, upload-time = "2025-10-06T05:36:47.8Z" }, + { url = "https://files.pythonhosted.org/packages/d2/5c/3bbfaa920dfab09e76946a5d2833a7cbdf7b9b4a91c714666ac4855b88b4/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94", size = 89235, upload-time = "2025-10-06T05:36:48.78Z" }, + { url = "https://files.pythonhosted.org/packages/d2/d6/f03961ef72166cec1687e84e8925838442b615bd0b8854b54923ce5b7b8a/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c", size = 50742, upload-time = "2025-10-06T05:36:49.837Z" }, + { url = "https://files.pythonhosted.org/packages/1e/bb/a6d12b7ba4c3337667d0e421f7181c82dda448ce4e7ad7ecd249a16fa806/frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52", size = 51725, upload-time = "2025-10-06T05:36:50.851Z" }, + { url = "https://files.pythonhosted.org/packages/bc/71/d1fed0ffe2c2ccd70b43714c6cab0f4188f09f8a67a7914a6b46ee30f274/frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51", size = 284533, upload-time = "2025-10-06T05:36:51.898Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/fb1685a7b009d89f9bf78a42d94461bc06581f6e718c39344754a5d9bada/frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65", size = 292506, upload-time = "2025-10-06T05:36:53.101Z" }, + { url = "https://files.pythonhosted.org/packages/e6/3b/b991fe1612703f7e0d05c0cf734c1b77aaf7c7d321df4572e8d36e7048c8/frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82", size = 274161, upload-time = "2025-10-06T05:36:54.309Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ec/c5c618767bcdf66e88945ec0157d7f6c4a1322f1473392319b7a2501ded7/frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714", size = 294676, upload-time = "2025-10-06T05:36:55.566Z" }, + { url = "https://files.pythonhosted.org/packages/7c/ce/3934758637d8f8a88d11f0585d6495ef54b2044ed6ec84492a91fa3b27aa/frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d", size = 300638, upload-time = "2025-10-06T05:36:56.758Z" }, + { url = "https://files.pythonhosted.org/packages/fc/4f/a7e4d0d467298f42de4b41cbc7ddaf19d3cfeabaf9ff97c20c6c7ee409f9/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506", size = 283067, upload-time = "2025-10-06T05:36:57.965Z" }, + { url = "https://files.pythonhosted.org/packages/dc/48/c7b163063d55a83772b268e6d1affb960771b0e203b632cfe09522d67ea5/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51", size = 292101, upload-time = "2025-10-06T05:36:59.237Z" }, + { url = "https://files.pythonhosted.org/packages/9f/d0/2366d3c4ecdc2fd391e0afa6e11500bfba0ea772764d631bbf82f0136c9d/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e", size = 289901, upload-time = "2025-10-06T05:37:00.811Z" }, + { url = "https://files.pythonhosted.org/packages/b8/94/daff920e82c1b70e3618a2ac39fbc01ae3e2ff6124e80739ce5d71c9b920/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0", size = 289395, upload-time = "2025-10-06T05:37:02.115Z" }, + { url = "https://files.pythonhosted.org/packages/e3/20/bba307ab4235a09fdcd3cc5508dbabd17c4634a1af4b96e0f69bfe551ebd/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41", size = 283659, upload-time = "2025-10-06T05:37:03.711Z" }, + { url = "https://files.pythonhosted.org/packages/fd/00/04ca1c3a7a124b6de4f8a9a17cc2fcad138b4608e7a3fc5877804b8715d7/frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b", size = 43492, upload-time = "2025-10-06T05:37:04.915Z" }, + { url = "https://files.pythonhosted.org/packages/59/5e/c69f733a86a94ab10f68e496dc6b7e8bc078ebb415281d5698313e3af3a1/frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888", size = 48034, upload-time = "2025-10-06T05:37:06.343Z" }, + { url = "https://files.pythonhosted.org/packages/16/6c/be9d79775d8abe79b05fa6d23da99ad6e7763a1d080fbae7290b286093fd/frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042", size = 41749, upload-time = "2025-10-06T05:37:07.431Z" }, + { url = "https://files.pythonhosted.org/packages/f1/c8/85da824b7e7b9b6e7f7705b2ecaf9591ba6f79c1177f324c2735e41d36a2/frozenlist-1.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0", size = 86127, upload-time = "2025-10-06T05:37:08.438Z" }, + { url = "https://files.pythonhosted.org/packages/8e/e8/a1185e236ec66c20afd72399522f142c3724c785789255202d27ae992818/frozenlist-1.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f", size = 49698, upload-time = "2025-10-06T05:37:09.48Z" }, + { url = "https://files.pythonhosted.org/packages/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c", size = 49749, upload-time = "2025-10-06T05:37:10.569Z" }, + { url = "https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2", size = 231298, upload-time = "2025-10-06T05:37:11.993Z" }, + { url = "https://files.pythonhosted.org/packages/3a/3b/d9b1e0b0eed36e70477ffb8360c49c85c8ca8ef9700a4e6711f39a6e8b45/frozenlist-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8", size = 232015, upload-time = "2025-10-06T05:37:13.194Z" }, + { url = "https://files.pythonhosted.org/packages/dc/94/be719d2766c1138148564a3960fc2c06eb688da592bdc25adcf856101be7/frozenlist-1.8.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686", size = 225038, upload-time = "2025-10-06T05:37:14.577Z" }, + { url = "https://files.pythonhosted.org/packages/e4/09/6712b6c5465f083f52f50cf74167b92d4ea2f50e46a9eea0523d658454ae/frozenlist-1.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e", size = 240130, upload-time = "2025-10-06T05:37:15.781Z" }, + { url = "https://files.pythonhosted.org/packages/f8/d4/cd065cdcf21550b54f3ce6a22e143ac9e4836ca42a0de1022da8498eac89/frozenlist-1.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a", size = 242845, upload-time = "2025-10-06T05:37:17.037Z" }, + { url = "https://files.pythonhosted.org/packages/62/c3/f57a5c8c70cd1ead3d5d5f776f89d33110b1addae0ab010ad774d9a44fb9/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128", size = 229131, upload-time = "2025-10-06T05:37:18.221Z" }, + { url = "https://files.pythonhosted.org/packages/6c/52/232476fe9cb64f0742f3fde2b7d26c1dac18b6d62071c74d4ded55e0ef94/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f", size = 240542, upload-time = "2025-10-06T05:37:19.771Z" }, + { url = "https://files.pythonhosted.org/packages/5f/85/07bf3f5d0fb5414aee5f47d33c6f5c77bfe49aac680bfece33d4fdf6a246/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7", size = 237308, upload-time = "2025-10-06T05:37:20.969Z" }, + { url = "https://files.pythonhosted.org/packages/11/99/ae3a33d5befd41ac0ca2cc7fd3aa707c9c324de2e89db0e0f45db9a64c26/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30", size = 238210, upload-time = "2025-10-06T05:37:22.252Z" }, + { url = "https://files.pythonhosted.org/packages/b2/60/b1d2da22f4970e7a155f0adde9b1435712ece01b3cd45ba63702aea33938/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7", size = 231972, upload-time = "2025-10-06T05:37:23.5Z" }, + { url = "https://files.pythonhosted.org/packages/3f/ab/945b2f32de889993b9c9133216c068b7fcf257d8595a0ac420ac8677cab0/frozenlist-1.8.0-cp314-cp314-win32.whl", hash = "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806", size = 40536, upload-time = "2025-10-06T05:37:25.581Z" }, + { url = "https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0", size = 44330, upload-time = "2025-10-06T05:37:26.928Z" }, + { url = "https://files.pythonhosted.org/packages/82/13/e6950121764f2676f43534c555249f57030150260aee9dcf7d64efda11dd/frozenlist-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b", size = 40627, upload-time = "2025-10-06T05:37:28.075Z" }, + { url = "https://files.pythonhosted.org/packages/c0/c7/43200656ecc4e02d3f8bc248df68256cd9572b3f0017f0a0c4e93440ae23/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d", size = 89238, upload-time = "2025-10-06T05:37:29.373Z" }, + { url = "https://files.pythonhosted.org/packages/d1/29/55c5f0689b9c0fb765055629f472c0de484dcaf0acee2f7707266ae3583c/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed", size = 50738, upload-time = "2025-10-06T05:37:30.792Z" }, + { url = "https://files.pythonhosted.org/packages/ba/7d/b7282a445956506fa11da8c2db7d276adcbf2b17d8bb8407a47685263f90/frozenlist-1.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930", size = 51739, upload-time = "2025-10-06T05:37:32.127Z" }, + { url = "https://files.pythonhosted.org/packages/62/1c/3d8622e60d0b767a5510d1d3cf21065b9db874696a51ea6d7a43180a259c/frozenlist-1.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c", size = 284186, upload-time = "2025-10-06T05:37:33.21Z" }, + { url = "https://files.pythonhosted.org/packages/2d/14/aa36d5f85a89679a85a1d44cd7a6657e0b1c75f61e7cad987b203d2daca8/frozenlist-1.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24", size = 292196, upload-time = "2025-10-06T05:37:36.107Z" }, + { url = "https://files.pythonhosted.org/packages/05/23/6bde59eb55abd407d34f77d39a5126fb7b4f109a3f611d3929f14b700c66/frozenlist-1.8.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37", size = 273830, upload-time = "2025-10-06T05:37:37.663Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3f/22cff331bfad7a8afa616289000ba793347fcd7bc275f3b28ecea2a27909/frozenlist-1.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a", size = 294289, upload-time = "2025-10-06T05:37:39.261Z" }, + { url = "https://files.pythonhosted.org/packages/a4/89/5b057c799de4838b6c69aa82b79705f2027615e01be996d2486a69ca99c4/frozenlist-1.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2", size = 300318, upload-time = "2025-10-06T05:37:43.213Z" }, + { url = "https://files.pythonhosted.org/packages/30/de/2c22ab3eb2a8af6d69dc799e48455813bab3690c760de58e1bf43b36da3e/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef", size = 282814, upload-time = "2025-10-06T05:37:45.337Z" }, + { url = "https://files.pythonhosted.org/packages/59/f7/970141a6a8dbd7f556d94977858cfb36fa9b66e0892c6dd780d2219d8cd8/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe", size = 291762, upload-time = "2025-10-06T05:37:46.657Z" }, + { url = "https://files.pythonhosted.org/packages/c1/15/ca1adae83a719f82df9116d66f5bb28bb95557b3951903d39135620ef157/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8", size = 289470, upload-time = "2025-10-06T05:37:47.946Z" }, + { url = "https://files.pythonhosted.org/packages/ac/83/dca6dc53bf657d371fbc88ddeb21b79891e747189c5de990b9dfff2ccba1/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a", size = 289042, upload-time = "2025-10-06T05:37:49.499Z" }, + { url = "https://files.pythonhosted.org/packages/96/52/abddd34ca99be142f354398700536c5bd315880ed0a213812bc491cff5e4/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e", size = 283148, upload-time = "2025-10-06T05:37:50.745Z" }, + { url = "https://files.pythonhosted.org/packages/af/d3/76bd4ed4317e7119c2b7f57c3f6934aba26d277acc6309f873341640e21f/frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df", size = 44676, upload-time = "2025-10-06T05:37:52.222Z" }, + { url = "https://files.pythonhosted.org/packages/89/76/c615883b7b521ead2944bb3480398cbb07e12b7b4e4d073d3752eb721558/frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd", size = 49451, upload-time = "2025-10-06T05:37:53.425Z" }, + { url = "https://files.pythonhosted.org/packages/e0/a3/5982da14e113d07b325230f95060e2169f5311b1017ea8af2a29b374c289/frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79", size = 42507, upload-time = "2025-10-06T05:37:54.513Z" }, + { url = "https://files.pythonhosted.org/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, +] + +[[package]] +name = "griffelib" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/33/e4/8d187ea29c2e30b3a09505c567513077d6117861bde1fbd997a167f262ec/griffelib-2.1.0.tar.gz", hash = "sha256:762a186d2c6fd6794d4ea20d428d597ffb857cb56b66421651cbba15bdd5e813", size = 216234, upload-time = "2026-06-19T12:05:42.278Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/d3/5268aeabf2ad82658c4e2ff3a060648d0f02f3926cb53247c0e4d0dab49e/griffelib-2.1.0-py3-none-any.whl", hash = "sha256:cc7b3d2d2865ad0b909fcc38086e3f554b5ea7acbaa7bbb7ecaa3f5dfb7d9f00", size = 142560, upload-time = "2026-06-19T12:05:38.742Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "httpx-sse" +version = "0.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/4c/751061ffa58615a32c31b2d82e8482be8dd4a89154f003147acee90f2be9/httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d", size = 15943, upload-time = "2025-10-10T21:48:22.271Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" }, +] + +[[package]] +name = "identify" +version = "2.6.19" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/52/63/51723b5f116cc04b061cb6f5a561790abf249d25931d515cd375e063e0f4/identify-2.6.19.tar.gz", hash = "sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842", size = 99567, upload-time = "2026-04-17T18:39:50.265Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl", hash = "sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a", size = 99397, upload-time = "2026-04-17T18:39:49.221Z" }, +] + +[[package]] +name = "idna" +version = "3.18" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/63/9496c57188a2ee585e0f1db071d75089a11e98aa86eb99d9d7618fc1edce/idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848", size = 196711, upload-time = "2026-06-02T14:34:07.794Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", size = 65455, upload-time = "2026-06-02T14:34:06.319Z" }, +] + +[[package]] +name = "importlib-metadata" +version = "9.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a9/01/15bb152d77b21318514a96f43af312635eb2500c96b55398d020c93d86ea/importlib_metadata-9.0.0.tar.gz", hash = "sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc", size = 56405, upload-time = "2026-03-20T06:42:56.999Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl", hash = "sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7", size = 27789, upload-time = "2026-03-20T06:42:55.665Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "ipykernel" +version = "7.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "appnope", marker = "sys_platform == 'darwin'" }, + { name = "comm" }, + { name = "debugpy" }, + { name = "ipython", version = "8.39.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "ipython", version = "9.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "matplotlib-inline" }, + { name = "nest-asyncio2" }, + { name = "packaging" }, + { name = "psutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/c4/e4a38f579de4225a561305666f7541cdabb30075def2aa1ac17bd73c1fb5/ipykernel-7.3.0.tar.gz", hash = "sha256:9acaaaf97d16355166e4085afe9d225bfbdf2b7ef520f9df3be8f2b248275e09", size = 184899, upload-time = "2026-06-10T08:41:25.481Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/02/77b271f5dc58bfbc0b577c877b2365d1ffea2afe66a80c13f2312820348c/ipykernel-7.3.0-py3-none-any.whl", hash = "sha256:897eb64da762549ef610698fca5e9675195ec6ac8ec7f19d81ce1ca20c876057", size = 120583, upload-time = "2026-06-10T08:41:23.648Z" }, +] + +[[package]] +name = "ipython" +version = "8.39.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version < '3.11' and sys_platform == 'win32'" }, + { name = "decorator", marker = "python_full_version < '3.11'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "jedi", marker = "python_full_version < '3.11'" }, + { name = "matplotlib-inline", marker = "python_full_version < '3.11'" }, + { name = "pexpect", marker = "python_full_version < '3.11' and sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit", marker = "python_full_version < '3.11'" }, + { name = "pygments", marker = "python_full_version < '3.11'" }, + { name = "stack-data", marker = "python_full_version < '3.11'" }, + { name = "traitlets", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/40/18/f8598d287006885e7136451fdea0755af4ebcbfe342836f24deefaed1164/ipython-8.39.0.tar.gz", hash = "sha256:4110ae96012c379b8b6db898a07e186c40a2a1ef5d57a7fa83166047d9da7624", size = 5513971, upload-time = "2026-03-27T10:02:13.94Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/56/4cc7fc9e9e3f38fd324f24f8afe0ad8bb5fa41283f37f1aaf9de0612c968/ipython-8.39.0-py3-none-any.whl", hash = "sha256:bb3c51c4fa8148ab1dea07a79584d1c854e234ea44aa1283bcb37bc75054651f", size = 831849, upload-time = "2026-03-27T10:02:07.846Z" }, +] + +[[package]] +name = "ipython" +version = "9.15.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.15' and sys_platform == 'win32'", + "python_full_version == '3.14.*' and sys_platform == 'win32'", + "python_full_version >= '3.15' and sys_platform == 'emscripten'", + "python_full_version == '3.14.*' and sys_platform == 'emscripten'", + "python_full_version >= '3.15' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.14.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version >= '3.11' and sys_platform == 'win32'" }, + { name = "decorator", marker = "python_full_version >= '3.11'" }, + { name = "ipython-pygments-lexers", marker = "python_full_version >= '3.11'" }, + { name = "jedi", marker = "python_full_version >= '3.11'" }, + { name = "matplotlib-inline", marker = "python_full_version >= '3.11'" }, + { name = "pexpect", marker = "python_full_version >= '3.11' and sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit", marker = "python_full_version >= '3.11'" }, + { name = "psutil", marker = "python_full_version >= '3.11' and sys_platform != 'cygwin' and sys_platform != 'emscripten'" }, + { name = "pygments", marker = "python_full_version >= '3.11'" }, + { name = "stack-data", marker = "python_full_version >= '3.11'" }, + { name = "traitlets", marker = "python_full_version >= '3.11'" }, + { name = "typing-extensions", marker = "python_full_version == '3.11.*'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/53/59/165d3b4d75cc34add3122c4417ecb229085140ac573103c223cd01dde96f/ipython-9.15.0.tar.gz", hash = "sha256:da2819ce2aa83135257df830660b1176d986c3d2876db24df01974fa955b2756", size = 4442580, upload-time = "2026-06-26T11:03:35.913Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/3a/948263ca3b9d65bb2b1b0c521b3a49fad5d59ada58724bd87d2bd5ff3f36/ipython-9.15.0-py3-none-any.whl", hash = "sha256:515ad9c3cdf0c932a5a9f6245419e8aba706b7bd03c3e1d3a1c83d9351d6aa6e", size = 630895, upload-time = "2026-06-26T11:03:33.809Z" }, +] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments", marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, +] + +[[package]] +name = "isort" +version = "6.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/82/fa43935523efdfcce6abbae9da7f372b627b27142c3419fcf13bf5b0c397/isort-6.1.0.tar.gz", hash = "sha256:9b8f96a14cfee0677e78e941ff62f03769a06d412aabb9e2a90487b3b7e8d481", size = 824325, upload-time = "2025-10-01T16:26:45.027Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/cc/9b681a170efab4868a032631dea1e8446d8ec718a7f657b94d49d1a12643/isort-6.1.0-py3-none-any.whl", hash = "sha256:58d8927ecce74e5087aef019f778d4081a3b6c98f15a80ba35782ca8a2097784", size = 94329, upload-time = "2025-10-01T16:26:43.291Z" }, +] + +[[package]] +name = "jaraco-classes" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", size = 11780, upload-time = "2024-03-31T07:27:36.643Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", size = 6777, upload-time = "2024-03-31T07:27:34.792Z" }, +] + +[[package]] +name = "jaraco-context" +version = "6.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "backports-tarfile", marker = "python_full_version < '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/af/50/4763cd07e722bb6285316d390a164bc7e479db9d90daa769f22578f698b4/jaraco_context-6.1.2.tar.gz", hash = "sha256:f1a6c9d391e661cc5b8d39861ff077a7dc24dc23833ccee564b234b81c82dfe3", size = 16801, upload-time = "2026-03-20T22:13:33.922Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f2/58/bc8954bda5fcda97bd7c19be11b85f91973d67a706ed4a3aec33e7de22db/jaraco_context-6.1.2-py3-none-any.whl", hash = "sha256:bf8150b79a2d5d91ae48629d8b427a8f7ba0e1097dd6202a9059f29a36379535", size = 7871, upload-time = "2026-03-20T22:13:32.808Z" }, +] + +[[package]] +name = "jaraco-functools" +version = "4.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6c/1f/c23395957d41ccf27c4e535c3d334c4051e5395b3752057ba4cbaec35c56/jaraco_functools-4.6.0.tar.gz", hash = "sha256:880c577ec9720b3a052d5bc611fb9f2269b3d87902ef42440df443b88e443280", size = 20837, upload-time = "2026-07-14T01:28:02.544Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/36/ecc85bc96c273dc8a11273ed4782272975e6338d4a3e9228621175edf0e3/jaraco_functools-4.6.0-py3-none-any.whl", hash = "sha256:99e3dc0060c5cbe8fcd1cdb36258e2a65ca40f1566b2033b12abb1bb44dd3c30", size = 11677, upload-time = "2026-07-14T01:28:01.59Z" }, +] + +[[package]] +name = "jedi" +version = "0.20.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parso" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/b7/a3635f6a2d7cf5b5dd98064fc1d5fbbafcb25477bcea204a3a92145d158b/jedi-0.20.0.tar.gz", hash = "sha256:c3f4ccbd276696f4b19c54618d4fb18f9fc24b0aef02acf704b23f487daa1011", size = 3119416, upload-time = "2026-05-01T23:38:47.814Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/93/242e2eab5fe682ffcb8b0084bde703a41d51e17ee0f3a31ff0d9d813620a/jedi-0.20.0-py2.py3-none-any.whl", hash = "sha256:7bdd9c2634f56713299976f4cbd59cb3fa92165cc5e05ea811fb253480728b67", size = 4884812, upload-time = "2026-05-01T23:38:43.919Z" }, +] + +[[package]] +name = "jeepney" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/6f/357efd7602486741aa73ffc0617fb310a29b588ed0fd69c2399acbb85b0c/jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732", size = 106758, upload-time = "2025-02-27T18:51:01.684Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", size = 49010, upload-time = "2025-02-27T18:51:00.104Z" }, +] + +[[package]] +name = "joserfc" +version = "1.7.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/e0/27a6a081ae25420eda6768ceae05d7022a7f2447f420588843f2a44e4298/joserfc-1.7.4.tar.gz", hash = "sha256:b3bc561672ae541b17a9237053b48a03dacddd92d68047b3ecdfb4b5714a88ed", size = 234027, upload-time = "2026-07-19T15:43:02.739Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/bf/249dcd99b3376375910b7fa922383b57792975c8758f50d44612e749226c/joserfc-1.7.4-py3-none-any.whl", hash = "sha256:32d46c2cd5e3203c13e87a6c61333cab310b1ba80cd54b4c4f386a848a122463", size = 71000, upload-time = "2026-07-19T15:43:01.299Z" }, +] + +[[package]] +name = "jsonref" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/0d/c1f3277e90ccdb50d33ed5ba1ec5b3f0a242ed8c1b1a85d3afeb68464dca/jsonref-1.1.0.tar.gz", hash = "sha256:32fe8e1d85af0fdefbebce950af85590b22b60f9e95443176adbde4e1ecea552", size = 8814, upload-time = "2023-01-16T16:10:04.455Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/ec/e1db9922bceb168197a558a2b8c03a7963f1afe93517ddd3cf99f202f996/jsonref-1.1.0-py3-none-any.whl", hash = "sha256:590dc7773df6c21cbf948b5dac07a72a251db28b0238ceecce0a2abfa8ec30a9", size = 9425, upload-time = "2023-01-16T16:10:02.255Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py", version = "0.30.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "rpds-py", version = "2026.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, +] + +[[package]] +name = "jsonschema-path" +version = "0.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "pathable" }, + { name = "pyyaml" }, + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/39/79/cd02a4df6d9270efdc7d3feefe6edd730b0820c39eeaa107a2faee8322d5/jsonschema_path-0.5.0.tar.gz", hash = "sha256:493b156ba895c97602655b620a8456caa2ce08c1aa389f5a7addec065e6e855c", size = 19597, upload-time = "2026-05-19T20:45:00.971Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/2c/9e69d73c4297508be9e3b64a970ea3971b3eb8db64ffc5802d40bd25981f/jsonschema_path-0.5.0-py3-none-any.whl", hash = "sha256:2790a070bc7abb08ea3dbe4d340ece4efadf639223001f020c7503229ba068e2", size = 24077, upload-time = "2026-05-19T20:44:59.225Z" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[package]] +name = "jupyter-client" +version = "8.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-core" }, + { name = "python-dateutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/dc/5512503b088997c2250b8bf18258fba9d9ce5ead641183700960d3c9d342/jupyter_client-8.9.1.tar.gz", hash = "sha256:a58f730dd9e728ba16ba1d62ebccf7ffe1ebbdbce4e95cfae941b7321ae1f4fa", size = 359256, upload-time = "2026-06-09T13:15:01.033Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/6f/56d39bf385c5c27988aebaf0c18a2a17e960575740100973511018bd904e/jupyter_client-8.9.1-py3-none-any.whl", hash = "sha256:0b7a295bc46e8751e9adae84781f726c851c1d911bd793edc4a3bde942e3da81", size = 109828, upload-time = "2026-06-09T13:14:58.835Z" }, +] + +[[package]] +name = "jupyter-core" +version = "5.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "platformdirs" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/49/9d1284d0dc65e2c757b74c6687b6d319b02f822ad039e5c512df9194d9dd/jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508", size = 89814, upload-time = "2025-10-16T19:19:18.444Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407", size = 29032, upload-time = "2025-10-16T19:19:16.783Z" }, +] + +[[package]] +name = "keyring" +version = "25.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "importlib-metadata", marker = "python_full_version < '3.12'" }, + { name = "jaraco-classes" }, + { name = "jaraco-context" }, + { name = "jaraco-functools" }, + { name = "jeepney", marker = "sys_platform == 'linux'" }, + { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, + { name = "secretstorage", marker = "sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/43/4b/674af6ef2f97d56f0ab5153bf0bfa28ccb6c3ed4d1babf4305449668807b/keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b", size = 63516, upload-time = "2025-11-16T16:26:09.482Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, +] + +[[package]] +name = "librt" +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/2f/3908645ddddab7120b46295e541ead308109fa48dbec7d67d7a778870d60/librt-0.13.0.tar.gz", hash = "sha256:1d2a610c14ac0d0750ee0a3ab8548e83155258387891caaca04def4bf7289781", size = 211402, upload-time = "2026-07-08T12:26:29.834Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/2f/ec5241c38e7fa0fe6c26bfc450e78b9489a6c3c08b394b85d2c10e506975/librt-0.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:34e47058fcc69a313293d6dee94216a4f30c929ae6f2476e58c5ba635aa639d5", size = 148654, upload-time = "2026-07-08T12:24:30.622Z" }, + { url = "https://files.pythonhosted.org/packages/a5/1a/d651e18d3ee7aa2879322368c4f278bb7ecaa6b90caadfdec4ebfa8389f3/librt-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dbdd5b6509d0c2a8fe72cf494c299a61dbd58142a90a4190664ae159e4a7b547", size = 153537, upload-time = "2026-07-08T12:24:31.773Z" }, + { url = "https://files.pythonhosted.org/packages/45/18/10bff2122577246009d9619b6569596daf69b7648812f997ca9ca0426f60/librt-0.13.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e56ea4ee4df77585a6b5c138f6538680886024fa559f5b55bd14b12e98e67b2", size = 494336, upload-time = "2026-07-08T12:24:33.079Z" }, + { url = "https://files.pythonhosted.org/packages/67/69/87dfee871b852970f137fdeae8e2ca356c5ab38e6f21d2a3299535fc3159/librt-0.13.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f1f9cc4d09a46d9cb3c2063ae100629d3f52a6517c3c08c2f4c9828261883929", size = 485393, upload-time = "2026-07-08T12:24:34.324Z" }, + { url = "https://files.pythonhosted.org/packages/e9/d5/625447a8c0441ff5f15f4ac5e1d323fb9d4d256ebfde7a3c8e003f646057/librt-0.13.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f125f5d46b20f89dc5587a55cc416b4ba2a5b2ffda36d048ee120e17598a653a", size = 515382, upload-time = "2026-07-08T12:24:35.575Z" }, + { url = "https://files.pythonhosted.org/packages/8d/d8/1c8c49ea04235960426444deece9092a6b3a9587a850a81bae2335317411/librt-0.13.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2608d3b39f9e0b4a66a130d9150c615cba40a5090d25eeeaa225e0e46de8c0ac", size = 509483, upload-time = "2026-07-08T12:24:36.923Z" }, + { url = "https://files.pythonhosted.org/packages/6f/65/f1760fc48050e215201a03506c32b7270159088d01f64557b53e39e74a45/librt-0.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9fd35e95ab5e45c3901d37110263c7db85a961110f5460588fe37f8c131f88a7", size = 532503, upload-time = "2026-07-08T12:24:38.203Z" }, + { url = "https://files.pythonhosted.org/packages/18/1b/793e281dcf494879eff99f642b63ebc9c7c58694a1c2d1e93362a22c7041/librt-0.13.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5f31b0aa13c9b04370d4da6be1ab7779776b3a075cceb6747a39a4be85fe1e40", size = 537027, upload-time = "2026-07-08T12:24:39.34Z" }, + { url = "https://files.pythonhosted.org/packages/69/45/0801bbb40c9eea795d3dd3ce91c4c5f3fe7d42d23ec4be3e8cb283bcc754/librt-0.13.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0b795f5fc70fbbb787ceaf79bb3a0d627bcc33c53de51741755263ec406b775a", size = 517100, upload-time = "2026-07-08T12:24:40.907Z" }, + { url = "https://files.pythonhosted.org/packages/a1/6c/eb5f514f8e29d4924bc0ff4601dd7b4175557e182e7c0721e84cffa39b8a/librt-0.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:36b306a623aaad96fe4b378692b54f9c0789fccd833b9851753d5fbf6138cfde", size = 558653, upload-time = "2026-07-08T12:24:42.359Z" }, + { url = "https://files.pythonhosted.org/packages/b4/bf/f140100d1b59fe87ff40b5ecbb4e27924335b189a784e230ee465452f6c2/librt-0.13.0-cp310-cp310-win32.whl", hash = "sha256:a3762e75fcac8c9e4dacaaf438bffd9003e2ca2c531b756f3c0035deefa674c8", size = 104402, upload-time = "2026-07-08T12:24:43.668Z" }, + { url = "https://files.pythonhosted.org/packages/22/7c/57e40fef7cfb61869341cb28bdcefe8a950bebcbecca74a397bae14dce4a/librt-0.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:d63bae12a8aeb51380be3438e4dc4bd27354d0f8e19166b2f44e3e94d6f552dc", size = 125002, upload-time = "2026-07-08T12:24:44.793Z" }, + { url = "https://files.pythonhosted.org/packages/89/25/a6498964cfeec270c468cffdc118f69c29b412593610d55fa1327ca51ff4/librt-0.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1b5a7bbff495baedbd9b916c367d66854008f8f3b575908ded477c499dc60082", size = 148029, upload-time = "2026-07-08T12:24:45.961Z" }, + { url = "https://files.pythonhosted.org/packages/78/59/dc86d1bffd8e0c2818bace29d9f7783cfbb8e0673bf3673b5bbd5bbe0420/librt-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34bc7938b9fdf14fe32a406c19c71faf894c5cee7e7474bd0be2f17200b82d14", size = 153036, upload-time = "2026-07-08T12:24:47.257Z" }, + { url = "https://files.pythonhosted.org/packages/29/3f/b923826660f02f286186cd9303d52bb05ced0a13708edc104dc8480920e3/librt-0.13.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f40e56b61b41be5f7dec938cfeffd660668cf4b5e72c78e7bd671d66b7bc2c79", size = 493062, upload-time = "2026-07-08T12:24:48.483Z" }, + { url = "https://files.pythonhosted.org/packages/88/87/6c0980a9c9b1302cb68d108906697b89eceb55889bb1dcf77c109aa56ca5/librt-0.13.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:9c5d02b89de5acd0379a51ec44a89476fb03df6145442e1c8ecd6bee2f91b176", size = 485510, upload-time = "2026-07-08T12:24:49.727Z" }, + { url = "https://files.pythonhosted.org/packages/32/81/795ae3b9df5dd94079fb807e38191855e023e8c6249014ae6bc3f0d9a490/librt-0.13.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7db9a3ff32ef5f7d1703d93831a3316cdf0b537de6a1cc03cc8fdd09b9194e89", size = 515909, upload-time = "2026-07-08T12:24:51.135Z" }, + { url = "https://files.pythonhosted.org/packages/20/e5/182de15abce8907108a6fdb41487de65beb5099b74dc5841b19b099168db/librt-0.13.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3dbb2a31882456cadc7053378e81ad7ed7693db4ac9f98ab5f81ef034aa8ec9f", size = 508620, upload-time = "2026-07-08T12:24:52.358Z" }, + { url = "https://files.pythonhosted.org/packages/32/03/33978d32db76e1f66377e8f78e42a2ca3c162143331677d1f50bbad36cfb/librt-0.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c6014e3c80f9c1fe268ef8b0e0ef113bac672cc032f2f93866e7ddad4f3e663d", size = 530363, upload-time = "2026-07-08T12:24:53.503Z" }, + { url = "https://files.pythonhosted.org/packages/e6/f5/b291fbd2d00f7d8287bcbf67b5aa0c6afed4bc26cef23e079629c47a2c04/librt-0.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:091b60a4d2174fc1ec5c34cdc0b72efb6224753d76b7da61ebeab7a191aec8bd", size = 534209, upload-time = "2026-07-08T12:24:55.138Z" }, + { url = "https://files.pythonhosted.org/packages/3e/03/6f41f17939d191bc21609f220da8509316bc62797f078545fe83be522e78/librt-0.13.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:66cb1138f384a191a6d75f986064841fcfdc0cea98f7bd9c9ab9b38049917588", size = 514254, upload-time = "2026-07-08T12:24:56.276Z" }, + { url = "https://files.pythonhosted.org/packages/af/c2/2e4befa5410a7443019c14abccc94ff619797171f6b72013635fb87f31d7/librt-0.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:17221a7569f8f292aa0014226e48aa25b8c2b08da18088cd230953d0ea0f9cd1", size = 557611, upload-time = "2026-07-08T12:24:57.561Z" }, + { url = "https://files.pythonhosted.org/packages/ab/54/8b69f81448417adbc040a2185f4e2eece1e1994b7dcfaeed4662b30f98a5/librt-0.13.0-cp311-cp311-win32.whl", hash = "sha256:fc67741da44c6eaa90e01eafb586bbba9b51eb5b6ed381ee6f5ae72eb3316d21", size = 104906, upload-time = "2026-07-08T12:24:58.806Z" }, + { url = "https://files.pythonhosted.org/packages/76/5a/f4aaf37b50f2fde12c8c663b83fdd499cdc24f957f19543d7414bfcc9e25/librt-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:cc99dfb62b23c9207c33d0be8a2e2af7a42e21e6ea388b380a0c948c7b88953b", size = 125852, upload-time = "2026-07-08T12:25:00.065Z" }, + { url = "https://files.pythonhosted.org/packages/f2/99/bf1820e6feeabc2f218c24450ec0c995d6a91e8ba0fd3caf042c9e8adb2a/librt-0.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:40ccd13c252d3fe473ffc8a57be7565abc8b64cf1b108344c859d5164f7f3e0c", size = 111832, upload-time = "2026-07-08T12:25:01.148Z" }, + { url = "https://files.pythonhosted.org/packages/f0/f4/b2933ddae222dac338476abb872641169a5cfed2c2bb5444a5b07b32b0c3/librt-0.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30536798f4504c0fad0885b1d371b0539abb081e4570c9d7c641cb51141b49f0", size = 150990, upload-time = "2026-07-08T12:25:02.42Z" }, + { url = "https://files.pythonhosted.org/packages/90/ef/db98f744ca50e6efc9c95c70ee49b77aefac31f6a3fc7c83754a42d6a74f/librt-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:93d24ebb82aa4420b1409c389e7857bc35bd0b668007ac8172427d5c73cc8cc5", size = 155238, upload-time = "2026-07-08T12:25:03.681Z" }, + { url = "https://files.pythonhosted.org/packages/03/e7/a197e7bc72baf2c61ce7fdc6906a5054dc05bd8da0819aa894e4857bf87e/librt-0.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb8a1adce42d8b75485a5d56a9623a50bcab995b6079f1dac59fc44034dd93d9", size = 503073, upload-time = "2026-07-08T12:25:05.049Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e7/7887712e27da7c1ab80fcabb1de6eb24243964f6557cae530d4b70706dbd/librt-0.13.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0763ca2ab66058174f9dee426dc64f5e0a89c24a7df8d3fe3f1836c04e25de4b", size = 496528, upload-time = "2026-07-08T12:25:06.26Z" }, + { url = "https://files.pythonhosted.org/packages/94/f0/f2283385bb6b950b26a1410f4ce51ec27231e0b3a4b925c46366d218b198/librt-0.13.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b222493da6e7b6199db9bd79502436cf5a27da3c1f7fa83c7e285444fc93fd03", size = 531786, upload-time = "2026-07-08T12:25:07.658Z" }, + { url = "https://files.pythonhosted.org/packages/36/11/69ac3b54766ffba5fd7e5acebfb048d66dbe1f9f2d14516c2b3edc59cf87/librt-0.13.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fadc63331f4388c3dc90090448f682a7e9feafc11481391c1e94f2f907a3976e", size = 524393, upload-time = "2026-07-08T12:25:09.121Z" }, + { url = "https://files.pythonhosted.org/packages/61/5f/d72f95fd444a926a3c14b4e24979474116988dd57a45be242077c45d3c22/librt-0.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:70d9c62a4cffd9f23396cd5ef93fc5d11b31596b9b7d6306074abe3d5fcf09bd", size = 543026, upload-time = "2026-07-08T12:25:10.459Z" }, + { url = "https://files.pythonhosted.org/packages/c4/08/dcd9993ad192737a004ba263d549f8ea605b326b952e7d6205c7d4170b76/librt-0.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:66c0e7e6b02a155576df2c77ec933a70b72da726e248c494abf690923e624348", size = 546829, upload-time = "2026-07-08T12:25:11.716Z" }, + { url = "https://files.pythonhosted.org/packages/96/d5/6d9bb2f54e4109a956b7128836529653eb9d740f784bc47ed10a02c1000e/librt-0.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:ac04bcd3328eb91d99dfedf6a60d9c1f15d3434e6f6daf922f0420f7d90b85c7", size = 535700, upload-time = "2026-07-08T12:25:13.144Z" }, + { url = "https://files.pythonhosted.org/packages/8c/f2/10946922503858a359492fa27f13e86228bde702116a740ac7b3cd185f24/librt-0.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:db327e7271e653c32040b85ae6188059c924b57d7e1e29f935523fa017cd4e82", size = 573566, upload-time = "2026-07-08T12:25:14.336Z" }, + { url = "https://files.pythonhosted.org/packages/48/a8/94f00e3c99479a18088af3685ea016c42f3c7d5d1964d8dbb40c08d7f1aa/librt-0.13.0-cp312-cp312-win32.whl", hash = "sha256:860bd1d8ba48456ce08feaf8d343a8aaeb2fa086f2bcaa2a923fa3f7a3ff9aa3", size = 106099, upload-time = "2026-07-08T12:25:16.159Z" }, + { url = "https://files.pythonhosted.org/packages/c9/7b/2da9c74c1ed25a89cc4e1c8e007ea2eb4a0f1fafa3e70d757fe3242c5c5c/librt-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:e54a315caf843c8d77e388cadc56ea9ded569935ee2d2347d7ea94992e5aa6fa", size = 126934, upload-time = "2026-07-08T12:25:17.275Z" }, + { url = "https://files.pythonhosted.org/packages/d0/65/aead61bbf3b5358593f9d4779d2a0e88eaf6ec191a6342dde36dd1df6371/librt-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:c718e99a0992127af84385378460db624103b559ab260435abcfe77a4e4ed1c1", size = 112236, upload-time = "2026-07-08T12:25:18.425Z" }, + { url = "https://files.pythonhosted.org/packages/67/3b/18e7b63255297a2bdc9c25c8d6d4ca8eca9f63aceb1252c0f7427ac7099e/librt-0.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a468951af16155824e88bdd8326ebe5bdb371f3ec0ac04642994b98201d914f3", size = 151027, upload-time = "2026-07-08T12:25:19.638Z" }, + { url = "https://files.pythonhosted.org/packages/4d/68/e2248452c00d1a03b45fee1752cdc8f790a476efd2402b75181da88a9e61/librt-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ae01d8512cc17079e53425635327dbf3f7ff57a42c00dec348bf79791c56444c", size = 155152, upload-time = "2026-07-08T12:25:20.851Z" }, + { url = "https://files.pythonhosted.org/packages/0e/16/52b1c99bf19057a062aac39c900cbb81499f6f75d6c537c14463d247ba78/librt-0.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:32c26893cd085c1efe83219e78d866da23fb20a066101b8f68210004361d224c", size = 502499, upload-time = "2026-07-08T12:25:22.055Z" }, + { url = "https://files.pythonhosted.org/packages/9f/54/b811151805c795f55e0dedee6ec687b75f9982a8105d240ea3910737a77b/librt-0.13.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5929da1981a46bcf4b28b1b9499905f0ff58e2419da402a048234e9783acbc4b", size = 496108, upload-time = "2026-07-08T12:25:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/8f/f8/094d6b2bd93f3fdaa54db54cc788c4a365333bddad65ab02e04da0b1d004/librt-0.13.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:94b85d664d777bab6c0d709416cb42938251fda9e221b79e3a2215d85df5f4f9", size = 531576, upload-time = "2026-07-08T12:25:24.648Z" }, + { url = "https://files.pythonhosted.org/packages/2e/40/541733d5755824f968f7ec39d78ffbd75d145964157ae5e69a09ec6d7326/librt-0.13.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:531b2df3e9fe96b1fcf73a6d165921e4656be5f58d631d384ebce344298368db", size = 524390, upload-time = "2026-07-08T12:25:25.898Z" }, + { url = "https://files.pythonhosted.org/packages/c6/b5/255673cfdbf5ba663339d36cd863c897289ab4337577e19f9405ce059f36/librt-0.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:109b84a9edf69ad89dc1f66358659e14a031baca95e3e5b0060bd903ede8efd6", size = 543053, upload-time = "2026-07-08T12:25:27.436Z" }, + { url = "https://files.pythonhosted.org/packages/9e/11/ab5005e9c9850710f21e354201bf090646349d3fabf5f951eaf70235729e/librt-0.13.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1304368a3e7ffc3e9db986796cc5326fdb5943a3567ecc137cff318e4240c0e7", size = 546387, upload-time = "2026-07-08T12:25:28.65Z" }, + { url = "https://files.pythonhosted.org/packages/a2/04/a5d7ce1d1df1afd15ca283dcdf7530ac073e12d69ae8c40879dda96f7868/librt-0.13.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e4f9b472e7d308d94b62c801982065661158c6ed02790d6c7ddb4337cea0f9c1", size = 535970, upload-time = "2026-07-08T12:25:30.171Z" }, + { url = "https://files.pythonhosted.org/packages/5a/76/927e267a6daa290174ac281b23c9804c8829b042ade9c6f24a065f540958/librt-0.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f836c37478f167a81200d8c8b2c920a22224564bed2c23d7aeec760965c367a", size = 573582, upload-time = "2026-07-08T12:25:31.507Z" }, + { url = "https://files.pythonhosted.org/packages/10/24/b6c5213efe39c19f9e13605644d0cf063b4ddaa33ac2e45b088e23a70e2e/librt-0.13.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:4000d961ff9598ac6ea603c6c836a5ed49bc205ade5fc378b998dfe1e2c36628", size = 82189, upload-time = "2026-07-08T12:25:32.675Z" }, + { url = "https://files.pythonhosted.org/packages/4c/00/d29736be177a906ac0b84a5b04b4fbfa22c776dc2f366de4172b0f968c08/librt-0.13.0-cp313-cp313-win32.whl", hash = "sha256:79e44cff71750d299d61a678e49995b0d5935a9cda238c2574daeca3ba536927", size = 106193, upload-time = "2026-07-08T12:25:33.692Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ac/aff6fb45393cb8912f39dfb156ef6b2d1cadb207ff465fc8f66141054be8/librt-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:54dab44a847d5ad1acd05c8a83fe518ae685516ecf4d3f7cc6e3df2a66767650", size = 126962, upload-time = "2026-07-08T12:25:34.769Z" }, + { url = "https://files.pythonhosted.org/packages/d9/3a/d68cb2b334d53fd30fac81d3a489ce4ba0d9506f4df43fcf676b68352b19/librt-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:d4cb6fbfdf874340ab5e51450753c0f817b6958a3621125ee695bbc3de866566", size = 112127, upload-time = "2026-07-08T12:25:35.981Z" }, + { url = "https://files.pythonhosted.org/packages/7b/66/f49ae0d592bd45b6941e9a8bafcb6a87cddcd501ee7874707e767f01b585/librt-0.13.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:25218d94b1d2cbc0ba1d8a3f9dc9af578d9646e5ed16443a70cde1dfdcce6d71", size = 149818, upload-time = "2026-07-08T12:25:37.203Z" }, + { url = "https://files.pythonhosted.org/packages/3d/50/51c76d74014d04fb95b6506d286808984b78a2f7a41039094e6b2194ac48/librt-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f26629539d4893c2957a16c41bb058e1e135c1f150f6a2e25ed047f64cf3f5c6", size = 154071, upload-time = "2026-07-08T12:25:39.399Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fe/f19b0f5f82d5a1f2da736586bc840abd00ce07d6388136ae80b7333883fc/librt-0.13.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4517d47b2b8af26975a406fba7d314de9696d864252e0257c6ea90238cfe27f", size = 494168, upload-time = "2026-07-08T12:25:40.641Z" }, + { url = "https://files.pythonhosted.org/packages/94/bc/b8550c75775127fd31a5f20e8775997f7b527ad661fc8ddccd7497c064f7/librt-0.13.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f19e181de5b3a1148bb3420b8c4b0b0ea0fce6950099724ad151d6cea5acc180", size = 491054, upload-time = "2026-07-08T12:25:41.905Z" }, + { url = "https://files.pythonhosted.org/packages/30/14/4d0204867623df3f33f86efd3d3692ba5e01321443f4d6eab35a22697618/librt-0.13.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22034924f5b42d5a56371cf271771bfeaabf235a7a8b6264bef2d20013f786c6", size = 523006, upload-time = "2026-07-08T12:25:43.327Z" }, + { url = "https://files.pythonhosted.org/packages/19/0a/c45fc9a260934696bace1ac5df1e148ac92bd71767aee3bf7cd7a4534f4c/librt-0.13.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c7897db4e95e22468bdda33d8e012ceacd0182abf001e6389d763f0def6286b9", size = 515058, upload-time = "2026-07-08T12:25:44.541Z" }, + { url = "https://files.pythonhosted.org/packages/13/0a/50c5ce45b326854ef8fa6ae4c36cf5142e5c55315eaf9e51d0ae73ac4da3/librt-0.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1ce61b3746545029d4f5c17d6bd74b676254ad98433086c846ffb5e8fa73f007", size = 534025, upload-time = "2026-07-08T12:25:45.825Z" }, + { url = "https://files.pythonhosted.org/packages/89/2d/08c413c8f93fc13b8103624fce38e5caa86cd08cbbc8465870ab287af54b/librt-0.13.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:46c330e82565962c761dbce7941be2cff7db674ee807455a8d0cadc5f9b759b0", size = 540557, upload-time = "2026-07-08T12:25:47.059Z" }, + { url = "https://files.pythonhosted.org/packages/b3/c1/93af71fb4a364952210051811dd4e40174e79656b050c89cacac18af3330/librt-0.13.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:375f5af8f99cbaa99dd293af986e3d57caabc9ba81a5d3f021603764854197a1", size = 523201, upload-time = "2026-07-08T12:25:48.392Z" }, + { url = "https://files.pythonhosted.org/packages/c1/6e/9766f07b676a4889d9f8bc2864e9ba5fff165653143ef4dda7df6aa34d16/librt-0.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9320d34c3376ae204b2cd176e8d4883a013934e0aef822f1aed9c536490c275d", size = 565740, upload-time = "2026-07-08T12:25:49.678Z" }, + { url = "https://files.pythonhosted.org/packages/a2/1e/664e3472ce2b6e10e9b83f29d4a36eb982ff6b5a169ae7567bba3a4c4ff5/librt-0.13.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:9af313c66157a69dc69ea0059a66961692250e0dc95af9c385a48ffb770a0d16", size = 81611, upload-time = "2026-07-08T12:25:50.857Z" }, + { url = "https://files.pythonhosted.org/packages/2f/d4/8582a4d65e2234673685e07309d02c230b28a85724eb0acbf13f019b7f6e/librt-0.13.0-cp314-cp314-win32.whl", hash = "sha256:f2a7253458e34f33543551394ae4fe104b497ec2a65ac266074de64c1df82e37", size = 100106, upload-time = "2026-07-08T12:25:52.03Z" }, + { url = "https://files.pythonhosted.org/packages/63/ce/0cb99efe6086b46cd985dc26672166fae312a239690e75871f7fafbd3fc5/librt-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:a3dfe4edf10e8ed7e55b026a8bfc2c2a8704218b659cd4bffdf604fab966dc39", size = 121209, upload-time = "2026-07-08T12:25:53.166Z" }, + { url = "https://files.pythonhosted.org/packages/26/85/4f3ccb083a3c9b0d42e223acdb3c3f507953324a59cdcab4826e8e2e3b89/librt-0.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:68a5faee4bba381cb93b5961f684a514cf0053cb92308ff9c792c2fea0b174c6", size = 106404, upload-time = "2026-07-08T12:25:54.253Z" }, + { url = "https://files.pythonhosted.org/packages/b2/77/333191499538c8e8189de7a4cba8e6f49ee949fd6d6e6324b21fd1522466/librt-0.13.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a38fb81d8376dfa2f8963b265fec07637802b0d01e2a127c19c66cb070fb24f5", size = 159231, upload-time = "2026-07-08T12:25:55.432Z" }, + { url = "https://files.pythonhosted.org/packages/7a/9e/2aa83758f22c278b837a1d8025898434ce2b8bff36678d5330ecaef56dff/librt-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d4c8d9bd5abce34b2e75edb3bf37ab0f34e49b1f915a40ae8468eb7c85bc5b46", size = 161300, upload-time = "2026-07-08T12:25:56.585Z" }, + { url = "https://files.pythonhosted.org/packages/bb/c0/86791e936553ca763d6b3c2fb4d31d596cd00e14fa631c283a40ba01559a/librt-0.13.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:387e2f1d27e89bffe0d3f520f0da0662c973fd607ca16c1808f8a5085419485e", size = 582056, upload-time = "2026-07-08T12:25:58.144Z" }, + { url = "https://files.pythonhosted.org/packages/a8/d3/a9ec15984a185e000c4d2a16ba28bd623124ad4c38a10974c7ff78e3a893/librt-0.13.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:4f6db193d2e5e0ed60359b9a5a682cd67205d0d3b1e459a867dd4b5c4e7eaa7a", size = 562758, upload-time = "2026-07-08T12:25:59.544Z" }, + { url = "https://files.pythonhosted.org/packages/3c/af/dbe36b78b19c06a55097f99305e4ea9458e2273e6ae16a3cbecaad7ee978/librt-0.13.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d38604854e8d22faadf683ec6c02bb0f886e2ba56ef981a1c36ee275f21ea22", size = 602095, upload-time = "2026-07-08T12:26:00.991Z" }, + { url = "https://files.pythonhosted.org/packages/2a/a8/2966891b4dd2830f5203fbee92ac2c4947653a2390ba73dfa44244fad025/librt-0.13.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:371f7ce73026815dafd51c50ce38416e91428b28c4b2ec97cd39271164b0045c", size = 593452, upload-time = "2026-07-08T12:26:02.352Z" }, + { url = "https://files.pythonhosted.org/packages/61/f5/4df8bfc8405ecf8c0d525b4d69636f694bdd8620b313ec8b76e54a5926cc/librt-0.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3aaedf52171bee90860704c560bc798fe83b76247df47568e0197e9b13c735a0", size = 623729, upload-time = "2026-07-08T12:26:04.294Z" }, + { url = "https://files.pythonhosted.org/packages/d6/13/9ac202dffc8db06f75d06c08c2f9f6ff054be67d21272dcc078fa1cc0c57/librt-0.13.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:96bad8725a4f196a798366c25ce075d1f7543a4ec045ffc13e6a7ec095cdab04", size = 617077, upload-time = "2026-07-08T12:26:05.845Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f0/ebe38610716aee5cb28efd95089bb90192096179802779381e1c5dcf239c/librt-0.13.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:6bf6a559ffe4a93bbea6cf31ddf01a7fd9ba342ef51f27beb178e318b74acd61", size = 599561, upload-time = "2026-07-08T12:26:07.21Z" }, + { url = "https://files.pythonhosted.org/packages/4f/5c/c2e72e236fff7abc716d5b1753b8b8cd3ea85ac46fe17d2e7c51d4e1c723/librt-0.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:301067672387902c55f94b51d5022304b36c966ea9fe1f21caab99a9bef487c9", size = 645511, upload-time = "2026-07-08T12:26:08.562Z" }, + { url = "https://files.pythonhosted.org/packages/0c/99/6203ce619dee940d6bfbe099ec3fe4be00a68e9d60f70abf906cf124fe66/librt-0.13.0-cp314-cp314t-win32.whl", hash = "sha256:5fdcf34f86de8fb66d7dc7589f96ba91c4aa46671200d400e6fd6f109a483f18", size = 104357, upload-time = "2026-07-08T12:26:09.828Z" }, + { url = "https://files.pythonhosted.org/packages/52/dd/843b6314087c41657c7036d7914d8f294bdf9b580aa8513ea0588c8e9a3d/librt-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:260c33e92263fa629b4f6d3c51967a1c2158fe6c33237aaa3ebeac586b085259", size = 126998, upload-time = "2026-07-08T12:26:10.975Z" }, + { url = "https://files.pythonhosted.org/packages/5f/5d/3dcec2884ba1b0806d1408612555c38dd5d68e90156b59f75f6e36435c3a/librt-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2f281549a4c52ac7bb97997f14353f8bd0e53a34ca0dad1c905cfd0b4a58ae99", size = 110771, upload-time = "2026-07-08T12:26:12.303Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" }, +] + +[[package]] +name = "matplotlib-inline" +version = "0.2.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/c0/9f7c9a46090390368a4d7bcb76bb87a4a36c421e4c0792cdb53486ffac7a/matplotlib_inline-0.2.2.tar.gz", hash = "sha256:72f3fe8fce36b70d4a5b612f899090cd0401deddc4ea90e1572b9f4bfb058c79", size = 8150, upload-time = "2026-05-08T17:33:33.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/09/5b161152e2d90f7b87f781c2e1267494aef9c32498df793f73ad0a0a494a/matplotlib_inline-0.2.2-py3-none-any.whl", hash = "sha256:3c821cf1c209f59fb2d2d64abbf5b23b67bcb2210d663f9918dd851c6da1fcf6", size = 9534, upload-time = "2026-05-08T17:33:32.055Z" }, +] + +[[package]] +name = "mccabe" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658, upload-time = "2022-01-24T01:14:51.113Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" }, +] + +[[package]] +name = "mcp" +version = "1.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "httpx" }, + { name = "httpx-sse" }, + { name = "jsonschema" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "pyjwt", extra = ["crypto"] }, + { name = "python-multipart" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "sse-starlette" }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, + { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6e/77/9450b8f251a13affb6281997d0523c4615f8a8b35d0b21ff30db3a5aac9d/mcp-1.28.1.tar.gz", hash = "sha256:d51e36a5f5644faea4f85ea649bfffa6bc6c26770d42798ad6a3de3d2ba69683", size = 638501, upload-time = "2026-06-26T12:57:29.093Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/5e/d118fce19f87a2e7d8101c35c8ae0ec289098a4df0ff244cec23e415aca0/mcp-1.28.1-py3-none-any.whl", hash = "sha256:2726bca5e7193f61c5dde8b12500a6de2d9acf6d1a1c0be9e8c2e706437991df", size = 222620, upload-time = "2026-06-26T12:57:27.218Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "more-itertools" +version = "11.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/de/1d/f4da6f02cdffe04d6362210b807146a26044c88d839208aec273bb0d9184/more_itertools-11.1.0.tar.gz", hash = "sha256:48e8f4d9e7e5878571ecf6f2b4e57634f93cd474cc8cfbd2376f2d11b396e30d", size = 145772, upload-time = "2026-05-22T14:14:29.909Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/3d/1087453384dbde46a8c7f9356eead2c58be8a7bf156bca40243377c85715/more_itertools-11.1.0-py3-none-any.whl", hash = "sha256:4b65538ae22f6fed0ce4874efd317463a7489796a0939fa66824dd542125a192", size = 72226, upload-time = "2026-05-22T14:14:28.824Z" }, +] + +[[package]] +name = "multidict" +version = "6.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1a/c2/c2d94cbe6ac1753f3fc980da97b3d930efe1da3af3c9f5125354436c073d/multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d", size = 102010, upload-time = "2026-01-26T02:46:45.979Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/0b/19348d4c98980c4851d2f943f8ebafdece2ae7ef737adcfa5994ce8e5f10/multidict-6.7.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c93c3db7ea657dd4637d57e74ab73de31bccefe144d3d4ce370052035bc85fb5", size = 77176, upload-time = "2026-01-26T02:42:59.784Z" }, + { url = "https://files.pythonhosted.org/packages/ef/04/9de3f8077852e3d438215c81e9b691244532d2e05b4270e89ce67b7d103c/multidict-6.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8", size = 44996, upload-time = "2026-01-26T02:43:01.674Z" }, + { url = "https://files.pythonhosted.org/packages/31/5c/08c7f7fe311f32e83f7621cd3f99d805f45519cd06fafb247628b861da7d/multidict-6.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdea2e7b2456cfb6694fb113066fd0ec7ea4d67e3a35e1f4cbeea0b448bf5872", size = 44631, upload-time = "2026-01-26T02:43:03.169Z" }, + { url = "https://files.pythonhosted.org/packages/b7/7f/0e3b1390ae772f27501199996b94b52ceeb64fe6f9120a32c6c3f6b781be/multidict-6.7.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17207077e29342fdc2c9a82e4b306f1127bf1ea91f8b71e02d4798a70bb99991", size = 242561, upload-time = "2026-01-26T02:43:04.733Z" }, + { url = "https://files.pythonhosted.org/packages/dd/f4/8719f4f167586af317b69dd3e90f913416c91ca610cac79a45c53f590312/multidict-6.7.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4f49cb5661344764e4c7c7973e92a47a59b8fc19b6523649ec9dc4960e58a03", size = 242223, upload-time = "2026-01-26T02:43:06.695Z" }, + { url = "https://files.pythonhosted.org/packages/47/ab/7c36164cce64a6ad19c6d9a85377b7178ecf3b89f8fd589c73381a5eedfd/multidict-6.7.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a9fc4caa29e2e6ae408d1c450ac8bf19892c5fca83ee634ecd88a53332c59981", size = 222322, upload-time = "2026-01-26T02:43:08.472Z" }, + { url = "https://files.pythonhosted.org/packages/f5/79/a25add6fb38035b5337bc5734f296d9afc99163403bbcf56d4170f97eb62/multidict-6.7.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c5f0c21549ab432b57dcc82130f388d84ad8179824cc3f223d5e7cfbfd4143f6", size = 254005, upload-time = "2026-01-26T02:43:10.127Z" }, + { url = "https://files.pythonhosted.org/packages/4a/7b/64a87cf98e12f756fc8bd444b001232ffff2be37288f018ad0d3f0aae931/multidict-6.7.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7dfb78d966b2c906ae1d28ccf6e6712a3cd04407ee5088cd276fe8cb42186190", size = 251173, upload-time = "2026-01-26T02:43:11.731Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ac/b605473de2bb404e742f2cc3583d12aedb2352a70e49ae8fce455b50c5aa/multidict-6.7.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b0d9b91d1aa44db9c1f1ecd0d9d2ae610b2f4f856448664e01a3b35899f3f92", size = 243273, upload-time = "2026-01-26T02:43:13.063Z" }, + { url = "https://files.pythonhosted.org/packages/03/65/11492d6a0e259783720f3bc1d9ea55579a76f1407e31ed44045c99542004/multidict-6.7.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dd96c01a9dcd4889dcfcf9eb5544ca0c77603f239e3ffab0524ec17aea9a93ee", size = 238956, upload-time = "2026-01-26T02:43:14.843Z" }, + { url = "https://files.pythonhosted.org/packages/5f/a7/7ee591302af64e7c196fb63fe856c788993c1372df765102bd0448e7e165/multidict-6.7.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:067343c68cd6612d375710f895337b3a98a033c94f14b9a99eff902f205424e2", size = 233477, upload-time = "2026-01-26T02:43:16.025Z" }, + { url = "https://files.pythonhosted.org/packages/9c/99/c109962d58756c35fd9992fed7f2355303846ea2ff054bb5f5e9d6b888de/multidict-6.7.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5884a04f4ff56c6120f6ccf703bdeb8b5079d808ba604d4d53aec0d55dc33568", size = 243615, upload-time = "2026-01-26T02:43:17.84Z" }, + { url = "https://files.pythonhosted.org/packages/d5/5f/1973e7c771c86e93dcfe1c9cc55a5481b610f6614acfc28c0d326fe6bfad/multidict-6.7.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8affcf1c98b82bc901702eb73b6947a1bfa170823c153fe8a47b5f5f02e48e40", size = 249930, upload-time = "2026-01-26T02:43:19.06Z" }, + { url = "https://files.pythonhosted.org/packages/5d/a5/f170fc2268c3243853580203378cd522446b2df632061e0a5409817854c7/multidict-6.7.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0d17522c37d03e85c8098ec8431636309b2682cf12e58f4dbc76121fb50e4962", size = 243807, upload-time = "2026-01-26T02:43:20.286Z" }, + { url = "https://files.pythonhosted.org/packages/de/01/73856fab6d125e5bc652c3986b90e8699a95e84b48d72f39ade6c0e74a8c/multidict-6.7.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:24c0cf81544ca5e17cfcb6e482e7a82cd475925242b308b890c9452a074d4505", size = 239103, upload-time = "2026-01-26T02:43:21.508Z" }, + { url = "https://files.pythonhosted.org/packages/e7/46/f1220bd9944d8aa40d8ccff100eeeee19b505b857b6f603d6078cb5315b0/multidict-6.7.1-cp310-cp310-win32.whl", hash = "sha256:d82dd730a95e6643802f4454b8fdecdf08667881a9c5670db85bc5a56693f122", size = 41416, upload-time = "2026-01-26T02:43:22.703Z" }, + { url = "https://files.pythonhosted.org/packages/68/00/9b38e272a770303692fc406c36e1a4c740f401522d5787691eb38a8925a8/multidict-6.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:cf37cbe5ced48d417ba045aca1b21bafca67489452debcde94778a576666a1df", size = 46022, upload-time = "2026-01-26T02:43:23.77Z" }, + { url = "https://files.pythonhosted.org/packages/64/65/d8d42490c02ee07b6bbe00f7190d70bb4738b3cce7629aaf9f213ef730dd/multidict-6.7.1-cp310-cp310-win_arm64.whl", hash = "sha256:59bc83d3f66b41dac1e7460aac1d196edc70c9ba3094965c467715a70ecb46db", size = 43238, upload-time = "2026-01-26T02:43:24.882Z" }, + { url = "https://files.pythonhosted.org/packages/ce/f1/a90635c4f88fb913fbf4ce660b83b7445b7a02615bda034b2f8eb38fd597/multidict-6.7.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d", size = 76626, upload-time = "2026-01-26T02:43:26.485Z" }, + { url = "https://files.pythonhosted.org/packages/a6/9b/267e64eaf6fc637a15b35f5de31a566634a2740f97d8d094a69d34f524a4/multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e", size = 44706, upload-time = "2026-01-26T02:43:27.607Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a4/d45caf2b97b035c57267791ecfaafbd59c68212004b3842830954bb4b02e/multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855", size = 44356, upload-time = "2026-01-26T02:43:28.661Z" }, + { url = "https://files.pythonhosted.org/packages/fd/d2/0a36c8473f0cbaeadd5db6c8b72d15bbceeec275807772bfcd059bef487d/multidict-6.7.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3", size = 244355, upload-time = "2026-01-26T02:43:31.165Z" }, + { url = "https://files.pythonhosted.org/packages/5d/16/8c65be997fd7dd311b7d39c7b6e71a0cb449bad093761481eccbbe4b42a2/multidict-6.7.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e", size = 246433, upload-time = "2026-01-26T02:43:32.581Z" }, + { url = "https://files.pythonhosted.org/packages/01/fb/4dbd7e848d2799c6a026ec88ad39cf2b8416aa167fcc903baa55ecaa045c/multidict-6.7.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a", size = 225376, upload-time = "2026-01-26T02:43:34.417Z" }, + { url = "https://files.pythonhosted.org/packages/b6/8a/4a3a6341eac3830f6053062f8fbc9a9e54407c80755b3f05bc427295c2d0/multidict-6.7.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8", size = 257365, upload-time = "2026-01-26T02:43:35.741Z" }, + { url = "https://files.pythonhosted.org/packages/f7/a2/dd575a69c1aa206e12d27d0770cdf9b92434b48a9ef0cd0d1afdecaa93c4/multidict-6.7.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0", size = 254747, upload-time = "2026-01-26T02:43:36.976Z" }, + { url = "https://files.pythonhosted.org/packages/5a/56/21b27c560c13822ed93133f08aa6372c53a8e067f11fbed37b4adcdac922/multidict-6.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144", size = 246293, upload-time = "2026-01-26T02:43:38.258Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a4/23466059dc3854763423d0ad6c0f3683a379d97673b1b89ec33826e46728/multidict-6.7.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49", size = 242962, upload-time = "2026-01-26T02:43:40.034Z" }, + { url = "https://files.pythonhosted.org/packages/1f/67/51dd754a3524d685958001e8fa20a0f5f90a6a856e0a9dcabff69be3dbb7/multidict-6.7.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71", size = 237360, upload-time = "2026-01-26T02:43:41.752Z" }, + { url = "https://files.pythonhosted.org/packages/64/3f/036dfc8c174934d4b55d86ff4f978e558b0e585cef70cfc1ad01adc6bf18/multidict-6.7.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3", size = 245940, upload-time = "2026-01-26T02:43:43.042Z" }, + { url = "https://files.pythonhosted.org/packages/3d/20/6214d3c105928ebc353a1c644a6ef1408bc5794fcb4f170bb524a3c16311/multidict-6.7.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c", size = 253502, upload-time = "2026-01-26T02:43:44.371Z" }, + { url = "https://files.pythonhosted.org/packages/b1/e2/c653bc4ae1be70a0f836b82172d643fcf1dade042ba2676ab08ec08bff0f/multidict-6.7.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0", size = 247065, upload-time = "2026-01-26T02:43:45.745Z" }, + { url = "https://files.pythonhosted.org/packages/c8/11/a854b4154cd3bd8b1fd375e8a8ca9d73be37610c361543d56f764109509b/multidict-6.7.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa", size = 241870, upload-time = "2026-01-26T02:43:47.054Z" }, + { url = "https://files.pythonhosted.org/packages/13/bf/9676c0392309b5fdae322333d22a829715b570edb9baa8016a517b55b558/multidict-6.7.1-cp311-cp311-win32.whl", hash = "sha256:d62b7f64ffde3b99d06b707a280db04fb3855b55f5a06df387236051d0668f4a", size = 41302, upload-time = "2026-01-26T02:43:48.753Z" }, + { url = "https://files.pythonhosted.org/packages/c9/68/f16a3a8ba6f7b6dc92a1f19669c0810bd2c43fc5a02da13b1cbf8e253845/multidict-6.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:bdbf9f3b332abd0cdb306e7c2113818ab1e922dc84b8f8fd06ec89ed2a19ab8b", size = 45981, upload-time = "2026-01-26T02:43:49.921Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ad/9dd5305253fa00cd3c7555dbef69d5bf4133debc53b87ab8d6a44d411665/multidict-6.7.1-cp311-cp311-win_arm64.whl", hash = "sha256:b8c990b037d2fff2f4e33d3f21b9b531c5745b33a49a7d6dbe7a177266af44f6", size = 43159, upload-time = "2026-01-26T02:43:51.635Z" }, + { url = "https://files.pythonhosted.org/packages/8d/9c/f20e0e2cf80e4b2e4b1c365bf5fe104ee633c751a724246262db8f1a0b13/multidict-6.7.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a90f75c956e32891a4eda3639ce6dd86e87105271f43d43442a3aedf3cddf172", size = 76893, upload-time = "2026-01-26T02:43:52.754Z" }, + { url = "https://files.pythonhosted.org/packages/fe/cf/18ef143a81610136d3da8193da9d80bfe1cb548a1e2d1c775f26b23d024a/multidict-6.7.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fccb473e87eaa1382689053e4a4618e7ba7b9b9b8d6adf2027ee474597128cd", size = 45456, upload-time = "2026-01-26T02:43:53.893Z" }, + { url = "https://files.pythonhosted.org/packages/a9/65/1caac9d4cd32e8433908683446eebc953e82d22b03d10d41a5f0fefe991b/multidict-6.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0fa96985700739c4c7853a43c0b3e169360d6855780021bfc6d0f1ce7c123e7", size = 43872, upload-time = "2026-01-26T02:43:55.041Z" }, + { url = "https://files.pythonhosted.org/packages/cf/3b/d6bd75dc4f3ff7c73766e04e705b00ed6dbbaccf670d9e05a12b006f5a21/multidict-6.7.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cb2a55f408c3043e42b40cc8eecd575afa27b7e0b956dfb190de0f8499a57a53", size = 251018, upload-time = "2026-01-26T02:43:56.198Z" }, + { url = "https://files.pythonhosted.org/packages/fd/80/c959c5933adedb9ac15152e4067c702a808ea183a8b64cf8f31af8ad3155/multidict-6.7.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb0ce7b2a32d09892b3dd6cc44877a0d02a33241fafca5f25c8b6b62374f8b75", size = 258883, upload-time = "2026-01-26T02:43:57.499Z" }, + { url = "https://files.pythonhosted.org/packages/86/85/7ed40adafea3d4f1c8b916e3b5cc3a8e07dfcdcb9cd72800f4ed3ca1b387/multidict-6.7.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c3a32d23520ee37bf327d1e1a656fec76a2edd5c038bf43eddfa0572ec49c60b", size = 242413, upload-time = "2026-01-26T02:43:58.755Z" }, + { url = "https://files.pythonhosted.org/packages/d2/57/b8565ff533e48595503c785f8361ff9a4fde4d67de25c207cd0ba3befd03/multidict-6.7.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9c90fed18bffc0189ba814749fdcc102b536e83a9f738a9003e569acd540a733", size = 268404, upload-time = "2026-01-26T02:44:00.216Z" }, + { url = "https://files.pythonhosted.org/packages/e0/50/9810c5c29350f7258180dfdcb2e52783a0632862eb334c4896ac717cebcb/multidict-6.7.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:da62917e6076f512daccfbbde27f46fed1c98fee202f0559adec8ee0de67f71a", size = 269456, upload-time = "2026-01-26T02:44:02.202Z" }, + { url = "https://files.pythonhosted.org/packages/f3/8d/5e5be3ced1d12966fefb5c4ea3b2a5b480afcea36406559442c6e31d4a48/multidict-6.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde23ef6ed9db7eaee6c37dcec08524cb43903c60b285b172b6c094711b3961", size = 256322, upload-time = "2026-01-26T02:44:03.56Z" }, + { url = "https://files.pythonhosted.org/packages/31/6e/d8a26d81ac166a5592782d208dd90dfdc0a7a218adaa52b45a672b46c122/multidict-6.7.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3758692429e4e32f1ba0df23219cd0b4fc0a52f476726fff9337d1a57676a582", size = 253955, upload-time = "2026-01-26T02:44:04.845Z" }, + { url = "https://files.pythonhosted.org/packages/59/4c/7c672c8aad41534ba619bcd4ade7a0dc87ed6b8b5c06149b85d3dd03f0cd/multidict-6.7.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:398c1478926eca669f2fd6a5856b6de9c0acf23a2cb59a14c0ba5844fa38077e", size = 251254, upload-time = "2026-01-26T02:44:06.133Z" }, + { url = "https://files.pythonhosted.org/packages/7b/bd/84c24de512cbafbdbc39439f74e967f19570ce7924e3007174a29c348916/multidict-6.7.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c102791b1c4f3ab36ce4101154549105a53dc828f016356b3e3bcae2e3a039d3", size = 252059, upload-time = "2026-01-26T02:44:07.518Z" }, + { url = "https://files.pythonhosted.org/packages/fa/ba/f5449385510825b73d01c2d4087bf6d2fccc20a2d42ac34df93191d3dd03/multidict-6.7.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a088b62bd733e2ad12c50dad01b7d0166c30287c166e137433d3b410add807a6", size = 263588, upload-time = "2026-01-26T02:44:09.382Z" }, + { url = "https://files.pythonhosted.org/packages/d7/11/afc7c677f68f75c84a69fe37184f0f82fce13ce4b92f49f3db280b7e92b3/multidict-6.7.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3d51ff4785d58d3f6c91bdbffcb5e1f7ddfda557727043aa20d20ec4f65e324a", size = 259642, upload-time = "2026-01-26T02:44:10.73Z" }, + { url = "https://files.pythonhosted.org/packages/2b/17/ebb9644da78c4ab36403739e0e6e0e30ebb135b9caf3440825001a0bddcb/multidict-6.7.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc5907494fccf3e7d3f94f95c91d6336b092b5fc83811720fae5e2765890dfba", size = 251377, upload-time = "2026-01-26T02:44:12.042Z" }, + { url = "https://files.pythonhosted.org/packages/ca/a4/840f5b97339e27846c46307f2530a2805d9d537d8b8bd416af031cad7fa0/multidict-6.7.1-cp312-cp312-win32.whl", hash = "sha256:28ca5ce2fd9716631133d0e9a9b9a745ad7f60bac2bccafb56aa380fc0b6c511", size = 41887, upload-time = "2026-01-26T02:44:14.245Z" }, + { url = "https://files.pythonhosted.org/packages/80/31/0b2517913687895f5904325c2069d6a3b78f66cc641a86a2baf75a05dcbb/multidict-6.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19", size = 46053, upload-time = "2026-01-26T02:44:15.371Z" }, + { url = "https://files.pythonhosted.org/packages/0c/5b/aba28e4ee4006ae4c7df8d327d31025d760ffa992ea23812a601d226e682/multidict-6.7.1-cp312-cp312-win_arm64.whl", hash = "sha256:ba0a9fb644d0c1a2194cf7ffb043bd852cea63a57f66fbd33959f7dae18517bf", size = 43307, upload-time = "2026-01-26T02:44:16.852Z" }, + { url = "https://files.pythonhosted.org/packages/f2/22/929c141d6c0dba87d3e1d38fbdf1ba8baba86b7776469f2bc2d3227a1e67/multidict-6.7.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2b41f5fed0ed563624f1c17630cb9941cf2309d4df00e494b551b5f3e3d67a23", size = 76174, upload-time = "2026-01-26T02:44:18.509Z" }, + { url = "https://files.pythonhosted.org/packages/c7/75/bc704ae15fee974f8fccd871305e254754167dce5f9e42d88a2def741a1d/multidict-6.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84e61e3af5463c19b67ced91f6c634effb89ef8bfc5ca0267f954451ed4bb6a2", size = 45116, upload-time = "2026-01-26T02:44:19.745Z" }, + { url = "https://files.pythonhosted.org/packages/79/76/55cd7186f498ed080a18440c9013011eb548f77ae1b297206d030eb1180a/multidict-6.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:935434b9853c7c112eee7ac891bc4cb86455aa631269ae35442cb316790c1445", size = 43524, upload-time = "2026-01-26T02:44:21.571Z" }, + { url = "https://files.pythonhosted.org/packages/e9/3c/414842ef8d5a1628d68edee29ba0e5bcf235dbfb3ccd3ea303a7fe8c72ff/multidict-6.7.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:432feb25a1cb67fe82a9680b4d65fb542e4635cb3166cd9c01560651ad60f177", size = 249368, upload-time = "2026-01-26T02:44:22.803Z" }, + { url = "https://files.pythonhosted.org/packages/f6/32/befed7f74c458b4a525e60519fe8d87eef72bb1e99924fa2b0f9d97a221e/multidict-6.7.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e82d14e3c948952a1a85503817e038cba5905a3352de76b9a465075d072fba23", size = 256952, upload-time = "2026-01-26T02:44:24.306Z" }, + { url = "https://files.pythonhosted.org/packages/03/d6/c878a44ba877f366630c860fdf74bfb203c33778f12b6ac274936853c451/multidict-6.7.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4cfb48c6ea66c83bcaaf7e4dfa7ec1b6bbcf751b7db85a328902796dfde4c060", size = 240317, upload-time = "2026-01-26T02:44:25.772Z" }, + { url = "https://files.pythonhosted.org/packages/68/49/57421b4d7ad2e9e60e25922b08ceb37e077b90444bde6ead629095327a6f/multidict-6.7.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1d540e51b7e8e170174555edecddbd5538105443754539193e3e1061864d444d", size = 267132, upload-time = "2026-01-26T02:44:27.648Z" }, + { url = "https://files.pythonhosted.org/packages/b7/fe/ec0edd52ddbcea2a2e89e174f0206444a61440b40f39704e64dc807a70bd/multidict-6.7.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:273d23f4b40f3dce4d6c8a821c741a86dec62cded82e1175ba3d99be128147ed", size = 268140, upload-time = "2026-01-26T02:44:29.588Z" }, + { url = "https://files.pythonhosted.org/packages/b0/73/6e1b01cbeb458807aa0831742232dbdd1fa92bfa33f52a3f176b4ff3dc11/multidict-6.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d624335fd4fa1c08a53f8b4be7676ebde19cd092b3895c421045ca87895b429", size = 254277, upload-time = "2026-01-26T02:44:30.902Z" }, + { url = "https://files.pythonhosted.org/packages/6a/b2/5fb8c124d7561a4974c342bc8c778b471ebbeb3cc17df696f034a7e9afe7/multidict-6.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:12fad252f8b267cc75b66e8fc51b3079604e8d43a75428ffe193cd9e2195dfd6", size = 252291, upload-time = "2026-01-26T02:44:32.31Z" }, + { url = "https://files.pythonhosted.org/packages/5a/96/51d4e4e06bcce92577fcd488e22600bd38e4fd59c20cb49434d054903bd2/multidict-6.7.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:03ede2a6ffbe8ef936b92cb4529f27f42be7f56afcdab5ab739cd5f27fb1cbf9", size = 250156, upload-time = "2026-01-26T02:44:33.734Z" }, + { url = "https://files.pythonhosted.org/packages/db/6b/420e173eec5fba721a50e2a9f89eda89d9c98fded1124f8d5c675f7a0c0f/multidict-6.7.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:90efbcf47dbe33dcf643a1e400d67d59abeac5db07dc3f27d6bdeae497a2198c", size = 249742, upload-time = "2026-01-26T02:44:35.222Z" }, + { url = "https://files.pythonhosted.org/packages/44/a3/ec5b5bd98f306bc2aa297b8c6f11a46714a56b1e6ef5ebda50a4f5d7c5fb/multidict-6.7.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c4b9bfc148f5a91be9244d6264c53035c8a0dcd2f51f1c3c6e30e30ebaa1c84", size = 262221, upload-time = "2026-01-26T02:44:36.604Z" }, + { url = "https://files.pythonhosted.org/packages/cd/f7/e8c0d0da0cd1e28d10e624604e1a36bcc3353aaebdfdc3a43c72bc683a12/multidict-6.7.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:401c5a650f3add2472d1d288c26deebc540f99e2fb83e9525007a74cd2116f1d", size = 258664, upload-time = "2026-01-26T02:44:38.008Z" }, + { url = "https://files.pythonhosted.org/packages/52/da/151a44e8016dd33feed44f730bd856a66257c1ee7aed4f44b649fb7edeb3/multidict-6.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:97891f3b1b3ffbded884e2916cacf3c6fc87b66bb0dde46f7357404750559f33", size = 249490, upload-time = "2026-01-26T02:44:39.386Z" }, + { url = "https://files.pythonhosted.org/packages/87/af/a3b86bf9630b732897f6fc3f4c4714b90aa4361983ccbdcd6c0339b21b0c/multidict-6.7.1-cp313-cp313-win32.whl", hash = "sha256:e1c5988359516095535c4301af38d8a8838534158f649c05dd1050222321bcb3", size = 41695, upload-time = "2026-01-26T02:44:41.318Z" }, + { url = "https://files.pythonhosted.org/packages/b2/35/e994121b0e90e46134673422dd564623f93304614f5d11886b1b3e06f503/multidict-6.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:960c83bf01a95b12b08fd54324a4eb1d5b52c88932b5cba5d6e712bb3ed12eb5", size = 45884, upload-time = "2026-01-26T02:44:42.488Z" }, + { url = "https://files.pythonhosted.org/packages/ca/61/42d3e5dbf661242a69c97ea363f2d7b46c567da8eadef8890022be6e2ab0/multidict-6.7.1-cp313-cp313-win_arm64.whl", hash = "sha256:563fe25c678aaba333d5399408f5ec3c383ca5b663e7f774dd179a520b8144df", size = 43122, upload-time = "2026-01-26T02:44:43.664Z" }, + { url = "https://files.pythonhosted.org/packages/6d/b3/e6b21c6c4f314bb956016b0b3ef2162590a529b84cb831c257519e7fde44/multidict-6.7.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:c76c4bec1538375dad9d452d246ca5368ad6e1c9039dadcf007ae59c70619ea1", size = 83175, upload-time = "2026-01-26T02:44:44.894Z" }, + { url = "https://files.pythonhosted.org/packages/fb/76/23ecd2abfe0957b234f6c960f4ade497f55f2c16aeb684d4ecdbf1c95791/multidict-6.7.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:57b46b24b5d5ebcc978da4ec23a819a9402b4228b8a90d9c656422b4bdd8a963", size = 48460, upload-time = "2026-01-26T02:44:46.106Z" }, + { url = "https://files.pythonhosted.org/packages/c4/57/a0ed92b23f3a042c36bc4227b72b97eca803f5f1801c1ab77c8a212d455e/multidict-6.7.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e954b24433c768ce78ab7929e84ccf3422e46deb45a4dc9f93438f8217fa2d34", size = 46930, upload-time = "2026-01-26T02:44:47.278Z" }, + { url = "https://files.pythonhosted.org/packages/b5/66/02ec7ace29162e447f6382c495dc95826bf931d3818799bbef11e8f7df1a/multidict-6.7.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3bd231490fa7217cc832528e1cd8752a96f0125ddd2b5749390f7c3ec8721b65", size = 242582, upload-time = "2026-01-26T02:44:48.604Z" }, + { url = "https://files.pythonhosted.org/packages/58/18/64f5a795e7677670e872673aca234162514696274597b3708b2c0d276cce/multidict-6.7.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:253282d70d67885a15c8a7716f3a73edf2d635793ceda8173b9ecc21f2fb8292", size = 250031, upload-time = "2026-01-26T02:44:50.544Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ed/e192291dbbe51a8290c5686f482084d31bcd9d09af24f63358c3d42fd284/multidict-6.7.1-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b4c48648d7649c9335cf1927a8b87fa692de3dcb15faa676c6a6f1f1aabda43", size = 228596, upload-time = "2026-01-26T02:44:51.951Z" }, + { url = "https://files.pythonhosted.org/packages/1e/7e/3562a15a60cf747397e7f2180b0a11dc0c38d9175a650e75fa1b4d325e15/multidict-6.7.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:98bc624954ec4d2c7cb074b8eefc2b5d0ce7d482e410df446414355d158fe4ca", size = 257492, upload-time = "2026-01-26T02:44:53.902Z" }, + { url = "https://files.pythonhosted.org/packages/24/02/7d0f9eae92b5249bb50ac1595b295f10e263dd0078ebb55115c31e0eaccd/multidict-6.7.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1b99af4d9eec0b49927b4402bcbb58dea89d3e0db8806a4086117019939ad3dd", size = 255899, upload-time = "2026-01-26T02:44:55.316Z" }, + { url = "https://files.pythonhosted.org/packages/00/e3/9b60ed9e23e64c73a5cde95269ef1330678e9c6e34dd4eb6b431b85b5a10/multidict-6.7.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aac4f16b472d5b7dc6f66a0d49dd57b0e0902090be16594dc9ebfd3d17c47e7", size = 247970, upload-time = "2026-01-26T02:44:56.783Z" }, + { url = "https://files.pythonhosted.org/packages/3e/06/538e58a63ed5cfb0bd4517e346b91da32fde409d839720f664e9a4ae4f9d/multidict-6.7.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:21f830fe223215dffd51f538e78c172ed7c7f60c9b96a2bf05c4848ad49921c3", size = 245060, upload-time = "2026-01-26T02:44:58.195Z" }, + { url = "https://files.pythonhosted.org/packages/b2/2f/d743a3045a97c895d401e9bd29aaa09b94f5cbdf1bd561609e5a6c431c70/multidict-6.7.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f5dd81c45b05518b9aa4da4aa74e1c93d715efa234fd3e8a179df611cc85e5f4", size = 235888, upload-time = "2026-01-26T02:44:59.57Z" }, + { url = "https://files.pythonhosted.org/packages/38/83/5a325cac191ab28b63c52f14f1131f3b0a55ba3b9aa65a6d0bf2a9b921a0/multidict-6.7.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:eb304767bca2bb92fb9c5bd33cedc95baee5bb5f6c88e63706533a1c06ad08c8", size = 243554, upload-time = "2026-01-26T02:45:01.054Z" }, + { url = "https://files.pythonhosted.org/packages/20/1f/9d2327086bd15da2725ef6aae624208e2ef828ed99892b17f60c344e57ed/multidict-6.7.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c9035dde0f916702850ef66460bc4239d89d08df4d02023a5926e7446724212c", size = 252341, upload-time = "2026-01-26T02:45:02.484Z" }, + { url = "https://files.pythonhosted.org/packages/e8/2c/2a1aa0280cf579d0f6eed8ee5211c4f1730bd7e06c636ba2ee6aafda302e/multidict-6.7.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:af959b9beeb66c822380f222f0e0a1889331597e81f1ded7f374f3ecb0fd6c52", size = 246391, upload-time = "2026-01-26T02:45:03.862Z" }, + { url = "https://files.pythonhosted.org/packages/e5/03/7ca022ffc36c5a3f6e03b179a5ceb829be9da5783e6fe395f347c0794680/multidict-6.7.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:41f2952231456154ee479651491e94118229844dd7226541788be783be2b5108", size = 243422, upload-time = "2026-01-26T02:45:05.296Z" }, + { url = "https://files.pythonhosted.org/packages/dc/1d/b31650eab6c5778aceed46ba735bd97f7c7d2f54b319fa916c0f96e7805b/multidict-6.7.1-cp313-cp313t-win32.whl", hash = "sha256:df9f19c28adcb40b6aae30bbaa1478c389efd50c28d541d76760199fc1037c32", size = 47770, upload-time = "2026-01-26T02:45:06.754Z" }, + { url = "https://files.pythonhosted.org/packages/ac/5b/2d2d1d522e51285bd61b1e20df8f47ae1a9d80839db0b24ea783b3832832/multidict-6.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d54ecf9f301853f2c5e802da559604b3e95bb7a3b01a9c295c6ee591b9882de8", size = 53109, upload-time = "2026-01-26T02:45:08.044Z" }, + { url = "https://files.pythonhosted.org/packages/3d/a3/cc409ba012c83ca024a308516703cf339bdc4b696195644a7215a5164a24/multidict-6.7.1-cp313-cp313t-win_arm64.whl", hash = "sha256:5a37ca18e360377cfda1d62f5f382ff41f2b8c4ccb329ed974cc2e1643440118", size = 45573, upload-time = "2026-01-26T02:45:09.349Z" }, + { url = "https://files.pythonhosted.org/packages/91/cc/db74228a8be41884a567e88a62fd589a913708fcf180d029898c17a9a371/multidict-6.7.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee", size = 75190, upload-time = "2026-01-26T02:45:10.651Z" }, + { url = "https://files.pythonhosted.org/packages/d5/22/492f2246bb5b534abd44804292e81eeaf835388901f0c574bac4eeec73c5/multidict-6.7.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2", size = 44486, upload-time = "2026-01-26T02:45:11.938Z" }, + { url = "https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1", size = 43219, upload-time = "2026-01-26T02:45:14.346Z" }, + { url = "https://files.pythonhosted.org/packages/24/bb/2c0c2287963f4259c85e8bcbba9182ced8d7fca65c780c38e99e61629d11/multidict-6.7.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d", size = 245132, upload-time = "2026-01-26T02:45:15.712Z" }, + { url = "https://files.pythonhosted.org/packages/a7/f9/44d4b3064c65079d2467888794dea218d1601898ac50222ab8a9a8094460/multidict-6.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31", size = 252420, upload-time = "2026-01-26T02:45:17.293Z" }, + { url = "https://files.pythonhosted.org/packages/8b/13/78f7275e73fa17b24c9a51b0bd9d73ba64bb32d0ed51b02a746eb876abe7/multidict-6.7.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048", size = 233510, upload-time = "2026-01-26T02:45:19.356Z" }, + { url = "https://files.pythonhosted.org/packages/4b/25/8167187f62ae3cbd52da7893f58cb036b47ea3fb67138787c76800158982/multidict-6.7.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362", size = 264094, upload-time = "2026-01-26T02:45:20.834Z" }, + { url = "https://files.pythonhosted.org/packages/a1/e7/69a3a83b7b030cf283fb06ce074a05a02322359783424d7edf0f15fe5022/multidict-6.7.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37", size = 260786, upload-time = "2026-01-26T02:45:22.818Z" }, + { url = "https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709", size = 248483, upload-time = "2026-01-26T02:45:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/48/5a/d5a99e3acbca0e29c5d9cba8f92ceb15dce78bab963b308ae692981e3a5d/multidict-6.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0", size = 248403, upload-time = "2026-01-26T02:45:25.982Z" }, + { url = "https://files.pythonhosted.org/packages/35/48/e58cd31f6c7d5102f2a4bf89f96b9cf7e00b6c6f3d04ecc44417c00a5a3c/multidict-6.7.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb", size = 240315, upload-time = "2026-01-26T02:45:27.487Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/1cd210229559cb90b6786c30676bb0c58249ff42f942765f88793b41fdce/multidict-6.7.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd", size = 245528, upload-time = "2026-01-26T02:45:28.991Z" }, + { url = "https://files.pythonhosted.org/packages/64/f2/6e1107d226278c876c783056b7db43d800bb64c6131cec9c8dfb6903698e/multidict-6.7.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601", size = 258784, upload-time = "2026-01-26T02:45:30.503Z" }, + { url = "https://files.pythonhosted.org/packages/4d/c1/11f664f14d525e4a1b5327a82d4de61a1db604ab34c6603bb3c2cc63ad34/multidict-6.7.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1", size = 251980, upload-time = "2026-01-26T02:45:32.603Z" }, + { url = "https://files.pythonhosted.org/packages/e1/9f/75a9ac888121d0c5bbd4ecf4eead45668b1766f6baabfb3b7f66a410e231/multidict-6.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b", size = 243602, upload-time = "2026-01-26T02:45:34.043Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e7/50bf7b004cc8525d80dbbbedfdc7aed3e4c323810890be4413e589074032/multidict-6.7.1-cp314-cp314-win32.whl", hash = "sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d", size = 40930, upload-time = "2026-01-26T02:45:36.278Z" }, + { url = "https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f", size = 45074, upload-time = "2026-01-26T02:45:37.546Z" }, + { url = "https://files.pythonhosted.org/packages/97/ab/22803b03285fa3a525f48217963da3a65ae40f6a1b6f6cf2768879e208f9/multidict-6.7.1-cp314-cp314-win_arm64.whl", hash = "sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5", size = 42471, upload-time = "2026-01-26T02:45:38.889Z" }, + { url = "https://files.pythonhosted.org/packages/e0/6d/f9293baa6146ba9507e360ea0292b6422b016907c393e2f63fc40ab7b7b5/multidict-6.7.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581", size = 82401, upload-time = "2026-01-26T02:45:40.254Z" }, + { url = "https://files.pythonhosted.org/packages/7a/68/53b5494738d83558d87c3c71a486504d8373421c3e0dbb6d0db48ad42ee0/multidict-6.7.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a", size = 48143, upload-time = "2026-01-26T02:45:41.635Z" }, + { url = "https://files.pythonhosted.org/packages/37/e8/5284c53310dcdc99ce5d66563f6e5773531a9b9fe9ec7a615e9bc306b05f/multidict-6.7.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c", size = 46507, upload-time = "2026-01-26T02:45:42.99Z" }, + { url = "https://files.pythonhosted.org/packages/e4/fc/6800d0e5b3875568b4083ecf5f310dcf91d86d52573160834fb4bfcf5e4f/multidict-6.7.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262", size = 239358, upload-time = "2026-01-26T02:45:44.376Z" }, + { url = "https://files.pythonhosted.org/packages/41/75/4ad0973179361cdf3a113905e6e088173198349131be2b390f9fa4da5fc6/multidict-6.7.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59", size = 246884, upload-time = "2026-01-26T02:45:47.167Z" }, + { url = "https://files.pythonhosted.org/packages/c3/9c/095bb28b5da139bd41fb9a5d5caff412584f377914bd8787c2aa98717130/multidict-6.7.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889", size = 225878, upload-time = "2026-01-26T02:45:48.698Z" }, + { url = "https://files.pythonhosted.org/packages/07/d0/c0a72000243756e8f5a277b6b514fa005f2c73d481b7d9e47cd4568aa2e4/multidict-6.7.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4", size = 253542, upload-time = "2026-01-26T02:45:50.164Z" }, + { url = "https://files.pythonhosted.org/packages/c0/6b/f69da15289e384ecf2a68837ec8b5ad8c33e973aa18b266f50fe55f24b8c/multidict-6.7.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d", size = 252403, upload-time = "2026-01-26T02:45:51.779Z" }, + { url = "https://files.pythonhosted.org/packages/a2/76/b9669547afa5a1a25cd93eaca91c0da1c095b06b6d2d8ec25b713588d3a1/multidict-6.7.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609", size = 244889, upload-time = "2026-01-26T02:45:53.27Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a9/a50d2669e506dad33cfc45b5d574a205587b7b8a5f426f2fbb2e90882588/multidict-6.7.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489", size = 241982, upload-time = "2026-01-26T02:45:54.919Z" }, + { url = "https://files.pythonhosted.org/packages/c5/bb/1609558ad8b456b4827d3c5a5b775c93b87878fd3117ed3db3423dfbce1b/multidict-6.7.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c", size = 232415, upload-time = "2026-01-26T02:45:56.981Z" }, + { url = "https://files.pythonhosted.org/packages/d8/59/6f61039d2aa9261871e03ab9dc058a550d240f25859b05b67fd70f80d4b3/multidict-6.7.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e", size = 240337, upload-time = "2026-01-26T02:45:58.698Z" }, + { url = "https://files.pythonhosted.org/packages/a1/29/fdc6a43c203890dc2ae9249971ecd0c41deaedfe00d25cb6564b2edd99eb/multidict-6.7.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c", size = 248788, upload-time = "2026-01-26T02:46:00.862Z" }, + { url = "https://files.pythonhosted.org/packages/a9/14/a153a06101323e4cf086ecee3faadba52ff71633d471f9685c42e3736163/multidict-6.7.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9", size = 242842, upload-time = "2026-01-26T02:46:02.824Z" }, + { url = "https://files.pythonhosted.org/packages/41/5f/604ae839e64a4a6efc80db94465348d3b328ee955e37acb24badbcd24d83/multidict-6.7.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2", size = 240237, upload-time = "2026-01-26T02:46:05.898Z" }, + { url = "https://files.pythonhosted.org/packages/5f/60/c3a5187bf66f6fb546ff4ab8fb5a077cbdd832d7b1908d4365c7f74a1917/multidict-6.7.1-cp314-cp314t-win32.whl", hash = "sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7", size = 48008, upload-time = "2026-01-26T02:46:07.468Z" }, + { url = "https://files.pythonhosted.org/packages/0c/f7/addf1087b860ac60e6f382240f64fb99f8bfb532bb06f7c542b83c29ca61/multidict-6.7.1-cp314-cp314t-win_amd64.whl", hash = "sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5", size = 53542, upload-time = "2026-01-26T02:46:08.809Z" }, + { url = "https://files.pythonhosted.org/packages/4c/81/4629d0aa32302ef7b2ec65c75a728cc5ff4fa410c50096174c1632e70b3e/multidict-6.7.1-cp314-cp314t-win_arm64.whl", hash = "sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2", size = 44719, upload-time = "2026-01-26T02:46:11.146Z" }, + { url = "https://files.pythonhosted.org/packages/81/08/7036c080d7117f28a4af526d794aab6a84463126db031b007717c1a6676e/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56", size = 12319, upload-time = "2026-01-26T02:46:44.004Z" }, +] + +[[package]] +name = "mypy" +version = "1.20.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, + { name = "mypy-extensions" }, + { name = "pathspec" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/af/e3d4b3e9ec91a0ff9aabfdb38692952acf49bbb899c2e4c29acb3a6da3ae/mypy-1.20.2.tar.gz", hash = "sha256:e8222c26daaafd9e8626dec58ae36029f82585890589576f769a650dd20fd665", size = 3817349, upload-time = "2026-04-21T17:12:28.473Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/97/ce2502df2cecf2ef997b6c6527c4a223b92feb9e7b790cdc8dcd683f3a8a/mypy-1.20.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cf5a4db6dca263010e2c7bff081c89383c72d187ba2cf4c44759aac970e2f0c4", size = 14457059, upload-time = "2026-04-21T17:06:14.935Z" }, + { url = "https://files.pythonhosted.org/packages/c9/34/417ee60b822cc80c0f3dc9f495ad7fd8dbb8d8b2cf4baf22d4046d25d01d/mypy-1.20.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7b0e817b518bff7facd7f85ea05b643ad8bdcce684cf29784987b0a7c8e1f997", size = 13346816, upload-time = "2026-04-21T17:10:41.433Z" }, + { url = "https://files.pythonhosted.org/packages/4a/85/e20951978702df58379d0bcc2e8f7ccdca4e78cd7dc66dd3ddbf9b29d517/mypy-1.20.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97d7b9a485b40f8ca425460e89bf1da2814625b2da627c0dcc6aa46c92631d14", size = 13772593, upload-time = "2026-04-21T17:08:11.24Z" }, + { url = "https://files.pythonhosted.org/packages/63/a5/5441a13259ec516c56fd5de0fd96a69a9590ae6c5e5d3e5174aa84b97973/mypy-1.20.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1e1c12f6d2db3d78b909b5f77513c11eb7f2dd2782b96a3ab6dffc7d44575c99", size = 14656635, upload-time = "2026-04-21T17:09:54.042Z" }, + { url = "https://files.pythonhosted.org/packages/3b/51/b89c69157c5e1f19fd125a65d991166a26906e7902f026f00feebbcfa2b9/mypy-1.20.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:89dce27e142d25ffbc154c1819383b69f2e9234dc4ed4766f42e0e8cb264ab5c", size = 14943278, upload-time = "2026-04-21T17:09:15.599Z" }, + { url = "https://files.pythonhosted.org/packages/e9/44/6b0eeecfe96d7cce1d71c66b8e03cb304aa70ec11f1955dc1d6b46aca3c3/mypy-1.20.2-cp310-cp310-win_amd64.whl", hash = "sha256:f376e37f9bf2a946872fc5fd1199c99310748e3c26c7a26683f13f8bdb756cbd", size = 10851915, upload-time = "2026-04-21T17:06:03.5Z" }, + { url = "https://files.pythonhosted.org/packages/3c/36/6593dc88545d75fb96416184be5392da5e2a8e8c2802a8597913e16ae25c/mypy-1.20.2-cp310-cp310-win_arm64.whl", hash = "sha256:6e2b469efd811707bc530fd1effef0f5d6eebcb7fe376affae69025da4b979a2", size = 9786676, upload-time = "2026-04-21T17:07:02.035Z" }, + { url = "https://files.pythonhosted.org/packages/1f/4d/9ebeae211caccbdaddde7ed5e31dfcf57faac66be9b11deb1dc6526c8078/mypy-1.20.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4077797a273e56e8843d001e9dfe4ba10e33323d6ade647ff260e5cd97d9758c", size = 14371307, upload-time = "2026-04-21T17:08:56.442Z" }, + { url = "https://files.pythonhosted.org/packages/95/d7/93473d34b61f04fac1aecc01368485c89c5c4af7a4b9a0cab5d77d04b63f/mypy-1.20.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cdecf62abcc4292500d7858aeae87a1f8f1150f4c4dd08fb0b336ee79b2a6df3", size = 13258917, upload-time = "2026-04-21T17:05:50.978Z" }, + { url = "https://files.pythonhosted.org/packages/e2/30/3dd903e8bafb7b5f7bf87fcd58f8382086dea2aa19f0a7b357f21f63071b/mypy-1.20.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c566c3a88b6ece59b3d70f65bedef17304f48eb52ff040a6a18214e1917b3254", size = 13700516, upload-time = "2026-04-21T17:11:33.161Z" }, + { url = "https://files.pythonhosted.org/packages/07/05/c61a140aba4c729ac7bc99ae26fc627c78a6e08f5b9dd319244ea71a3d7e/mypy-1.20.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0deb80d062b2479f2c87ae568f89845afc71d11bc41b04179e58165fd9f31e98", size = 14562889, upload-time = "2026-04-21T17:05:27.674Z" }, + { url = "https://files.pythonhosted.org/packages/fd/87/da78243742ffa8a36d98c3010f0d829f93d5da4e6786f1a1a6f2ad616502/mypy-1.20.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bba9ad231e92a3e424b3e56b65aa17704993425bba97e302c832f9466bb85bac", size = 14803844, upload-time = "2026-04-21T17:10:06.2Z" }, + { url = "https://files.pythonhosted.org/packages/37/52/10a1ddf91b40f843943a3c6db51e2df59c9e237f29d355e95eaab427461f/mypy-1.20.2-cp311-cp311-win_amd64.whl", hash = "sha256:baf593f2765fa3a6b1ef95807dbaa3d25b594f6a52adcc506a6b9cb115e1be67", size = 10846300, upload-time = "2026-04-21T17:12:23.886Z" }, + { url = "https://files.pythonhosted.org/packages/20/02/f9a4415b664c53bd34d6709be59da303abcae986dc4ac847b402edb6fa1e/mypy-1.20.2-cp311-cp311-win_arm64.whl", hash = "sha256:20175a1c0f49863946ec20b7f63255768058ac4f07d2b9ded6a6b46cfb5a9100", size = 9779498, upload-time = "2026-04-21T17:09:23.695Z" }, + { url = "https://files.pythonhosted.org/packages/71/4e/7560e4528db9e9b147e4c0f22660466bf30a0a1fe3d63d1b9d3b0fd354ee/mypy-1.20.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4dbfcf869f6b0517f70cf0030ba6ea1d6645e132337a7d5204a18d8d5636c02b", size = 14539393, upload-time = "2026-04-21T17:07:12.52Z" }, + { url = "https://files.pythonhosted.org/packages/32/d9/34a5efed8124f5a9234f55ac6a4ced4201e2c5b81e1109c49ad23190ec8c/mypy-1.20.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4b6481b228d072315b053210b01ac320e1be243dc17f9e5887ef167f23f5fae4", size = 13361642, upload-time = "2026-04-21T17:06:53.742Z" }, + { url = "https://files.pythonhosted.org/packages/d1/14/eb377acf78c03c92d566a1510cda8137348215b5335085ef662ab82ecd3a/mypy-1.20.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:34397cdced6b90b836e38182076049fdb41424322e0b0728c946b0939ebdf9f6", size = 13740347, upload-time = "2026-04-21T17:12:04.73Z" }, + { url = "https://files.pythonhosted.org/packages/b9/94/7e4634a32b641aa1c112422eed1bbece61ee16205f674190e8b536f884de/mypy-1.20.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5da6976f20cae27059ea8d0c86e7cef3de720e04c4bb9ee18e3690fdb792066", size = 14734042, upload-time = "2026-04-21T17:07:43.16Z" }, + { url = "https://files.pythonhosted.org/packages/7a/f3/f7e62395cb7f434541b4491a01149a4439e28ace4c0c632bbf5431e92d1f/mypy-1.20.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:56908d7e08318d39f85b1f0c6cfd47b0cac1a130da677630dac0de3e0623e102", size = 14964958, upload-time = "2026-04-21T17:11:00.665Z" }, + { url = "https://files.pythonhosted.org/packages/3e/0d/47e3c3a0ec2a876e35aeac365df3cac7776c36bbd4ed18cc521e1b9d255b/mypy-1.20.2-cp312-cp312-win_amd64.whl", hash = "sha256:d52ad8d78522da1d308789df651ee5379088e77c76cb1994858d40a426b343b9", size = 10911340, upload-time = "2026-04-21T17:10:49.179Z" }, + { url = "https://files.pythonhosted.org/packages/d6/b2/6c852d72e0ea8b01f49da817fb52539993cde327e7d010e0103dc12d0dac/mypy-1.20.2-cp312-cp312-win_arm64.whl", hash = "sha256:785b08db19c9f214dc37d65f7c165d19a30fcecb48abfa30f31b01b5acaabb58", size = 9833947, upload-time = "2026-04-21T17:09:05.267Z" }, + { url = "https://files.pythonhosted.org/packages/5b/c4/b93812d3a192c9bcf5df405bd2f30277cd0e48106a14d1023c7f6ed6e39b/mypy-1.20.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:edfbfca868cdd6bd8d974a60f8a3682f5565d3f5c99b327640cedd24c4264026", size = 14524670, upload-time = "2026-04-21T17:10:30.737Z" }, + { url = "https://files.pythonhosted.org/packages/f3/47/42c122501bff18eaf1e8f457f5c017933452d8acdc52918a9f59f6812955/mypy-1.20.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e2877a02380adfcdbc69071a0f74d6e9dbbf593c0dc9d174e1f223ffd5281943", size = 13336218, upload-time = "2026-04-21T17:08:44.069Z" }, + { url = "https://files.pythonhosted.org/packages/92/8f/75bbc92f41725fbd585fb17b440b1119b576105df1013622983e18640a93/mypy-1.20.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7488448de6007cd5177c6cea0517ac33b4c0f5ee9b5e9f2be51ce75511a85517", size = 13724906, upload-time = "2026-04-21T17:08:01.02Z" }, + { url = "https://files.pythonhosted.org/packages/a1/32/4c49da27a606167391ff0c39aa955707a00edc500572e562f7c36c08a71f/mypy-1.20.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bb9c2fa06887e21d6a3a868762acb82aec34e2c6fd0174064f27c93ede68ad15", size = 14726046, upload-time = "2026-04-21T17:11:22.354Z" }, + { url = "https://files.pythonhosted.org/packages/7f/fc/4e354a1bd70216359deb0c9c54847ee6b32ef78dfb09f5131ff99b494078/mypy-1.20.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d56a78b646f2e3daa865bc70cd5ec5a46c50045801ca8ff17a0c43abc97e3ee", size = 14955587, upload-time = "2026-04-21T17:12:16.033Z" }, + { url = "https://files.pythonhosted.org/packages/62/b2/c0f2056e9eb8f08c62cafd9715e4584b89132bdc832fcf85d27d07b5f3e5/mypy-1.20.2-cp313-cp313-win_amd64.whl", hash = "sha256:2a4102b03bb7481d9a91a6da8d174740c9c8c4401024684b9ca3b7cc5e49852f", size = 10922681, upload-time = "2026-04-21T17:06:35.842Z" }, + { url = "https://files.pythonhosted.org/packages/e5/14/065e333721f05de8ef683d0aa804c23026bcc287446b61cac657b902ccac/mypy-1.20.2-cp313-cp313-win_arm64.whl", hash = "sha256:a95a9248b0c6fd933a442c03c3b113c3b61320086b88e2c444676d3fd1ca3330", size = 9830560, upload-time = "2026-04-21T17:07:51.023Z" }, + { url = "https://files.pythonhosted.org/packages/ae/d1/b4ec96b0ecc620a4443570c6e95c867903428cfcde4206518eafdd5880c3/mypy-1.20.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:419413398fe250aae057fd2fe50166b61077083c9b82754c341cf4fd73038f30", size = 14524561, upload-time = "2026-04-21T17:06:27.325Z" }, + { url = "https://files.pythonhosted.org/packages/3a/63/d2c2ff4fa66bc49477d32dfa26e8a167ba803ea6a69c5efb416036909d30/mypy-1.20.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e73c07f23009962885c197ccb9b41356a30cc0e5a1d0c2ea8fd8fb1362d7f924", size = 13363883, upload-time = "2026-04-21T17:11:11.239Z" }, + { url = "https://files.pythonhosted.org/packages/2a/56/983916806bf4eddeaaa2c9230903c3669c6718552a921154e1c5182c701f/mypy-1.20.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c64e5973df366b747646fc98da921f9d6eba9716d57d1db94a83c026a08e0fb", size = 13742945, upload-time = "2026-04-21T17:08:34.181Z" }, + { url = "https://files.pythonhosted.org/packages/19/65/0cd9285ab010ee8214c83d67c6b49417c40d86ce46f1aa109457b5a9b8d7/mypy-1.20.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a65aa591af023864fd08a97da9974e919452cfe19cb146c8a5dc692626445dc", size = 14706163, upload-time = "2026-04-21T17:05:15.51Z" }, + { url = "https://files.pythonhosted.org/packages/94/97/48ff3b297cafcc94d185243a9190836fb1b01c1b0918fff64e941e973cc9/mypy-1.20.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4fef51b01e638974a6e69885687e9bd40c8d1e09a6cd291cca0619625cf1f558", size = 14938677, upload-time = "2026-04-21T17:05:39.562Z" }, + { url = "https://files.pythonhosted.org/packages/fd/a1/1b4233d255bdd0b38a1f284feeb1c143ca508c19184964e22f8d837ec851/mypy-1.20.2-cp314-cp314-win_amd64.whl", hash = "sha256:913485a03f1bcf5d279409a9d2b9ed565c151f61c09f29991e5faa14033da4c8", size = 11089322, upload-time = "2026-04-21T17:06:44.29Z" }, + { url = "https://files.pythonhosted.org/packages/78/c2/ce7ee2ba36aeb954ba50f18fa25d9c1188578654b97d02a66a15b6f09531/mypy-1.20.2-cp314-cp314-win_arm64.whl", hash = "sha256:c3bae4f855d965b5453784300c12ffc63a548304ac7f99e55d4dc7c898673aa3", size = 10017775, upload-time = "2026-04-21T17:07:20.732Z" }, + { url = "https://files.pythonhosted.org/packages/4e/a1/9d93a7d0b5859af0ead82b4888b46df6c8797e1bc5e1e262a08518c6d48e/mypy-1.20.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:2de3dcea53babc1c3237a19002bc3d228ce1833278f093b8d619e06e7cc79609", size = 15549002, upload-time = "2026-04-21T17:08:23.107Z" }, + { url = "https://files.pythonhosted.org/packages/00/d2/09a6a10ee1bf0008f6c144d9676f2ca6a12512151b4e0ad0ff6c4fac5337/mypy-1.20.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:52b176444e2e5054dfcbcb8c75b0b719865c96247b37407184bbfca5c353f2c2", size = 14401942, upload-time = "2026-04-21T17:07:31.837Z" }, + { url = "https://files.pythonhosted.org/packages/57/da/9594b75c3c019e805250bed3583bdf4443ff9e6ef08f97e39ae308cb06f2/mypy-1.20.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:688c3312e5dadb573a2c69c82af3a298d43ecf9e6d264e0f95df960b5f6ac19c", size = 15041649, upload-time = "2026-04-21T17:09:34.653Z" }, + { url = "https://files.pythonhosted.org/packages/97/77/f75a65c278e6e8eba2071f7f5a90481891053ecc39878cc444634d892abe/mypy-1.20.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29752dbbf8cc53f89f6ac096d363314333045c257c9c75cbd189ca2de0455744", size = 15864588, upload-time = "2026-04-21T17:11:44.936Z" }, + { url = "https://files.pythonhosted.org/packages/d7/46/1a4e1c66e96c1a3246ddf5403d122ac9b0a8d2b7e65730b9d6533ba7a6d3/mypy-1.20.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:803203d2b6ea644982c644895c2f78b28d0e208bba7b27d9b921e0ec5eb207c6", size = 16093956, upload-time = "2026-04-21T17:10:17.683Z" }, + { url = "https://files.pythonhosted.org/packages/5a/2c/78a8851264dec38cd736ca5b8bc9380674df0dd0be7792f538916157716c/mypy-1.20.2-cp314-cp314t-win_amd64.whl", hash = "sha256:9bcb8aa397ff0093c824182fd76a935a9ba7ad097fcbef80ae89bf6c1731d8ec", size = 12568661, upload-time = "2026-04-21T17:11:54.473Z" }, + { url = "https://files.pythonhosted.org/packages/83/01/cd7318aa03493322ce275a0e14f4f52b8896335e4e79d4fb8153a7ad2b77/mypy-1.20.2-cp314-cp314t-win_arm64.whl", hash = "sha256:e061b58443f1736f8a37c48978d7ab581636d6ab03e3d4f99e3fa90463bb9382", size = 10389240, upload-time = "2026-04-21T17:09:42.719Z" }, + { url = "https://files.pythonhosted.org/packages/28/9a/f23c163e25b11074188251b0b5a0342625fc1cdb6af604757174fa9acc9b/mypy-1.20.2-py3-none-any.whl", hash = "sha256:a94c5a76ab46c5e6257c7972b6c8cff0574201ca7dc05647e33e795d78680563", size = 2637314, upload-time = "2026-04-21T17:05:54.5Z" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + +[[package]] +name = "nest-asyncio2" +version = "1.7.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b4/73/731debf26e27e0a0323d7bda270dc2f634b398e38f040a09da1f4351d0aa/nest_asyncio2-1.7.2.tar.gz", hash = "sha256:1921d70b92cc4612c374928d081552efb59b83d91b2b789d935c665fa01729a8", size = 14743, upload-time = "2026-02-13T00:34:04.386Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/3c/3179b85b0e1c3659f0369940200cd6d0fa900e6cefcc7ea0bc6dd0e29ffb/nest_asyncio2-1.7.2-py3-none-any.whl", hash = "sha256:f5dfa702f3f81f6a03857e9a19e2ba578c0946a4ad417b4c50a24d7ba641fe01", size = 7843, upload-time = "2026-02-13T00:34:02.691Z" }, +] + +[[package]] +name = "nodeenv" +version = "1.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, +] + +[[package]] +name = "numpy" +version = "2.2.6" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" }, + { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" }, + { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" }, + { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" }, + { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" }, + { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" }, + { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" }, + { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" }, + { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" }, + { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" }, + { url = "https://files.pythonhosted.org/packages/da/a8/4f83e2aa666a9fbf56d6118faaaf5f1974d456b1823fda0a176eff722839/numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f9f1adb22318e121c5c69a09142811a201ef17ab257a1e66ca3025065b7f53ae", size = 21176963, upload-time = "2025-05-17T21:31:19.36Z" }, + { url = "https://files.pythonhosted.org/packages/b3/2b/64e1affc7972decb74c9e29e5649fac940514910960ba25cd9af4488b66c/numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c820a93b0255bc360f53eca31a0e676fd1101f673dda8da93454a12e23fc5f7a", size = 14406743, upload-time = "2025-05-17T21:31:41.087Z" }, + { url = "https://files.pythonhosted.org/packages/4a/9f/0121e375000b5e50ffdd8b25bf78d8e1a5aa4cca3f185d41265198c7b834/numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3d70692235e759f260c3d837193090014aebdf026dfd167834bcba43e30c2a42", size = 5352616, upload-time = "2025-05-17T21:31:50.072Z" }, + { url = "https://files.pythonhosted.org/packages/31/0d/b48c405c91693635fbe2dcd7bc84a33a602add5f63286e024d3b6741411c/numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:481b49095335f8eed42e39e8041327c05b0f6f4780488f61286ed3c01368d491", size = 6889579, upload-time = "2025-05-17T21:32:01.712Z" }, + { url = "https://files.pythonhosted.org/packages/52/b8/7f0554d49b565d0171eab6e99001846882000883998e7b7d9f0d98b1f934/numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b64d8d4d17135e00c8e346e0a738deb17e754230d7e0810ac5012750bbd85a5a", size = 14312005, upload-time = "2025-05-17T21:32:23.332Z" }, + { url = "https://files.pythonhosted.org/packages/b3/dd/2238b898e51bd6d389b7389ffb20d7f4c10066d80351187ec8e303a5a475/numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba10f8411898fc418a521833e014a77d3ca01c15b0c6cdcce6a0d2897e6dbbdf", size = 16821570, upload-time = "2025-05-17T21:32:47.991Z" }, + { url = "https://files.pythonhosted.org/packages/83/6c/44d0325722cf644f191042bf47eedad61c1e6df2432ed65cbe28509d404e/numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd48227a919f1bafbdda0583705e547892342c26fb127219d60a5c36882609d1", size = 15818548, upload-time = "2025-05-17T21:33:11.728Z" }, + { url = "https://files.pythonhosted.org/packages/ae/9d/81e8216030ce66be25279098789b665d49ff19eef08bfa8cb96d4957f422/numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9551a499bf125c1d4f9e250377c1ee2eddd02e01eac6644c080162c0c51778ab", size = 18620521, upload-time = "2025-05-17T21:33:39.139Z" }, + { url = "https://files.pythonhosted.org/packages/6a/fd/e19617b9530b031db51b0926eed5345ce8ddc669bb3bc0044b23e275ebe8/numpy-2.2.6-cp311-cp311-win32.whl", hash = "sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47", size = 6525866, upload-time = "2025-05-17T21:33:50.273Z" }, + { url = "https://files.pythonhosted.org/packages/31/0a/f354fb7176b81747d870f7991dc763e157a934c717b67b58456bc63da3df/numpy-2.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:e8213002e427c69c45a52bbd94163084025f533a55a59d6f9c5b820774ef3303", size = 12907455, upload-time = "2025-05-17T21:34:09.135Z" }, + { url = "https://files.pythonhosted.org/packages/82/5d/c00588b6cf18e1da539b45d3598d3557084990dcc4331960c15ee776ee41/numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff", size = 20875348, upload-time = "2025-05-17T21:34:39.648Z" }, + { url = "https://files.pythonhosted.org/packages/66/ee/560deadcdde6c2f90200450d5938f63a34b37e27ebff162810f716f6a230/numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c", size = 14119362, upload-time = "2025-05-17T21:35:01.241Z" }, + { url = "https://files.pythonhosted.org/packages/3c/65/4baa99f1c53b30adf0acd9a5519078871ddde8d2339dc5a7fde80d9d87da/numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3", size = 5084103, upload-time = "2025-05-17T21:35:10.622Z" }, + { url = "https://files.pythonhosted.org/packages/cc/89/e5a34c071a0570cc40c9a54eb472d113eea6d002e9ae12bb3a8407fb912e/numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282", size = 6625382, upload-time = "2025-05-17T21:35:21.414Z" }, + { url = "https://files.pythonhosted.org/packages/f8/35/8c80729f1ff76b3921d5c9487c7ac3de9b2a103b1cd05e905b3090513510/numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87", size = 14018462, upload-time = "2025-05-17T21:35:42.174Z" }, + { url = "https://files.pythonhosted.org/packages/8c/3d/1e1db36cfd41f895d266b103df00ca5b3cbe965184df824dec5c08c6b803/numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249", size = 16527618, upload-time = "2025-05-17T21:36:06.711Z" }, + { url = "https://files.pythonhosted.org/packages/61/c6/03ed30992602c85aa3cd95b9070a514f8b3c33e31124694438d88809ae36/numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49", size = 15505511, upload-time = "2025-05-17T21:36:29.965Z" }, + { url = "https://files.pythonhosted.org/packages/b7/25/5761d832a81df431e260719ec45de696414266613c9ee268394dd5ad8236/numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de", size = 18313783, upload-time = "2025-05-17T21:36:56.883Z" }, + { url = "https://files.pythonhosted.org/packages/57/0a/72d5a3527c5ebffcd47bde9162c39fae1f90138c961e5296491ce778e682/numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4", size = 6246506, upload-time = "2025-05-17T21:37:07.368Z" }, + { url = "https://files.pythonhosted.org/packages/36/fa/8c9210162ca1b88529ab76b41ba02d433fd54fecaf6feb70ef9f124683f1/numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2", size = 12614190, upload-time = "2025-05-17T21:37:26.213Z" }, + { url = "https://files.pythonhosted.org/packages/f9/5c/6657823f4f594f72b5471f1db1ab12e26e890bb2e41897522d134d2a3e81/numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84", size = 20867828, upload-time = "2025-05-17T21:37:56.699Z" }, + { url = "https://files.pythonhosted.org/packages/dc/9e/14520dc3dadf3c803473bd07e9b2bd1b69bc583cb2497b47000fed2fa92f/numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b", size = 14143006, upload-time = "2025-05-17T21:38:18.291Z" }, + { url = "https://files.pythonhosted.org/packages/4f/06/7e96c57d90bebdce9918412087fc22ca9851cceaf5567a45c1f404480e9e/numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d", size = 5076765, upload-time = "2025-05-17T21:38:27.319Z" }, + { url = "https://files.pythonhosted.org/packages/73/ed/63d920c23b4289fdac96ddbdd6132e9427790977d5457cd132f18e76eae0/numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566", size = 6617736, upload-time = "2025-05-17T21:38:38.141Z" }, + { url = "https://files.pythonhosted.org/packages/85/c5/e19c8f99d83fd377ec8c7e0cf627a8049746da54afc24ef0a0cb73d5dfb5/numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f", size = 14010719, upload-time = "2025-05-17T21:38:58.433Z" }, + { url = "https://files.pythonhosted.org/packages/19/49/4df9123aafa7b539317bf6d342cb6d227e49f7a35b99c287a6109b13dd93/numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f", size = 16526072, upload-time = "2025-05-17T21:39:22.638Z" }, + { url = "https://files.pythonhosted.org/packages/b2/6c/04b5f47f4f32f7c2b0e7260442a8cbcf8168b0e1a41ff1495da42f42a14f/numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868", size = 15503213, upload-time = "2025-05-17T21:39:45.865Z" }, + { url = "https://files.pythonhosted.org/packages/17/0a/5cd92e352c1307640d5b6fec1b2ffb06cd0dabe7d7b8227f97933d378422/numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d", size = 18316632, upload-time = "2025-05-17T21:40:13.331Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3b/5cba2b1d88760ef86596ad0f3d484b1cbff7c115ae2429678465057c5155/numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd", size = 6244532, upload-time = "2025-05-17T21:43:46.099Z" }, + { url = "https://files.pythonhosted.org/packages/cb/3b/d58c12eafcb298d4e6d0d40216866ab15f59e55d148a5658bb3132311fcf/numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c", size = 12610885, upload-time = "2025-05-17T21:44:05.145Z" }, + { url = "https://files.pythonhosted.org/packages/6b/9e/4bf918b818e516322db999ac25d00c75788ddfd2d2ade4fa66f1f38097e1/numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6", size = 20963467, upload-time = "2025-05-17T21:40:44Z" }, + { url = "https://files.pythonhosted.org/packages/61/66/d2de6b291507517ff2e438e13ff7b1e2cdbdb7cb40b3ed475377aece69f9/numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda", size = 14225144, upload-time = "2025-05-17T21:41:05.695Z" }, + { url = "https://files.pythonhosted.org/packages/e4/25/480387655407ead912e28ba3a820bc69af9adf13bcbe40b299d454ec011f/numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40", size = 5200217, upload-time = "2025-05-17T21:41:15.903Z" }, + { url = "https://files.pythonhosted.org/packages/aa/4a/6e313b5108f53dcbf3aca0c0f3e9c92f4c10ce57a0a721851f9785872895/numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8", size = 6712014, upload-time = "2025-05-17T21:41:27.321Z" }, + { url = "https://files.pythonhosted.org/packages/b7/30/172c2d5c4be71fdf476e9de553443cf8e25feddbe185e0bd88b096915bcc/numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f", size = 14077935, upload-time = "2025-05-17T21:41:49.738Z" }, + { url = "https://files.pythonhosted.org/packages/12/fb/9e743f8d4e4d3c710902cf87af3512082ae3d43b945d5d16563f26ec251d/numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa", size = 16600122, upload-time = "2025-05-17T21:42:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/12/75/ee20da0e58d3a66f204f38916757e01e33a9737d0b22373b3eb5a27358f9/numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571", size = 15586143, upload-time = "2025-05-17T21:42:37.464Z" }, + { url = "https://files.pythonhosted.org/packages/76/95/bef5b37f29fc5e739947e9ce5179ad402875633308504a52d188302319c8/numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1", size = 18385260, upload-time = "2025-05-17T21:43:05.189Z" }, + { url = "https://files.pythonhosted.org/packages/09/04/f2f83279d287407cf36a7a8053a5abe7be3622a4363337338f2585e4afda/numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff", size = 6377225, upload-time = "2025-05-17T21:43:16.254Z" }, + { url = "https://files.pythonhosted.org/packages/67/0e/35082d13c09c02c011cf21570543d202ad929d961c02a147493cb0c2bdf5/numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06", size = 12771374, upload-time = "2025-05-17T21:43:35.479Z" }, + { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" }, + { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" }, + { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" }, + { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" }, +] + +[[package]] +name = "numpy" +version = "2.4.6" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version == '3.11.*' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", +] +sdist = { url = "https://files.pythonhosted.org/packages/d0/ad/fed0499ce6a338d2a03ebae59cd15093910c8875328855781952abf6c2fe/numpy-2.4.6.tar.gz", hash = "sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda", size = 20735807, upload-time = "2026-05-18T23:37:14.07Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/49/ec46835a70be8fa6446c495126ac84fdb28cb2558e1620ffb87a10c8b64c/numpy-2.4.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4", size = 16969194, upload-time = "2026-05-18T23:33:13.503Z" }, + { url = "https://files.pythonhosted.org/packages/0e/0d/f5957185c0ee2f3e12f78715aa9e3b353fd83633316c8532b38faa37e3f6/numpy-2.4.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:110f8b71aacb688ec69062bb7f6938a0f8acb01b7c1c4beb453c65b6d234584d", size = 14964111, upload-time = "2026-05-18T23:33:17.795Z" }, + { url = "https://files.pythonhosted.org/packages/ad/40/40a40ee0ddf7ceb782c49af278894b686e586d65d8c1889c8b5da01a3d7d/numpy-2.4.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:4cfe66903cc32a9921a6733d96b19bb6abf310397581bbad89c228f5abaf0ee8", size = 5469159, upload-time = "2026-05-18T23:33:20.654Z" }, + { url = "https://files.pythonhosted.org/packages/63/13/f9a8046535cb21deae82f8d03de9617e08882d274fad2539630761888228/numpy-2.4.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8155154c7c691289fe18f510b5d4657c68c67989f293f0535a91360392ff6538", size = 6798936, upload-time = "2026-05-18T23:33:22.987Z" }, + { url = "https://files.pythonhosted.org/packages/33/a8/6fa8c1a345a8c85dbb21932c447bee07c30a2c2a3f31e369c0a84b300147/numpy-2.4.6-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ab0a9c4ffb1a6d95ef519fe4247dba8eb6b18ad93999f76b7f657039acabd47", size = 15966692, upload-time = "2026-05-18T23:33:26.62Z" }, + { url = "https://files.pythonhosted.org/packages/02/03/74fe2a4cb3817d94d86402f2506554130a2f01414e299b5a843e5a8a957f/numpy-2.4.6-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89cd468399cfd2504718f0ba50e410dca55a170b61a02ad92bb18c8a65186e93", size = 16918164, upload-time = "2026-05-18T23:33:29.955Z" }, + { url = "https://files.pythonhosted.org/packages/c5/80/3615be3313f7e7696609bc194b9f0101da809df79e859bdb84e0cd043f46/numpy-2.4.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2d37ab77531417474168eb79d6d80b14f821a966818505d03013d0833edb7a8", size = 17322877, upload-time = "2026-05-18T23:33:34.724Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ac/a691e0fe2675e370d0e08ff905adc49a1c8830e8cae03efe4477e92cd55d/numpy-2.4.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f407cb6b8e9d6d8c626bc73c945db1706035af8fd632295547bf1c9e46d092d6", size = 18651487, upload-time = "2026-05-18T23:33:38.217Z" }, + { url = "https://files.pythonhosted.org/packages/15/a7/9bc1cd626d7bf6869bfedf27b91b6ab5dd607758bf8e959d6fa80c6a59cb/numpy-2.4.6-cp311-cp311-win32.whl", hash = "sha256:ddea102b48f9e339f3948bf22040944184627a30fdf7f858667673b9c5f033c8", size = 6233945, upload-time = "2026-05-18T23:33:41.331Z" }, + { url = "https://files.pythonhosted.org/packages/c5/31/7fc6239c12bce7e931463251cca4426c465e1876ba3cc785402ef4dd8f4e/numpy-2.4.6-cp311-cp311-win_amd64.whl", hash = "sha256:1e254a00cdf42b1e4d5b3d68d33af63268d41340d8885df2ab6470f2e1500147", size = 12608406, upload-time = "2026-05-18T23:33:44.131Z" }, + { url = "https://files.pythonhosted.org/packages/27/83/140f85a466595a16382996a1bf06b2b54bcd597488921b0c9daaeeda72af/numpy-2.4.6-cp311-cp311-win_arm64.whl", hash = "sha256:ed9749eef4cbd126da3dc1d6bcb3a57f5eb7ac6a6484146bdbf743f552dfc577", size = 10479528, upload-time = "2026-05-18T23:33:50.725Z" }, + { url = "https://files.pythonhosted.org/packages/95/2a/3d7b5ac8aac24feaf9ad7ed58f45b0bbc06d37e4338ae84c9f2298b570f9/numpy-2.4.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:001fbb8e08d942dd57599e781f2472269ee7f2755fae407b4f67b2f0b17da3f1", size = 16689119, upload-time = "2026-05-18T23:33:54.065Z" }, + { url = "https://files.pythonhosted.org/packages/ea/12/92c4c131527599e8288d6918e888d88726f84d805d784b771f32408aeaef/numpy-2.4.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ebfb099f8dcf083deef3ac1ca4c1503f387cf76296fcb3816b66f5ecb5f54fdb", size = 14699246, upload-time = "2026-05-18T23:33:57.621Z" }, + { url = "https://files.pythonhosted.org/packages/ad/fe/c0a6b7b2ca128a8fb228575147073b660656734b8ebe4d76c8fd748dcc79/numpy-2.4.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3213d622a0283a39a93d188f3cf72b26862df52fbb4ca3697f51705016523d41", size = 5204410, upload-time = "2026-05-18T23:34:00.302Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d4/9770d14ba719432bb90a421bfd443872ed0f70f7264b64bec12ea363d5fd/numpy-2.4.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:357cc07a6d7b0b182ff02249616a03742827ebb1277546b5c7cd7f7620a45698", size = 6551240, upload-time = "2026-05-18T23:34:02.852Z" }, + { url = "https://files.pythonhosted.org/packages/c9/c6/50a46a6205feba2343f1d6d17438107c5dc491ed1c736e6ea68689fd906b/numpy-2.4.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f9fb9157b4ce2971008323afe46053787b526ef624fea915b261468a8421a0f", size = 15671012, upload-time = "2026-05-18T23:34:05.485Z" }, + { url = "https://files.pythonhosted.org/packages/99/60/14115e6364fa676c5397c2ad3004e527e9aa487abf5d0706ec81bbd08529/numpy-2.4.6-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90f9849678c75fe7afa2d348ac842c168b0a4d3d61919687216dfc547976d853", size = 16645538, upload-time = "2026-05-18T23:34:09.265Z" }, + { url = "https://files.pythonhosted.org/packages/ae/c5/693cbe59e57db94d2231fa519ca3978dc9e19da5a8f088588f5c6e947ff2/numpy-2.4.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c1a2af6c6ef86344a6b0db6b97834208bf598db514f2b155042439b62605601a", size = 17020706, upload-time = "2026-05-18T23:34:13.053Z" }, + { url = "https://files.pythonhosted.org/packages/ef/fc/85b7c4eff9b4966ade25c2273cf7e7012e92366c032058653934b37de044/numpy-2.4.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5805d5a22fd19c8ccff10a9561f9df94436b0545619ea579db2d3c35294bce2", size = 18368541, upload-time = "2026-05-18T23:34:17.024Z" }, + { url = "https://files.pythonhosted.org/packages/f6/81/e1b27545deedce7f4a0b348618c6b62d74e36a4dc9ccd42f3eb2f85eee32/numpy-2.4.6-cp312-cp312-win32.whl", hash = "sha256:e3eeb0aabd6bd5ce64faae67e9935203a6991b4bc2a485a767fbafb2c5125f45", size = 5962825, upload-time = "2026-05-18T23:34:20.3Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ca/feab00bd44aa5fe1ad2c18f08b4d3bb92e26484b0b1d1443897809ed528c/numpy-2.4.6-cp312-cp312-win_amd64.whl", hash = "sha256:d8e8286dd7cea7895157318d1b91cdacac64c479f3cbc8dce548331728484751", size = 12321687, upload-time = "2026-05-18T23:34:23.095Z" }, + { url = "https://files.pythonhosted.org/packages/63/cf/5a6d34850a39d1093558564f77ee8e8e0bee5061151b8f05a55711001ec7/numpy-2.4.6-cp312-cp312-win_arm64.whl", hash = "sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8", size = 10221482, upload-time = "2026-05-18T23:34:25.876Z" }, + { url = "https://files.pythonhosted.org/packages/fb/82/bdab26d7438c6791ca31b7c024ca37c1eab8b726ba236129005cd4a06e45/numpy-2.4.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:511dbaf848decaaaf4b4ca48032619fb3138710c4bf7da7617765edad1ef96b0", size = 16684648, upload-time = "2026-05-18T23:34:29.41Z" }, + { url = "https://files.pythonhosted.org/packages/1b/30/a80189bcc7f5e4258b3fbc3968d909d1756f54d023299ecc39ad6fdb9ef8/numpy-2.4.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bf162abab1c1a736333192707cef898e735a5ca00f38f27eeedf44b39d9e85eb", size = 14693902, upload-time = "2026-05-18T23:34:33.013Z" }, + { url = "https://files.pythonhosted.org/packages/97/12/70b5d0d7c15e1ebb8a6a84a8caa1d19e181d84fb58bb6d70aca29099dec1/numpy-2.4.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:043191bfa8eab18c776647b62723ac9dddece59743b13f49b2016094129c2b3f", size = 5198992, upload-time = "2026-05-18T23:34:36.132Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8c/ebd2a8f8a83541f8d38cc5667e8c2b69cecfd30da6e45693e8158857d44b/numpy-2.4.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:6180d8b35af935aed8ece3a85e0a43f87393ae0ac87c8d2c8bd2c993f7270ef3", size = 6546944, upload-time = "2026-05-18T23:34:38.484Z" }, + { url = "https://files.pythonhosted.org/packages/bb/c5/7b863a97a91671a0338f4253bd3b5a3d3852f0692dae91711c9f4a10e787/numpy-2.4.6-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72fbe16c6fac95aedf5937fa873445cec2110be35d8a4e9433d7501fd98dae6b", size = 15669392, upload-time = "2026-05-18T23:34:41.257Z" }, + { url = "https://files.pythonhosted.org/packages/a5/9d/3584b9984ca4c047aea75214ce1a4c4c73d849bd71b604264b7f5653f8a8/numpy-2.4.6-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7830bab239b79cda9c08c2da014761cafb48da6150e1da17ac06283f43b6089", size = 16633220, upload-time = "2026-05-18T23:34:45.075Z" }, + { url = "https://files.pythonhosted.org/packages/05/ae/7c67fba23bd98caec7c99261f3a16072ade14813486b0282cb29846de832/numpy-2.4.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ef4aea96ce4d3b074422cb4f2f64e216bf9e213004bb58ecfdf50ea02ea8eb9a", size = 17020800, upload-time = "2026-05-18T23:34:49.065Z" }, + { url = "https://files.pythonhosted.org/packages/d9/5d/3b6725cb31d983c5e66916f5d36f6d7e5521129e4c4404d64f918292a5b6/numpy-2.4.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dfa20cc6ca228e6b155b11da03825975ce66aea520985dbbddf0f2a5a495c605", size = 18357600, upload-time = "2026-05-18T23:34:52.709Z" }, + { url = "https://files.pythonhosted.org/packages/f7/da/2ccc6c2fe8898dee01d90c75c5f5f914a23daf99e3e0f59516a08760c8b5/numpy-2.4.6-cp313-cp313-win32.whl", hash = "sha256:56b39e5e0622a09a25bf5baf62f4bcf0cb8a41ae6e2819cf49bbc5a74c083f91", size = 5961134, upload-time = "2026-05-18T23:34:55.618Z" }, + { url = "https://files.pythonhosted.org/packages/b5/cd/9cc4dc876fb065d5c220aae4d5e14826b2715331bb7618ce1fb07a679d99/numpy-2.4.6-cp313-cp313-win_amd64.whl", hash = "sha256:c4fc99836233ea196540b17ab0983aff60ed07941751930f5f4d05bc3b3b7359", size = 12318598, upload-time = "2026-05-18T23:34:58.928Z" }, + { url = "https://files.pythonhosted.org/packages/39/1e/c0bcba1f8694116485fe28fd1be698c278fcda4141c5b0e53a2aed8b12a8/numpy-2.4.6-cp313-cp313-win_arm64.whl", hash = "sha256:a7c711e21628b52034bb5ab8d1bce291f752fcc5e92accc615778acee1ff4778", size = 10222272, upload-time = "2026-05-18T23:35:02.167Z" }, + { url = "https://files.pythonhosted.org/packages/63/6d/cc5619247c8f4204e507f5883528372e4ac4bb189e579fb859a12e480b1f/numpy-2.4.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:112b06a867b235ef466ed3508ddf0238050df9c727cafb5301ac385b899189a1", size = 14821197, upload-time = "2026-05-18T23:35:05.468Z" }, + { url = "https://files.pythonhosted.org/packages/00/58/f1c39161c87d9e9bed660f1ed4bafc0e403d5ec9650b6dd77aead07d489b/numpy-2.4.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:eaf7fa2de5c0be8ae6ff8e9bea2ccd725e980541244521d8d4b5f3354a27babe", size = 5326287, upload-time = "2026-05-18T23:35:08.693Z" }, + { url = "https://files.pythonhosted.org/packages/af/57/3917ab0fd97f271a8694513581b8a36c655f111c446852c302f04ccdb6fc/numpy-2.4.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:7265a2f3d436e54ef9f2b52b5c937e6be778781bd97a590319d7348f1c1ca997", size = 6646763, upload-time = "2026-05-18T23:35:11.459Z" }, + { url = "https://files.pythonhosted.org/packages/eb/0f/037e64c494b67581ae18193d770adef354c41f3f2c8ebf865602d949bf8f/numpy-2.4.6-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20", size = 15728070, upload-time = "2026-05-18T23:35:14.79Z" }, + { url = "https://files.pythonhosted.org/packages/21/a6/5d2bae9c9542eb4df16dc9c46dc79c186e9bad53805dfa5399a6023c6db0/numpy-2.4.6-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ede83e07a75dd06bc501566c1eca2afc0d61677c1472ac9ad93fdee6e638a48d", size = 16681752, upload-time = "2026-05-18T23:35:18.836Z" }, + { url = "https://files.pythonhosted.org/packages/92/14/23d1dfb410ae362cd59ce53e936b1513d545eb40db3949ced632e19a459e/numpy-2.4.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:68bb27509ac1b9a3443094260f6326150663b06abe40b73a2f81160623da5b67", size = 17086024, upload-time = "2026-05-18T23:35:22.52Z" }, + { url = "https://files.pythonhosted.org/packages/4b/6e/23595a2c642cdf3bc567877064bdd7f91c8b0038a4453cf2daf7248eafe9/numpy-2.4.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a0df0043bdb289bde1f62da130d20df23d58b45429f752bc7a8fc5325a225ecd", size = 18403398, upload-time = "2026-05-18T23:35:26.398Z" }, + { url = "https://files.pythonhosted.org/packages/8a/90/0ac3bc947217e66dec77e7cbc6a1979d1af70b6461b82f620d3bccd5e4c8/numpy-2.4.6-cp313-cp313t-win32.whl", hash = "sha256:29a287e0cf63ff528da061de6b9f64a4618da591ca1046aafc54062e40ca7eab", size = 6084971, upload-time = "2026-05-18T23:35:29.387Z" }, + { url = "https://files.pythonhosted.org/packages/77/71/5673e351671a1d2bd6063b91b44f70c0affea7d1516fa7a6572941ba4aa1/numpy-2.4.6-cp313-cp313t-win_amd64.whl", hash = "sha256:25c692919ac5a01f170a3bfcd62d745b24fd095c353d50812637d6fcab442e75", size = 12458532, upload-time = "2026-05-18T23:35:32.175Z" }, + { url = "https://files.pythonhosted.org/packages/3f/88/19d3503c5046e688f049274b27a3ef3d771152fa80d3ba3d01a3dff61abe/numpy-2.4.6-cp313-cp313t-win_arm64.whl", hash = "sha256:1e978ec1e8bd0e0e4de6bb75de9d30cbb74db6b6a2bb727618613703ca0167dd", size = 10291881, upload-time = "2026-05-18T23:35:35.465Z" }, + { url = "https://files.pythonhosted.org/packages/f8/91/3ab2044d05fd16d343c5ac2e69b127f1b2854040dd20b193257c78028bd3/numpy-2.4.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06ca2f61ec4385a07a6977c55ba998a4466c123642b4a32694d3128fce18c079", size = 16683458, upload-time = "2026-05-18T23:35:38.353Z" }, + { url = "https://files.pythonhosted.org/packages/8e/62/764ce66fa4147ae6d73071a3abf804ffe606f174618697c571acdf26a7c9/numpy-2.4.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7", size = 14704559, upload-time = "2026-05-18T23:35:42.14Z" }, + { url = "https://files.pythonhosted.org/packages/60/61/23f27c172f022e04025b7dc2367f4d63c1a398120607ec896228649a6f48/numpy-2.4.6-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:d581b735e177fdcdce6fed8e7e8880a3fb6ee4e3653a3ac6af01c6f4c03effc5", size = 5209716, upload-time = "2026-05-18T23:35:45.377Z" }, + { url = "https://files.pythonhosted.org/packages/03/71/21cf70dc6ea3e3acb95fc53a265b2fc248b981f0194ceb5b475271b8809d/numpy-2.4.6-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:0a041d3d761dc3c35cc56ce0351506a02bcbc25f7b169f652435141a17db9096", size = 6543947, upload-time = "2026-05-18T23:35:47.926Z" }, + { url = "https://files.pythonhosted.org/packages/d5/91/64288395ee1799bd2e0b04a305dce9666da90c961e1f3fe982a05ee1c036/numpy-2.4.6-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40fdc1ae7125e518ea98e53e69a4ebc27e1fd50510c47b7ea130cf21e5e1d42b", size = 15685197, upload-time = "2026-05-18T23:35:50.863Z" }, + { url = "https://files.pythonhosted.org/packages/f3/eb/ebffaa97dc55502df69584a8f0dcf07f69a3e0b3e2323670a2722db9aa39/numpy-2.4.6-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8", size = 16638245, upload-time = "2026-05-18T23:35:54.752Z" }, + { url = "https://files.pythonhosted.org/packages/b8/0b/54f9da33128d7e350fab89c7455902eeae70349ee52bddb448dc4a576f45/numpy-2.4.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:33111801a01c12a8a1e3721f0a9232f8cfc8ae2c6b7098167e6f623c6073f402", size = 17036587, upload-time = "2026-05-18T23:35:58.355Z" }, + { url = "https://files.pythonhosted.org/packages/b6/f0/fdebc1052db1cc37c64beb22072d67cd6d1c71adca1299f53dec2b5e20d3/numpy-2.4.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae506e6902902557576a26ff33eda8695e7ecb3cb36c3b573a0765dee114ebdb", size = 18363226, upload-time = "2026-05-18T23:36:02.845Z" }, + { url = "https://files.pythonhosted.org/packages/aa/b4/298628d98c72b57e57f7165ae6a481a1deaf6f3c28262a6e4c739c275930/numpy-2.4.6-cp314-cp314-win32.whl", hash = "sha256:aaf159caa35993cb1f56fb9b8e4610d35758e7ca005412eb1daa856a78c9c4b1", size = 6010196, upload-time = "2026-05-18T23:36:05.92Z" }, + { url = "https://files.pythonhosted.org/packages/df/ac/46de6dda46478f7942f839e094970be2d4a861e005c4b3bf07c92e291a09/numpy-2.4.6-cp314-cp314-win_amd64.whl", hash = "sha256:b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261", size = 12450334, upload-time = "2026-05-18T23:36:09.107Z" }, + { url = "https://files.pythonhosted.org/packages/78/92/b8b798ac784102c0da830d2257d59358e3d3d90d1e2b3f2575dad976c5cf/numpy-2.4.6-cp314-cp314-win_arm64.whl", hash = "sha256:6f41ae150c4e32db4f3310cdaf64b1593a03dbabe29eec77fc9b50fe64061df6", size = 10495678, upload-time = "2026-05-18T23:36:12.766Z" }, + { url = "https://files.pythonhosted.org/packages/30/34/ec28d1aa8115971537c01469ab2011ee96827930f0a124de1000cc2a7ed7/numpy-2.4.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ece3d2cfe132e7d51f44a832b303895e6f2d499c5e74dfbdb06ee246147a304a", size = 14823672, upload-time = "2026-05-18T23:36:16.473Z" }, + { url = "https://files.pythonhosted.org/packages/16/bd/f6d1fede4e54e8042a7ff97bb495510f3c220f94bcd9e8b228e87c92cc0d/numpy-2.4.6-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:e3e5193ef5a3dc73bceee50f7fdc2c90dbb76c42df8d8fae3d1067a583df579e", size = 5328731, upload-time = "2026-05-18T23:36:19.767Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f0/e105b9e2fd728a9910103884decd6951d9dd73896b914a98d9a231de02ee/numpy-2.4.6-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:17f9ade344e7d9b464a084d69bcf18fc691cb1db67c62ed80820bf4926d78f0e", size = 6649805, upload-time = "2026-05-18T23:36:22.266Z" }, + { url = "https://files.pythonhosted.org/packages/82/dd/1206a7ca6ab15e3f02069707ca96222e202af681bb73756da7527f3cb837/numpy-2.4.6-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cd5ffd25db4e7ba6a375693b3fc0fc1791ec636c17db3720da19bde7180ec43", size = 15730496, upload-time = "2026-05-18T23:36:25.713Z" }, + { url = "https://files.pythonhosted.org/packages/51/e7/38d3ea825dcab85a591734decb2f6c67caa7c8367d374df1a1c3842f9b07/numpy-2.4.6-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d92c3819208a60205a12a245c91ad70cb0a85336659b19b834205573ac8456e", size = 16679616, upload-time = "2026-05-18T23:36:29.652Z" }, + { url = "https://files.pythonhosted.org/packages/93/b7/caabfdf53edf663e0b4eb74d7d405d83baef09eb5e83bcd32d601d72b93e/numpy-2.4.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e85b752a1e912b70eaad4fafbd4d1238007ab221de2009b9a2f5ae7461239895", size = 17085145, upload-time = "2026-05-18T23:36:33.449Z" }, + { url = "https://files.pythonhosted.org/packages/f9/45/68d7c33a6bcf3e5aa3bdbd57a367e6f615286dfd6482f97e8ffeb734306e/numpy-2.4.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:29cb7f67d10b479ff07c17d33e39f78c07f71c40ef30d63c153d340e96cd3fb4", size = 18403813, upload-time = "2026-05-18T23:36:37.369Z" }, + { url = "https://files.pythonhosted.org/packages/9c/50/0753655aa844c99cd9e018aacf76f130f1bd81d881bb74bc0aef5d73a8ba/numpy-2.4.6-cp314-cp314t-win32.whl", hash = "sha256:260a5d70215b61ab4fadf5c7baacd64821842975eea312125ed3c39a6391b063", size = 6156982, upload-time = "2026-05-18T23:36:40.817Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d4/7c67becf668f973cb490cec3e98dfd799d866f9c989a54d355672cfa0db6/numpy-2.4.6-cp314-cp314t-win_amd64.whl", hash = "sha256:81a1cca95ed5bb92aa8b10dd2cdc9a0d3853a50fad926c28b5d7e8ea54389627", size = 12638908, upload-time = "2026-05-18T23:36:43.996Z" }, + { url = "https://files.pythonhosted.org/packages/43/bb/e1c71a4295b1b1d1393d50dbb4f2a36283c6859d9d3892e84f00ec5a91d5/numpy-2.4.6-cp314-cp314t-win_arm64.whl", hash = "sha256:0c9136e14ed34a9e343a31c533d78a9813a69a3148332bce5e9821cb2f996e66", size = 10565867, upload-time = "2026-05-18T23:36:47.114Z" }, + { url = "https://files.pythonhosted.org/packages/de/12/b422cc84439adc0d00de605bf4a308890ae5c26f2c71fbd73e5d08fbb0dd/numpy-2.4.6-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:55cced7c52e981362f708ad635198e97a752dfba412cc03c23bbf3bd8d5cd662", size = 16847511, upload-time = "2026-05-18T23:36:50.673Z" }, + { url = "https://files.pythonhosted.org/packages/44/53/f481bef68011740f8849418d82db07230e825013f31f4eef5ba5b805316a/numpy-2.4.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d6da64deb6b8ed903e7560180a92f2d804ee1ba5eeb849ac2748b8c1aba1f6d7", size = 14889064, upload-time = "2026-05-18T23:36:53.879Z" }, + { url = "https://files.pythonhosted.org/packages/7f/57/42ed575c10ced8af951d426bc4e1f8aff16fd851db33f067036215a7f860/numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:68a5124b13fa6cc2086764a20005d30bc0548146f7f5322f02fce212ca14317f", size = 5394157, upload-time = "2026-05-18T23:36:57.194Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ef/f66cc724fcc36c1e364c67f51ae9146090b8b584f27d58b97fdae3edd737/numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:948424b06129ce883307e8cff868c31396d8dc7630a59c61d70d98dbe70f222c", size = 6708728, upload-time = "2026-05-18T23:36:59.575Z" }, + { url = "https://files.pythonhosted.org/packages/1a/9c/c531f2293b91265d8b48e9b329f54fdd7ffae73cb4134ea10cca4237e9cc/numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbbdb29840ca3d91ee0fece42fc29278886d908280bfec0a5846c6f901a3eb0", size = 15798374, upload-time = "2026-05-18T23:37:02.674Z" }, + { url = "https://files.pythonhosted.org/packages/1a/b0/413077f6b1153ed3cba361401c6783bbad6114804a000cc22eb71c13e190/numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8ad03c0965fb3c692200e74d458ca28c1dbb4ce96f9a479a8aa041ad5fabca02", size = 16747286, upload-time = "2026-05-18T23:37:06.327Z" }, + { url = "https://files.pythonhosted.org/packages/15/ce/e5ec180bc41812edcd8daeb8639d205622c0e8c02259d8ab25a0201b3c2a/numpy-2.4.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:2803abfebfc990042cd494d8ce2d5f82e9d847af6d35ec486923aa19dbad5e73", size = 12504263, upload-time = "2026-05-18T23:37:09.715Z" }, +] + +[[package]] +name = "numpy" +version = "2.5.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.15' and sys_platform == 'win32'", + "python_full_version == '3.14.*' and sys_platform == 'win32'", + "python_full_version >= '3.15' and sys_platform == 'emscripten'", + "python_full_version == '3.14.*' and sys_platform == 'emscripten'", + "python_full_version >= '3.15' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.14.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", +] +sdist = { url = "https://files.pythonhosted.org/packages/22/fd/89965aa4ac08c74998539fcbf24fa3540f3e15237fbeb6bcf9c908f4aade/numpy-2.5.1.tar.gz", hash = "sha256:a48a113e6afea91f5608793bafa7ef2ad481fefbda87ec5069f483de61cb9fa3", size = 20755553, upload-time = "2026-07-04T17:08:00.933Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/7b/14687aa674250e5e546f616f486b0d56d3631cd5b2415739141ce40bdcea/numpy-2.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2c889b56fe48b1018f764b0eec8df59ab654e9148aa91faa12596043500de277", size = 16801574, upload-time = "2026-07-04T17:06:12.423Z" }, + { url = "https://files.pythonhosted.org/packages/e1/19/cc5bb2a3f2913d27d6dbb2c78d25921fabaedc6741d4a5a615a11f3c5bf3/numpy-2.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab451b59c5643c570974c43aef780703ef1d3b4965d2be07afd530615a9358d1", size = 11772250, upload-time = "2026-07-04T17:06:15.726Z" }, + { url = "https://files.pythonhosted.org/packages/42/77/fdf34a71dd30f54979b18603bee915e0aaf825b07afe79acd60b04b691e2/numpy-2.5.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:78798bd5b9ad744056af8efa90e3b9ddaa53272a0848a483084a1cc0a13b2dc0", size = 5331516, upload-time = "2026-07-04T17:06:17.913Z" }, + { url = "https://files.pythonhosted.org/packages/ce/e2/eb7efa015b4cce41e2517bf182a7fce0d7d5b9d9ed76a29bfa0f4fe4505c/numpy-2.5.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:2ae0ca40bcb22d6ba59c1dfd5446f49940b0f2d821fde133f10dda11f816b84e", size = 6664863, upload-time = "2026-07-04T17:06:20.02Z" }, + { url = "https://files.pythonhosted.org/packages/a9/4b/a2b32dd94ee9ffbeecb28152240042a3949db33b1c834d44090b80e1b3b8/numpy-2.5.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:61ac47e772e6b8ea489e1d2f441a34c5c3ac17327e7ce294cbdf535795ad4e75", size = 15167977, upload-time = "2026-07-04T17:06:21.621Z" }, + { url = "https://files.pythonhosted.org/packages/b8/a9/6e73d68500f80773f65f0654ea932019d6694329a0eb0ed0533de38df376/numpy-2.5.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:59fda5e192b570217ec2580c96f00e9a7e12ef6866a900eb089b62c1a32545ca", size = 16672469, upload-time = "2026-07-04T17:06:24.064Z" }, + { url = "https://files.pythonhosted.org/packages/24/7d/ad3e59015135f5261c95fd4cafeff159c955febd83a99a1d9250c4233815/numpy-2.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f7119ebff1a9829e9f431a4f9d28e703023bb6b9fe7c8f724467dbfc27c94ab3", size = 16527531, upload-time = "2026-07-04T17:06:26.69Z" }, + { url = "https://files.pythonhosted.org/packages/83/d0/a39b2fbcde9cb17a1dac678f254b33a6336298af9df338824c685425d5e8/numpy-2.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e824c2acf8862052246be5a44c15da1777940c60d010dd2aab897824d9c430f9", size = 18431940, upload-time = "2026-07-04T17:06:29.521Z" }, + { url = "https://files.pythonhosted.org/packages/04/12/cff070947791c1ed425ff76413189adbdc2fbe215eba7ce7fa454a03c7f8/numpy-2.5.1-cp312-cp312-win32.whl", hash = "sha256:08d60c810432eb83360958dea0999ac4cfb94531ea8efcbf0b7f277c2068aeb2", size = 6066764, upload-time = "2026-07-04T17:06:32.571Z" }, + { url = "https://files.pythonhosted.org/packages/65/66/53f31807a48a750f9d748da273bc3fcedd12b27ff1f3e373bfec55ef2dc0/numpy-2.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:f7d60026c0bdb1380e83bfa7a0419c4577ee4b9a08880afcb6dadeb74c649fa2", size = 12430966, upload-time = "2026-07-04T17:06:34.926Z" }, + { url = "https://files.pythonhosted.org/packages/2b/2a/d1a88066b1c14186f5d3c0d18c94f17b064511982bab0578d49ee9d43c29/numpy-2.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:17a25e09640602e10bc8de0e6fa2b3fd68eedd84ba6d7842dc8f32f9ab87bd0b", size = 10350488, upload-time = "2026-07-04T17:06:37.785Z" }, + { url = "https://files.pythonhosted.org/packages/eb/07/ec2a3f0c91761581d4b7104a740791800025983f9a4dc4e73f91a99aeac4/numpy-2.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0bfebd8695f9863592fe744be833a258120b14a9f39da255e8aa8fade2c0ddd1", size = 16796419, upload-time = "2026-07-04T17:06:40.37Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ab/ddb499fc4f8780354395face5b65c7fd107bcd6e1d667a5f07d046956f6f/numpy-2.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:30b44a6b53a7ae63c54c089a8726e5563ed302716c5b7ccc85afade40b0e7ff6", size = 11765832, upload-time = "2026-07-04T17:06:42.768Z" }, + { url = "https://files.pythonhosted.org/packages/88/b3/3c28c558a09fc72100c646dac6d2fce8e834c471b0edca01a29996706117/numpy-2.5.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:6165343f81b56ef8f514f396989e529b61d9dc709b99421b07e9f3e698e2287d", size = 5325143, upload-time = "2026-07-04T17:06:45.466Z" }, + { url = "https://files.pythonhosted.org/packages/5e/0e/ce19b985bb15c596f4f05954e76cccc77c845083b3b8f938a6c68e523128/numpy-2.5.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4939237038ada79308dda3204ac6462df056b5672b2e25db1149cf873668b3e1", size = 6659749, upload-time = "2026-07-04T17:06:47.288Z" }, + { url = "https://files.pythonhosted.org/packages/2e/20/1ee6614d64332a1bba6411f38e68cb79eec1b2459e20a623777c5c5492a2/numpy-2.5.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c6759f538fb912fc46de0a6b1758ccf7b57bc7c7ebebc23974fdac3de8db0cd", size = 15164716, upload-time = "2026-07-04T17:06:49.494Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a7/2bcd3fdbb87804755c35b729bf8709d62025c5f4cfd7d5b2415997097515/numpy-2.5.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9726558e8db4a5bf7929a70ae50f63abda4daf0efe810e3bfbab95976f75fc1a", size = 16661440, upload-time = "2026-07-04T17:06:52.061Z" }, + { url = "https://files.pythonhosted.org/packages/fc/d7/a41e3310c886fe457d36e670bbf24fae411aca8a7b6ad92a32afd924077c/numpy-2.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3935f3b419b244a02732676fa5317a9193cc596a4c0646db07e5b421229ac9f7", size = 16526305, upload-time = "2026-07-04T17:06:54.605Z" }, + { url = "https://files.pythonhosted.org/packages/53/75/4333a9a707c1edd3a4e1a0c58eca52c0f31e55089fa80db02b5565b24df7/numpy-2.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc932a65ded7ce9013d120845a2514dcccb1a67bfc8deb8d37633762951904a6", size = 18423008, upload-time = "2026-07-04T17:06:57.54Z" }, + { url = "https://files.pythonhosted.org/packages/ee/90/e314a32b1c11a2ffe818ddad3a57b50b4b6e1b6c487192eb50cdef0415d0/numpy-2.5.1-cp313-cp313-win32.whl", hash = "sha256:4b4ff1608417eb7a59da7b967bbb798cacfe071d2caf526a24281cd562072ed9", size = 6063885, upload-time = "2026-07-04T17:07:00.14Z" }, + { url = "https://files.pythonhosted.org/packages/10/70/800b3fca480af32df9e8ea9f3d4a0c8feb4b32d7f195d174eabbda4829ad/numpy-2.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:6c3fe51bc6a16453d452997053454f309e8e0ed7b42d6b361ce4ac8c32913d74", size = 12425674, upload-time = "2026-07-04T17:07:02.387Z" }, + { url = "https://files.pythonhosted.org/packages/8b/0b/196350c122f50f6ca56846f2d71efd5e0d24b7b2e07355e019b2e2c7a11e/numpy-2.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:f7feb014281029e628ba2d5a007407443b06e418b6fe451d1e2adcbc8eba0107", size = 10350256, upload-time = "2026-07-04T17:07:04.878Z" }, + { url = "https://files.pythonhosted.org/packages/db/f4/731b6085a83faf6ca843394cbd5e217280c214399f7e8b21b9f552af0ae2/numpy-2.5.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:7c786fe9a5bbe360022e584c5a34cf6b54265c71bd7ec8ac3d8fec38968071f8", size = 16795063, upload-time = "2026-07-04T17:07:07.374Z" }, + { url = "https://files.pythonhosted.org/packages/bf/64/0e215f2048dd11a55bb989ed41b3585ef57452404e638d703a211a3e4157/numpy-2.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32985c896d897419ef8da6917872d80b78ad0ea26d85b23245c7366ffde76d75", size = 11776652, upload-time = "2026-07-04T17:07:09.907Z" }, + { url = "https://files.pythonhosted.org/packages/b5/59/2b844c7a6e9deff69b404a66221e1542937734f65d5e6e39411876053862/numpy-2.5.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:efd736408cc97c79b9e6917338dfc8f06013b2274f992e96b1d9a81a71e2a2c2", size = 5335944, upload-time = "2026-07-04T17:07:12.227Z" }, + { url = "https://files.pythonhosted.org/packages/86/51/9bf7cb2cabcebc9e017e4ec7e6322b378317a542c08b4cb68479c1efc716/numpy-2.5.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:ab84dc6b074fa881cae55bea94cc4f68e285181ba7f32497bf7dee6b1496165b", size = 6656266, upload-time = "2026-07-04T17:07:14.368Z" }, + { url = "https://files.pythonhosted.org/packages/83/3e/fb7615b211b82a32f44d5180a6d421b61f84d4fadd578b48ba4ac34e189f/numpy-2.5.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caf3e317d33d60c37986b452613f4ab51246d0691350c03d0cb4a898627f4a95", size = 15179720, upload-time = "2026-07-04T17:07:16.272Z" }, + { url = "https://files.pythonhosted.org/packages/41/5f/0f992cb24560673496c5d68de61913b57166ce530ffda07c1f280e0cc464/numpy-2.5.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:54ad769f17bc2d833b620851989f62054fb9ab93c969d9e1dc3c8e3d56beea21", size = 16664835, upload-time = "2026-07-04T17:07:19.021Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2f/97d6475ee91afe2587797d09446f9d3e475ad4cb681662d824809327b75a/numpy-2.5.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c12afb53450fa976d4c681c50a7423729a4c51c0465ed9f32b8a9cabbc472373", size = 16539135, upload-time = "2026-07-04T17:07:22.015Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5b/4db81e4ba0be7e2776b1de68c82aa862c7f8ec27e1b4927d4ae075e20678/numpy-2.5.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e8c11c405efc5ff6816d5983c96cdfa215bab3428961243af3ff59b228490438", size = 18426684, upload-time = "2026-07-04T17:07:24.941Z" }, + { url = "https://files.pythonhosted.org/packages/1f/64/c0ba2d90724d450279a7df8f32057241070250a26a7e2b5337d77347f481/numpy-2.5.1-cp314-cp314-win32.whl", hash = "sha256:f2479a47f8d5932d1718168a681ad6e536a9df484c83cfcf9de365e164537ace", size = 6116103, upload-time = "2026-07-04T17:07:27.622Z" }, + { url = "https://files.pythonhosted.org/packages/c1/1a/837f9ed7405adcd7a40538792eb169eddd8fa5630c16a1ef49dae71a30f4/numpy-2.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:24d0eb82c0541d3415a33425db64ae439dffccd7b4dbcb30e7c35120205c506a", size = 12562177, upload-time = "2026-07-04T17:07:29.887Z" }, + { url = "https://files.pythonhosted.org/packages/22/ed/49707938b6dd0a78a9178dd93227dc89e4c11af47f5c798d70366e8d0483/numpy-2.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:5a4c988b38d261deeeaad9954e3deb091ad905c94e8bb6708654ef1d97f286b0", size = 10627739, upload-time = "2026-07-04T17:07:32.568Z" }, + { url = "https://files.pythonhosted.org/packages/a6/c7/bb4b882cfe7f299cbc8b66e42e7dd78cf9d14e40f9469fc5e3db7e15b3bd/numpy-2.5.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a33276be12fa045805f477f22482088b66bb758ffbe89a9d21457de863a32e22", size = 11894709, upload-time = "2026-07-04T17:07:34.941Z" }, + { url = "https://files.pythonhosted.org/packages/40/3f/5af7f4a7f6224aef48017aa82bb6174c7a659d724be0c75017b7e64a55b4/numpy-2.5.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:f089d7b00756190aacf1f5d34bdf38c3c430ac82b4f868f8cede73380460fce7", size = 5453810, upload-time = "2026-07-04T17:07:37.495Z" }, + { url = "https://files.pythonhosted.org/packages/20/c9/3474309bc94d634d3f9c3eddf03250ecb8c22cd948ef16fef69a77cc5d7b/numpy-2.5.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:09e9bfd8d2cf479c7d174804fb3811c53a8e9f20a37444008606b57d6b7a826d", size = 6761189, upload-time = "2026-07-04T17:07:39.563Z" }, + { url = "https://files.pythonhosted.org/packages/90/8a/558ae39fdd55d7e7f7fef9a84a6e964ac6b23edbd2a07e52bb084500507d/numpy-2.5.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e68d8dd1e7eba712948f2053a29ec86917bc70ba1358df869d9f06649ef9cf09", size = 15225039, upload-time = "2026-07-04T17:07:41.682Z" }, + { url = "https://files.pythonhosted.org/packages/63/27/ca7392b2d030277bdf0273e7d23255b3ee57d57a7c170a6f4fb3981e1e5d/numpy-2.5.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:99d5095fa265a0c4152e7bb12759e14381ef5496152f1ce58f44bdf55c44beb4", size = 16701306, upload-time = "2026-07-04T17:07:44.611Z" }, + { url = "https://files.pythonhosted.org/packages/02/42/03d53ae7996c44d4374a8262e9dc41671fd56cbb98f7d47ef85cf5da4c6b/numpy-2.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ab87a91b3cc3382b8956095bd8f95e00cf679bb81554339be1a2ba404a1473c1", size = 16589955, upload-time = "2026-07-04T17:07:47.694Z" }, + { url = "https://files.pythonhosted.org/packages/7b/15/6c1784ae469640e65db111e9a34b3d0f14d91e8a38b9ce34810ced370dbb/numpy-2.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:224ca51130ef7da85bea2191625181cb4f337f9cb64b471f10c1a12aa8b60077", size = 18464252, upload-time = "2026-07-04T17:07:50.684Z" }, + { url = "https://files.pythonhosted.org/packages/94/a8/f98e50356cf167df656c526c2dfeec2d7dde182f2a3da4b458a5938e2776/numpy-2.5.1-cp314-cp314t-win32.whl", hash = "sha256:6eab239876581b2b3c5a242281b6007bbdbcd1c7085d7709bb57c5929b11e6bf", size = 6263298, upload-time = "2026-07-04T17:07:53.445Z" }, + { url = "https://files.pythonhosted.org/packages/72/ac/96ae880cdecad0b3275d9359fcec72667b49a4863c9f12942e43679dda02/numpy-2.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:83ce9c80d5b521b0d77ddcbe5447c218d247929b6cc056ca5351342accfff0af", size = 12748623, upload-time = "2026-07-04T17:07:55.384Z" }, + { url = "https://files.pythonhosted.org/packages/a1/5a/4d2b1601df3602dba7a14f3348ba9bfe94a18adb428e693df6154c293831/numpy-2.5.1-cp314-cp314t-win_arm64.whl", hash = "sha256:5a6db61f9aaa57e369905c67d852045d3c4f7126405b29d09b19dec118e9c9cb", size = 10697674, upload-time = "2026-07-04T17:07:58.506Z" }, +] + +[[package]] +name = "openapi-pydantic" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/2e/58d83848dd1a79cb92ed8e63f6ba901ca282c5f09d04af9423ec26c56fd7/openapi_pydantic-0.5.1.tar.gz", hash = "sha256:ff6835af6bde7a459fb93eb93bb92b8749b754fc6e51b2f1590a19dc3005ee0d", size = 60892, upload-time = "2025-01-08T19:29:27.083Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/cf/03675d8bd8ecbf4445504d8071adab19f5f993676795708e36402ab38263/openapi_pydantic-0.5.1-py3-none-any.whl", hash = "sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146", size = 96381, upload-time = "2025-01-08T19:29:25.275Z" }, +] + +[[package]] +name = "openbb-core" +version = "2.0.0" +source = { editable = "../../core" } +dependencies = [ + { name = "aiohttp" }, + { name = "fastapi" }, + { name = "importlib-metadata" }, + { name = "pydantic" }, + { name = "pyjwt" }, + { name = "python-dotenv" }, + { name = "python-multipart" }, + { name = "requests" }, + { name = "ruff" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "uuid7" }, + { name = "uvicorn" }, + { name = "websockets" }, +] + +[package.optional-dependencies] +pandas = [ + { name = "pandas", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "pandas", version = "3.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] + +[package.metadata] +requires-dist = [ + { name = "aiohttp", specifier = ">=3.13.3" }, + { name = "fastapi", specifier = ">=0.136.3" }, + { name = "importlib-metadata", specifier = ">=6.8.0" }, + { name = "pandas", marker = "extra == 'pandas'", specifier = ">=1.5.3" }, + { name = "pydantic", specifier = ">=2.12.3,<3.0.0" }, + { name = "pyjwt", specifier = ">=2.13.0" }, + { name = "python-dotenv", specifier = ">=1.0.0" }, + { name = "python-multipart", specifier = ">=0.0.29" }, + { name = "requests", specifier = ">=2.34.2" }, + { name = "ruff", specifier = ">=0.15,<0.16" }, + { name = "tomli", marker = "python_full_version < '3.11'", specifier = ">=2.0.0" }, + { name = "uuid7", specifier = ">=0.1.0" }, + { name = "uvicorn", specifier = ">=0.48.0" }, + { name = "websockets", specifier = ">=15.0" }, +] +provides-extras = ["pandas"] + +[package.metadata.requires-dev] +dev = [{ name = "openbb-devtools", editable = "../../extensions/devtools" }] + +[[package]] +name = "openbb-devtools" +version = "2.0.0" +source = { editable = "../../extensions/devtools" } +dependencies = [ + { name = "aiohttp" }, + { name = "codespell" }, + { name = "ipykernel" }, + { name = "pre-commit" }, + { name = "pydocstyle" }, + { name = "pytest" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, + { name = "pytest-freezer" }, + { name = "pytest-order" }, + { name = "pytest-recorder" }, + { name = "pytest-subtests" }, + { name = "ruff" }, + { name = "tox" }, + { name = "ty" }, + { name = "types-python-dateutil" }, + { name = "types-requests" }, + { name = "types-toml" }, +] + +[package.metadata] +requires-dist = [ + { name = "aiohttp", specifier = "<3.14" }, + { name = "codespell", specifier = ">=2.2.5,<3.0.0" }, + { name = "ipykernel", specifier = ">=6.30.1" }, + { name = "pre-commit", specifier = ">=3.5.0,<4.0.0" }, + { name = "pydocstyle", specifier = ">=6.3.0,<7.0.0" }, + { name = "pytest", specifier = ">=9.0.3" }, + { name = "pytest-asyncio", specifier = ">=1.3.0,<2.0.0" }, + { name = "pytest-cov", specifier = ">=4.1.0,<5.0.0" }, + { name = "pytest-freezer", specifier = ">=0.4.9,<1.0.0" }, + { name = "pytest-order", specifier = ">=1.3.0,<2.0.0" }, + { name = "pytest-recorder", specifier = ">=0.6.5" }, + { name = "pytest-subtests", specifier = ">=0.11.0,<1.0.0" }, + { name = "ruff", specifier = ">=0.15,<0.16" }, + { name = "tox", specifier = ">=4.11.3,<5.0.0" }, + { name = "ty", specifier = ">=0.0.40" }, + { name = "types-python-dateutil", specifier = ">=2.8.19.14,<3.0.0" }, + { name = "types-requests", specifier = ">=2.32,<3.0.0" }, + { name = "types-toml", specifier = ">=0.10.8.7,<1.0.0" }, +] + +[[package]] +name = "openbb-platform-api" +version = "2.0.0" +source = { editable = "../../extensions/platform_api" } +dependencies = [ + { name = "deepdiff" }, + { name = "openbb-core" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] + +[package.metadata] +requires-dist = [ + { name = "deepdiff", specifier = ">=8.6.2" }, + { name = "openbb-core", editable = "../../core" }, + { name = "tomli", marker = "python_full_version < '3.11'", specifier = ">=2.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "httpx", specifier = ">=0.28.0,<1.0.0" }, + { name = "openbb-devtools", editable = "../../extensions/devtools" }, +] + +[[package]] +name = "openbb-us-eia" +version = "2.0.0" +source = { editable = "." } +dependencies = [ + { name = "async-lru" }, + { name = "curl-cffi" }, + { name = "fastmcp" }, + { name = "feedparser" }, + { name = "openbb-core", extra = ["pandas"] }, + { name = "openpyxl" }, + { name = "xlrd" }, +] + +[package.dev-dependencies] +dev = [ + { name = "openbb-devtools" }, + { name = "openbb-platform-api" }, +] + +[package.metadata] +requires-dist = [ + { name = "async-lru", specifier = ">=2" }, + { name = "curl-cffi", specifier = ">=0.7" }, + { name = "fastmcp", specifier = ">=2.0" }, + { name = "feedparser", specifier = ">=6.0" }, + { name = "openbb-core", extras = ["pandas"], editable = "../../core" }, + { name = "openpyxl", specifier = ">=3.1.5" }, + { name = "xlrd", specifier = ">=2.0.1" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "openbb-devtools", editable = "../../extensions/devtools" }, + { name = "openbb-platform-api", editable = "../../extensions/platform_api" }, +] + +[[package]] +name = "openpyxl" +version = "3.1.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "et-xmlfile" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/f9/88d94a75de065ea32619465d2f77b29a0469500e99012523b91cc4141cd1/openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050", size = 186464, upload-time = "2024-06-28T14:03:44.161Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/da/977ded879c29cbd04de313843e76868e6e13408a94ed6b987245dc7c8506/openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2", size = 250910, upload-time = "2024-06-28T14:03:41.161Z" }, +] + +[[package]] +name = "opentelemetry-api" +version = "1.44.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ee/8b/aa9e2d8b8dfa7c946f7dec5d1f8f6ba8eca062f43509a06bdb5ce93d26c0/opentelemetry_api-1.44.0.tar.gz", hash = "sha256:67647e5e9566edcf421166fdf022b3537f818635daa852b289e34604dc6fb33a", size = 72406, upload-time = "2026-07-16T15:25:32.678Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/6f/a04e900f465ff3221ccc395522503e2d10e79fa21f2723c8e177aae1e0d1/opentelemetry_api-1.44.0-py3-none-any.whl", hash = "sha256:94b98c893a91b88657eaac1e3ba89618cdb85be6918196705354f34728b2cdef", size = 60018, upload-time = "2026-07-16T15:25:11.657Z" }, +] + +[[package]] +name = "orderly-set" +version = "5.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4a/88/39c83c35d5e97cc203e9e77a4f93bf87ec89cf6a22ac4818fdcc65d66584/orderly_set-5.5.0.tar.gz", hash = "sha256:e87185c8e4d8afa64e7f8160ee2c542a475b738bc891dc3f58102e654125e6ce", size = 27414, upload-time = "2025-07-10T20:10:55.885Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/27/fb8d7338b4d551900fa3e580acbe7a0cf655d940e164cb5c00ec31961094/orderly_set-5.5.0-py3-none-any.whl", hash = "sha256:46f0b801948e98f427b412fcabb831677194c05c3b699b80de260374baa0b1e7", size = 13068, upload-time = "2025-07-10T20:10:54.377Z" }, +] + +[[package]] +name = "packaging" +version = "26.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, +] + +[[package]] +name = "pandas" +version = "2.3.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +dependencies = [ + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "python-dateutil", marker = "python_full_version < '3.11'" }, + { name = "pytz", marker = "python_full_version < '3.11'" }, + { name = "tzdata", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/f7/f425a00df4fcc22b292c6895c6831c0c8ae1d9fac1e024d16f98a9ce8749/pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c", size = 11555763, upload-time = "2025-09-29T23:16:53.287Z" }, + { url = "https://files.pythonhosted.org/packages/13/4f/66d99628ff8ce7857aca52fed8f0066ce209f96be2fede6cef9f84e8d04f/pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a", size = 10801217, upload-time = "2025-09-29T23:17:04.522Z" }, + { url = "https://files.pythonhosted.org/packages/1d/03/3fc4a529a7710f890a239cc496fc6d50ad4a0995657dccc1d64695adb9f4/pandas-2.3.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1", size = 12148791, upload-time = "2025-09-29T23:17:18.444Z" }, + { url = "https://files.pythonhosted.org/packages/40/a8/4dac1f8f8235e5d25b9955d02ff6f29396191d4e665d71122c3722ca83c5/pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838", size = 12769373, upload-time = "2025-09-29T23:17:35.846Z" }, + { url = "https://files.pythonhosted.org/packages/df/91/82cc5169b6b25440a7fc0ef3a694582418d875c8e3ebf796a6d6470aa578/pandas-2.3.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250", size = 13200444, upload-time = "2025-09-29T23:17:49.341Z" }, + { url = "https://files.pythonhosted.org/packages/10/ae/89b3283800ab58f7af2952704078555fa60c807fff764395bb57ea0b0dbd/pandas-2.3.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4", size = 13858459, upload-time = "2025-09-29T23:18:03.722Z" }, + { url = "https://files.pythonhosted.org/packages/85/72/530900610650f54a35a19476eca5104f38555afccda1aa11a92ee14cb21d/pandas-2.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826", size = 11346086, upload-time = "2025-09-29T23:18:18.505Z" }, + { url = "https://files.pythonhosted.org/packages/c1/fa/7ac648108144a095b4fb6aa3de1954689f7af60a14cf25583f4960ecb878/pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523", size = 11578790, upload-time = "2025-09-29T23:18:30.065Z" }, + { url = "https://files.pythonhosted.org/packages/9b/35/74442388c6cf008882d4d4bdfc4109be87e9b8b7ccd097ad1e7f006e2e95/pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45", size = 10833831, upload-time = "2025-09-29T23:38:56.071Z" }, + { url = "https://files.pythonhosted.org/packages/fe/e4/de154cbfeee13383ad58d23017da99390b91d73f8c11856f2095e813201b/pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66", size = 12199267, upload-time = "2025-09-29T23:18:41.627Z" }, + { url = "https://files.pythonhosted.org/packages/bf/c9/63f8d545568d9ab91476b1818b4741f521646cbdd151c6efebf40d6de6f7/pandas-2.3.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b", size = 12789281, upload-time = "2025-09-29T23:18:56.834Z" }, + { url = "https://files.pythonhosted.org/packages/f2/00/a5ac8c7a0e67fd1a6059e40aa08fa1c52cc00709077d2300e210c3ce0322/pandas-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791", size = 13240453, upload-time = "2025-09-29T23:19:09.247Z" }, + { url = "https://files.pythonhosted.org/packages/27/4d/5c23a5bc7bd209231618dd9e606ce076272c9bc4f12023a70e03a86b4067/pandas-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151", size = 13890361, upload-time = "2025-09-29T23:19:25.342Z" }, + { url = "https://files.pythonhosted.org/packages/8e/59/712db1d7040520de7a4965df15b774348980e6df45c129b8c64d0dbe74ef/pandas-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c", size = 11348702, upload-time = "2025-09-29T23:19:38.296Z" }, + { url = "https://files.pythonhosted.org/packages/9c/fb/231d89e8637c808b997d172b18e9d4a4bc7bf31296196c260526055d1ea0/pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53", size = 11597846, upload-time = "2025-09-29T23:19:48.856Z" }, + { url = "https://files.pythonhosted.org/packages/5c/bd/bf8064d9cfa214294356c2d6702b716d3cf3bb24be59287a6a21e24cae6b/pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35", size = 10729618, upload-time = "2025-09-29T23:39:08.659Z" }, + { url = "https://files.pythonhosted.org/packages/57/56/cf2dbe1a3f5271370669475ead12ce77c61726ffd19a35546e31aa8edf4e/pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908", size = 11737212, upload-time = "2025-09-29T23:19:59.765Z" }, + { url = "https://files.pythonhosted.org/packages/e5/63/cd7d615331b328e287d8233ba9fdf191a9c2d11b6af0c7a59cfcec23de68/pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89", size = 12362693, upload-time = "2025-09-29T23:20:14.098Z" }, + { url = "https://files.pythonhosted.org/packages/a6/de/8b1895b107277d52f2b42d3a6806e69cfef0d5cf1d0ba343470b9d8e0a04/pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98", size = 12771002, upload-time = "2025-09-29T23:20:26.76Z" }, + { url = "https://files.pythonhosted.org/packages/87/21/84072af3187a677c5893b170ba2c8fbe450a6ff911234916da889b698220/pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084", size = 13450971, upload-time = "2025-09-29T23:20:41.344Z" }, + { url = "https://files.pythonhosted.org/packages/86/41/585a168330ff063014880a80d744219dbf1dd7a1c706e75ab3425a987384/pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b", size = 10992722, upload-time = "2025-09-29T23:20:54.139Z" }, + { url = "https://files.pythonhosted.org/packages/cd/4b/18b035ee18f97c1040d94debd8f2e737000ad70ccc8f5513f4eefad75f4b/pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713", size = 11544671, upload-time = "2025-09-29T23:21:05.024Z" }, + { url = "https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8", size = 10680807, upload-time = "2025-09-29T23:21:15.979Z" }, + { url = "https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d", size = 11709872, upload-time = "2025-09-29T23:21:27.165Z" }, + { url = "https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac", size = 12306371, upload-time = "2025-09-29T23:21:40.532Z" }, + { url = "https://files.pythonhosted.org/packages/33/81/a3afc88fca4aa925804a27d2676d22dcd2031c2ebe08aabd0ae55b9ff282/pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c", size = 12765333, upload-time = "2025-09-29T23:21:55.77Z" }, + { url = "https://files.pythonhosted.org/packages/8d/0f/b4d4ae743a83742f1153464cf1a8ecfafc3ac59722a0b5c8602310cb7158/pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493", size = 13418120, upload-time = "2025-09-29T23:22:10.109Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c7/e54682c96a895d0c808453269e0b5928a07a127a15704fedb643e9b0a4c8/pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee", size = 10993991, upload-time = "2025-09-29T23:25:04.889Z" }, + { url = "https://files.pythonhosted.org/packages/f9/ca/3f8d4f49740799189e1395812f3bf23b5e8fc7c190827d55a610da72ce55/pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5", size = 12048227, upload-time = "2025-09-29T23:22:24.343Z" }, + { url = "https://files.pythonhosted.org/packages/0e/5a/f43efec3e8c0cc92c4663ccad372dbdff72b60bdb56b2749f04aa1d07d7e/pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21", size = 11411056, upload-time = "2025-09-29T23:22:37.762Z" }, + { url = "https://files.pythonhosted.org/packages/46/b1/85331edfc591208c9d1a63a06baa67b21d332e63b7a591a5ba42a10bb507/pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78", size = 11645189, upload-time = "2025-09-29T23:22:51.688Z" }, + { url = "https://files.pythonhosted.org/packages/44/23/78d645adc35d94d1ac4f2a3c4112ab6f5b8999f4898b8cdf01252f8df4a9/pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110", size = 12121912, upload-time = "2025-09-29T23:23:05.042Z" }, + { url = "https://files.pythonhosted.org/packages/53/da/d10013df5e6aaef6b425aa0c32e1fc1f3e431e4bcabd420517dceadce354/pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86", size = 12712160, upload-time = "2025-09-29T23:23:28.57Z" }, + { url = "https://files.pythonhosted.org/packages/bd/17/e756653095a083d8a37cbd816cb87148debcfcd920129b25f99dd8d04271/pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc", size = 13199233, upload-time = "2025-09-29T23:24:24.876Z" }, + { url = "https://files.pythonhosted.org/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0", size = 11540635, upload-time = "2025-09-29T23:25:52.486Z" }, + { url = "https://files.pythonhosted.org/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593", size = 10759079, upload-time = "2025-09-29T23:26:33.204Z" }, + { url = "https://files.pythonhosted.org/packages/ca/05/d01ef80a7a3a12b2f8bbf16daba1e17c98a2f039cbc8e2f77a2c5a63d382/pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c", size = 11814049, upload-time = "2025-09-29T23:27:15.384Z" }, + { url = "https://files.pythonhosted.org/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b", size = 12332638, upload-time = "2025-09-29T23:27:51.625Z" }, + { url = "https://files.pythonhosted.org/packages/c5/33/dd70400631b62b9b29c3c93d2feee1d0964dc2bae2e5ad7a6c73a7f25325/pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6", size = 12886834, upload-time = "2025-09-29T23:28:21.289Z" }, + { url = "https://files.pythonhosted.org/packages/d3/18/b5d48f55821228d0d2692b34fd5034bb185e854bdb592e9c640f6290e012/pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3", size = 13409925, upload-time = "2025-09-29T23:28:58.261Z" }, + { url = "https://files.pythonhosted.org/packages/a6/3d/124ac75fcd0ecc09b8fdccb0246ef65e35b012030defb0e0eba2cbbbe948/pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5", size = 11109071, upload-time = "2025-09-29T23:32:27.484Z" }, + { url = "https://files.pythonhosted.org/packages/89/9c/0e21c895c38a157e0faa1fb64587a9226d6dd46452cac4532d80c3c4a244/pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec", size = 12048504, upload-time = "2025-09-29T23:29:31.47Z" }, + { url = "https://files.pythonhosted.org/packages/d7/82/b69a1c95df796858777b68fbe6a81d37443a33319761d7c652ce77797475/pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7", size = 11410702, upload-time = "2025-09-29T23:29:54.591Z" }, + { url = "https://files.pythonhosted.org/packages/f9/88/702bde3ba0a94b8c73a0181e05144b10f13f29ebfc2150c3a79062a8195d/pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450", size = 11634535, upload-time = "2025-09-29T23:30:21.003Z" }, + { url = "https://files.pythonhosted.org/packages/a4/1e/1bac1a839d12e6a82ec6cb40cda2edde64a2013a66963293696bbf31fbbb/pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5", size = 12121582, upload-time = "2025-09-29T23:30:43.391Z" }, + { url = "https://files.pythonhosted.org/packages/44/91/483de934193e12a3b1d6ae7c8645d083ff88dec75f46e827562f1e4b4da6/pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788", size = 12699963, upload-time = "2025-09-29T23:31:10.009Z" }, + { url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" }, +] + +[[package]] +name = "pandas" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.15' and sys_platform == 'win32'", + "python_full_version == '3.14.*' and sys_platform == 'win32'", + "python_full_version >= '3.15' and sys_platform == 'emscripten'", + "python_full_version == '3.14.*' and sys_platform == 'emscripten'", + "python_full_version >= '3.15' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.14.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", +] +dependencies = [ + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, + { name = "numpy", version = "2.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "python-dateutil", marker = "python_full_version >= '3.11'" }, + { name = "tzdata", marker = "(python_full_version >= '3.11' and sys_platform == 'emscripten') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/87/4341c6252d1c47b08768c3d25ac487362bf403f0313ddae4a2a26c9b1b4c/pandas-3.0.3.tar.gz", hash = "sha256:696a4a00a2a2a35d4e5deb3fc946641b96c944f02230e4f76137fe35d806c4fc", size = 4651414, upload-time = "2026-05-11T18:54:29.21Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/16/b5c76b838fd9bf6ce84d3a53346b8874ec05c5f0040d75ef2c320100cd2a/pandas-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:455f6f8139d4282188f526868dbc3c828470e88a3d9d59a891bd46a455f21b98", size = 10338495, upload-time = "2026-05-11T18:52:11.558Z" }, + { url = "https://files.pythonhosted.org/packages/5a/b0/a4ffc4ae74d2d822200dcc46898987d8eb6032d1e2b219cae39da6f5cbcc/pandas-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4e15135e2ee5df1063313e2425ceef8ac0f4ae775893815b0923651b806a5639", size = 9938250, upload-time = "2026-05-11T18:52:17.005Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b2/3323601a52caee42c019e370090ca4544b241437240ca04f786cce82b0cf/pandas-3.0.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:05f1f1752b8533ea03f7f39a9c15b1a058d067bb48f4748948e7a8691e0510f2", size = 10770558, upload-time = "2026-05-11T18:52:19.865Z" }, + { url = "https://files.pythonhosted.org/packages/32/f1/bbecd2f867b97abebe0f9b53d750f862251b40337e061b36676ded3d920f/pandas-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a1e45c80cceb3b4a21bc5939d52e8cbd8d9b7305309219d59e9754d9ce09e27", size = 11274611, upload-time = "2026-05-11T18:52:22.622Z" }, + { url = "https://files.pythonhosted.org/packages/7f/4f/eafabf2d5fae5adf143b4d18d3706c5efdc368a7c4eb1ee8a3eddabbd0f6/pandas-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:14da8316da4d0c5a77618425996bfb1248ca87fc2c1486e6fde4652bd18b5824", size = 11784670, upload-time = "2026-05-11T18:52:25.4Z" }, + { url = "https://files.pythonhosted.org/packages/49/44/1eb20389301b57b19cc099a1c2f662501f72f08a65f912d05822613c1532/pandas-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a55066a0505dae0ba2b50a46637db34b46f9094c65c5d4800794ef6335010938", size = 12353708, upload-time = "2026-05-11T18:52:28.139Z" }, + { url = "https://files.pythonhosted.org/packages/eb/62/c321f13b5ba1819fc8dca456c7fce578da2dcfecff1abbf0eaddf8406c0f/pandas-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6674ab18ad8c57802867264b00e15e7bb904700cdd9046e3b2fa1fce237439ea", size = 9907609, upload-time = "2026-05-11T18:52:30.982Z" }, + { url = "https://files.pythonhosted.org/packages/53/85/1b7f563ebc6357c27233a02a96b589bcce1fa9c6eb89fb4f0e56421d277e/pandas-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:5cc09a68b3120e0f54870dede8287a7bb1fa463907e4fcec1ea77cab6179bf7a", size = 9165596, upload-time = "2026-05-11T18:52:33.334Z" }, + { url = "https://files.pythonhosted.org/packages/24/f1/392f8c5bfc16f66a0d2d41561c01627c228fe7ed2a0d056ef11315042570/pandas-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fed2ff7fd9779120e388e285fc029bd5cf9490cdd2e4166a9ee22c0e49a9ab09", size = 10357846, upload-time = "2026-05-11T18:52:36.143Z" }, + { url = "https://files.pythonhosted.org/packages/cf/3d/b16412745651e855f357e5e66930248688378853a6e2698a214e331fba1f/pandas-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b168fc218fd80a6cbdbdbc1a97ddc7889ed057d7eb45f50d866ceab5f39904c4", size = 9899550, upload-time = "2026-05-11T18:52:38.976Z" }, + { url = "https://files.pythonhosted.org/packages/31/a8/fa2535168fffcedf67f4f6de28d2dd903a747ca7c8ea6989451aaeb3a92f/pandas-3.0.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0383c72c75cdcca61a9e116e611143902dbfd08bff356829c2f6d1cf40a9ca8c", size = 10412965, upload-time = "2026-05-11T18:52:41.915Z" }, + { url = "https://files.pythonhosted.org/packages/65/b6/09b01cdbc15224e2850365192d17b7bdebb8bdbd8780ed221fcdf0d9a515/pandas-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6dc0b3fd2169c9157deed50b4d519553a3655c8c6a96027136d654592be973a9", size = 10894600, upload-time = "2026-05-11T18:52:45.02Z" }, + { url = "https://files.pythonhosted.org/packages/c9/a4/2eb28f2fccb4ced4a2c79ab2a5dee9ade1ebf44922ebad6fea158c9f95d4/pandas-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e65d5407dc0b394f509699650e4a2ec01c0514f21850f453fa60f3be79a5dbf", size = 11422824, upload-time = "2026-05-11T18:52:48.058Z" }, + { url = "https://files.pythonhosted.org/packages/f8/45/830bb57f533a4604b355e07edcb8ea18cf88b5f94e5fca92f27052d7c597/pandas-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f8894dc474d648fe7b6ff0ca9b0bd73950d19952bc1a6534540762c5d79d305c", size = 11950889, upload-time = "2026-05-11T18:52:50.905Z" }, + { url = "https://files.pythonhosted.org/packages/b9/c5/fc1b368f303087d20e8c9bf3d6ceb186263cfac0ade735cd938538bea839/pandas-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:c7be265b62cef88e253a941e4698604973736dcfe242fdb5198f0f7bc473cdcc", size = 9755463, upload-time = "2026-05-11T18:52:53.386Z" }, + { url = "https://files.pythonhosted.org/packages/86/bd/fda8f9705b1b09c6ebe14bfc0fa0e4ec8584d54ea673628f157ff55131af/pandas-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:557409bc4178e70ee8d9ddb494798e51ebf6ea59330f6be22c51bab2a7db6c49", size = 9066158, upload-time = "2026-05-11T18:52:56.038Z" }, + { url = "https://files.pythonhosted.org/packages/c5/90/62d8302883c44308c477e222c3daf7c813a34c8e96985882fbd53d964352/pandas-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:67b3b64c11910cfa29f4e94a14d3bff9ee693b6fc76055e7cad549cee0aec5fa", size = 10331071, upload-time = "2026-05-11T18:52:58.838Z" }, + { url = "https://files.pythonhosted.org/packages/7f/ae/6a6493c783a101f165e4356953ba3c74d6f77f0042fa7d753da9dfbb640c/pandas-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:39436b377d56d2a2e52d0395bdbee171f01068e99af5250509aceeb929f765c7", size = 9875690, upload-time = "2026-05-11T18:53:01.431Z" }, + { url = "https://files.pythonhosted.org/packages/62/7c/5df8e9f56c69a2769fbe9382a5ef8f2658c007e376434e1e2cbb57ad895f/pandas-3.0.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4be06d68f9ddcfc645b87534911da79a8fbffc7573c80e0edcf42a5020624d8", size = 10381634, upload-time = "2026-05-11T18:53:04.393Z" }, + { url = "https://files.pythonhosted.org/packages/99/68/1237369725aa617bb358263d535803e3053fdbc593513ec5ed9c9896b5b6/pandas-3.0.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a4eeb6830daf35a71cc09649bd823e2b542dac246cdee9614c6e4bd65028cd6a", size = 10891243, upload-time = "2026-05-11T18:53:07.643Z" }, + { url = "https://files.pythonhosted.org/packages/25/93/77d108e8af7222b4a503ebde0e30215b1c2e4f8e53a526431890f22d5586/pandas-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1928e07221f82db493cd4af1e23c1bfca524a19a4699887975bff68f49a72bfb", size = 11388659, upload-time = "2026-05-11T18:53:10.634Z" }, + { url = "https://files.pythonhosted.org/packages/d0/bd/eff5b4399f332ac386c853f6cd2bd3fa2ca0061b9f36ecd9c4d7c4265649/pandas-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51b1fe551acb77dac643c6fda86084d8d446c10fe64b06a9cc29c4cc8540e7f2", size = 11942880, upload-time = "2026-05-11T18:53:13.536Z" }, + { url = "https://files.pythonhosted.org/packages/2c/20/559ace4200982c3887d0b86bfd0d856a2143ef8ddab63cc07934951a964c/pandas-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:a82d532a3351d435432cd913edbccaf8b8e01d4dd0e5ced5a8d2e8ecd94c7e44", size = 9757091, upload-time = "2026-05-11T18:53:16.306Z" }, + { url = "https://files.pythonhosted.org/packages/3a/66/69055a09fe200f29f922a3eeec4804611900b95f52d932ece3393c3c0c19/pandas-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:275c14e0fce14a2ec20eee474aecd305478ea3c1e6f6a9d8fe219a165542717e", size = 9057282, upload-time = "2026-05-11T18:53:18.768Z" }, + { url = "https://files.pythonhosted.org/packages/57/0e/efe801b0e6811e8e650cd21b7f2608e30f08a7067e2bf6e8752b0d56ee3c/pandas-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:46997386d528eb40376ecd6b033cf4a8a1e5282580f68f43de875b78cba2199d", size = 10767016, upload-time = "2026-05-11T18:53:21.227Z" }, + { url = "https://files.pythonhosted.org/packages/ea/dc/eb55135a1d5f0f0519f28da1f609a206d2cad1f9c35c32d51e38dd7261ae/pandas-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:261e308dfb22448384b7580cf719d2f998fe2966c92893c3e77d14008af1f066", size = 10420210, upload-time = "2026-05-11T18:53:23.982Z" }, + { url = "https://files.pythonhosted.org/packages/c6/3e/b1d5d955ce33ffecb407465a60bc32769d74fcf68224b7ae67ae11d4dea4/pandas-3.0.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dd1a5d1def6a46002e964510bdc67c368aa0951df5d1d9f8365336f5a1f490cd", size = 10336126, upload-time = "2026-05-11T18:53:26.731Z" }, + { url = "https://files.pythonhosted.org/packages/f5/76/a01261711ab60a22d71b862f0de20e4c504bf80457270ad8cb42110f6abc/pandas-3.0.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d72828c20c6d6e83e1e22a6a3b47b326b71664112fa9705dcbccfd7a39b62085", size = 10728051, upload-time = "2026-05-11T18:53:29.125Z" }, + { url = "https://files.pythonhosted.org/packages/e9/21/ea191195e587b18cf682e97f433f81b2d0fbe341380e80a3e0d6e4403c8e/pandas-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d26cbe1fcfc12e8fd900e2454163e466b2d3af84f7c75481df7683ffc073d870", size = 11350796, upload-time = "2026-05-11T18:53:32.056Z" }, + { url = "https://files.pythonhosted.org/packages/64/69/f0eaaf54939f0e8c6768fd06be9af2cef9b36048b96dfb9e1b2c685a807e/pandas-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3e91cec1879ada0624fc3dc9953c5cbd60208e59c0db28f540c5d6d47502422f", size = 11799741, upload-time = "2026-05-11T18:53:34.985Z" }, + { url = "https://files.pythonhosted.org/packages/45/a4/865e0e510cae5fc2194de4db28be638952de942571ba9125934fd9c01d47/pandas-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:08d789b41f87e0905880e293cedf6197ce71fe67cc081358b1e148a491b9bd13", size = 10499958, upload-time = "2026-05-11T18:53:37.857Z" }, + { url = "https://files.pythonhosted.org/packages/86/54/effdcc3c0ff7a08037889200e148ebe94c16c4f653be078c7b3675955df1/pandas-3.0.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:3650109c0f22879df8bd6179ab9ee3d7f1d1d4e7e0094a3f0032d9f51e2e64ac", size = 10336065, upload-time = "2026-05-11T18:53:41.099Z" }, + { url = "https://files.pythonhosted.org/packages/68/10/bf2d6738d72748b961a3751ab89522d58c54efc36a8e1a12161216cd45cf/pandas-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:bab900348131a7db1f69a7309ef141fd5680f1487094193bcbbb61791573bf8f", size = 9926101, upload-time = "2026-05-11T18:53:43.515Z" }, + { url = "https://files.pythonhosted.org/packages/ae/e9/e35cf11c8a136e757b956f5f0efdcaa50aecde85ea055f1898dfc68262f3/pandas-3.0.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba7e08b9ac1d54569cd1e256e3668975ed624d6826f7b68df0342b012007bddb", size = 10457553, upload-time = "2026-05-11T18:53:46.394Z" }, + { url = "https://files.pythonhosted.org/packages/58/3b/1cdec6772bdbaf7b25dab360c59f03cadf05492dd724c6540af905389b07/pandas-3.0.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d71c63ae4ebdbf70209742096f1fc46a83a0613c99d4b23766cced9ff8cd62a", size = 10914065, upload-time = "2026-05-11T18:53:49.134Z" }, + { url = "https://files.pythonhosted.org/packages/c4/c2/1ef644445fcd72e3627bceec77e3560636f87ddce4ed841afe76b83b5bf9/pandas-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e3a2ec42c98ffa2565a67e08e218d06d72576d758d90facb7c00805194d8f360", size = 11459188, upload-time = "2026-05-11T18:53:52.527Z" }, + { url = "https://files.pythonhosted.org/packages/7e/49/4d8d4f42cbc9c4adc7a1870f269c02cbd6cd40d059622c06fb298addcbad/pandas-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:335f62418ed562cfc3c49e9e196375c28b729dcef8543abf4f9438e381bf3c76", size = 11982966, upload-time = "2026-05-11T18:53:55.043Z" }, + { url = "https://files.pythonhosted.org/packages/38/55/792619469bab9882d8bbd5865d45a72f6478762d04a9af4bf0d08c503e95/pandas-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:3c20a521bbb85902f79f7270c80a59e1b5452d96d170c034f207181870f97ac5", size = 9876755, upload-time = "2026-05-11T18:53:58.067Z" }, + { url = "https://files.pythonhosted.org/packages/2a/af/33c469653b0ba03b50c3a98192d4c07f0c75c66b263ceb097fce0ee97d31/pandas-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:a2d2dff8a04f3917b55ab3910c32990f8ddf7eceba114947838cefa976a68977", size = 9198658, upload-time = "2026-05-11T18:54:00.733Z" }, + { url = "https://files.pythonhosted.org/packages/a2/fa/b8c257bd76b8bd060c3a9151c1fca05e9b9c5e3af5d0f549c0356f6d143d/pandas-3.0.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:0d589105b3c14645af1738ff279b2995102d8f7a03b0a66dc8d95550eb513e04", size = 10787242, upload-time = "2026-05-11T18:54:03.564Z" }, + { url = "https://files.pythonhosted.org/packages/54/eb/f19206ffb0bf1919002969aa448b4702c6594845156a6f8050674855aac3/pandas-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:13fc1e853d9e04743d11ba75a985ccbc2a317fe07d8af61e445a6fd24dacd6a6", size = 10436369, upload-time = "2026-05-11T18:54:06.311Z" }, + { url = "https://files.pythonhosted.org/packages/fd/24/c7c39fb4fe22b71a0c2d78bf0c585c600092d85f94f086d2b3b2f6ca27e2/pandas-3.0.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:819959dab7bbd0049c15623fbac4e29a191b9528160a61fb1032242d8ced2d9c", size = 10358306, upload-time = "2026-05-11T18:54:09.085Z" }, + { url = "https://files.pythonhosted.org/packages/16/ec/dd2a9eb7fa1204df88c0864164e35b228ac581062ac612ba0a67fd812e4c/pandas-3.0.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:60ae316d3fd75d1858d450d0db0103ea2be3e7d4a95ec2f064f7e2ae63f7b028", size = 10758394, upload-time = "2026-05-11T18:54:11.956Z" }, + { url = "https://files.pythonhosted.org/packages/95/6e/00c61ea8e85b4f6d8d35e11852a1a4998fc7fafc91c6a602d1cc9c972d64/pandas-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd3a518890b400d32f9023722dc9a9a5c969f00b415419a3c06c043f09bb5d7d", size = 11375717, upload-time = "2026-05-11T18:54:14.539Z" }, + { url = "https://files.pythonhosted.org/packages/31/89/8fc1c268969fac43688d65fd92e67df24bd128d53cb4d2eee534cd307399/pandas-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9c39be2d709d01fa972a0cabc522389fceca4f3969332ba25a7d6c5802cf976a", size = 11828897, upload-time = "2026-05-11T18:54:17.146Z" }, + { url = "https://files.pythonhosted.org/packages/56/3b/e7d20dea247a3e6dc0bd8a6953854afbedc03951def4e7371e05e7263e25/pandas-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4db8c527972a821cf5286b40ccc57642a39bc62e62022b42f99f8a67fca8c3a1", size = 10900855, upload-time = "2026-05-11T18:54:19.72Z" }, + { url = "https://files.pythonhosted.org/packages/0f/54/68a0978d1ef8502b8492099beaa6e7a0c1b32e3b5d4f677f5810cb08711c/pandas-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b2c95f8bfc1ee412bf482605d7bfd30c12d1d26bd59fdd91efeef1d4718decb1", size = 9466464, upload-time = "2026-05-11T18:54:22.754Z" }, +] + +[[package]] +name = "parso" +version = "0.8.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/4b/90c937815137d43ce71ba043cd3566221e9df6b9c805f24b5d138c9d40a7/parso-0.8.7.tar.gz", hash = "sha256:eaaac4c9fdd5e9e8852dc778d2d7405897ec510f2a298071453e5e3a07914bb1", size = 401824, upload-time = "2026-05-01T23:13:02.138Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/5d/8268b644392ee874ee82a635cd0df1773de230bde356c38de28e298392cc/parso-0.8.7-py2.py3-none-any.whl", hash = "sha256:a8926eb2a1b915486941fdbd31e86a4baf88fe8c210f25f2f35ecec5b574ca1c", size = 107025, upload-time = "2026-05-01T23:12:58.867Z" }, +] + +[[package]] +name = "pathable" +version = "0.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/66/f3/5a20387de9bcd0607871bfc2198ee0e15836da7baa4592ccd7f24c27c986/pathable-0.6.0.tar.gz", hash = "sha256:6404b8b82aef5ff0fd478934137128b99b12212ba35afdde5525ca4f8388ea58", size = 18970, upload-time = "2026-05-19T18:15:11.911Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/e8/6d75ffd9784bce2e93d1ae4415649427e39a53bb172d4672b2b59c6f0a7b/pathable-0.6.0-py3-none-any.whl", hash = "sha256:82c4ca6c98c502ad12e0d4e9779b6210afee93c38990988c8c5d1b49bdcdf566", size = 18983, upload-time = "2026-05-19T18:15:10.728Z" }, +] + +[[package]] +name = "pathspec" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/82/42f767fc1c1143d6fd36efb827202a2d997a375e160a71eb2888a925aac1/pathspec-1.1.1.tar.gz", hash = "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a", size = 135180, upload-time = "2026-04-27T01:46:08.907Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189", size = 57328, upload-time = "2026-04-27T01:46:07.06Z" }, +] + +[[package]] +name = "pexpect" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess", marker = "(python_full_version < '3.11' and sys_platform == 'emscripten') or (python_full_version < '3.11' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/47/e4501f49c178ae1d9f4a75073fda4204f52647993f075a9db4d14930e0c5/platformdirs-4.10.0.tar.gz", hash = "sha256:31e761a6a0ca04faf7353ea759bdba55652be214725111e5aac52dfa29d4bef7", size = 31224, upload-time = "2026-05-28T03:32:53.587Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/e6/cd9575ac904136b3cbf7aa7ee819ef86eedb7274e46f230e94ea4342e729/platformdirs-4.10.0-py3-none-any.whl", hash = "sha256:fb516cdb12eb0d857d0cd85a7c57cea4d060bee4578d6cf5a14dfdf8cbf8784a", size = 22743, upload-time = "2026-05-28T03:32:52.175Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "pre-commit" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cfgv" }, + { name = "identify" }, + { name = "nodeenv" }, + { name = "pyyaml" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/64/10/97ee2fa54dff1e9da9badbc5e35d0bbaef0776271ea5907eccf64140f72f/pre_commit-3.8.0.tar.gz", hash = "sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af", size = 177815, upload-time = "2024-07-28T19:59:01.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/92/caae8c86e94681b42c246f0bca35c059a2f0529e5b92619f6aba4cf7e7b6/pre_commit-3.8.0-py2.py3-none-any.whl", hash = "sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f", size = 204643, upload-time = "2024-07-28T19:58:59.335Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + +[[package]] +name = "propcache" +version = "0.5.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/44/c87281c333769159c50594f22610f77398a47ccbfbbf23074e744e86f87c/propcache-0.5.2.tar.gz", hash = "sha256:01c4fc7480cd0598bb4b57022df55b9ca296da7fc5a8760bd8451a7e63a7d427", size = 50208, upload-time = "2026-05-08T21:02:12.199Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/56/030b7b4719d53085722893e0009dffb9236aa10bca1b12121bdc5626ef16/propcache-0.5.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a81be28596d6559f6131ef33e10200de6e17643b3c74ce03f9eb103be6ae8b", size = 93417, upload-time = "2026-05-08T20:59:15.597Z" }, + { url = "https://files.pythonhosted.org/packages/1a/55/1140a8e067b8ec093a18a4ae7bb0045d9db65da38a08618ddc5e2f1994aa/propcache-0.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29cbaac5ea0212663e6845e04b5e188d5a6ae6dd919810ac835bf1d3b42c3f4c", size = 53847, upload-time = "2026-05-08T20:59:17.096Z" }, + { url = "https://files.pythonhosted.org/packages/20/42/0e7443c90310498561addf346e7d57fe3c6ba1914e1ba938b5464c7bbfd2/propcache-0.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6bf3be92233808fcd338eba0fb4d0b59ec5772af4f4ecfcec450d1bfc0f8b5eb", size = 53512, upload-time = "2026-05-08T20:59:18.64Z" }, + { url = "https://files.pythonhosted.org/packages/b7/db/cf51a71bab2009517d1a7f0ee07657e3bd446c4d69f67e6966cf17bcf956/propcache-0.5.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2f8ea531c794b9d6274acd4e8d2c2ebcac590a4361d27482edd3010b79f1325e", size = 58068, upload-time = "2026-05-08T20:59:20.683Z" }, + { url = "https://files.pythonhosted.org/packages/b7/43/39b6bdee9699fa1e1641c519feeb64a67e2a9f93bb465c70776b37a7333f/propcache-0.5.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:decfca4c79dd53ebab484b00cc4b6717d8c369f86e74aa4ca395a64ac651495e", size = 61020, upload-time = "2026-05-08T20:59:22.112Z" }, + { url = "https://files.pythonhosted.org/packages/26/0b/843726fbb0a29a8c5684fdb25971823638399f31e52e9d1f06a02dc9aa6b/propcache-0.5.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4621064bbf28fa77ff64dd5d94367c04684c67d3a5bf1dff25f0cd0d98a38f3b", size = 62732, upload-time = "2026-05-08T20:59:23.805Z" }, + { url = "https://files.pythonhosted.org/packages/39/6e/899fed76dc1942b8a64193a4f059d7f1a2c7ef65085e8a9366ed8ec0d199/propcache-0.5.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b96db7141a592cbc968daf1feea83a118e6ab378af4abbc72b248c895414c22d", size = 60140, upload-time = "2026-05-08T20:59:25.389Z" }, + { url = "https://files.pythonhosted.org/packages/ab/09/3da4be9b5b879219ad234aa535b3dd4a080ed1ad48d3a73ca07a9e798f22/propcache-0.5.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1ca071adabaab6e9219924bbe00af821f1ee7de113a9eca1cdc292de3d120f4d", size = 60400, upload-time = "2026-05-08T20:59:27.238Z" }, + { url = "https://files.pythonhosted.org/packages/60/2f/09b72b874a9aa0044faf52a69807a6ed618e267ceaa9ec4a63195fa5b504/propcache-0.5.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e4294d04a94dcab1b3bccd8b66d962dcad411a1d19414b2a41d1445f1de32ad0", size = 58155, upload-time = "2026-05-08T20:59:28.48Z" }, + { url = "https://files.pythonhosted.org/packages/8a/37/97489848c54c95578045473954f10956d619ce6a09e7ac137b71cdcb698b/propcache-0.5.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a0e399a2eccb91ed18721f86aa85757727400b6865c89e88934781deb9c8498b", size = 57037, upload-time = "2026-05-08T20:59:30.146Z" }, + { url = "https://files.pythonhosted.org/packages/22/db/6c695285ccfc49012743ee9c98212b8c5dd0aed7b63cfd816d4a0f7a1601/propcache-0.5.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:823581fd5cb08b12a48bfa11fe962a7916766b6170c17b028fbdf762b85eb9bf", size = 61103, upload-time = "2026-05-08T20:59:31.626Z" }, + { url = "https://files.pythonhosted.org/packages/98/a9/1e500401ca593b0bdb6bf75a70bc2d723835fd53360edff6af70692c7546/propcache-0.5.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:949c91d1a990cf3b2e8188dfcfb25005e0b834a06c63fa4ef9f360878ce21ecf", size = 60394, upload-time = "2026-05-08T20:59:32.829Z" }, + { url = "https://files.pythonhosted.org/packages/1f/87/f638b6e375eae0f30a1a2325d8b34fd85fdc785bb9960cf805f3bf1ec69a/propcache-0.5.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:cc1177027eda740fdb152706bd215a3f124e3eea15afc39f2cb9fe351b50619e", size = 63084, upload-time = "2026-05-08T20:59:35.964Z" }, + { url = "https://files.pythonhosted.org/packages/f6/18/884573f5d97b6d9eba68de759a82c901b7e39d7904d30f7b8d58d42d2a12/propcache-0.5.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b05d643f944a8c3c4bd86d65ffd87bf3264b617f87791940302bc474d2ff5274", size = 60999, upload-time = "2026-05-08T20:59:38.481Z" }, + { url = "https://files.pythonhosted.org/packages/8f/1a/c3915eb059ceec9e758a56e4cfd955292bc0f201be2176a46b76d94b303a/propcache-0.5.2-cp310-cp310-win32.whl", hash = "sha256:8114f28879e0904748e831c3a7774261bd9e75f49be089f389a76f959dcd13fe", size = 39036, upload-time = "2026-05-08T20:59:40.323Z" }, + { url = "https://files.pythonhosted.org/packages/5b/02/1dfd5607501a602d19c1c449d2d193b7d1c611f9246b4059026a1189a80e/propcache-0.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:5fcb98e7598b1ee0addab320d90f65b530297a867dbfe9de52ea838077e16e3d", size = 42190, upload-time = "2026-05-08T20:59:42.232Z" }, + { url = "https://files.pythonhosted.org/packages/57/93/f71588ad08b3e6f4b555b5ef215808a3c02b042d0151ad82fa6f15be677a/propcache-0.5.2-cp310-cp310-win_arm64.whl", hash = "sha256:04dc2390d9edbbaef7461f33322555976ffddf0b650a038649d026358714e6c5", size = 38545, upload-time = "2026-05-08T20:59:44.087Z" }, + { url = "https://files.pythonhosted.org/packages/e7/f1/8a8cc1c2c7e7934ab77e0163414f736fadbc0f5e8dd9673b952355ac175b/propcache-0.5.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:74b70780220e2dd89175ca24b81b68b67c83db499ae611e7f2313cb329801c78", size = 90744, upload-time = "2026-05-08T20:59:45.799Z" }, + { url = "https://files.pythonhosted.org/packages/c2/f4/651b1225e976bd1a2ba5cfba0c29d096581c2636b437e3a9a7ab6276270a/propcache-0.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4840ab0ae0216d952f4b53dc6d0b992bfc2bedbfe360bdd9b548bc184c08959", size = 52033, upload-time = "2026-05-08T20:59:47.408Z" }, + { url = "https://files.pythonhosted.org/packages/15/a8/8ede85d6aa1f79fc7dc2f8fd2c8d65920b8272c3892903c8a1affde48cfb/propcache-0.5.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c6844ba6364fb12f403928a82cfd295ab103a2b315c77c747b2dbe4a41894ea7", size = 52754, upload-time = "2026-05-08T20:59:49.202Z" }, + { url = "https://files.pythonhosted.org/packages/7d/fe/b3551b41bbc2f5b5bb088fc6920567cd43101253e68fbaa261339eb96fe1/propcache-0.5.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2293949b855ce597f2826452d17c2d545fb5622379c4ea6fdf525e9b8e8a2511", size = 57573, upload-time = "2026-05-08T20:59:50.778Z" }, + { url = "https://files.pythonhosted.org/packages/83/27/ab851ebd1b7172e3e161f5f8d39e315d54a91bea246f01f4d872d3376aef/propcache-0.5.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0fd59b5af35f74da48d905dcbad55449ba13be91823cb05a9bd590bbf5b61660", size = 60645, upload-time = "2026-05-08T20:59:52.227Z" }, + { url = "https://files.pythonhosted.org/packages/95/7d/466b3d18022e9897cbda9c735c493c5bd747d7a4c6f5ea1480b4cec434b6/propcache-0.5.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29f9309a2e42b0d273be006fdb4be2d6c39a47f6f57d8fb1cf9f81481df81b66", size = 61563, upload-time = "2026-05-08T20:59:53.866Z" }, + { url = "https://files.pythonhosted.org/packages/27/1b/16ab7f2cf2041da2f60d156ba64c2484eadf9168075b4ff43c3ef60045af/propcache-0.5.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5aaa2b923c1944ac8febd6609cb373540a5563e7cbcb0fd770f75dace2eb817b", size = 58888, upload-time = "2026-05-08T20:59:55.457Z" }, + { url = "https://files.pythonhosted.org/packages/0a/67/bb777ffd907633563bf35fd859c4ce97b0512c32f4633cf5d1eb7c33512b/propcache-0.5.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66ea454f095ddf5b6b14f56c064c0941c4788be11e18d2464cf643bf7203ff67", size = 59253, upload-time = "2026-05-08T20:59:57.075Z" }, + { url = "https://files.pythonhosted.org/packages/b9/42/64f8d90b73fd9cdc1499b48057ff6d9cd2a98a25734c9bb62ecf07e87061/propcache-0.5.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:95f1e3f4760d404b13c9976c0229b2b49a3c8e2c62a9ce92efdd2b11ada75e3f", size = 57558, upload-time = "2026-05-08T20:59:58.602Z" }, + { url = "https://files.pythonhosted.org/packages/eb/02/dba5bc03c9041f2092ea55a449caf5dfe68352c6654511b29ba0654ddb69/propcache-0.5.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:85341b12b9d55bad0bded24cac341bb34289469e03a11f3f583ea1cc1db0326c", size = 55007, upload-time = "2026-05-08T20:59:59.837Z" }, + { url = "https://files.pythonhosted.org/packages/14/c0/43f649c7aa2a77a3b100d84e9dea3a483120ecb608bfe36ce49eaff517fe/propcache-0.5.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:26a4dca084132874e639895c3135dfad5eb20bae209f62d1aeb31b03e601c3c0", size = 60355, upload-time = "2026-05-08T21:00:01.144Z" }, + { url = "https://files.pythonhosted.org/packages/83/c0/435dafd27f1cb4a495381dae60e25883ccfe4020bb72818e8184c1678092/propcache-0.5.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3b199b9b2b3d6a7edf3183ba8a9a137a22b97f7df525feb5ae1eccf026d2a9c6", size = 59057, upload-time = "2026-05-08T21:00:02.401Z" }, + { url = "https://files.pythonhosted.org/packages/53/ae/6e292df9135d659944e96cb3389258e4a663e5b2b5f6c217ef0ddc8d2f73/propcache-0.5.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e59bc9e66329185b93dab73f210f1a37f81cb40f321501db8017c9aea15dba27", size = 61938, upload-time = "2026-05-08T21:00:03.638Z" }, + { url = "https://files.pythonhosted.org/packages/0b/42/314ebc50d8159055411fd6b0bda322ff510e4b1f7d2e4927940ad0f6af20/propcache-0.5.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:552ffadf6ad409844bc5919c42a0a83d88314cedddaea0e41e80a8b8fffe881f", size = 59731, upload-time = "2026-05-08T21:00:04.881Z" }, + { url = "https://files.pythonhosted.org/packages/b8/9b/2da6dee38871c3c8772fabc2758325a5c9077d6d18c597737dc04dd884cd/propcache-0.5.2-cp311-cp311-win32.whl", hash = "sha256:cd416c1de191973c52ff1a12a57446bfc7642797b282d7caf2162d7d1b8aa9a0", size = 38966, upload-time = "2026-05-08T21:00:06.511Z" }, + { url = "https://files.pythonhosted.org/packages/42/4e/f17363fb58c0afe05b067361cb6d86ed2d29de6506779a27547c4d183075/propcache-0.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:44e488ef40dbb452700b2b1f8188934121f6648f52c295055662d2191959ff82", size = 42135, upload-time = "2026-05-08T21:00:08.088Z" }, + { url = "https://files.pythonhosted.org/packages/c6/eb/6af6685077d22e8b33358d3c548e3282706a0b3cd85044ffba4e5dd08e3b/propcache-0.5.2-cp311-cp311-win_arm64.whl", hash = "sha256:54adaa85a22078d1e306304a40984dc5be99d599bf3dc0a24dc98f7daeab89ab", size = 38381, upload-time = "2026-05-08T21:00:09.692Z" }, + { url = "https://files.pythonhosted.org/packages/4a/cb/e27bc2b2737a0bb49962b275efa051e8f1c35a936df7d5139b6b658b7dc9/propcache-0.5.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:806719138ecd720339a12410fb9614ac9b2b2d3a5fdf8235d56981c36f4039ba", size = 95887, upload-time = "2026-05-08T21:00:11.277Z" }, + { url = "https://files.pythonhosted.org/packages/e6/13/b8ae04c59392f8d11c6cd9fb4011d1dc7c86b81225c770280300e259ffe1/propcache-0.5.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:db2b80ea58eab4f86b2beec3cc8b39e8ff9276ac20e96b7cce43c8ae84cd6b5a", size = 54654, upload-time = "2026-05-08T21:00:12.604Z" }, + { url = "https://files.pythonhosted.org/packages/2c/7d/49777a3e20b55863d4794384a38acd460c04157b0a00f8602b0d508b8431/propcache-0.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e5cbfac9f61484f7e9f3597775500cd3ebe8274e9b050c38f9525c77c97520bf", size = 55190, upload-time = "2026-05-08T21:00:13.935Z" }, + { url = "https://files.pythonhosted.org/packages/44/c7/085d0cd63062e84044e3f05797749c3f8e3938ff3aeb0eb2f69d43fafc91/propcache-0.5.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbc581d2814337da56222fab8dc5f161cd798a434e49bac27930aaef798e144", size = 59995, upload-time = "2026-05-08T21:00:15.526Z" }, + { url = "https://files.pythonhosted.org/packages/9c/42/32cf8e3009e92b2645cf1e944f701e8ea4e924dffde1ee26db860bcbf7e4/propcache-0.5.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:857187f381f88c8e2fa2fe56ab94879d011b883d5a2ee5a1b60a8cd2a06846d9", size = 63422, upload-time = "2026-05-08T21:00:16.824Z" }, + { url = "https://files.pythonhosted.org/packages/9e/1b/f112433f99fc979431b87a39ef169e3f8df070d99a72792c56d6937ac48b/propcache-0.5.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:178b4a2cdaac1818e2bf1c5a99b94383fa73ea5382e032a48dec07dc5668dc42", size = 64342, upload-time = "2026-05-08T21:00:18.362Z" }, + { url = "https://files.pythonhosted.org/packages/14/15/5574111ae50dd6e879456888c0eadd4c5a869959775854e18e18a6b345f3/propcache-0.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f328175a2cde1f0ff2c4ed8ce968b9dcfb55f3a7153f39e2957ed994da13476", size = 61639, upload-time = "2026-05-08T21:00:19.692Z" }, + { url = "https://files.pythonhosted.org/packages/cc/da/4d775080b1490c0ae604acda868bd71aabe3a89ed16f2aa4339eb8a283e7/propcache-0.5.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5671d09a36b06d0fd4a3da0fccbcae360e9b1570924171a15e9e0997f0249fba", size = 61588, upload-time = "2026-05-08T21:00:21.155Z" }, + { url = "https://files.pythonhosted.org/packages/04/ac/f076982cbe2195ee9cf32de5a1e46951d9fb399fc207f390562dd0fd8fb2/propcache-0.5.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80168e2ebe4d3ec6599d10ad8f520304ae1cad9b6c5a95372aef1b66b7bfb53a", size = 60029, upload-time = "2026-05-08T21:00:22.713Z" }, + { url = "https://files.pythonhosted.org/packages/70/60/189be62e0dd898dce3b331e1b8c7a543cd3a405ac0c81fe8ee8a9d5d77e1/propcache-0.5.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:45f11346f884bc47444f6e6647131055844134c3175b629f84952e2b5cd62b64", size = 56774, upload-time = "2026-05-08T21:00:24.001Z" }, + { url = "https://files.pythonhosted.org/packages/ea/9e/93377b9c7939c1ffae98f878dee955efadfd638078bc86dbc21f9d52f651/propcache-0.5.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8e778ebd44ef4f66ed60a0416b06b489687db264a9c0b3620362f26489492913", size = 63532, upload-time = "2026-05-08T21:00:25.545Z" }, + { url = "https://files.pythonhosted.org/packages/14/f9/590ef6cfb9b8028d516d287812ece32bb0bc5f11fbb9c8bf6b2e6313fec8/propcache-0.5.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:c0cb9ed24c8964e172768d455a38254c2dd8a552905729ce006cad3d3dda59b1", size = 61592, upload-time = "2026-05-08T21:00:27.186Z" }, + { url = "https://files.pythonhosted.org/packages/b4/5e/70958b3034c297a630bba2f17ca7abc2d5f39a803ad7e370ab79d1ecd022/propcache-0.5.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1d1ad32d9d4355e2be65574fd0bfd3677e7066b009cd5b9b2dee8aa6a6393b33", size = 64788, upload-time = "2026-05-08T21:00:28.8Z" }, + { url = "https://files.pythonhosted.org/packages/12/fd/77fe5936d8c3086ca9048f7f415f122ed82e53884a9ec193646b42deef06/propcache-0.5.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c80f4ba3e8f00189165999a742ee526ebeccedf6c3f7beb0c7df821e9772435a", size = 62514, upload-time = "2026-05-08T21:00:30.098Z" }, + { url = "https://files.pythonhosted.org/packages/cf/74/66bd798b5b3be70aa1b391f5cc9d6a0a5532d7fd3b19ec0b213e72e6ad9d/propcache-0.5.2-cp312-cp312-win32.whl", hash = "sha256:8c7972d8f193740d9175f0998ab38717e6cd322d5935c5b0fef8c0d323fd9031", size = 39018, upload-time = "2026-05-08T21:00:31.622Z" }, + { url = "https://files.pythonhosted.org/packages/61/7c/5c0d34aa3024694d6dcb9271cdbdd08c4e47c1c0ad95ec7e7bc74cdea145/propcache-0.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:d9ee8826a7d47863a08ac44e1a5f611a462eefc3a194b492da242128bec75b42", size = 42322, upload-time = "2026-05-08T21:00:32.918Z" }, + { url = "https://files.pythonhosted.org/packages/4d/91/875812f1a3feb20ceba818ef39fbe4d92f1081e04ac815c822496d0d038b/propcache-0.5.2-cp312-cp312-win_arm64.whl", hash = "sha256:2800a4a8ead6b28cccd1ec54b59346f0def7922ee1c7598e8499c733cfbb7c84", size = 38172, upload-time = "2026-05-08T21:00:35.124Z" }, + { url = "https://files.pythonhosted.org/packages/c5/09/f049e45385503fe67db75a6b6186a7b9f0c3930366dc960522c312a825b1/propcache-0.5.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:099aaf4b4d1a02265b92a977edf00b5c4f63b3b17ac6de39b0d637c9cac0188a", size = 94457, upload-time = "2026-05-08T21:00:36.355Z" }, + { url = "https://files.pythonhosted.org/packages/6b/65/83d1d05655baf63113731bd5a1008435e14f8d1e5a06cbe4ec5b23ad7a31/propcache-0.5.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:68ce1c44c7a813a7f71ea04315a8c7b330b63db99d059a797a4651bb6f69f117", size = 53835, upload-time = "2026-05-08T21:00:38.072Z" }, + { url = "https://files.pythonhosted.org/packages/a9/12/a6ba6482bb5ea3260c000c9b20881c95fa11c6b30173715668259f844ed7/propcache-0.5.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fc299c129490f55f254cd90be0deca4764e36e9a7c08b4aa588479a3bbed3098", size = 54545, upload-time = "2026-05-08T21:00:39.319Z" }, + { url = "https://files.pythonhosted.org/packages/a9/19/7fa086f5764c59ec8a8e157cd93aa8497acc00aba9dcdec56bfffb32602d/propcache-0.5.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a6ae2198be502c10f09b2516e7b5d019816924bc3183a43ce792a7bd6625e6f4", size = 59886, upload-time = "2026-05-08T21:00:40.621Z" }, + { url = "https://files.pythonhosted.org/packages/a1/e4/5d7663dc8235956c8f5281698a3af1d351d8820341ddd890f59d9a9127f2/propcache-0.5.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6041d31504dc1779d700e1edcfb08eea334b357620b06681a4eabb57a74e574e", size = 63261, upload-time = "2026-05-08T21:00:41.775Z" }, + { url = "https://files.pythonhosted.org/packages/4a/4a/15a03adee24d6350da4292caeac44c34c033d2afe5e87eb370f38854560f/propcache-0.5.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7eabc04151c78a9f4d5bbb5f1faf571e4defeb4b585e0fe95b60ff2dbe4d3d7", size = 64184, upload-time = "2026-05-08T21:00:43.018Z" }, + { url = "https://files.pythonhosted.org/packages/8b/c6/979176efdaa3d239e36d503d5af63a0a773b36662ed8f52e5b6a6d9fd40e/propcache-0.5.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4db0ba63d693afd40d249bd93f842b5f144f8fcbb83de05660373bcf30517b1d", size = 61534, upload-time = "2026-05-08T21:00:44.507Z" }, + { url = "https://files.pythonhosted.org/packages/c8/22/63e8cd1bae4c2d2be6493b6b7d10566ddafad88137cfbc99964a1119853c/propcache-0.5.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1dbcf7675229b35d31abb6547d8ebc8c27a830ac3f9a794edff6254873ec7c0a", size = 61500, upload-time = "2026-05-08T21:00:45.796Z" }, + { url = "https://files.pythonhosted.org/packages/60/5a/28e5d9acbac1cc9ccb67045e8c1b943aa8d79fdf39c93bd73cacd68008ea/propcache-0.5.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d310c013aad2c72f1c3f2f8dd3279d460a858c551f97aeb8c63e4693cca7b4d2", size = 59994, upload-time = "2026-05-08T21:00:47.093Z" }, + { url = "https://files.pythonhosted.org/packages/f3/40/db650677f554a95b9c01a7c9d93d629e93a15562f5deb4573c9ee136fed2/propcache-0.5.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:06187263ddad280d05b4d8a8b3bb7d164cbebd469236544a42e6d9b28ac6a4fa", size = 56884, upload-time = "2026-05-08T21:00:48.376Z" }, + { url = "https://files.pythonhosted.org/packages/80/45/70b39b89516ff8b96bf732fa6fded8cef20f293cb1508690101c3c07ec51/propcache-0.5.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3115559b8effafd63b142ea5ed53d63a16ea6469cbc63dce4ee194b42db5d853", size = 63464, upload-time = "2026-05-08T21:00:49.954Z" }, + { url = "https://files.pythonhosted.org/packages/f9/e2/fa59d3a89eac5534293124af4f1d0d0ada091ce4a0ab4610ce03fd2bdd8d/propcache-0.5.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c60462af8e6dc30c35407c7237ea908d777b22862bbee27bc4699c0d8bcdc45a", size = 61588, upload-time = "2026-05-08T21:00:51.281Z" }, + { url = "https://files.pythonhosted.org/packages/0b/97/efb547a55c4bc7381cfb202d6a2239ac621045277bc1ea5dfd3a7f0516c0/propcache-0.5.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:40314bca9ac559716fe374094fc81c11dcc34b64fd6c585360f5775690505704", size = 64667, upload-time = "2026-05-08T21:00:52.602Z" }, + { url = "https://files.pythonhosted.org/packages/92/56/f5c7d9b4b7595d5127da38974d791b2153f3d1eae6c674af3583ace92ad3/propcache-0.5.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cfa21e036ce1e1db2be04ba3b85d2df1bb1702fa01932d984c5464c665228ff4", size = 62463, upload-time = "2026-05-08T21:00:54.303Z" }, + { url = "https://files.pythonhosted.org/packages/bd/3b/484a3a65fc9f9f60c41dcd17b428bace5389544e2c680994534a20755066/propcache-0.5.2-cp313-cp313-win32.whl", hash = "sha256:f156a3529f38063b6dbaf356e15602a7f95f8055b1295a438433a6386f10463d", size = 38621, upload-time = "2026-05-08T21:00:55.808Z" }, + { url = "https://files.pythonhosted.org/packages/1c/fd/3f0f10dba4dabad3bf53102be007abf55481067952bde0fdddff439e7c61/propcache-0.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:dfed59d0a5aeb01e242e66ff0300bc4a265a7c05f612d30016f0b60b1017d757", size = 41649, upload-time = "2026-05-08T21:00:57.061Z" }, + { url = "https://files.pythonhosted.org/packages/90/ec/6ce619cc32bb500a482f811f9cd509368b4e58e638d13f2c68f370d6b475/propcache-0.5.2-cp313-cp313-win_arm64.whl", hash = "sha256:ba338430e87ceb9c8f0cf754de38a9860560261e56c00376debd628698a7364f", size = 37636, upload-time = "2026-05-08T21:00:58.646Z" }, + { url = "https://files.pythonhosted.org/packages/1b/82/c1d268bbbf2ef981c5bf0fbbe746db617c66e3bcefe431a1aa8943fbe23a/propcache-0.5.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a592f5f3da71c8691c788c13cb6734b6d17663d2e1cb8caddf0673d01ef8847d", size = 98872, upload-time = "2026-05-08T21:00:59.889Z" }, + { url = "https://files.pythonhosted.org/packages/f4/d4/52c871e73e864e6b34c0e2d58ac1ec5ccd149497ddc7ad2137ae98323a35/propcache-0.5.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6a997d0489e9668a384fcfd5061b857aa5361de73191cac204d04b889cfbbafa", size = 56257, upload-time = "2026-05-08T21:01:01.195Z" }, + { url = "https://files.pythonhosted.org/packages/67/f0/9b90ca2a210b3d09bcfcd96ecd0f55545c091535abce2a45de2775cfd357/propcache-0.5.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:10734b5484ea113152ee25a91dccedf81631791805d2c9ccb054958e51842c94", size = 56696, upload-time = "2026-05-08T21:01:02.941Z" }, + { url = "https://files.pythonhosted.org/packages/9d/0e/6e9d4ba07c8e56e21ddec1e75f12148142b21ca83a51871babce095334f4/propcache-0.5.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cafca7e56c12bb02ae16d283742bef25a61122e9dab2b5b3f2ccbe589ce32164", size = 62378, upload-time = "2026-05-08T21:01:04.475Z" }, + { url = "https://files.pythonhosted.org/packages/65/19/c10badaa463dde8a27ce884f8ee2ec37e6035b7c9f5ff0c8f74f06f08dac/propcache-0.5.2-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f064f8d2b59177878b7615df1735cd8fe3462ed6be8c7b217d17a276489c2b7f", size = 65283, upload-time = "2026-05-08T21:01:05.959Z" }, + { url = "https://files.pythonhosted.org/packages/b0/b6/93bea99ca80e19cef6512a8580e5b7857bbe09422d9daa7fd4ef5723306c/propcache-0.5.2-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f78abfa8dfc32376fd1aacf597b2f2fbbe0ea751419aee718af5d4f82537ef8c", size = 66616, upload-time = "2026-05-08T21:01:07.228Z" }, + { url = "https://files.pythonhosted.org/packages/83/e4/5c7462e50625f051f37fb38b8224f7639f667184bbd34424ec83819bb1b7/propcache-0.5.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7467da8a9822bf1a55336f877340c5bcbd3c482afc43a99771169f74a26dedc", size = 63773, upload-time = "2026-05-08T21:01:08.514Z" }, + { url = "https://files.pythonhosted.org/packages/ca/b6/99238894047b13c823be25027e736626cd414a52a5e30d2c3347c2733529/propcache-0.5.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a6ddc6ac9e25de626c1f129c1b467d7ecd33ce2237d3fd0c4e429feef0a7ee1f", size = 63664, upload-time = "2026-05-08T21:01:09.874Z" }, + { url = "https://files.pythonhosted.org/packages/85/1e/a3a1a63116a2b8edb415a8bb9a6f0c34bd03830b1e18e8ce2904e1dc1cf4/propcache-0.5.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2f22cbbac9e26a8e864c0985ff1268d5d939d53d9d9411a9824279097e03a2cb", size = 62643, upload-time = "2026-05-08T21:01:11.132Z" }, + { url = "https://files.pythonhosted.org/packages/e4/03/893cf147de2fc6543c5eaa07ad833170e7e2a2385725bbebe8c0503723bb/propcache-0.5.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:fc76378c62a0f04d0cd82fbb1a2cd2d7e28fcb40d5873f28a6c44e388aaa2751", size = 59595, upload-time = "2026-05-08T21:01:12.387Z" }, + { url = "https://files.pythonhosted.org/packages/86/3b/04c1a2e12c57766568ba75ba72b3bf2042818d4c1425fab6fc07155c7cff/propcache-0.5.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:acd2c8edba48e31e58a363b8cf4e5c7db3b04b3f9e371f601df30d9b0d244836", size = 65711, upload-time = "2026-05-08T21:01:13.676Z" }, + { url = "https://files.pythonhosted.org/packages/1c/34/80f8d0099f8d6bacc4de1624c85672681c8cd1149ca2da0e38fd120b817f/propcache-0.5.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:452b5065457eb9991ec5eb38ff41d6cd4c991c9ac7c531c4d5849ae473a9a13f", size = 64247, upload-time = "2026-05-08T21:01:14.936Z" }, + { url = "https://files.pythonhosted.org/packages/f3/1a/8b08f3a5f1037e9e370c55883ceeeee0f6dd0416fb2d2d67b8bfc91f2a79/propcache-0.5.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:3430bb2bfe1331885c427745a751e774ee679fd4344f80b97bf879815fe8fa55", size = 67102, upload-time = "2026-05-08T21:01:16.281Z" }, + { url = "https://files.pythonhosted.org/packages/34/68/8bdb7bb7756d76e005490649d10e4a8369e610c74d619f71e1aedf889e9c/propcache-0.5.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cef6cea3922890dd6c9654971001fa797b526c16ab5e1e46c05fd6f877be7568", size = 64964, upload-time = "2026-05-08T21:01:17.57Z" }, + { url = "https://files.pythonhosted.org/packages/0a/aa/50fb0b5d3968b61a510926ff8b8465f1d6e976b3ab74496d7a4b9fc42515/propcache-0.5.2-cp313-cp313t-win32.whl", hash = "sha256:72d61e16dd78228b58c5d47be830ff3da7e5f139abdf0aef9d86cde1c5cf2191", size = 42546, upload-time = "2026-05-08T21:01:18.946Z" }, + { url = "https://files.pythonhosted.org/packages/ae/4c/0ddbae64321bd4a95bcbfc19307238016b5b1fee645c84626c8d539e5b74/propcache-0.5.2-cp313-cp313t-win_amd64.whl", hash = "sha256:0958834041a0166d343b8d2cedcd8bcbaeb4fdbe0cf08320c5379f143c3be6e7", size = 46330, upload-time = "2026-05-08T21:01:20.162Z" }, + { url = "https://files.pythonhosted.org/packages/00/d9/9cddc8efb78d8af264c5ec9f6d10b62f57c515feda8d321595f56010fb23/propcache-0.5.2-cp313-cp313t-win_arm64.whl", hash = "sha256:6de8bd93ddde9b992cf2b2e0d796d501a19026b5b9fd87356d7d0779531a8d96", size = 40521, upload-time = "2026-05-08T21:01:21.399Z" }, + { url = "https://files.pythonhosted.org/packages/e2/ea/23ee535d90ce8bcc465a3028eb3cc0ce3bd1005f4bb27710b30587de798d/propcache-0.5.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:46088abff4cba581dea21ae0467a480526cb25aa5f3c269e909f800328bc3999", size = 94662, upload-time = "2026-05-08T21:01:22.683Z" }, + { url = "https://files.pythonhosted.org/packages/b5/06/c5a52f419b5d8972f8d46a7577476090d8e3263ff589ce40b5ca4968d5be/propcache-0.5.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fc88b26f08d634f7bc819a7852e5214f5802641ab8d9fd5326892292eee1993e", size = 53928, upload-time = "2026-05-08T21:01:23.986Z" }, + { url = "https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97797ebb098e670a2f92dd66f32897e30d7615b14e7f59711de23e30a9072539", size = 54650, upload-time = "2026-05-08T21:01:25.305Z" }, + { url = "https://files.pythonhosted.org/packages/70/06/2f46c318e3307cd7a6a7481def374ce838c0fe20084b39dd54b0879d0e99/propcache-0.5.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba57fffe4ac99c5d30076161b5866336d97600769bad35cc68f7774b15298a4e", size = 59912, upload-time = "2026-05-08T21:01:26.545Z" }, + { url = "https://files.pythonhosted.org/packages/4c/29/fe1aebec2ce57ab985a9c382bded1124431f85078113aa222c5d278430d4/propcache-0.5.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:583c19759d9eec1e5b69e2fbef36a7d9c326041be9746cb822d335c8cedc2979", size = 63300, upload-time = "2026-05-08T21:01:27.937Z" }, + { url = "https://files.pythonhosted.org/packages/b4/18/2334b26768b6c82be8c69e83671b767d5ef426aa09b0cba6c2ea47816774/propcache-0.5.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d0326e2e5e1f3163fa306c834e48e8d490e5fae607a097a40c0648109b47ba80", size = 64208, upload-time = "2026-05-08T21:01:29.484Z" }, + { url = "https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e00820e192c8dbebcafb383ebbf99030895f09905e7a0eb2e0340a0bcc2bc825", size = 61633, upload-time = "2026-05-08T21:01:31.068Z" }, + { url = "https://files.pythonhosted.org/packages/c4/46/b3ff8aba2b4953a3e50de2cf72f1b5748b8eca93b15f3dc2c84339084c09/propcache-0.5.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c66afea89b1e43725731d2004732a046fe6fe955d51f952c3e95a7314a284a39", size = 61724, upload-time = "2026-05-08T21:01:32.374Z" }, + { url = "https://files.pythonhosted.org/packages/c5/01/814cfcafbcff954f94c01cf30e097ddc88a076b5440fbcf4570753437d40/propcache-0.5.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc37dec6c6cdad0b57881a5658fd14fbf53e333b1a86cf86559f190e1d9ec4", size = 60069, upload-time = "2026-05-08T21:01:33.67Z" }, + { url = "https://files.pythonhosted.org/packages/da/68/5c6f7622d510cc666a300687e06fd060c1a43361c0c9b20d284f06d8096a/propcache-0.5.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:5570dbcc97571c15f68068e529c92715a12f8d54030e272d264b377e22bd17a5", size = 57099, upload-time = "2026-05-08T21:01:34.915Z" }, + { url = "https://files.pythonhosted.org/packages/55/27/9cb0b4c679124085327957d42521c99dba04c88c90c3e55a6f0b633ebccc/propcache-0.5.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f814362777a9f841adddb200ecdf8f5cb1e5a3c4b7a86378edbd6ccb26edd702", size = 63391, upload-time = "2026-05-08T21:01:36.231Z" }, + { url = "https://files.pythonhosted.org/packages/f0/9d/7258aaa5bdf60fc6f27591eef6fe52768cb0beda7140be477c8b12c9794a/propcache-0.5.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:196913dea116aeb5a2ba95af4ddcb7ea85559ae07d8eee8751688310d09168c3", size = 61626, upload-time = "2026-05-08T21:01:37.545Z" }, + { url = "https://files.pythonhosted.org/packages/8e/0d/41c602003e8a9b16fe1e7eadf62c7bfba9d5474370b24200bf48b315f45f/propcache-0.5.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:6e7b8719005dd1175be4ab1cd25e9b98659a5e0347331506ec6760d2773a7fb5", size = 64781, upload-time = "2026-05-08T21:01:38.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f3/38e66b1856e9bd079deea015bc4a55f7767c0e4db2f7dcf69e7e680ba4ce/propcache-0.5.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:51f96d685ab16e88cab128cd37a52c5da540809c8b879fa047731bfcb4ad35a4", size = 62570, upload-time = "2026-05-08T21:01:40.415Z" }, + { url = "https://files.pythonhosted.org/packages/95/ca/bbfe9b910ce57dde8bb4876b4520fc02a4e89497c10de26be936758a3aaa/propcache-0.5.2-cp314-cp314-win32.whl", hash = "sha256:cc6fc3cc62e8501d3ed62894425040d2728ecddb1ed072737a5c70bd537aa9f0", size = 39436, upload-time = "2026-05-08T21:01:41.654Z" }, + { url = "https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl", hash = "sha256:81e3a30b0bb60caa22033dd0f8a3618d1d67356212514f62c57db75cb0ef410c", size = 42373, upload-time = "2026-05-08T21:01:43.041Z" }, + { url = "https://files.pythonhosted.org/packages/44/68/9ea5103f41d5217d7d6ec24db90018e23aebec070c3f9a6e54d12b841fd8/propcache-0.5.2-cp314-cp314-win_arm64.whl", hash = "sha256:0d2c9bf8528f135dbb805ce027567e09164f7efa51a2be07458a2c0420f292d0", size = 38554, upload-time = "2026-05-08T21:01:44.336Z" }, + { url = "https://files.pythonhosted.org/packages/8a/81/fadf555f42d3b762eea8a53950b0489fdc0aa9da5f8ed9e10ce0a4e01b48/propcache-0.5.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:4bc8ff1feffc6a61c7002ffe84634c41b822e104990ae009f44a0834430070bb", size = 99395, upload-time = "2026-05-08T21:01:45.883Z" }, + { url = "https://files.pythonhosted.org/packages/f5/c9/c61e134a686949cf7971af3a390148b1156f7be81c73bc0cd12c873e2d48/propcache-0.5.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:79aa3ff0a9b566633b642fa9caf7e21ed1c13d6feca718187873f199e1514078", size = 56653, upload-time = "2026-05-08T21:01:47.307Z" }, + { url = "https://files.pythonhosted.org/packages/cb/73/daf935ea7048ddd7ec8eec5345b4a40b619d2d178b3c0a0900796bc3c794/propcache-0.5.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1b31822f4474c4036bae62de9402710051d431a606d6a0f907fec79935a071aa", size = 56914, upload-time = "2026-05-08T21:01:48.573Z" }, + { url = "https://files.pythonhosted.org/packages/79/9f/aba959b435ea18617edd7cf0a7ad0b9c574b8fc7e3d2cd55fb59cb255d33/propcache-0.5.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fef48778b5a2a756523fdb781326b028ca75e32858b04f2cdd19f394564917", size = 62567, upload-time = "2026-05-08T21:01:49.903Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a1/859942de9a791ff42f6141736f5b37749b8f53e65edfa49638c67dd67e6a/propcache-0.5.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8b73ab70f1a3351fbc71f663b3e645af6dd0329100c353081cf69c37433fc6fe", size = 65542, upload-time = "2026-05-08T21:01:51.204Z" }, + { url = "https://files.pythonhosted.org/packages/b5/61/315bc0fd6c0fc7f80a528b8afd209e5fc4a875ea79571b91b8f50f442907/propcache-0.5.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5538d2c13d93e4698af7e092b57bc7298fd35d1d58e656ae18f23ee0d0378e03", size = 66845, upload-time = "2026-05-08T21:01:52.539Z" }, + { url = "https://files.pythonhosted.org/packages/47/f7/9f8122e3132e8e354ac41975ef8f1099be7d5a16bc7ae562734e993665c0/propcache-0.5.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd645f03898405cabe694fb8bc35241e3a9c332ec85627584fe3de201452b335", size = 63985, upload-time = "2026-05-08T21:01:53.847Z" }, + { url = "https://files.pythonhosted.org/packages/c8/54/c317819ec157cbf6f35df9df9657a6f82daf34d5faf15948b2f639c2192e/propcache-0.5.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a473b3440261e0c60706e732b2ed2f517857344fc21bf48fdfe211e2d98eb285", size = 63999, upload-time = "2026-05-08T21:01:55.179Z" }, + { url = "https://files.pythonhosted.org/packages/5a/56/387e3f7dfce0a9233df41fb888aa1c30222cb4bbbf09537c02dd9bd85fe2/propcache-0.5.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7afa37062e6650640e932e4cc9297d81f9f42d9944029cc386b8247dea4da837", size = 62779, upload-time = "2026-05-08T21:01:57.489Z" }, + { url = "https://files.pythonhosted.org/packages/a1/9c/596784cb5824ed61ee960d3f8655a3f0993e107c6e98ab6c818b7fb92ccb/propcache-0.5.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:8a90efd5777e996e42d568db9ac740b944d691e565cbfd31b2f7832f9184b2b8", size = 59796, upload-time = "2026-05-08T21:01:58.736Z" }, + { url = "https://files.pythonhosted.org/packages/c2/3d/1a6cfa1726a48542c1e8784a0761421476a5b68e09b7f36bf95eb954aaba/propcache-0.5.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:f19bb891234d72535764d703bfed1153cc34f4214d5bd7150aee1eec9e8f4366", size = 66023, upload-time = "2026-05-08T21:02:00.228Z" }, + { url = "https://files.pythonhosted.org/packages/e4/0e/05fd6990369477076e4e280bcb970de760fddf0161a46e988bc95f7940ec/propcache-0.5.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:32775082acd2d807ee3db715c7770d38767b817870acfa08c29e057f3c4d5b56", size = 64448, upload-time = "2026-05-08T21:02:01.888Z" }, + { url = "https://files.pythonhosted.org/packages/cd/86/5f8da315a4309c62c10c0b2516b17492d5d3bbe1bb862b96604db67e2a37/propcache-0.5.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9282fb1a3bccd038da9f768b927b24a0c753e466c086b7c4f3c6982851eefb2d", size = 67329, upload-time = "2026-05-08T21:02:03.484Z" }, + { url = "https://files.pythonhosted.org/packages/da/d3/3368efe79ab21f0cdf86ef49895811c9cc933131d4cde1f28a624e22e712/propcache-0.5.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cc49723e2f60d6b32a0f0b08a3fd6d13203c07f1cd9566cfce0f12a917c967a2", size = 65172, upload-time = "2026-05-08T21:02:04.745Z" }, + { url = "https://files.pythonhosted.org/packages/d5/07/127e8b0bacfb325396196f9d976a22453049b89b9b2b08477cc3145faa44/propcache-0.5.2-cp314-cp314t-win32.whl", hash = "sha256:2d7aa89ebca5acc98cba9d1472d976e394782f587bad6661003602a619fd1821", size = 43813, upload-time = "2026-05-08T21:02:06.025Z" }, + { url = "https://files.pythonhosted.org/packages/88/fb/46dad6c0ae49ed230ab1b16c890c2b6314e2403e6c412976f4a72d64a527/propcache-0.5.2-cp314-cp314t-win_amd64.whl", hash = "sha256:d447bb0b3054be5818458fbb171208b1d9ff11eba14e18ca18b90cbb45767370", size = 47764, upload-time = "2026-05-08T21:02:07.353Z" }, + { url = "https://files.pythonhosted.org/packages/e7/c4/a47d0a63aa309d10d59ede6e9d4cff03a344a79d1f0f4cd0cd74997b53e0/propcache-0.5.2-cp314-cp314t-win_arm64.whl", hash = "sha256:fe67a3d11cd9b4efabfa45c3d00ffba2b26811442a73a581a94b67c2b5faccf6", size = 41140, upload-time = "2026-05-08T21:02:09.065Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ed/1cdcab6ba3d6ab7feca11fc14f0eeea80755bb53ef4e892079f31b10a25f/propcache-0.5.2-py3-none-any.whl", hash = "sha256:be1ddfcbb376e3de5d2e2db1d58d6d67463e6b4f9f040c000de8e300295465fe", size = 14036, upload-time = "2026-05-08T21:02:10.673Z" }, +] + +[[package]] +name = "psutil" +version = "7.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b", size = 130595, upload-time = "2026-01-28T18:14:57.293Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea", size = 131082, upload-time = "2026-01-28T18:14:59.732Z" }, + { url = "https://files.pythonhosted.org/packages/37/d6/246513fbf9fa174af531f28412297dd05241d97a75911ac8febefa1a53c6/psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63", size = 181476, upload-time = "2026-01-28T18:15:01.884Z" }, + { url = "https://files.pythonhosted.org/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312", size = 184062, upload-time = "2026-01-28T18:15:04.436Z" }, + { url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b", size = 139893, upload-time = "2026-01-28T18:15:06.378Z" }, + { url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9", size = 135589, upload-time = "2026-01-28T18:15:08.03Z" }, + { url = "https://files.pythonhosted.org/packages/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00", size = 130664, upload-time = "2026-01-28T18:15:09.469Z" }, + { url = "https://files.pythonhosted.org/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9", size = 131087, upload-time = "2026-01-28T18:15:11.724Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2e/e6782744700d6759ebce3043dcfa661fb61e2fb752b91cdeae9af12c2178/psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a", size = 182383, upload-time = "2026-01-28T18:15:13.445Z" }, + { url = "https://files.pythonhosted.org/packages/57/49/0a41cefd10cb7505cdc04dab3eacf24c0c2cb158a998b8c7b1d27ee2c1f5/psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf", size = 185210, upload-time = "2026-01-28T18:15:16.002Z" }, + { url = "https://files.pythonhosted.org/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1", size = 141228, upload-time = "2026-01-28T18:15:18.385Z" }, + { url = "https://files.pythonhosted.org/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841", size = 136284, upload-time = "2026-01-28T18:15:19.912Z" }, + { url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" }, + { url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" }, + { url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" }, + { url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" }, + { url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" }, + { url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" }, + { url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737, upload-time = "2026-01-28T18:15:33.849Z" }, + { url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" }, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, +] + +[[package]] +name = "py-key-value-aio" +version = "0.4.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beartype" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fb/e2/d689d922894a7ecde73b6daeaf9b13dab5aae06fe6aaaf7514722644d382/py_key_value_aio-0.4.5.tar.gz", hash = "sha256:c6563a2c6abe5da5e20f4f9e875c2a9b425a2244a54fadbf46cf140a9eea45d7", size = 107547, upload-time = "2026-05-27T16:37:08.107Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/95/b8ba862968712caa12a19666175334fa979e1f198b896a430adb3bacfe87/py_key_value_aio-0.4.5-py3-none-any.whl", hash = "sha256:ab862adbcb8c72547d1c57821f22cbbb71ab86509039c96f36e914e0336c8dd7", size = 170005, upload-time = "2026-05-27T16:37:06.629Z" }, +] + +[package.optional-dependencies] +filetree = [ + { name = "aiofile", version = "3.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "aiofile", version = "3.11.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "anyio" }, +] +keyring = [ + { name = "keyring" }, +] +memory = [ + { name = "cachetools" }, +] + +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + +[[package]] +name = "pydantic" +version = "2.13.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" }, +] + +[package.optional-dependencies] +email = [ + { name = "email-validator" }, +] + +[[package]] +name = "pydantic-core" +version = "2.46.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/08/f1ba952f1c8ae5581c70fa9c6da89f247b83e3dd8c09c035d5d7931fc23d/pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4", size = 2113146, upload-time = "2026-05-06T13:37:36.537Z" }, + { url = "https://files.pythonhosted.org/packages/56/c6/65f646c7ff09bd257f660434adb45c4dfcbbcebcc030562fecf6f5bf887d/pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5", size = 1949769, upload-time = "2026-05-06T13:37:46.365Z" }, + { url = "https://files.pythonhosted.org/packages/64/ba/bfb1d928fd5b49e1258935ff104ae356e9fd89384a55bf9f847e9193ad40/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63e0198ca18aad131c089b9204c23079c3afa95487e561f4c522d519e55aba", size = 1974958, upload-time = "2026-05-06T13:37:28.611Z" }, + { url = "https://files.pythonhosted.org/packages/4e/74/76223bfb117b64af743c9b6670d1364516f5c0604f96b48f3272f6af6cc6/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f47286a97f0bc9b8859519809077b91b2cefe4ae47fcbf5e466a009c1c5d742b", size = 2042118, upload-time = "2026-05-06T13:36:55.216Z" }, + { url = "https://files.pythonhosted.org/packages/cb/7b/848732968bc8f48f3187542f08358b9d842db564147b256669426ebb1652/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:905a0ed8ea6f2d61c1738835f99b699348d7857379083e5fc497fa0c967a407c", size = 2222876, upload-time = "2026-05-06T13:38:25.455Z" }, + { url = "https://files.pythonhosted.org/packages/b5/2f/e90b63ee2e14bd8d3db8f705a6d75d64e6ee1b7c2c8833747ce706e1e0ce/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea793e075b70290d89d8142074262885d3f7da19634845135751bd6344f73b50", size = 2286703, upload-time = "2026-05-06T13:37:53.304Z" }, + { url = "https://files.pythonhosted.org/packages/ba/1e/acc4d70f88a0a277e4a1fa77ebb985ceabaf900430f875bf9338e11c9420/pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395aebd9183f9d112f569aeb5b2214d1a10a33bec8456447f7fbdfa51d38d4cd", size = 2092042, upload-time = "2026-05-06T13:38:46.981Z" }, + { url = "https://files.pythonhosted.org/packages/a9/da/0a422b57bf8504102bf3c4ccea9c41bab5a5cee6a54650acf8faf67f5a24/pydantic_core-2.46.4-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b078afbc25f3a1436c7a1d2cd3e322497ee99615ba97c563566fdf46aff1ee01", size = 2117231, upload-time = "2026-05-06T13:39:23.146Z" }, + { url = "https://files.pythonhosted.org/packages/bd/2a/2ac13c3af305843e23c5078c53d135656b3f05a2fd78cb7bbbb12e97b473/pydantic_core-2.46.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f747929cf940cddb5b3668a390056ddd5ba2e5010615ea2dcf4f9c4f3ab8791d", size = 2168388, upload-time = "2026-05-06T13:40:08.06Z" }, + { url = "https://files.pythonhosted.org/packages/72/04/2beacf7e1607e93eefe4aed1b4709f079b905fb77530179d4f7c71745f22/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:daa27d92c36f24388fe3ad306b174781c747627f134452e4f128ea00ce1fe8c4", size = 2184769, upload-time = "2026-05-06T13:38:13.901Z" }, + { url = "https://files.pythonhosted.org/packages/9e/29/d2b9fd9f539133548eaf622c06a4ce176cb46ac59f32d0359c4abc0de047/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:19e51f073cd3df251856a8a4189fbdf1de4012c3ebacfb1884f94f1eb406079f", size = 2319312, upload-time = "2026-05-06T13:39:08.24Z" }, + { url = "https://files.pythonhosted.org/packages/7c/af/0f7a5b85fec6075bea96e3ef9187de38fccced0de92c1e7feda8d5cc7bb9/pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1747f85cee84c26985853c6f3d9bd3e75da5212912443fa111c113b9c246f39", size = 2361817, upload-time = "2026-05-06T13:38:43.2Z" }, + { url = "https://files.pythonhosted.org/packages/25/a4/73363fec545fd3ec025490bdda2743c56d0dd5b6266b1a53bbe9e4265375/pydantic_core-2.46.4-cp310-cp310-win32.whl", hash = "sha256:2f84c03c8607173d16b5a854ec68a2f9079ae03237a54fb506d13af47e1d018d", size = 1987085, upload-time = "2026-05-06T13:39:25.497Z" }, + { url = "https://files.pythonhosted.org/packages/01/aa/62f082da2c91fac1c234bc9ee0066257ce83f0604abd72e4c9d5991f2d84/pydantic_core-2.46.4-cp310-cp310-win_amd64.whl", hash = "sha256:8358a950c8909158e3df31538a7e4edc2d7265a7c54b47f0864d9e5bae9dcebf", size = 2074311, upload-time = "2026-05-06T13:39:59.922Z" }, + { url = "https://files.pythonhosted.org/packages/5c/fa/6d7708d2cfc1a832acb6aeb0cd16e801902df8a0f583bb3b4b527fde022e/pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594", size = 2111872, upload-time = "2026-05-06T13:40:27.596Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6f/aa064a3e74b5745afbdf250594f38e7ead05e2d651bcb35994b9417a0d4d/pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c", size = 1948255, upload-time = "2026-05-06T13:39:12.574Z" }, + { url = "https://files.pythonhosted.org/packages/43/3a/41114a9f7569b84b4d84e7a018c57c56347dac30c0d4a872946ec4e36c46/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826", size = 1972827, upload-time = "2026-05-06T13:38:19.841Z" }, + { url = "https://files.pythonhosted.org/packages/ef/25/1ab42e8048fe551934d9884e8d64daa7e990ad386f310a15981aeb6a5b08/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04", size = 2041051, upload-time = "2026-05-06T13:38:10.447Z" }, + { url = "https://files.pythonhosted.org/packages/94/c2/1a934597ddf08da410385b3b7aae91956a5a76c635effef456074fad7e88/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e", size = 2221314, upload-time = "2026-05-06T13:40:13.089Z" }, + { url = "https://files.pythonhosted.org/packages/02/6d/9e8ad178c9c4df27ad3c8f25d1fe2a7ab0d2ba0559fad4aee5d3d1f16771/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3", size = 2285146, upload-time = "2026-05-06T13:38:59.224Z" }, + { url = "https://files.pythonhosted.org/packages/80/50/540cd3aeefc041beb111125c4bff779831a2111fc6b15a9138cda277d32c/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4", size = 2089685, upload-time = "2026-05-06T13:38:17.762Z" }, + { url = "https://files.pythonhosted.org/packages/6b/a4/b440ad35f05f6a38f89fa0f149accb3f0e02be94ca5e15f3c449a61b4bc9/pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398", size = 2115420, upload-time = "2026-05-06T13:37:58.195Z" }, + { url = "https://files.pythonhosted.org/packages/99/61/de4f55db8dfd57bfdfa9a12ec90fe1b57c4f41062f7ca86f08586b3e0ac0/pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3", size = 2165122, upload-time = "2026-05-06T13:37:01.167Z" }, + { url = "https://files.pythonhosted.org/packages/f7/52/7c529d7bdb2d1068bd52f51fe32572c8301f9a4febf1948f10639f1436f5/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848", size = 2182573, upload-time = "2026-05-06T13:38:45.04Z" }, + { url = "https://files.pythonhosted.org/packages/37/b3/7c40325848ba78247f2812dcf9c7274e38cd801820ca6dd9fe63bcfb0eb4/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3", size = 2317139, upload-time = "2026-05-06T13:37:15.539Z" }, + { url = "https://files.pythonhosted.org/packages/d9/37/f913f81a657c865b75da6c0dbed79876073c2a43b5bd9edbe8da785e4d49/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109", size = 2360433, upload-time = "2026-05-06T13:37:30.099Z" }, + { url = "https://files.pythonhosted.org/packages/c4/67/6acaa1be2567f9256b056d8477158cac7240813956ce86e49deae8e173b4/pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda", size = 1985513, upload-time = "2026-05-06T13:38:15.669Z" }, + { url = "https://files.pythonhosted.org/packages/aa/e6/c505f83dfeda9a2e5c995cfd872949e4d05e12f7feb3dca72f633daefa94/pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33", size = 2071114, upload-time = "2026-05-06T13:40:35.416Z" }, + { url = "https://files.pythonhosted.org/packages/0f/da/7a263a96d965d9d0df5e8de8a475f33495451117035b09acb110288c381f/pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d", size = 2044298, upload-time = "2026-05-06T13:38:29.754Z" }, + { url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" }, + { url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" }, + { url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" }, + { url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" }, + { url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" }, + { url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" }, + { url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" }, + { url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" }, + { url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" }, + { url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" }, + { url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" }, + { url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" }, + { url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" }, + { url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" }, + { url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" }, + { url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" }, + { url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" }, + { url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" }, + { url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" }, + { url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" }, + { url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" }, + { url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" }, + { url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" }, + { url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" }, + { url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" }, + { url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" }, + { url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" }, + { url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" }, + { url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" }, + { url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" }, + { url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" }, + { url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" }, + { url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" }, + { url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" }, + { url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" }, + { url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" }, + { url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" }, + { url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" }, + { url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" }, + { url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" }, + { url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" }, + { url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" }, + { url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" }, + { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" }, + { url = "https://files.pythonhosted.org/packages/ee/a4/73995fd4ebbb46ba0ee51e6fa049b8f02c40daebb762208feda8a6b7894d/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c", size = 2111589, upload-time = "2026-05-06T13:37:10.817Z" }, + { url = "https://files.pythonhosted.org/packages/fb/7f/f37d3a5e8bfcc2e403f5c57a730f2d815693fb42119e8ea48b3789335af1/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b", size = 1944552, upload-time = "2026-05-06T13:36:56.717Z" }, + { url = "https://files.pythonhosted.org/packages/15/3c/d7eb777b3ff43e8433a4efb39a17aa8fd98a4ee8561a24a67ef5db07b2d6/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b", size = 1982984, upload-time = "2026-05-06T13:39:06.207Z" }, + { url = "https://files.pythonhosted.org/packages/63/87/70b9f40170a81afd55ca26c9b2acb25c20d64bcfbf888fafecb3ba077d4c/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea", size = 2138417, upload-time = "2026-05-06T13:39:45.476Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" }, + { url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" }, + { url = "https://files.pythonhosted.org/packages/11/cb/428de0385b6c8d44b716feba566abfacfbd23ee3c4439faa789a1456242f/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0", size = 2112782, upload-time = "2026-05-06T13:37:04.016Z" }, + { url = "https://files.pythonhosted.org/packages/0b/b5/6a17bdadd0fc1f170adfd05a20d37c832f52b117b4d9131da1f41bb097ce/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7", size = 1952146, upload-time = "2026-05-06T13:39:43.092Z" }, + { url = "https://files.pythonhosted.org/packages/2a/dc/03734d80e362cd43ef65428e9de77c730ce7f2f11c60d2b1e1b39f0fbf99/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2", size = 2134492, upload-time = "2026-05-06T13:36:58.124Z" }, + { url = "https://files.pythonhosted.org/packages/de/df/5e5ffc085ed07cc22d298134d3d911c63e91f6a0eb91fe646750a3209910/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9", size = 2156604, upload-time = "2026-05-06T13:37:49.88Z" }, + { url = "https://files.pythonhosted.org/packages/81/44/6e112a4253e56f5705467cbab7ab5e91ee7398ba3d56d358635958893d3e/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf", size = 2183828, upload-time = "2026-05-06T13:37:43.053Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ad/5565071e937d8e752842ac241463944c9eb14c87e2d269f2658a5bd05e98/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30", size = 2310000, upload-time = "2026-05-06T13:37:56.694Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c3/66883a5cec183e7fba4d024b4cbbe61851a63750ef606b0afecc46d1f2bf/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc", size = 2361286, upload-time = "2026-05-06T13:40:05.667Z" }, + { url = "https://files.pythonhosted.org/packages/4b/2d/69abac8f838090bbecd5df894befb2c2619e7996a98ddb949db9f3b93225/pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983", size = 2193071, upload-time = "2026-05-06T13:38:08.682Z" }, +] + +[[package]] +name = "pydantic-settings" +version = "2.14.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/b5/8f48e906c3e0205276e8bd8cb7512217a87b2685304d64be27cad5b3019f/pydantic_settings-2.14.2.tar.gz", hash = "sha256:c19dd64b19097f1de80184f0cc7b0272a13ae6e170cbf240a3e27e381ed14a5f", size = 237700, upload-time = "2026-06-19T13:44:56.324Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/c1/6e422f34e569cf8e18df68d1939c81c099d2b61e4f7d9621c8a77560799c/pydantic_settings-2.14.2-py3-none-any.whl", hash = "sha256:a20c97b37910b6550d5ea50fbcc2d4187defe58cd57070b73863d069419c9440", size = 61715, upload-time = "2026-06-19T13:44:55.02Z" }, +] + +[[package]] +name = "pydocstyle" +version = "6.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "snowballstemmer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e9/5c/d5385ca59fd065e3c6a5fe19f9bc9d5ea7f2509fa8c9c22fb6b2031dd953/pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1", size = 36796, upload-time = "2023-01-17T20:29:19.838Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/ea/99ddefac41971acad68f14114f38261c1f27dac0b3ec529824ebc739bdaa/pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019", size = 38038, upload-time = "2023-01-17T20:29:18.094Z" }, +] + +[[package]] +name = "pygments" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, +] + +[[package]] +name = "pyjwt" +version = "2.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515, upload-time = "2026-05-21T19:54:36.618Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/5e/ecf12fdb62546d64385c158514e9b2b671f7832108ef2ecd2020ce0af2d1/pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728", size = 31274, upload-time = "2026-05-21T19:54:35.362Z" }, +] + +[package.optional-dependencies] +crypto = [ + { name = "cryptography" }, +] + +[[package]] +name = "pylint" +version = "3.3.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "astroid" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "dill" }, + { name = "isort" }, + { name = "mccabe" }, + { name = "platformdirs" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "tomlkit" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/9d/81c84a312d1fa8133b0db0c76148542a98349298a01747ab122f9314b04e/pylint-3.3.9.tar.gz", hash = "sha256:d312737d7b25ccf6b01cc4ac629b5dcd14a0fcf3ec392735ac70f137a9d5f83a", size = 1525946, upload-time = "2025-10-05T18:41:43.786Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/a7/69460c4a6af7575449e615144aa2205b89408dc2969b87bc3df2f262ad0b/pylint-3.3.9-py3-none-any.whl", hash = "sha256:01f9b0462c7730f94786c283f3e52a1fbdf0494bbe0971a78d7277ef46a751e7", size = 523465, upload-time = "2025-10-05T18:41:41.766Z" }, +] + +[[package]] +name = "pyperclip" +version = "1.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/52/d87eba7cb129b81563019d1679026e7a112ef76855d6159d24754dbd2a51/pyperclip-1.11.0.tar.gz", hash = "sha256:244035963e4428530d9e3a6101a1ef97209c6825edab1567beac148ccc1db1b6", size = 12185, upload-time = "2025-09-26T14:40:37.245Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/80/fc9d01d5ed37ba4c42ca2b55b4339ae6e200b456be3a1aaddf4a9fa99b8c/pyperclip-1.11.0-py3-none-any.whl", hash = "sha256:299403e9ff44581cb9ba2ffeed69c7aa96a008622ad0c46cb575ca75b5b84273", size = 11063, upload-time = "2025-09-26T14:40:36.069Z" }, +] + +[[package]] +name = "pyproject-api" +version = "1.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/62/62/0fe346fe380b1aafaf819c8cb195d3241bb4f355f908e6339814131a830b/pyproject_api-1.10.1.tar.gz", hash = "sha256:c2b2726bd7aa9217b6c50b621fef5b2ae5def4d55b779c9e0694c15e0a8517ba", size = 23477, upload-time = "2026-05-28T14:22:14.049Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/d7/29e1e5e882f79133631f7bcace42d23db493f616463c157a1ab614bf69dd/pyproject_api-1.10.1-py3-none-any.whl", hash = "sha256:fa9e6f66c35b5017e909825d8f2b5d5482ea699d7be809d21c03bd1f7317f36a", size = 12992, upload-time = "2026-05-28T14:22:12.711Z" }, +] + +[[package]] +name = "pytest" +version = "9.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, +] + +[[package]] +name = "pytest-asyncio" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "backports-asyncio-runner", marker = "python_full_version < '3.11'" }, + { name = "pytest" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/43/7c/d36d04db312ecf4298932ef77e6e4a9e8ad017906e24e34f0b0c361a2473/pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42", size = 58514, upload-time = "2026-05-26T09:56:04.083Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/e2/08a497ef684b88559c9cc5f4ad53a37e7b99e727094a86d6ea32536d5d3c/pytest_asyncio-1.4.0-py3-none-any.whl", hash = "sha256:933ca923a23075a87fb7070c0ec272a6848489824d887c85c812670932835aa1", size = 16930, upload-time = "2026-05-26T09:56:02.576Z" }, +] + +[[package]] +name = "pytest-cov" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coverage", extra = ["toml"] }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/15/da3df99fd551507694a9b01f512a2f6cf1254f33601605843c3775f39460/pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6", size = 63245, upload-time = "2023-05-24T18:44:56.845Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/4b/8b78d126e275efa2379b1c2e09dc52cf70df16fc3b90613ef82531499d73/pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a", size = 21949, upload-time = "2023-05-24T18:44:54.079Z" }, +] + +[[package]] +name = "pytest-freezer" +version = "0.4.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "freezegun" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/81/f0/98dcbc5324064360b19850b14c84cea9ca50785d921741dbfc442346e925/pytest_freezer-0.4.9.tar.gz", hash = "sha256:21bf16bc9cc46bf98f94382c4b5c3c389be7056ff0be33029111ae11b3f1c82a", size = 3177, upload-time = "2024-12-12T08:53:08.684Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/e9/30252bc05bcf67200a17f4f0b4cc7598f0a68df4fa9fa356193aa899f145/pytest_freezer-0.4.9-py3-none-any.whl", hash = "sha256:8b6c50523b7d4aec4590b52bfa5ff766d772ce506e2bf4846c88041ea9ccae59", size = 3192, upload-time = "2024-12-12T08:53:07.641Z" }, +] + +[[package]] +name = "pytest-mock" +version = "3.15.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/68/14/eb014d26be205d38ad5ad20d9a80f7d201472e08167f0bb4361e251084a9/pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f", size = 34036, upload-time = "2025-09-16T16:37:27.081Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d", size = 10095, upload-time = "2025-09-16T16:37:25.734Z" }, +] + +[[package]] +name = "pytest-order" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/97/d8/82a5dc2aad3392f66c9741960fcbeeb45dd4d62eedb218aed6c52eea36eb/pytest_order-1.5.0.tar.gz", hash = "sha256:96acd7587b5a2855dcaa4a898288103d202894a61afd813adbc9b77aab04d90d", size = 54136, upload-time = "2026-06-13T05:39:41.636Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/5c/bd6a85b44beb8bd74c0e86ab699ef0e096e260dc90458b84fc54c28e4335/pytest_order-1.5.0-py3-none-any.whl", hash = "sha256:667ba2b7303fe2c529848663e0a41dfb0cc4d64f09f87272e4a9a1751efb52b2", size = 16634, upload-time = "2026-06-13T05:39:40.431Z" }, +] + +[[package]] +name = "pytest-recorder" +version = "0.6.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "black" }, + { name = "cryptography" }, + { name = "idna" }, + { name = "mypy" }, + { name = "pylint" }, + { name = "pytest" }, + { name = "pytest-mock" }, + { name = "time-machine" }, + { name = "vcrpy", marker = "platform_python_implementation == 'CPython'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/50/af42c0dd030259de336a4b93495e0021e66a107afd9c5ed87fc57f594971/pytest_recorder-0.6.6.tar.gz", hash = "sha256:1005b7a9d993a9d6c6fdc7cf18b48d687fb5324ab81da82fab65034362ffddb2", size = 16990, upload-time = "2026-06-24T17:02:45.574Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/06/07ca6377a619bb97c0debc7b97a5fc16b74ca632746eb1f0b6f3e8cb9194/pytest_recorder-0.6.6-py3-none-any.whl", hash = "sha256:66516eaeca0200a687f884e426bcdb6733ea0495c5e2d8bb4e3e2b0e8c595571", size = 22021, upload-time = "2026-06-24T17:02:46.445Z" }, +] + +[[package]] +name = "pytest-subtests" +version = "0.15.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bb/d9/20097971a8d315e011e055d512fa120fd6be3bdb8f4b3aa3e3c6bf77bebc/pytest_subtests-0.15.0.tar.gz", hash = "sha256:cb495bde05551b784b8f0b8adfaa27edb4131469a27c339b80fd8d6ba33f887c", size = 18525, upload-time = "2025-10-20T16:26:18.358Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/64/bba465299b37448b4c1b84c7a04178399ac22d47b3dc5db1874fe55a2bd3/pytest_subtests-0.15.0-py3-none-any.whl", hash = "sha256:da2d0ce348e1f8d831d5a40d81e3aeac439fec50bd5251cbb7791402696a9493", size = 9185, upload-time = "2025-10-20T16:26:17.239Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "python-discovery" +version = "1.4.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/26/8b004cc36f430345136f6f00fa1aa9ed596c8ed1e8504625fa79522ff39c/python_discovery-1.4.3.tar.gz", hash = "sha256:ad57d7045a862460d4a235986c33f13ed707d3aeb9153fa47eb7dfd0d4673289", size = 70438, upload-time = "2026-07-03T13:21:51.621Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/28/78/9b77ecb4644d1bbea94d29abf78f21c47eca6eb79e9745b702ec0bed2e19/python_discovery-1.4.3-py3-none-any.whl", hash = "sha256:b6e1e4a7d9e3f6948c39746ffe8218225162d738ba39d05ab1d2f6c1cac4878c", size = 33885, upload-time = "2026-07-03T13:21:50.174Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, +] + +[[package]] +name = "python-multipart" +version = "0.0.32" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/42/55c32bb9b12693c092ad250a0e82edb5b31ddeda6eb772de5f308b3804ad/python_multipart-0.0.32.tar.gz", hash = "sha256:be54b7f3fa167bb83e4fcd936b887b708f4e57fe75911c02aebf53efaf8d938e", size = 46881, upload-time = "2026-06-04T16:18:58.647Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/04/e8135ebd1ad02c56ec633277529b2602ff99ff634be76cdba5744cf554fd/python_multipart-0.0.32-py3-none-any.whl", hash = "sha256:ff6d3f776f16878c894e52e107296ffc890e913c611b1a4ec6c44e2821fe2e23", size = 30042, upload-time = "2026-06-04T16:18:57.319Z" }, +] + +[[package]] +name = "pytokens" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b6/34/b4e015b99031667a7b960f888889c5bd34ef585c85e1cb56a594b92836ac/pytokens-0.4.1.tar.gz", hash = "sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a", size = 23015, upload-time = "2026-01-30T01:03:45.924Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/24/f206113e05cb8ef51b3850e7ef88f20da6f4bf932190ceb48bd3da103e10/pytokens-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a44ed93ea23415c54f3face3b65ef2b844d96aeb3455b8a69b3df6beab6acc5", size = 161522, upload-time = "2026-01-30T01:02:50.393Z" }, + { url = "https://files.pythonhosted.org/packages/d4/e9/06a6bf1b90c2ed81a9c7d2544232fe5d2891d1cd480e8a1809ca354a8eb2/pytokens-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:add8bf86b71a5d9fb5b89f023a80b791e04fba57960aa790cc6125f7f1d39dfe", size = 246945, upload-time = "2026-01-30T01:02:52.399Z" }, + { url = "https://files.pythonhosted.org/packages/69/66/f6fb1007a4c3d8b682d5d65b7c1fb33257587a5f782647091e3408abe0b8/pytokens-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:670d286910b531c7b7e3c0b453fd8156f250adb140146d234a82219459b9640c", size = 259525, upload-time = "2026-01-30T01:02:53.737Z" }, + { url = "https://files.pythonhosted.org/packages/04/92/086f89b4d622a18418bac74ab5db7f68cf0c21cf7cc92de6c7b919d76c88/pytokens-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4e691d7f5186bd2842c14813f79f8884bb03f5995f0575272009982c5ac6c0f7", size = 262693, upload-time = "2026-01-30T01:02:54.871Z" }, + { url = "https://files.pythonhosted.org/packages/b4/7b/8b31c347cf94a3f900bdde750b2e9131575a61fdb620d3d3c75832262137/pytokens-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:27b83ad28825978742beef057bfe406ad6ed524b2d28c252c5de7b4a6dd48fa2", size = 103567, upload-time = "2026-01-30T01:02:56.414Z" }, + { url = "https://files.pythonhosted.org/packages/3d/92/790ebe03f07b57e53b10884c329b9a1a308648fc083a6d4a39a10a28c8fc/pytokens-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d70e77c55ae8380c91c0c18dea05951482e263982911fc7410b1ffd1dadd3440", size = 160864, upload-time = "2026-01-30T01:02:57.882Z" }, + { url = "https://files.pythonhosted.org/packages/13/25/a4f555281d975bfdd1eba731450e2fe3a95870274da73fb12c40aeae7625/pytokens-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a58d057208cb9075c144950d789511220b07636dd2e4708d5645d24de666bdc", size = 248565, upload-time = "2026-01-30T01:02:59.912Z" }, + { url = "https://files.pythonhosted.org/packages/17/50/bc0394b4ad5b1601be22fa43652173d47e4c9efbf0044c62e9a59b747c56/pytokens-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b49750419d300e2b5a3813cf229d4e5a4c728dae470bcc89867a9ad6f25a722d", size = 260824, upload-time = "2026-01-30T01:03:01.471Z" }, + { url = "https://files.pythonhosted.org/packages/4e/54/3e04f9d92a4be4fc6c80016bc396b923d2a6933ae94b5f557c939c460ee0/pytokens-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9907d61f15bf7261d7e775bd5d7ee4d2930e04424bab1972591918497623a16", size = 264075, upload-time = "2026-01-30T01:03:04.143Z" }, + { url = "https://files.pythonhosted.org/packages/d1/1b/44b0326cb5470a4375f37988aea5d61b5cc52407143303015ebee94abfd6/pytokens-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee44d0f85b803321710f9239f335aafe16553b39106384cef8e6de40cb4ef2f6", size = 103323, upload-time = "2026-01-30T01:03:05.412Z" }, + { url = "https://files.pythonhosted.org/packages/41/5d/e44573011401fb82e9d51e97f1290ceb377800fb4eed650b96f4753b499c/pytokens-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:140709331e846b728475786df8aeb27d24f48cbcf7bcd449f8de75cae7a45083", size = 160663, upload-time = "2026-01-30T01:03:06.473Z" }, + { url = "https://files.pythonhosted.org/packages/f0/e6/5bbc3019f8e6f21d09c41f8b8654536117e5e211a85d89212d59cbdab381/pytokens-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d6c4268598f762bc8e91f5dbf2ab2f61f7b95bdc07953b602db879b3c8c18e1", size = 255626, upload-time = "2026-01-30T01:03:08.177Z" }, + { url = "https://files.pythonhosted.org/packages/bf/3c/2d5297d82286f6f3d92770289fd439956b201c0a4fc7e72efb9b2293758e/pytokens-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24afde1f53d95348b5a0eb19488661147285ca4dd7ed752bbc3e1c6242a304d1", size = 269779, upload-time = "2026-01-30T01:03:09.756Z" }, + { url = "https://files.pythonhosted.org/packages/20/01/7436e9ad693cebda0551203e0bf28f7669976c60ad07d6402098208476de/pytokens-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5ad948d085ed6c16413eb5fec6b3e02fa00dc29a2534f088d3302c47eb59adf9", size = 268076, upload-time = "2026-01-30T01:03:10.957Z" }, + { url = "https://files.pythonhosted.org/packages/2e/df/533c82a3c752ba13ae7ef238b7f8cdd272cf1475f03c63ac6cf3fcfb00b6/pytokens-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:3f901fe783e06e48e8cbdc82d631fca8f118333798193e026a50ce1b3757ea68", size = 103552, upload-time = "2026-01-30T01:03:12.066Z" }, + { url = "https://files.pythonhosted.org/packages/cb/dc/08b1a080372afda3cceb4f3c0a7ba2bde9d6a5241f1edb02a22a019ee147/pytokens-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8bdb9d0ce90cbf99c525e75a2fa415144fd570a1ba987380190e8b786bc6ef9b", size = 160720, upload-time = "2026-01-30T01:03:13.843Z" }, + { url = "https://files.pythonhosted.org/packages/64/0c/41ea22205da480837a700e395507e6a24425151dfb7ead73343d6e2d7ffe/pytokens-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5502408cab1cb18e128570f8d598981c68a50d0cbd7c61312a90507cd3a1276f", size = 254204, upload-time = "2026-01-30T01:03:14.886Z" }, + { url = "https://files.pythonhosted.org/packages/e0/d2/afe5c7f8607018beb99971489dbb846508f1b8f351fcefc225fcf4b2adc0/pytokens-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29d1d8fb1030af4d231789959f21821ab6325e463f0503a61d204343c9b355d1", size = 268423, upload-time = "2026-01-30T01:03:15.936Z" }, + { url = "https://files.pythonhosted.org/packages/68/d4/00ffdbd370410c04e9591da9220a68dc1693ef7499173eb3e30d06e05ed1/pytokens-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b08dd6b86058b6dc07efe9e98414f5102974716232d10f32ff39701e841c4", size = 266859, upload-time = "2026-01-30T01:03:17.458Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c9/c3161313b4ca0c601eeefabd3d3b576edaa9afdefd32da97210700e47652/pytokens-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:9bd7d7f544d362576be74f9d5901a22f317efc20046efe2034dced238cbbfe78", size = 103520, upload-time = "2026-01-30T01:03:18.652Z" }, + { url = "https://files.pythonhosted.org/packages/8f/a7/b470f672e6fc5fee0a01d9e75005a0e617e162381974213a945fcd274843/pytokens-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4a14d5f5fc78ce85e426aa159489e2d5961acf0e47575e08f35584009178e321", size = 160821, upload-time = "2026-01-30T01:03:19.684Z" }, + { url = "https://files.pythonhosted.org/packages/80/98/e83a36fe8d170c911f864bfded690d2542bfcfacb9c649d11a9e6eb9dc41/pytokens-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f50fd18543be72da51dd505e2ed20d2228c74e0464e4262e4899797803d7fa", size = 254263, upload-time = "2026-01-30T01:03:20.834Z" }, + { url = "https://files.pythonhosted.org/packages/0f/95/70d7041273890f9f97a24234c00b746e8da86df462620194cef1d411ddeb/pytokens-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc74c035f9bfca0255c1af77ddd2d6ae8419012805453e4b0e7513e17904545d", size = 268071, upload-time = "2026-01-30T01:03:21.888Z" }, + { url = "https://files.pythonhosted.org/packages/da/79/76e6d09ae19c99404656d7db9c35dfd20f2086f3eb6ecb496b5b31163bad/pytokens-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f66a6bbe741bd431f6d741e617e0f39ec7257ca1f89089593479347cc4d13324", size = 271716, upload-time = "2026-01-30T01:03:23.633Z" }, + { url = "https://files.pythonhosted.org/packages/79/37/482e55fa1602e0a7ff012661d8c946bafdc05e480ea5a32f4f7e336d4aa9/pytokens-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:b35d7e5ad269804f6697727702da3c517bb8a5228afa450ab0fa787732055fc9", size = 104539, upload-time = "2026-01-30T01:03:24.788Z" }, + { url = "https://files.pythonhosted.org/packages/30/e8/20e7db907c23f3d63b0be3b8a4fd1927f6da2395f5bcc7f72242bb963dfe/pytokens-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8fcb9ba3709ff77e77f1c7022ff11d13553f3c30299a9fe246a166903e9091eb", size = 168474, upload-time = "2026-01-30T01:03:26.428Z" }, + { url = "https://files.pythonhosted.org/packages/d6/81/88a95ee9fafdd8f5f3452107748fd04c24930d500b9aba9738f3ade642cc/pytokens-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79fc6b8699564e1f9b521582c35435f1bd32dd06822322ec44afdeba666d8cb3", size = 290473, upload-time = "2026-01-30T01:03:27.415Z" }, + { url = "https://files.pythonhosted.org/packages/cf/35/3aa899645e29b6375b4aed9f8d21df219e7c958c4c186b465e42ee0a06bf/pytokens-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d31b97b3de0f61571a124a00ffe9a81fb9939146c122c11060725bd5aea79975", size = 303485, upload-time = "2026-01-30T01:03:28.558Z" }, + { url = "https://files.pythonhosted.org/packages/52/a0/07907b6ff512674d9b201859f7d212298c44933633c946703a20c25e9d81/pytokens-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:967cf6e3fd4adf7de8fc73cd3043754ae79c36475c1c11d514fc72cf5490094a", size = 306698, upload-time = "2026-01-30T01:03:29.653Z" }, + { url = "https://files.pythonhosted.org/packages/39/2a/cbbf9250020a4a8dd53ba83a46c097b69e5eb49dd14e708f496f548c6612/pytokens-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:584c80c24b078eec1e227079d56dc22ff755e0ba8654d8383b2c549107528918", size = 116287, upload-time = "2026-01-30T01:03:30.912Z" }, + { url = "https://files.pythonhosted.org/packages/c6/78/397db326746f0a342855b81216ae1f0a32965deccfd7c830a2dbc66d2483/pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de", size = 13729, upload-time = "2026-01-30T01:03:45.029Z" }, +] + +[[package]] +name = "pytz" +version = "2026.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ff/46/dd499ec9038423421951e4fad73051febaa13d2df82b4064f87af8b8c0c3/pytz-2026.2.tar.gz", hash = "sha256:0e60b47b29f21574376f218fe21abc009894a2321ea16c6754f3cad6eb7cdd6a", size = 320861, upload-time = "2026-05-04T01:35:29.667Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/dd/96da98f892250475bdf2328112d7468abdd4acc7b902b6af23f4ed958ea0/pytz-2026.2-py2.py3-none-any.whl", hash = "sha256:04156e608bee23d3792fd45c94ae47fae1036688e75032eea2e3bf0323d1f126", size = 510141, upload-time = "2026-05-04T01:35:27.408Z" }, +] + +[[package]] +name = "pywin32" +version = "312" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/1b/9cfdeac80ee45bebbbcb31f1b7b99a0d81a1c72de48d837be984e0e88b1d/pywin32-312-cp310-cp310-win32.whl", hash = "sha256:772235332b5d1024c696f11cea1ae4be7930f0a8b894bb43db14e3f435f1ff7e", size = 6361387, upload-time = "2026-06-04T07:49:14.329Z" }, + { url = "https://files.pythonhosted.org/packages/33/b1/7afc96d041d982c27bc2df6f853d43f01fd273e3d39d04be3647ddeb533d/pywin32-312-cp310-cp310-win_amd64.whl", hash = "sha256:5dbc35d2b5320dc07f25fa31269cfb767471002b17de5eb067d03da68c7cb2db", size = 6926780, upload-time = "2026-06-04T07:49:16.881Z" }, + { url = "https://files.pythonhosted.org/packages/ce/3a/4140da9ad54108e517f4a16b2d83da3033e08662144623e1239587cb7db6/pywin32-312-cp310-cp310-win_arm64.whl", hash = "sha256:3020656e34f1cf7faeb7bccd2b84653a607c6ff0c55ada85e6487d61716deabd", size = 4307203, upload-time = "2026-06-04T07:49:18.993Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f5/10a6e845a00fc5e7afd0a988b744f403d4d57162a28d160a093c4d9322f0/pywin32-312-cp311-cp311-win32.whl", hash = "sha256:17948aeadbdb091f0ced6ef0841620794e68327b94ee415571c1203594b7215c", size = 6362659, upload-time = "2026-06-04T07:49:21.349Z" }, + { url = "https://files.pythonhosted.org/packages/35/c4/dcd2d62b5944b6d5db53413a5899016ccd57ffcb7278f3f81655d25d2027/pywin32-312-cp311-cp311-win_amd64.whl", hash = "sha256:d11417d84412f859b722fad0841b3614459ed0047f7542d8362e77884f6b6e8a", size = 6928825, upload-time = "2026-06-04T07:49:23.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/56/3cbb433fe4501cdba2eb9040f56a4e1a8243faa4186b25295564d1a7a79d/pywin32-312-cp311-cp311-win_arm64.whl", hash = "sha256:b2200a054ca6d6625c4842fc56a4976a4b47f96b73dbe5538c3f813a80359f47", size = 6721875, upload-time = "2026-06-04T07:49:26.416Z" }, + { url = "https://files.pythonhosted.org/packages/83/ff/32aa7d2ed0ab12b323aaa64f9b75e6ad4f8fd09f9ccfc28c79414d46838d/pywin32-312-cp312-cp312-win32.whl", hash = "sha256:dab4f65ac9c4e48400a2a0530c46c3c579cd5905ecd11b80692373915269208b", size = 6371877, upload-time = "2026-06-04T07:49:28.836Z" }, + { url = "https://files.pythonhosted.org/packages/03/d9/77040d3b43df3f3be32ea289433d660d2727f5ba327bc73be835127d9d60/pywin32-312-cp312-cp312-win_amd64.whl", hash = "sha256:b457f6d628a47e8a7346ce22acb7e1a46a4a78b52e1d17e1af56871bd19a93bc", size = 6914841, upload-time = "2026-06-04T07:49:31.85Z" }, + { url = "https://files.pythonhosted.org/packages/e3/cc/7b1ec671775756020a0ee7f4feeaf3c568f0ab86bd3900088cf986937a92/pywin32-312-cp312-cp312-win_arm64.whl", hash = "sha256:6017c58e12f6809fbb0555b75df144c2922a9ffd18e4b9b5afa863b6c1a9d950", size = 6727901, upload-time = "2026-06-04T07:49:34.244Z" }, + { url = "https://files.pythonhosted.org/packages/2d/41/12fbfd7f36ed2146d8bc9de96c2741296bf0d490b98508496cff322e274c/pywin32-312-cp313-cp313-win32.whl", hash = "sha256:7a27df850933d16a8eabfbaeb73d52b273e2da667f80d70b01a89d1f6828d02c", size = 6370184, upload-time = "2026-06-04T07:49:36.253Z" }, + { url = "https://files.pythonhosted.org/packages/ba/db/36a78e3403099d31d9746d13fdcde5accc43c1155f375a34d15983a479a7/pywin32-312-cp313-cp313-win_amd64.whl", hash = "sha256:c53e878d15a1c44788082bfe712a905433473aa38f86375b7cf8b45e3acbaaf9", size = 6914298, upload-time = "2026-06-04T07:49:38.876Z" }, + { url = "https://files.pythonhosted.org/packages/84/37/c1697194092b76de9ed47ca124323f02c57ffc8a45c06f88a3d5acaf01eb/pywin32-312-cp313-cp313-win_arm64.whl", hash = "sha256:59aba5d5940842075343a5ddc6b11f1cdf0d1567fe745290359dfbcc7c2eb831", size = 6727640, upload-time = "2026-06-04T07:49:41.083Z" }, + { url = "https://files.pythonhosted.org/packages/fc/2b/1f3cded5822fd49c02f40544cbb5f58c7cfd6b1694869fd476cb6170ee97/pywin32-312-cp314-cp314-win32.whl", hash = "sha256:a77a90fbb6881238d2ca9c6fd797b25817f3768fe78d214a90137ff055a75f5b", size = 6468928, upload-time = "2026-06-04T07:49:43.188Z" }, + { url = "https://files.pythonhosted.org/packages/21/82/3bf86d2e2808902013132e1ce905a7da0da53790f3836c64bf44d55e24f3/pywin32-312-cp314-cp314-win_amd64.whl", hash = "sha256:a4dd3a848290ef724347b19f301045831d8e802fa4464f491b98b1e0a081432e", size = 7024157, upload-time = "2026-06-04T07:49:45.34Z" }, + { url = "https://files.pythonhosted.org/packages/a4/0e/73f6d6800b4f27655abd9e9f6aaeaefcddb2b946e4674efa2bab184a7f7b/pywin32-312-cp314-cp314-win_arm64.whl", hash = "sha256:9fce94568364e0155e6dfb781ac5d95903be8baf28670632beab1b523f300daa", size = 6839598, upload-time = "2026-06-04T07:49:47.613Z" }, + { url = "https://files.pythonhosted.org/packages/eb/61/caa39686032d2ebdd04ff0ab5cbe163126c0066d98e00c9018646e42393b/pywin32-312-cp315-cp315-win32.whl", hash = "sha256:5c1fbe4a937a73ae9297384a3da38518cbc694c68ad8a809b2e19acd350f03ed", size = 6471159, upload-time = "2026-06-04T07:49:50.035Z" }, + { url = "https://files.pythonhosted.org/packages/0f/cd/7e1de64a4a6f69c04214169657ccab0d93a670ea50e35eb8f489d7378249/pywin32-312-cp315-cp315-win_amd64.whl", hash = "sha256:c2f03a0f73f804a13c2735b99392b0cd426bb4f2c4d0178e5ac966a0f21618d5", size = 7025293, upload-time = "2026-06-04T07:49:54.857Z" }, + { url = "https://files.pythonhosted.org/packages/23/ed/4532e9388e65fa16b46776ef47ad631a64eda1631884488af707666350ed/pywin32-312-cp315-cp315-win_arm64.whl", hash = "sha256:a8597d28f267b39074aef51fa593530082b39cbe5a074226096857b1fed2dfb9", size = 6840337, upload-time = "2026-06-04T07:49:57.531Z" }, +] + +[[package]] +name = "pywin32-ctypes" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, + { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, + { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, + { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, + { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, + { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, + { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, + { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, + { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "pyzmq" +version = "27.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "implementation_name == 'pypy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750, upload-time = "2025-09-08T23:10:18.157Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/b9/52aa9ec2867528b54f1e60846728d8b4d84726630874fee3a91e66c7df81/pyzmq-27.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:508e23ec9bc44c0005c4946ea013d9317ae00ac67778bd47519fdf5a0e930ff4", size = 1329850, upload-time = "2025-09-08T23:07:26.274Z" }, + { url = "https://files.pythonhosted.org/packages/99/64/5653e7b7425b169f994835a2b2abf9486264401fdef18df91ddae47ce2cc/pyzmq-27.1.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:507b6f430bdcf0ee48c0d30e734ea89ce5567fd7b8a0f0044a369c176aa44556", size = 906380, upload-time = "2025-09-08T23:07:29.78Z" }, + { url = "https://files.pythonhosted.org/packages/73/78/7d713284dbe022f6440e391bd1f3c48d9185673878034cfb3939cdf333b2/pyzmq-27.1.0-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf7b38f9fd7b81cb6d9391b2946382c8237fd814075c6aa9c3b746d53076023b", size = 666421, upload-time = "2025-09-08T23:07:31.263Z" }, + { url = "https://files.pythonhosted.org/packages/30/76/8f099f9d6482450428b17c4d6b241281af7ce6a9de8149ca8c1c649f6792/pyzmq-27.1.0-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03ff0b279b40d687691a6217c12242ee71f0fba28bf8626ff50e3ef0f4410e1e", size = 854149, upload-time = "2025-09-08T23:07:33.17Z" }, + { url = "https://files.pythonhosted.org/packages/59/f0/37fbfff06c68016019043897e4c969ceab18bde46cd2aca89821fcf4fb2e/pyzmq-27.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:677e744fee605753eac48198b15a2124016c009a11056f93807000ab11ce6526", size = 1655070, upload-time = "2025-09-08T23:07:35.205Z" }, + { url = "https://files.pythonhosted.org/packages/47/14/7254be73f7a8edc3587609554fcaa7bfd30649bf89cd260e4487ca70fdaa/pyzmq-27.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd2fec2b13137416a1c5648b7009499bcc8fea78154cd888855fa32514f3dad1", size = 2033441, upload-time = "2025-09-08T23:07:37.432Z" }, + { url = "https://files.pythonhosted.org/packages/22/dc/49f2be26c6f86f347e796a4d99b19167fc94503f0af3fd010ad262158822/pyzmq-27.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:08e90bb4b57603b84eab1d0ca05b3bbb10f60c1839dc471fc1c9e1507bef3386", size = 1891529, upload-time = "2025-09-08T23:07:39.047Z" }, + { url = "https://files.pythonhosted.org/packages/a3/3e/154fb963ae25be70c0064ce97776c937ecc7d8b0259f22858154a9999769/pyzmq-27.1.0-cp310-cp310-win32.whl", hash = "sha256:a5b42d7a0658b515319148875fcb782bbf118dd41c671b62dae33666c2213bda", size = 567276, upload-time = "2025-09-08T23:07:40.695Z" }, + { url = "https://files.pythonhosted.org/packages/62/b2/f4ab56c8c595abcb26b2be5fd9fa9e6899c1e5ad54964e93ae8bb35482be/pyzmq-27.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:c0bb87227430ee3aefcc0ade2088100e528d5d3298a0a715a64f3d04c60ba02f", size = 632208, upload-time = "2025-09-08T23:07:42.298Z" }, + { url = "https://files.pythonhosted.org/packages/3b/e3/be2cc7ab8332bdac0522fdb64c17b1b6241a795bee02e0196636ec5beb79/pyzmq-27.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:9a916f76c2ab8d045b19f2286851a38e9ac94ea91faf65bd64735924522a8b32", size = 559766, upload-time = "2025-09-08T23:07:43.869Z" }, + { url = "https://files.pythonhosted.org/packages/06/5d/305323ba86b284e6fcb0d842d6adaa2999035f70f8c38a9b6d21ad28c3d4/pyzmq-27.1.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:226b091818d461a3bef763805e75685e478ac17e9008f49fce2d3e52b3d58b86", size = 1333328, upload-time = "2025-09-08T23:07:45.946Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a0/fc7e78a23748ad5443ac3275943457e8452da67fda347e05260261108cbc/pyzmq-27.1.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0790a0161c281ca9723f804871b4027f2e8b5a528d357c8952d08cd1a9c15581", size = 908803, upload-time = "2025-09-08T23:07:47.551Z" }, + { url = "https://files.pythonhosted.org/packages/7e/22/37d15eb05f3bdfa4abea6f6d96eb3bb58585fbd3e4e0ded4e743bc650c97/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c895a6f35476b0c3a54e3eb6ccf41bf3018de937016e6e18748317f25d4e925f", size = 668836, upload-time = "2025-09-08T23:07:49.436Z" }, + { url = "https://files.pythonhosted.org/packages/b1/c4/2a6fe5111a01005fc7af3878259ce17684fabb8852815eda6225620f3c59/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bbf8d3630bf96550b3be8e1fc0fea5cbdc8d5466c1192887bd94869da17a63e", size = 857038, upload-time = "2025-09-08T23:07:51.234Z" }, + { url = "https://files.pythonhosted.org/packages/cb/eb/bfdcb41d0db9cd233d6fb22dc131583774135505ada800ebf14dfb0a7c40/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:15c8bd0fe0dabf808e2d7a681398c4e5ded70a551ab47482067a572c054c8e2e", size = 1657531, upload-time = "2025-09-08T23:07:52.795Z" }, + { url = "https://files.pythonhosted.org/packages/ab/21/e3180ca269ed4a0de5c34417dfe71a8ae80421198be83ee619a8a485b0c7/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bafcb3dd171b4ae9f19ee6380dfc71ce0390fefaf26b504c0e5f628d7c8c54f2", size = 2034786, upload-time = "2025-09-08T23:07:55.047Z" }, + { url = "https://files.pythonhosted.org/packages/3b/b1/5e21d0b517434b7f33588ff76c177c5a167858cc38ef740608898cd329f2/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e829529fcaa09937189178115c49c504e69289abd39967cd8a4c215761373394", size = 1894220, upload-time = "2025-09-08T23:07:57.172Z" }, + { url = "https://files.pythonhosted.org/packages/03/f2/44913a6ff6941905efc24a1acf3d3cb6146b636c546c7406c38c49c403d4/pyzmq-27.1.0-cp311-cp311-win32.whl", hash = "sha256:6df079c47d5902af6db298ec92151db82ecb557af663098b92f2508c398bb54f", size = 567155, upload-time = "2025-09-08T23:07:59.05Z" }, + { url = "https://files.pythonhosted.org/packages/23/6d/d8d92a0eb270a925c9b4dd039c0b4dc10abc2fcbc48331788824ef113935/pyzmq-27.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:190cbf120fbc0fc4957b56866830def56628934a9d112aec0e2507aa6a032b97", size = 633428, upload-time = "2025-09-08T23:08:00.663Z" }, + { url = "https://files.pythonhosted.org/packages/ae/14/01afebc96c5abbbd713ecfc7469cfb1bc801c819a74ed5c9fad9a48801cb/pyzmq-27.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:eca6b47df11a132d1745eb3b5b5e557a7dae2c303277aa0e69c6ba91b8736e07", size = 559497, upload-time = "2025-09-08T23:08:02.15Z" }, + { url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc", size = 1306279, upload-time = "2025-09-08T23:08:03.807Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113", size = 895645, upload-time = "2025-09-08T23:08:05.301Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233", size = 652574, upload-time = "2025-09-08T23:08:06.828Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31", size = 840995, upload-time = "2025-09-08T23:08:08.396Z" }, + { url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28", size = 1642070, upload-time = "2025-09-08T23:08:09.989Z" }, + { url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856", size = 2021121, upload-time = "2025-09-08T23:08:11.907Z" }, + { url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496", size = 1878550, upload-time = "2025-09-08T23:08:13.513Z" }, + { url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd", size = 559184, upload-time = "2025-09-08T23:08:15.163Z" }, + { url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf", size = 619480, upload-time = "2025-09-08T23:08:17.192Z" }, + { url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f", size = 552993, upload-time = "2025-09-08T23:08:18.926Z" }, + { url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5", size = 1122436, upload-time = "2025-09-08T23:08:20.801Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6", size = 1156301, upload-time = "2025-09-08T23:08:22.47Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7", size = 1341197, upload-time = "2025-09-08T23:08:24.286Z" }, + { url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05", size = 897275, upload-time = "2025-09-08T23:08:26.063Z" }, + { url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9", size = 660469, upload-time = "2025-09-08T23:08:27.623Z" }, + { url = "https://files.pythonhosted.org/packages/3e/cd/9822a7af117f4bc0f1952dbe9ef8358eb50a24928efd5edf54210b850259/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128", size = 847961, upload-time = "2025-09-08T23:08:29.672Z" }, + { url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39", size = 1650282, upload-time = "2025-09-08T23:08:31.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97", size = 2024468, upload-time = "2025-09-08T23:08:33.543Z" }, + { url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db", size = 1885394, upload-time = "2025-09-08T23:08:35.51Z" }, + { url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl", hash = "sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c", size = 574964, upload-time = "2025-09-08T23:08:37.178Z" }, + { url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2", size = 641029, upload-time = "2025-09-08T23:08:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e", size = 561541, upload-time = "2025-09-08T23:08:42.668Z" }, + { url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a", size = 1341197, upload-time = "2025-09-08T23:08:44.973Z" }, + { url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea", size = 897175, upload-time = "2025-09-08T23:08:46.601Z" }, + { url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96", size = 660427, upload-time = "2025-09-08T23:08:48.187Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d2/5f36552c2d3e5685abe60dfa56f91169f7a2d99bbaf67c5271022ab40863/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d", size = 847929, upload-time = "2025-09-08T23:08:49.76Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146", size = 1650193, upload-time = "2025-09-08T23:08:51.7Z" }, + { url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd", size = 2024388, upload-time = "2025-09-08T23:08:53.393Z" }, + { url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a", size = 1885316, upload-time = "2025-09-08T23:08:55.702Z" }, + { url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472, upload-time = "2025-09-08T23:08:58.18Z" }, + { url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401, upload-time = "2025-09-08T23:08:59.802Z" }, + { url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170, upload-time = "2025-09-08T23:09:01.418Z" }, + { url = "https://files.pythonhosted.org/packages/f3/81/a65e71c1552f74dec9dff91d95bafb6e0d33338a8dfefbc88aa562a20c92/pyzmq-27.1.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c17e03cbc9312bee223864f1a2b13a99522e0dc9f7c5df0177cd45210ac286e6", size = 836266, upload-time = "2025-09-08T23:09:40.048Z" }, + { url = "https://files.pythonhosted.org/packages/58/ed/0202ca350f4f2b69faa95c6d931e3c05c3a397c184cacb84cb4f8f42f287/pyzmq-27.1.0-pp310-pypy310_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f328d01128373cb6763823b2b4e7f73bdf767834268c565151eacb3b7a392f90", size = 800206, upload-time = "2025-09-08T23:09:41.902Z" }, + { url = "https://files.pythonhosted.org/packages/47/42/1ff831fa87fe8f0a840ddb399054ca0009605d820e2b44ea43114f5459f4/pyzmq-27.1.0-pp310-pypy310_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c1790386614232e1b3a40a958454bdd42c6d1811837b15ddbb052a032a43f62", size = 567747, upload-time = "2025-09-08T23:09:43.741Z" }, + { url = "https://files.pythonhosted.org/packages/d1/db/5c4d6807434751e3f21231bee98109aa57b9b9b55e058e450d0aef59b70f/pyzmq-27.1.0-pp310-pypy310_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:448f9cb54eb0cee4732b46584f2710c8bc178b0e5371d9e4fc8125201e413a74", size = 747371, upload-time = "2025-09-08T23:09:45.575Z" }, + { url = "https://files.pythonhosted.org/packages/26/af/78ce193dbf03567eb8c0dc30e3df2b9e56f12a670bf7eb20f9fb532c7e8a/pyzmq-27.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:05b12f2d32112bf8c95ef2e74ec4f1d4beb01f8b5e703b38537f8849f92cb9ba", size = 544862, upload-time = "2025-09-08T23:09:47.448Z" }, + { url = "https://files.pythonhosted.org/packages/4c/c6/c4dcdecdbaa70969ee1fdced6d7b8f60cfabe64d25361f27ac4665a70620/pyzmq-27.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:18770c8d3563715387139060d37859c02ce40718d1faf299abddcdcc6a649066", size = 836265, upload-time = "2025-09-08T23:09:49.376Z" }, + { url = "https://files.pythonhosted.org/packages/3e/79/f38c92eeaeb03a2ccc2ba9866f0439593bb08c5e3b714ac1d553e5c96e25/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:ac25465d42f92e990f8d8b0546b01c391ad431c3bf447683fdc40565941d0604", size = 800208, upload-time = "2025-09-08T23:09:51.073Z" }, + { url = "https://files.pythonhosted.org/packages/49/0e/3f0d0d335c6b3abb9b7b723776d0b21fa7f3a6c819a0db6097059aada160/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53b40f8ae006f2734ee7608d59ed661419f087521edbfc2149c3932e9c14808c", size = 567747, upload-time = "2025-09-08T23:09:52.698Z" }, + { url = "https://files.pythonhosted.org/packages/a1/cf/f2b3784d536250ffd4be70e049f3b60981235d70c6e8ce7e3ef21e1adb25/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f605d884e7c8be8fe1aa94e0a783bf3f591b84c24e4bc4f3e7564c82ac25e271", size = 747371, upload-time = "2025-09-08T23:09:54.563Z" }, + { url = "https://files.pythonhosted.org/packages/01/1b/5dbe84eefc86f48473947e2f41711aded97eecef1231f4558f1f02713c12/pyzmq-27.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c9f7f6e13dff2e44a6afeaf2cf54cee5929ad64afaf4d40b50f93c58fc687355", size = 544862, upload-time = "2025-09-08T23:09:56.509Z" }, +] + +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py", version = "0.30.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "rpds-py", version = "2026.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + +[[package]] +name = "requests" +version = "2.34.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, +] + +[[package]] +name = "rich" +version = "15.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, +] + +[[package]] +name = "rich-rst" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments" }, + { name = "rich" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e2/d6/d0b9fafc73b65767200da027acab1db1bdb1048f4fea5ebf659df01c700e/rich_rst-2.1.0.tar.gz", hash = "sha256:f4d117b49697f338769759fa5cacf5197da4888b347b9fda2e50aef5cd8d93bd", size = 302732, upload-time = "2026-07-05T02:59:44.308Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/68/1fc93dd759605b5d00fc98b50200739e41ed32bd22d6ba35ca6c3932371b/rich_rst-2.1.0-py3-none-any.whl", hash = "sha256:7ecd1343ee12c879d0e7ae74c3eb6d263b023d2929c6d114212eb1fd91057255", size = 272987, upload-time = "2026-07-05T02:59:42.792Z" }, +] + +[[package]] +name = "rpds-py" +version = "0.30.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/0c/0c411a0ec64ccb6d104dcabe0e713e05e153a9a2c3c2bd2b32ce412166fe/rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288", size = 370490, upload-time = "2025-11-30T20:21:33.256Z" }, + { url = "https://files.pythonhosted.org/packages/19/6a/4ba3d0fb7297ebae71171822554abe48d7cab29c28b8f9f2c04b79988c05/rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00", size = 359751, upload-time = "2025-11-30T20:21:34.591Z" }, + { url = "https://files.pythonhosted.org/packages/cd/7c/e4933565ef7f7a0818985d87c15d9d273f1a649afa6a52ea35ad011195ea/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389a2d49eded1896c3d48b0136ead37c48e221b391c052fba3f4055c367f60a6", size = 389696, upload-time = "2025-11-30T20:21:36.122Z" }, + { url = "https://files.pythonhosted.org/packages/5e/01/6271a2511ad0815f00f7ed4390cf2567bec1d4b1da39e2c27a41e6e3b4de/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:32c8528634e1bf7121f3de08fa85b138f4e0dc47657866630611b03967f041d7", size = 403136, upload-time = "2025-11-30T20:21:37.728Z" }, + { url = "https://files.pythonhosted.org/packages/55/64/c857eb7cd7541e9b4eee9d49c196e833128a55b89a9850a9c9ac33ccf897/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f207f69853edd6f6700b86efb84999651baf3789e78a466431df1331608e5324", size = 524699, upload-time = "2025-11-30T20:21:38.92Z" }, + { url = "https://files.pythonhosted.org/packages/9c/ed/94816543404078af9ab26159c44f9e98e20fe47e2126d5d32c9d9948d10a/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67b02ec25ba7a9e8fa74c63b6ca44cf5707f2fbfadae3ee8e7494297d56aa9df", size = 412022, upload-time = "2025-11-30T20:21:40.407Z" }, + { url = "https://files.pythonhosted.org/packages/61/b5/707f6cf0066a6412aacc11d17920ea2e19e5b2f04081c64526eb35b5c6e7/rpds_py-0.30.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0e95f6819a19965ff420f65578bacb0b00f251fefe2c8b23347c37174271f3", size = 390522, upload-time = "2025-11-30T20:21:42.17Z" }, + { url = "https://files.pythonhosted.org/packages/13/4e/57a85fda37a229ff4226f8cbcf09f2a455d1ed20e802ce5b2b4a7f5ed053/rpds_py-0.30.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:a452763cc5198f2f98898eb98f7569649fe5da666c2dc6b5ddb10fde5a574221", size = 404579, upload-time = "2025-11-30T20:21:43.769Z" }, + { url = "https://files.pythonhosted.org/packages/f9/da/c9339293513ec680a721e0e16bf2bac3db6e5d7e922488de471308349bba/rpds_py-0.30.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e0b65193a413ccc930671c55153a03ee57cecb49e6227204b04fae512eb657a7", size = 421305, upload-time = "2025-11-30T20:21:44.994Z" }, + { url = "https://files.pythonhosted.org/packages/f9/be/522cb84751114f4ad9d822ff5a1aa3c98006341895d5f084779b99596e5c/rpds_py-0.30.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:858738e9c32147f78b3ac24dc0edb6610000e56dc0f700fd5f651d0a0f0eb9ff", size = 572503, upload-time = "2025-11-30T20:21:46.91Z" }, + { url = "https://files.pythonhosted.org/packages/a2/9b/de879f7e7ceddc973ea6e4629e9b380213a6938a249e94b0cdbcc325bb66/rpds_py-0.30.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:da279aa314f00acbb803da1e76fa18666778e8a8f83484fba94526da5de2cba7", size = 598322, upload-time = "2025-11-30T20:21:48.709Z" }, + { url = "https://files.pythonhosted.org/packages/48/ac/f01fc22efec3f37d8a914fc1b2fb9bcafd56a299edbe96406f3053edea5a/rpds_py-0.30.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c64d38fb49b6cdeda16ab49e35fe0da2e1e9b34bc38bd78386530f218b37139", size = 560792, upload-time = "2025-11-30T20:21:50.024Z" }, + { url = "https://files.pythonhosted.org/packages/e2/da/4e2b19d0f131f35b6146425f846563d0ce036763e38913d917187307a671/rpds_py-0.30.0-cp310-cp310-win32.whl", hash = "sha256:6de2a32a1665b93233cde140ff8b3467bdb9e2af2b91079f0333a0974d12d464", size = 221901, upload-time = "2025-11-30T20:21:51.32Z" }, + { url = "https://files.pythonhosted.org/packages/96/cb/156d7a5cf4f78a7cc571465d8aec7a3c447c94f6749c5123f08438bcf7bc/rpds_py-0.30.0-cp310-cp310-win_amd64.whl", hash = "sha256:1726859cd0de969f88dc8673bdd954185b9104e05806be64bcd87badbe313169", size = 235823, upload-time = "2025-11-30T20:21:52.505Z" }, + { url = "https://files.pythonhosted.org/packages/4d/6e/f964e88b3d2abee2a82c1ac8366da848fce1c6d834dc2132c3fda3970290/rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425", size = 370157, upload-time = "2025-11-30T20:21:53.789Z" }, + { url = "https://files.pythonhosted.org/packages/94/ba/24e5ebb7c1c82e74c4e4f33b2112a5573ddc703915b13a073737b59b86e0/rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d", size = 359676, upload-time = "2025-11-30T20:21:55.475Z" }, + { url = "https://files.pythonhosted.org/packages/84/86/04dbba1b087227747d64d80c3b74df946b986c57af0a9f0c98726d4d7a3b/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4", size = 389938, upload-time = "2025-11-30T20:21:57.079Z" }, + { url = "https://files.pythonhosted.org/packages/42/bb/1463f0b1722b7f45431bdd468301991d1328b16cffe0b1c2918eba2c4eee/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f", size = 402932, upload-time = "2025-11-30T20:21:58.47Z" }, + { url = "https://files.pythonhosted.org/packages/99/ee/2520700a5c1f2d76631f948b0736cdf9b0acb25abd0ca8e889b5c62ac2e3/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4", size = 525830, upload-time = "2025-11-30T20:21:59.699Z" }, + { url = "https://files.pythonhosted.org/packages/e0/ad/bd0331f740f5705cc555a5e17fdf334671262160270962e69a2bdef3bf76/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97", size = 412033, upload-time = "2025-11-30T20:22:00.991Z" }, + { url = "https://files.pythonhosted.org/packages/f8/1e/372195d326549bb51f0ba0f2ecb9874579906b97e08880e7a65c3bef1a99/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89", size = 390828, upload-time = "2025-11-30T20:22:02.723Z" }, + { url = "https://files.pythonhosted.org/packages/ab/2b/d88bb33294e3e0c76bc8f351a3721212713629ffca1700fa94979cb3eae8/rpds_py-0.30.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d", size = 404683, upload-time = "2025-11-30T20:22:04.367Z" }, + { url = "https://files.pythonhosted.org/packages/50/32/c759a8d42bcb5289c1fac697cd92f6fe01a018dd937e62ae77e0e7f15702/rpds_py-0.30.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038", size = 421583, upload-time = "2025-11-30T20:22:05.814Z" }, + { url = "https://files.pythonhosted.org/packages/2b/81/e729761dbd55ddf5d84ec4ff1f47857f4374b0f19bdabfcf929164da3e24/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7", size = 572496, upload-time = "2025-11-30T20:22:07.713Z" }, + { url = "https://files.pythonhosted.org/packages/14/f6/69066a924c3557c9c30baa6ec3a0aa07526305684c6f86c696b08860726c/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed", size = 598669, upload-time = "2025-11-30T20:22:09.312Z" }, + { url = "https://files.pythonhosted.org/packages/5f/48/905896b1eb8a05630d20333d1d8ffd162394127b74ce0b0784ae04498d32/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85", size = 561011, upload-time = "2025-11-30T20:22:11.309Z" }, + { url = "https://files.pythonhosted.org/packages/22/16/cd3027c7e279d22e5eb431dd3c0fbc677bed58797fe7581e148f3f68818b/rpds_py-0.30.0-cp311-cp311-win32.whl", hash = "sha256:55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c", size = 221406, upload-time = "2025-11-30T20:22:13.101Z" }, + { url = "https://files.pythonhosted.org/packages/fa/5b/e7b7aa136f28462b344e652ee010d4de26ee9fd16f1bfd5811f5153ccf89/rpds_py-0.30.0-cp311-cp311-win_amd64.whl", hash = "sha256:a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825", size = 236024, upload-time = "2025-11-30T20:22:14.853Z" }, + { url = "https://files.pythonhosted.org/packages/14/a6/364bba985e4c13658edb156640608f2c9e1d3ea3c81b27aa9d889fff0e31/rpds_py-0.30.0-cp311-cp311-win_arm64.whl", hash = "sha256:47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229", size = 229069, upload-time = "2025-11-30T20:22:16.577Z" }, + { url = "https://files.pythonhosted.org/packages/03/e7/98a2f4ac921d82f33e03f3835f5bf3a4a40aa1bfdc57975e74a97b2b4bdd/rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad", size = 375086, upload-time = "2025-11-30T20:22:17.93Z" }, + { url = "https://files.pythonhosted.org/packages/4d/a1/bca7fd3d452b272e13335db8d6b0b3ecde0f90ad6f16f3328c6fb150c889/rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05", size = 359053, upload-time = "2025-11-30T20:22:19.297Z" }, + { url = "https://files.pythonhosted.org/packages/65/1c/ae157e83a6357eceff62ba7e52113e3ec4834a84cfe07fa4b0757a7d105f/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28", size = 390763, upload-time = "2025-11-30T20:22:21.661Z" }, + { url = "https://files.pythonhosted.org/packages/d4/36/eb2eb8515e2ad24c0bd43c3ee9cd74c33f7ca6430755ccdb240fd3144c44/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd", size = 408951, upload-time = "2025-11-30T20:22:23.408Z" }, + { url = "https://files.pythonhosted.org/packages/d6/65/ad8dc1784a331fabbd740ef6f71ce2198c7ed0890dab595adb9ea2d775a1/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f", size = 514622, upload-time = "2025-11-30T20:22:25.16Z" }, + { url = "https://files.pythonhosted.org/packages/63/8e/0cfa7ae158e15e143fe03993b5bcd743a59f541f5952e1546b1ac1b5fd45/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1", size = 414492, upload-time = "2025-11-30T20:22:26.505Z" }, + { url = "https://files.pythonhosted.org/packages/60/1b/6f8f29f3f995c7ffdde46a626ddccd7c63aefc0efae881dc13b6e5d5bb16/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23", size = 394080, upload-time = "2025-11-30T20:22:27.934Z" }, + { url = "https://files.pythonhosted.org/packages/6d/d5/a266341051a7a3ca2f4b750a3aa4abc986378431fc2da508c5034d081b70/rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6", size = 408680, upload-time = "2025-11-30T20:22:29.341Z" }, + { url = "https://files.pythonhosted.org/packages/10/3b/71b725851df9ab7a7a4e33cf36d241933da66040d195a84781f49c50490c/rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51", size = 423589, upload-time = "2025-11-30T20:22:31.469Z" }, + { url = "https://files.pythonhosted.org/packages/00/2b/e59e58c544dc9bd8bd8384ecdb8ea91f6727f0e37a7131baeff8d6f51661/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5", size = 573289, upload-time = "2025-11-30T20:22:32.997Z" }, + { url = "https://files.pythonhosted.org/packages/da/3e/a18e6f5b460893172a7d6a680e86d3b6bc87a54c1f0b03446a3c8c7b588f/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e", size = 599737, upload-time = "2025-11-30T20:22:34.419Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e2/714694e4b87b85a18e2c243614974413c60aa107fd815b8cbc42b873d1d7/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394", size = 563120, upload-time = "2025-11-30T20:22:35.903Z" }, + { url = "https://files.pythonhosted.org/packages/6f/ab/d5d5e3bcedb0a77f4f613706b750e50a5a3ba1c15ccd3665ecc636c968fd/rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf", size = 223782, upload-time = "2025-11-30T20:22:37.271Z" }, + { url = "https://files.pythonhosted.org/packages/39/3b/f786af9957306fdc38a74cef405b7b93180f481fb48453a114bb6465744a/rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b", size = 240463, upload-time = "2025-11-30T20:22:39.021Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d2/b91dc748126c1559042cfe41990deb92c4ee3e2b415f6b5234969ffaf0cc/rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e", size = 230868, upload-time = "2025-11-30T20:22:40.493Z" }, + { url = "https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887, upload-time = "2025-11-30T20:22:41.812Z" }, + { url = "https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904, upload-time = "2025-11-30T20:22:43.479Z" }, + { url = "https://files.pythonhosted.org/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945, upload-time = "2025-11-30T20:22:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783, upload-time = "2025-11-30T20:22:46.103Z" }, + { url = "https://files.pythonhosted.org/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021, upload-time = "2025-11-30T20:22:47.458Z" }, + { url = "https://files.pythonhosted.org/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589, upload-time = "2025-11-30T20:22:48.872Z" }, + { url = "https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025, upload-time = "2025-11-30T20:22:50.196Z" }, + { url = "https://files.pythonhosted.org/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895, upload-time = "2025-11-30T20:22:51.87Z" }, + { url = "https://files.pythonhosted.org/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799, upload-time = "2025-11-30T20:22:53.341Z" }, + { url = "https://files.pythonhosted.org/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731, upload-time = "2025-11-30T20:22:54.778Z" }, + { url = "https://files.pythonhosted.org/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027, upload-time = "2025-11-30T20:22:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020, upload-time = "2025-11-30T20:22:58.2Z" }, + { url = "https://files.pythonhosted.org/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139, upload-time = "2025-11-30T20:23:00.209Z" }, + { url = "https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224, upload-time = "2025-11-30T20:23:02.008Z" }, + { url = "https://files.pythonhosted.org/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645, upload-time = "2025-11-30T20:23:03.43Z" }, + { url = "https://files.pythonhosted.org/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443, upload-time = "2025-11-30T20:23:04.878Z" }, + { url = "https://files.pythonhosted.org/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375, upload-time = "2025-11-30T20:23:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850, upload-time = "2025-11-30T20:23:07.825Z" }, + { url = "https://files.pythonhosted.org/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812, upload-time = "2025-11-30T20:23:09.228Z" }, + { url = "https://files.pythonhosted.org/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841, upload-time = "2025-11-30T20:23:11.186Z" }, + { url = "https://files.pythonhosted.org/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149, upload-time = "2025-11-30T20:23:12.864Z" }, + { url = "https://files.pythonhosted.org/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843, upload-time = "2025-11-30T20:23:14.638Z" }, + { url = "https://files.pythonhosted.org/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507, upload-time = "2025-11-30T20:23:16.105Z" }, + { url = "https://files.pythonhosted.org/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949, upload-time = "2025-11-30T20:23:17.539Z" }, + { url = "https://files.pythonhosted.org/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790, upload-time = "2025-11-30T20:23:19.029Z" }, + { url = "https://files.pythonhosted.org/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217, upload-time = "2025-11-30T20:23:20.885Z" }, + { url = "https://files.pythonhosted.org/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806, upload-time = "2025-11-30T20:23:22.488Z" }, + { url = "https://files.pythonhosted.org/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341, upload-time = "2025-11-30T20:23:24.449Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768, upload-time = "2025-11-30T20:23:25.908Z" }, + { url = "https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0", size = 362099, upload-time = "2025-11-30T20:23:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be", size = 353192, upload-time = "2025-11-30T20:23:29.151Z" }, + { url = "https://files.pythonhosted.org/packages/bf/c4/76eb0e1e72d1a9c4703c69607cec123c29028bff28ce41588792417098ac/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f", size = 384080, upload-time = "2025-11-30T20:23:30.785Z" }, + { url = "https://files.pythonhosted.org/packages/72/87/87ea665e92f3298d1b26d78814721dc39ed8d2c74b86e83348d6b48a6f31/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f", size = 394841, upload-time = "2025-11-30T20:23:32.209Z" }, + { url = "https://files.pythonhosted.org/packages/77/ad/7783a89ca0587c15dcbf139b4a8364a872a25f861bdb88ed99f9b0dec985/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87", size = 516670, upload-time = "2025-11-30T20:23:33.742Z" }, + { url = "https://files.pythonhosted.org/packages/5b/3c/2882bdac942bd2172f3da574eab16f309ae10a3925644e969536553cb4ee/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18", size = 408005, upload-time = "2025-11-30T20:23:35.253Z" }, + { url = "https://files.pythonhosted.org/packages/ce/81/9a91c0111ce1758c92516a3e44776920b579d9a7c09b2b06b642d4de3f0f/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad", size = 382112, upload-time = "2025-11-30T20:23:36.842Z" }, + { url = "https://files.pythonhosted.org/packages/cf/8e/1da49d4a107027e5fbc64daeab96a0706361a2918da10cb41769244b805d/rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07", size = 399049, upload-time = "2025-11-30T20:23:38.343Z" }, + { url = "https://files.pythonhosted.org/packages/df/5a/7ee239b1aa48a127570ec03becbb29c9d5a9eb092febbd1699d567cae859/rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f", size = 415661, upload-time = "2025-11-30T20:23:40.263Z" }, + { url = "https://files.pythonhosted.org/packages/70/ea/caa143cf6b772f823bc7929a45da1fa83569ee49b11d18d0ada7f5ee6fd6/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65", size = 565606, upload-time = "2025-11-30T20:23:42.186Z" }, + { url = "https://files.pythonhosted.org/packages/64/91/ac20ba2d69303f961ad8cf55bf7dbdb4763f627291ba3d0d7d67333cced9/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f", size = 591126, upload-time = "2025-11-30T20:23:44.086Z" }, + { url = "https://files.pythonhosted.org/packages/21/20/7ff5f3c8b00c8a95f75985128c26ba44503fb35b8e0259d812766ea966c7/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53", size = 553371, upload-time = "2025-11-30T20:23:46.004Z" }, + { url = "https://files.pythonhosted.org/packages/72/c7/81dadd7b27c8ee391c132a6b192111ca58d866577ce2d9b0ca157552cce0/rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed", size = 215298, upload-time = "2025-11-30T20:23:47.696Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d2/1aaac33287e8cfb07aab2e6b8ac1deca62f6f65411344f1433c55e6f3eb8/rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950", size = 228604, upload-time = "2025-11-30T20:23:49.501Z" }, + { url = "https://files.pythonhosted.org/packages/e8/95/ab005315818cc519ad074cb7784dae60d939163108bd2b394e60dc7b5461/rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6", size = 222391, upload-time = "2025-11-30T20:23:50.96Z" }, + { url = "https://files.pythonhosted.org/packages/9e/68/154fe0194d83b973cdedcdcc88947a2752411165930182ae41d983dcefa6/rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb", size = 364868, upload-time = "2025-11-30T20:23:52.494Z" }, + { url = "https://files.pythonhosted.org/packages/83/69/8bbc8b07ec854d92a8b75668c24d2abcb1719ebf890f5604c61c9369a16f/rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8", size = 353747, upload-time = "2025-11-30T20:23:54.036Z" }, + { url = "https://files.pythonhosted.org/packages/ab/00/ba2e50183dbd9abcce9497fa5149c62b4ff3e22d338a30d690f9af970561/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7", size = 383795, upload-time = "2025-11-30T20:23:55.556Z" }, + { url = "https://files.pythonhosted.org/packages/05/6f/86f0272b84926bcb0e4c972262f54223e8ecc556b3224d281e6598fc9268/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898", size = 393330, upload-time = "2025-11-30T20:23:57.033Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e9/0e02bb2e6dc63d212641da45df2b0bf29699d01715913e0d0f017ee29438/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e", size = 518194, upload-time = "2025-11-30T20:23:58.637Z" }, + { url = "https://files.pythonhosted.org/packages/ee/ca/be7bca14cf21513bdf9c0606aba17d1f389ea2b6987035eb4f62bd923f25/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419", size = 408340, upload-time = "2025-11-30T20:24:00.2Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c7/736e00ebf39ed81d75544c0da6ef7b0998f8201b369acf842f9a90dc8fce/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551", size = 383765, upload-time = "2025-11-30T20:24:01.759Z" }, + { url = "https://files.pythonhosted.org/packages/4a/3f/da50dfde9956aaf365c4adc9533b100008ed31aea635f2b8d7b627e25b49/rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8", size = 396834, upload-time = "2025-11-30T20:24:03.687Z" }, + { url = "https://files.pythonhosted.org/packages/4e/00/34bcc2565b6020eab2623349efbdec810676ad571995911f1abdae62a3a0/rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5", size = 415470, upload-time = "2025-11-30T20:24:05.232Z" }, + { url = "https://files.pythonhosted.org/packages/8c/28/882e72b5b3e6f718d5453bd4d0d9cf8df36fddeb4ddbbab17869d5868616/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404", size = 565630, upload-time = "2025-11-30T20:24:06.878Z" }, + { url = "https://files.pythonhosted.org/packages/3b/97/04a65539c17692de5b85c6e293520fd01317fd878ea1995f0367d4532fb1/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856", size = 591148, upload-time = "2025-11-30T20:24:08.445Z" }, + { url = "https://files.pythonhosted.org/packages/85/70/92482ccffb96f5441aab93e26c4d66489eb599efdcf96fad90c14bbfb976/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40", size = 556030, upload-time = "2025-11-30T20:24:10.956Z" }, + { url = "https://files.pythonhosted.org/packages/20/53/7c7e784abfa500a2b6b583b147ee4bb5a2b3747a9166bab52fec4b5b5e7d/rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0", size = 211570, upload-time = "2025-11-30T20:24:12.735Z" }, + { url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", size = 226532, upload-time = "2025-11-30T20:24:14.634Z" }, + { url = "https://files.pythonhosted.org/packages/69/71/3f34339ee70521864411f8b6992e7ab13ac30d8e4e3309e07c7361767d91/rpds_py-0.30.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58", size = 372292, upload-time = "2025-11-30T20:24:16.537Z" }, + { url = "https://files.pythonhosted.org/packages/57/09/f183df9b8f2d66720d2ef71075c59f7e1b336bec7ee4c48f0a2b06857653/rpds_py-0.30.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a", size = 362128, upload-time = "2025-11-30T20:24:18.086Z" }, + { url = "https://files.pythonhosted.org/packages/7a/68/5c2594e937253457342e078f0cc1ded3dd7b2ad59afdbf2d354869110a02/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb", size = 391542, upload-time = "2025-11-30T20:24:20.092Z" }, + { url = "https://files.pythonhosted.org/packages/49/5c/31ef1afd70b4b4fbdb2800249f34c57c64beb687495b10aec0365f53dfc4/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c", size = 404004, upload-time = "2025-11-30T20:24:22.231Z" }, + { url = "https://files.pythonhosted.org/packages/e3/63/0cfbea38d05756f3440ce6534d51a491d26176ac045e2707adc99bb6e60a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3", size = 527063, upload-time = "2025-11-30T20:24:24.302Z" }, + { url = "https://files.pythonhosted.org/packages/42/e6/01e1f72a2456678b0f618fc9a1a13f882061690893c192fcad9f2926553a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5", size = 413099, upload-time = "2025-11-30T20:24:25.916Z" }, + { url = "https://files.pythonhosted.org/packages/b8/25/8df56677f209003dcbb180765520c544525e3ef21ea72279c98b9aa7c7fb/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738", size = 392177, upload-time = "2025-11-30T20:24:27.834Z" }, + { url = "https://files.pythonhosted.org/packages/4a/b4/0a771378c5f16f8115f796d1f437950158679bcd2a7c68cf251cfb00ed5b/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f", size = 406015, upload-time = "2025-11-30T20:24:29.457Z" }, + { url = "https://files.pythonhosted.org/packages/36/d8/456dbba0af75049dc6f63ff295a2f92766b9d521fa00de67a2bd6427d57a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877", size = 423736, upload-time = "2025-11-30T20:24:31.22Z" }, + { url = "https://files.pythonhosted.org/packages/13/64/b4d76f227d5c45a7e0b796c674fd81b0a6c4fbd48dc29271857d8219571c/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a", size = 573981, upload-time = "2025-11-30T20:24:32.934Z" }, + { url = "https://files.pythonhosted.org/packages/20/91/092bacadeda3edf92bf743cc96a7be133e13a39cdbfd7b5082e7ab638406/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4", size = 599782, upload-time = "2025-11-30T20:24:35.169Z" }, + { url = "https://files.pythonhosted.org/packages/d1/b7/b95708304cd49b7b6f82fdd039f1748b66ec2b21d6a45180910802f1abf1/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e", size = 562191, upload-time = "2025-11-30T20:24:36.853Z" }, +] + +[[package]] +name = "rpds-py" +version = "2026.6.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.15' and sys_platform == 'win32'", + "python_full_version == '3.14.*' and sys_platform == 'win32'", + "python_full_version >= '3.15' and sys_platform == 'emscripten'", + "python_full_version == '3.14.*' and sys_platform == 'emscripten'", + "python_full_version >= '3.15' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.14.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", +] +sdist = { url = "https://files.pythonhosted.org/packages/aa/2a/9618a122aeb2a169a28b03889a2995fe297588964333d4a7d67bdf46e147/rpds_py-2026.6.3.tar.gz", hash = "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4", size = 64051, upload-time = "2026-06-30T07:17:53.009Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/1f/a2dca5ffdbf1d475ffc4e80e4d5d720ff3a00f691795910116960ee12511/rpds_py-2026.6.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7b689145a1485c335569bd056464f3243a29af7ed3871c7be31ad624ba239bc7", size = 342174, upload-time = "2026-06-30T07:14:54.821Z" }, + { url = "https://files.pythonhosted.org/packages/4d/dc/323d08583c0832911768663d1944f0107fcd4088704858d84b5e06d105a0/rpds_py-2026.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:db08f45aecde626498fb3df07bcf6d2ec040af42e859a4f5040d79c200342911", size = 345513, upload-time = "2026-06-30T07:14:56.515Z" }, + { url = "https://files.pythonhosted.org/packages/0b/2a/e31989834d18d2f26ec1d2774c5b1eb3331df4ea8ada525175294c94b48a/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acc992ab27b15f852c76755eb2ab7dce86585ddadba6fa5946e58556088845b4", size = 373783, upload-time = "2026-06-30T07:14:57.736Z" }, + { url = "https://files.pythonhosted.org/packages/87/fe/e80107ee3639585c9941c17d6a42cd65325022f656c023191fce78c324c8/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f88d653e7b3b779d71ae7454e20dcc9b6bae903f33c269db9f2be41bda3f261", size = 378316, upload-time = "2026-06-30T07:14:59.077Z" }, + { url = "https://files.pythonhosted.org/packages/22/6f/81e3adf81acfb6fa694de2a6e4e7d8863121e3e0799e0a7725e6cf5679c4/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e52655eaf81e32593abedaa4bfe33170c8cfedf3365ed9be6e11e07f148f0278", size = 499423, upload-time = "2026-06-30T07:15:00.488Z" }, + { url = "https://files.pythonhosted.org/packages/2d/9a/41263969df0ce3d9af2a96d5005a288200af1989aed3354bfceb5fc0b21f/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dfcc8b909769d19db55c7cc9541eb64b9b774b1057ffffb4f1048070475bb9f9", size = 386077, upload-time = "2026-06-30T07:15:01.911Z" }, + { url = "https://files.pythonhosted.org/packages/5e/19/7e98f468bd50346faff5b10e5297374b443bfdddacc8e9fbc65984539597/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c1255b302953c86a486b81d330d5ee1d5bd937691ce271b6be0ef0e299eaab7", size = 371315, upload-time = "2026-06-30T07:15:03.317Z" }, + { url = "https://files.pythonhosted.org/packages/99/3c/2b973b4d371906a134b03decfea7f5d9835a2c6d263454392e15b64b5b18/rpds_py-2026.6.3-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:8d2294a31386bfa251d8c8a39472beee17db67d4f1a6eabea665d35c9a4461c3", size = 383502, upload-time = "2026-06-30T07:15:04.627Z" }, + { url = "https://files.pythonhosted.org/packages/98/2a/12e2799500af0a307bca76b63361c51f9fe479223561489c29eea1f2ee41/rpds_py-2026.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8f23ead891a3b762f35ab3b04623da7056545b48aa60d59957e6789914545da", size = 402673, upload-time = "2026-06-30T07:15:05.856Z" }, + { url = "https://files.pythonhosted.org/packages/2d/e3/21e5872d165fe08be4f229e3d5ee9d90019c0bf0e5538de60dbd54009450/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:421aba32367055614287a4292b6a17f1939c9452299f7a0209c117e990b646d4", size = 549964, upload-time = "2026-06-30T07:15:07.159Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d0/5ee0fe36844297de8123bee27bc12078c1a7416ad9f1b8a8ca18d6b0c0ac/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1e5822dfc2f0d4ab7e745eaa6d85945069329beeccef965af3f3bb26058fcab6", size = 615446, upload-time = "2026-06-30T07:15:08.531Z" }, + { url = "https://files.pythonhosted.org/packages/b1/80/1ea5873cb683f2fbe5f21b23ea1f6d179ead19f3c5b249b7eb5dca568ef2/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83e35b57523816c8613fd0776b40cd8bb9f596b37ddd2692eb4a6bb5ab2f8c93", size = 576975, upload-time = "2026-06-30T07:15:09.97Z" }, + { url = "https://files.pythonhosted.org/packages/c9/e1/90ef639217a5ddb15b7f4f61b1c33911fd044ad03c311bafdd2bcab85582/rpds_py-2026.6.3-cp311-cp311-win32.whl", hash = "sha256:de3eceba0b683bcbb1ab93da016d0270df1f9ae7be716b40214c5dafac6ea45a", size = 204453, upload-time = "2026-06-30T07:15:11.324Z" }, + { url = "https://files.pythonhosted.org/packages/f2/b7/b7a1695d7af36f521fb11e80d6d3adbd744f73b921859bd3c2a2c0dc706f/rpds_py-2026.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:2c54a076ca4d370980ab57bc0e31df57bbe8d41340436a90ef8b1219a3cbb127", size = 223219, upload-time = "2026-06-30T07:15:12.476Z" }, + { url = "https://files.pythonhosted.org/packages/d7/a2/145afacf796e4506062825941176ad9445c2dcf2b3b6a1f13d3030a15e19/rpds_py-2026.6.3-cp311-cp311-win_arm64.whl", hash = "sha256:168c733a7112e071bb7a66460e667edfcff06c017a3c523f7a8a8e08d0140804", size = 219137, upload-time = "2026-06-30T07:15:13.631Z" }, + { url = "https://files.pythonhosted.org/packages/5c/be/2e8974163072e7bab7df1a5acd54c4498e75e35d6d18b864d3a9d5dadc92/rpds_py-2026.6.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a0811d33247c3d6128a3001d763f2aa056bb3425204335400ac54f89eec3a0d0", size = 343691, upload-time = "2026-06-30T07:15:14.96Z" }, + { url = "https://files.pythonhosted.org/packages/a4/73/319dfa745dd668efe89309141ded489126461fcecd2b8f3a3cda185129b6/rpds_py-2026.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:538949e262e46caa31ac01bdb3c1e8f642622922cacbabbae6a8445d9dc33eaf", size = 338542, upload-time = "2026-06-30T07:15:16.267Z" }, + { url = "https://files.pythonhosted.org/packages/21/63/4239893be1c4d09b709b1a8f6be4188f0870084ff547f46606b8a75f1b03/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55927d532399c2c646100ff7feb48eaa940ad70f42cd68e1328f3ded9f81ca24", size = 368180, upload-time = "2026-06-30T07:15:17.62Z" }, + { url = "https://files.pythonhosted.org/packages/1c/ca/9c5de382225234ceb37b1844ebdb140db12b2a278bb9efe2fcd19f6c82ce/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f56f1695bc5c0871cbc33dc0130fcf503aab0c57dcc5a6700a4f49eba4f2652e", size = 375067, upload-time = "2026-06-30T07:15:18.952Z" }, + { url = "https://files.pythonhosted.org/packages/87/dc/863f69d1bf04ade34b7fe0d59b9fdf6f0135fe2d7cbca74f1d665589559d/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:270b293dae9058fc9fcedab50f13cebf46fb8ed1d1d54e0521a9da5d6b211975", size = 490509, upload-time = "2026-06-30T07:15:20.434Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ef/eac16a12048b45ec7c7fa94f2be3438a5f26bf9cc8580b18a1cfd609b7f6/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:127565fead0a10943b282957bd5447804ff3160ad79f2ad2635e6d249e380680", size = 382754, upload-time = "2026-06-30T07:15:21.831Z" }, + { url = "https://files.pythonhosted.org/packages/04/8f/d2f3f532616be4d06c316ef119683e832bd3d41e112bf3a88f4151c95b17/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecabd69db66de867690f9797f2f8fa27ba501bbc24540cbdbdc649cd15888ba6", size = 366189, upload-time = "2026-06-30T07:15:23.371Z" }, + { url = "https://files.pythonhosted.org/packages/e3/29/41a7b0e98a4b44cd676ab7598419623373eb43b20be68c084935c1a8cf88/rpds_py-2026.6.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:58eadac9cd119677b60e1cf8ac4052f35949d71b8a9e5556efccbe82533cf22a", size = 377750, upload-time = "2026-06-30T07:15:24.659Z" }, + { url = "https://files.pythonhosted.org/packages/2e/05/ecda0bec46f9a1565090bcdc941d023f6a25aff85fda28f89f8d19878152/rpds_py-2026.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7491ee23305ac3eb59e492b6945881f5cd77a6f731061a3f25b77fd40f9e99a4", size = 395576, upload-time = "2026-06-30T07:15:25.987Z" }, + { url = "https://files.pythonhosted.org/packages/68/a8/6ed52f03ee6cb854ce78785cc9a9a672eb880e83fd7224d471f667d151f1/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2c99f7e8ccb3dd6e3e4bfeac657a7b208c9bac8075f4b078c02d7404c34107fa", size = 543807, upload-time = "2026-06-30T07:15:27.356Z" }, + { url = "https://files.pythonhosted.org/packages/8f/d6/156c0d3eea27ba09b92562ba2364ba124c0a061b199e17eac637cd25a5e2/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:62698275682bf121181861295c9181e789030a2d516071f5b8f3c23c170cd0fc", size = 611187, upload-time = "2026-06-30T07:15:28.931Z" }, + { url = "https://files.pythonhosted.org/packages/f1/31/774212ed989c62f7f310220089f9b0a3fb8f40f5443d1727abd5d9f52bc9/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a214c993455f99a89aaeadc9b21241900037adc9d97203e374d75513c5911822", size = 573030, upload-time = "2026-06-30T07:15:30.553Z" }, + { url = "https://files.pythonhosted.org/packages/c9/50/22f73127a41f1ce4f87fe39aadfb9a126345801c274aa93ae88456249327/rpds_py-2026.6.3-cp312-cp312-win32.whl", hash = "sha256:501f9f04a588d6a09179368c57071301445191767c64e4b52a6aa9871f1ef5ed", size = 202185, upload-time = "2026-06-30T07:15:32.027Z" }, + { url = "https://files.pythonhosted.org/packages/04/3a/f0ee4d4dde9d3b69dedf1b5f74e7a40017046d55052d173e418c6a94f960/rpds_py-2026.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:2c958bf94822e9290a40aaf2a822d4bc5c88099093e3948ad6c571eca9272e5f", size = 220394, upload-time = "2026-06-30T07:15:33.359Z" }, + { url = "https://files.pythonhosted.org/packages/f3/83/3382fe37f809b59f02aac04dbc4e765b480b46ee0227ed516e3bdc4d3dfc/rpds_py-2026.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:22bffe6042b9bcb0822bcd1955ec00e245daf17b4344e4ed8e9551b976b63e96", size = 215753, upload-time = "2026-06-30T07:15:34.778Z" }, + { url = "https://files.pythonhosted.org/packages/a4/9e/b818ee580026ec578138e961027a68820c40afeb1ec8f6819b54fb99e196/rpds_py-2026.6.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3cfe765c1da0072636ca06628261e0ea05688e160d5c8a03e0217c3854037223", size = 343012, upload-time = "2026-06-30T07:15:36.005Z" }, + { url = "https://files.pythonhosted.org/packages/f3/6b/686d9dc4359a8f163cfbbf89ee0b4e586431de22fe8248edb63a8cf50d49/rpds_py-2026.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f4d78253f6996be4901669ad25319f842f740eccf4d58e3c7f3dd39e6dde1d8f", size = 338203, upload-time = "2026-06-30T07:15:37.462Z" }, + { url = "https://files.pythonhosted.org/packages/9e/9b/069aa329940f8207615e091f5eedbbd40e1e15eac68a0790fd05ccdf796c/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54f45a148e28767bf343d33a684693c70e451c6f4c0e9904709a723fafbdfc1f", size = 367984, upload-time = "2026-06-30T07:15:39.008Z" }, + { url = "https://files.pythonhosted.org/packages/14/db/34c203e4becff3703e4d3bc121842c00b8689197f398161203a880052f4e/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:842e7b070435622248c7a2c44ae53fa1440e073cc3023bc919fed570884097a7", size = 374815, upload-time = "2026-06-30T07:15:40.253Z" }, + { url = "https://files.pythonhosted.org/packages/ee/7d/8071067d2cc453d916ad836e828c943f575e8a44612537759002a1e07381/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8020133a74bd81b4572dd8e4be028a6b1ebcd70e6726edc3918008c08bee6ee6", size = 490545, upload-time = "2026-06-30T07:15:41.729Z" }, + { url = "https://files.pythonhosted.org/packages/a3/42/da06c5aa8f0484ff07f270787434204d9f4535e2f8c3b51ed402267e63c3/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdc7e35386f3847df728fbcb5e887e2d79c19e2fa1eba9e51b6621d23e3243af", size = 382828, upload-time = "2026-06-30T07:15:43.327Z" }, + { url = "https://files.pythonhosted.org/packages/57/d7/fe978efc2ae50abe48eb7464668ea99f53c010c60aeebb7b35ad27f23661/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acac386b453c2516111b50985d60ce46e7fadb5ea71ae7b25f4c946935bf27cf", size = 365678, upload-time = "2026-06-30T07:15:44.992Z" }, + { url = "https://files.pythonhosted.org/packages/69/9d/1d8922e1990b2a6eb532b6ff53d3e73d2b3bbffc84116c75826bee73dfc6/rpds_py-2026.6.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:425560c6fa0415f27261727bb20bd097568485e5eb0c121f1949417d1c516885", size = 377811, upload-time = "2026-06-30T07:15:46.523Z" }, + { url = "https://files.pythonhosted.org/packages/b1/3d/198dceafb4fb034a6a47347e1b0735d34e0bd4a50be4e898d408ee66cb14/rpds_py-2026.6.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a550fb4950a06dde3beb4721f5ad4b25bf4513784665b0a8522c792e2bd822a4", size = 395382, upload-time = "2026-06-30T07:15:47.955Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f1/13968e49655d40b6b19d8b9140296bbc6f1d86b3f0f6c346cf9f1adddf4b/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f4bca01b63096f606e095734dd56e74e175f94cfbf24ff3d63281cec61f7bb7", size = 543832, upload-time = "2026-06-30T07:15:49.33Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ab/289bcb1b90bd3e40a2900c561fa0e2087345ecbb094f0b870f2345142b7c/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ccffae9a092a00deb7efd545fe5e2c33c33b88e7c054337e9a74c179347d0b7d", size = 611011, upload-time = "2026-06-30T07:15:50.847Z" }, + { url = "https://files.pythonhosted.org/packages/1e/16/5043105e679436ccfbc8e5e0dd2d663ed18a8b8113515fd06a5e5d77c83e/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1cf01971c4f2c5553b772a542e4aaf191789cd331bc2cd4ff0e6e65ba49e1e97", size = 572431, upload-time = "2026-06-30T07:15:52.394Z" }, + { url = "https://files.pythonhosted.org/packages/85/ed/adab103321c0a6565d5ae1c2998349bc3ee175b82ccc5ae8fc04cc413075/rpds_py-2026.6.3-cp313-cp313-win32.whl", hash = "sha256:8c3d1e9c15b9d51ca0391e13da1a25a0a4df3c58a37c9dc368e0736cf7f69df0", size = 201710, upload-time = "2026-06-30T07:15:53.894Z" }, + { url = "https://files.pythonhosted.org/packages/7b/ed/a03b09668e74e5dabbf2e211f6468e1820c0552f7b0500082da31841bf7b/rpds_py-2026.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:9250a9a0a6fd4648b3f868da8d91a4c52b5811a62df58e753d50ae4454a36f80", size = 219454, upload-time = "2026-06-30T07:15:55.25Z" }, + { url = "https://files.pythonhosted.org/packages/27/17/b8642c12930b71bc2b25831f6708ccf0f75abcd11883932ec9ce54ba3a78/rpds_py-2026.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:900a67df3fd1660b035a4761c4ce73c382ea6b35f90f9863c36c6fd8bf8b09bb", size = 215063, upload-time = "2026-06-30T07:15:56.573Z" }, + { url = "https://files.pythonhosted.org/packages/b6/36/7fbe9dcdaf857fb3f63c2a2284b62492d95f5e8334e947e5fb6e7f68c9be/rpds_py-2026.6.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:931908d9fc855d8f74783377822be318edb6dcb19e47169dc038f9a1bf60b06e", size = 344510, upload-time = "2026-06-30T07:15:57.921Z" }, + { url = "https://files.pythonhosted.org/packages/ba/54/f785cc3d3f60839ca57a5af4927a9f347b07b2799c373fc20f7949f87c7e/rpds_py-2026.6.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7469697dce35be237db177d42e2a2ee26e6dcc5fc052078a6fefabd288c6edd", size = 339495, upload-time = "2026-06-30T07:15:59.238Z" }, + { url = "https://files.pythonhosted.org/packages/63/ef/d4cdaf309e6b095b43597103cf8c0b951d6cca2acce68c474f75ec12e0c7/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcfbcf66006befb9fd2aeaa9e01feaf881b4dc330a02ba07d2322b1c11be7b5d", size = 369454, upload-time = "2026-06-30T07:16:01.021Z" }, + { url = "https://files.pythonhosted.org/packages/96/4a/9559a68b7ee15db09d7981212e8c2e219d2a1d6d4faa0391d813c3496a36/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847927daf4cffbd4e90e42bc890069897101edd015f956cb8721b3473372edda", size = 374583, upload-time = "2026-06-30T07:16:02.287Z" }, + { url = "https://files.pythonhosted.org/packages/ef/75/8964aa7d2c6e8ac43eba8eb6e6b0fdda1f46d39f2fc3e6aa9f2cb17f485d/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aca6c1ef08a82bfe327cc156da694660f599923e2e6665b6d81c9c2d0ac9ffc8", size = 492919, upload-time = "2026-06-30T07:16:03.723Z" }, + { url = "https://files.pythonhosted.org/packages/8f/97/6908094ac804115e65aedfd90f1b5fee4eebebd3f6c4cfc5419939267565/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ae50181a047c871561212bb97f7932a2d45fb53e947bd9b57ebad85b529cbc53", size = 383725, upload-time = "2026-06-30T07:16:05.305Z" }, + { url = "https://files.pythonhosted.org/packages/d1/9c/0d1fdc2e7aba23e290d603bc494e97bd205bae262ce33c6b32a69768ed5e/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc319e5a1de4b6913aac94bf6a2f9e847371e0a140a43dd4991db1a09bc2d504", size = 367255, upload-time = "2026-06-30T07:16:07.086Z" }, + { url = "https://files.pythonhosted.org/packages/c4/fe/f0209ca4a9ed074bc8acb44dfd0e81c3122e94c9689f5645b7973a866719/rpds_py-2026.6.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:e4316bf32babbed84e691e352faf967ce2f0f024174a8643c37c94a1080374fc", size = 379060, upload-time = "2026-06-30T07:16:08.525Z" }, + { url = "https://files.pythonhosted.org/packages/c6/8d/f1cc54c616b9d8897de8738aac148d20afca93f68187475fe194d09a71b9/rpds_py-2026.6.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8c6e5a2f750cc71c3e3b11d71661f21d6f9bc6cebc6564b1466417a1ec03ec77", size = 395960, upload-time = "2026-06-30T07:16:09.989Z" }, + { url = "https://files.pythonhosted.org/packages/fb/04/aafff00f73aeca2945f734f1d483c64ab8f472d0864ab02377fd8e89c3b2/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4470ce197d4090875cf6affbf1f853338387428df97c4fb7b7106317b8214698", size = 545356, upload-time = "2026-06-30T07:16:11.816Z" }, + { url = "https://files.pythonhosted.org/packages/fd/cc/e229663b9e4ddac5a4acbe9085dd80a71af2a5d356b8b39d6bff233f24b0/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ea964164cc9afa72d4d9b23cc28dafae93693c0a53e0b42acbff15b22c3f9ddd", size = 612319, upload-time = "2026-06-30T07:16:13.586Z" }, + { url = "https://files.pythonhosted.org/packages/e3/7a/8a0e6d3e6cd066af108b71b43122c3fe158dd9eb86acac626593a2582eb1/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:639c8929aa0afe81be836b04de888460d6bed38b9c54cfc18da8f6bfabf5af5d", size = 573508, upload-time = "2026-06-30T07:16:15.23Z" }, + { url = "https://files.pythonhosted.org/packages/87/03/2a69ab618a789cf6cf85c86bb844c62d090e700ab1a2aa676b3741b6c516/rpds_py-2026.6.3-cp314-cp314-win32.whl", hash = "sha256:882076c00c0a608b131187055ddc5ae29f2e7eaf870d6168980420d58528a5c8", size = 202504, upload-time = "2026-06-30T07:16:16.893Z" }, + { url = "https://files.pythonhosted.org/packages/85/62/a3892ba945f4e24c78f352e5de3c7620d8479f73f211406a97263d13c7d2/rpds_py-2026.6.3-cp314-cp314-win_amd64.whl", hash = "sha256:0be972be84cfcaf46c8c6edf690ca0f154ac17babf1f6a955a51579b34ad2dc5", size = 220380, upload-time = "2026-06-30T07:16:18.108Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e7/c2bd44dc831931815ad11ebb5f430b5a0a4d3caa9de837107876c30c3432/rpds_py-2026.6.3-cp314-cp314-win_arm64.whl", hash = "sha256:2a9c6f195058cb45335e8cc3802745c603d716eb96bc9625950c1aac71c0c703", size = 215976, upload-time = "2026-06-30T07:16:19.654Z" }, + { url = "https://files.pythonhosted.org/packages/79/9c/fff7b74bce9a091ec9a012a03f9ff5f69364eaf9451060dfc4486da2ffdd/rpds_py-2026.6.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:f90938e92afda60266da758ee7d363447f7f0138c9559f9e1811629580582d90", size = 346840, upload-time = "2026-06-30T07:16:21.268Z" }, + { url = "https://files.pythonhosted.org/packages/e9/44/77bcb1168b33704908295533d27f10eb811e9e3e193e8993dc99572211d3/rpds_py-2026.6.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec829541c45bca16e61c7ae50c20501f213605beb75d1aba91a6ee37fbbb56a4", size = 340282, upload-time = "2026-06-30T07:16:22.875Z" }, + { url = "https://files.pythonhosted.org/packages/87/3c/7a9081c7c9e645b39efe19e4ffbeccd80add246327cd9b888aecffd72317/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd70d95892096cdb26f15a00c45907b17817577aa8d1c76b2dcc2788391f9e9", size = 370403, upload-time = "2026-06-30T07:16:24.415Z" }, + { url = "https://files.pythonhosted.org/packages/f7/69/af47021eb7dad6ff3396cb001c08f0f3c4d06c20253f75be6421a59fe6b7/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29dfa0533a5d4c94d4dfa1b694fcb56c9c63aad8330ffdd816fd225d0a7a162f", size = 376055, upload-time = "2026-06-30T07:16:26.111Z" }, + { url = "https://files.pythonhosted.org/packages/81/fc/a3bcf517084396a6dd258c592567a3c011ba4557f2fde23dceaf26e74f2e/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af05d726809bff6b141be124d4c7ce998f9c9c7f30edb1f46c07aa103d540b41", size = 494419, upload-time = "2026-06-30T07:16:27.596Z" }, + { url = "https://files.pythonhosted.org/packages/c9/eb/13d529d1788135425c7bf207f8463458ca5d92e43f3f701365b83e9dffc1/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9826217f048f620d9a712672818bf231442c1b35d96b227a07eabd11b4bb6945", size = 384848, upload-time = "2026-06-30T07:16:29.183Z" }, + { url = "https://files.pythonhosted.org/packages/8e/f4/b7ac49f30013aba8f7b9566b1dd07e81de95e708c1374b7bacc5b9bc5c9c/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:536bceea4fa4acf7e1c61da2b5786304367c816c8895be71b8f537c480b0ea1f", size = 371369, upload-time = "2026-06-30T07:16:30.912Z" }, + { url = "https://files.pythonhosted.org/packages/31/86/6260bafa622f788b07ddec0e52d810305c8b9b0b8c27f58a2ab04bf62b4f/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:bc0011654b91cc4fb2ae701bec0a0ba1e552c0714247fa7af6c59e0ccfa3a4e1", size = 379673, upload-time = "2026-06-30T07:16:32.486Z" }, + { url = "https://files.pythonhosted.org/packages/19/c3/03f1ee79a047b48daeca157c89a18509cde22b6b951d642b9b0af1be660a/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:539d75de9e0d536c84ff18dfeb805398e58227001ce09231a26a08b9aed1ee0e", size = 397500, upload-time = "2026-06-30T07:16:34.471Z" }, + { url = "https://files.pythonhosted.org/packages/f0/95/8ed0cd8c377dca12aea498f119fe639fc474d1461545c39d2b5872eb1c0f/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:166cf54d9f44fc6ceb53c7860258dde44a81406646de79f8ed3234fca3b6e538", size = 545978, upload-time = "2026-06-30T07:16:36.45Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f2/0eb57f0eaa83f8fc152a7e03de968ab77e1f00732bebc892b190c6eebde7/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:d34c20167764fbcf927194d532dd7e0c56772f0a5f943fa5ef9e9afbba8fb9db", size = 613350, upload-time = "2026-06-30T07:16:38.213Z" }, + { url = "https://files.pythonhosted.org/packages/5b/de/e0674bdbc3ef7634989b3f854c3f34bc1f587d36e5bfdc5c378d57034619/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ea7bb13b7c9a29791f87a0387ba7d3ad3a6d783d827e4d3f27b40a0ff44495e2", size = 576486, upload-time = "2026-06-30T07:16:39.797Z" }, + { url = "https://files.pythonhosted.org/packages/f2/f6/21101359743cd136ada781e8210a85769578422ba460672eea0e29739200/rpds_py-2026.6.3-cp314-cp314t-win32.whl", hash = "sha256:6de4744d05bd1aa1be4ed7ea1189e3979196808008113bbbf899a460966b925e", size = 201068, upload-time = "2026-06-30T07:16:41.316Z" }, + { url = "https://files.pythonhosted.org/packages/a6/b2/9574d4d44f7760c2aa32d92a0a4f41698e33f5b204a0bf5c9758f52c79d5/rpds_py-2026.6.3-cp314-cp314t-win_amd64.whl", hash = "sha256:c7b9a2f8f4d8e90af72571d3d495deebdd7e3c75451f5b41719aee166e940fc2", size = 220600, upload-time = "2026-06-30T07:16:43.091Z" }, + { url = "https://files.pythonhosted.org/packages/08/ae/f23a2697e6ee6340a578b0f136be6483657bef0c6f9497b752bb5c0964bb/rpds_py-2026.6.3-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:e059c5dde6452b44424bd1834557556c226b57781dee1227af23518459722b13", size = 344726, upload-time = "2026-06-30T07:16:44.5Z" }, + { url = "https://files.pythonhosted.org/packages/c3/63/e7b3a1a5358dd32c930a1062d8e15b67fd6e8922e81df9e91706d66ee5c8/rpds_py-2026.6.3-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2f7c26fbc5acd2522b95d4177fe4710ffd8e9b20529e703ffbf8db4d93903f05", size = 339587, upload-time = "2026-06-30T07:16:46.255Z" }, + { url = "https://files.pythonhosted.org/packages/ec/64/10a85681916ca55fffb91b0a211f84e34297c109243484dd6394660a8a7c/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3086b538543802f84c843911242db20447de00d8752dd0efc936dbcf02218ba", size = 369585, upload-time = "2026-06-30T07:16:48.101Z" }, + { url = "https://files.pythonhosted.org/packages/76/c2/baf95c7c38823e12ba34407c5f5767a89e5cf2233895e56f608167ae9493/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f2e5c5ee828d42cb11760761c0af6507927bec42d0ad5458f97c9203b054617", size = 375479, upload-time = "2026-06-30T07:16:49.93Z" }, + { url = "https://files.pythonhosted.org/packages/6a/94/0aad06c72d65101e11d33528d438cda99a39ce0da99466e156158f2541d3/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed0c1e5d10cdc7135537988c74a0188da68e2f3c30813ba3744ab1e42e0480f9", size = 492418, upload-time = "2026-06-30T07:16:51.641Z" }, + { url = "https://files.pythonhosted.org/packages/b5/17/de3f5a479a1f056535d7489819639d8cd591ea6281d700390b43b1abd745/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c2642a7603ec0b16ed77da4555db3b4b472341904873788327c0b0d7b95f1bb", size = 384123, upload-time = "2026-06-30T07:16:53.622Z" }, + { url = "https://files.pythonhosted.org/packages/46/7d/bf09bd1b145bb2671c03e1e6d1ab8651858d90d8c7dfeadd85a37a934fd8/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e4320744c1ffdd95a603def63344bfab2d33edeab301c5007e7de9f9f5b3885", size = 367351, upload-time = "2026-06-30T07:16:55.241Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ea/1bb734f314b8be319149ddee80b18bd41372bdcfbdf88d28131c0cd37719/rpds_py-2026.6.3-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:a9f4645593036b81bbdb36b9c8e0ea0d1c3fee968c4d59db0344c14087ef143a", size = 378827, upload-time = "2026-06-30T07:16:56.841Z" }, + { url = "https://files.pythonhosted.org/packages/4b/93/d9611e5b25e26df9a3649813ed66193ace9347a7c7fc4ab7cf70e94851c0/rpds_py-2026.6.3-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e55d236be29255554da47abe5c577637db7c24a02b8b46f0ca9524c855801868", size = 395966, upload-time = "2026-06-30T07:16:58.557Z" }, + { url = "https://files.pythonhosted.org/packages/c3/cb/99d77e16e5534ae1d90629bbe419ba6ee170833a6a85e3aa1cc41726fbbc/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:24e9c5386e16669b674a69c156c8eeefcb578f3b3397b713b08e6d60f3c7b187", size = 545680, upload-time = "2026-06-30T07:17:00.164Z" }, + { url = "https://files.pythonhosted.org/packages/59/15/11a29755f790cef7a2f755e8e14f4f0c33f39489e1893a632a2eee59672b/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:c60924535c75f1566b6eb75b5c31a48a43fef04fa2d0d201acbad8a9969c6107", size = 611853, upload-time = "2026-06-30T07:17:01.962Z" }, + { url = "https://files.pythonhosted.org/packages/68/86/0c27547e21644da938fb530f7e1a8148dd24d02db07e7a5f2567a17ce710/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:38a2fea2787428f811719ceb9114cb78964a3138838320c29ac39526c79c16ba", size = 573715, upload-time = "2026-06-30T07:17:03.693Z" }, + { url = "https://files.pythonhosted.org/packages/29/71/4d8fcf700931815594bce892255bbd973b94efaf0fc1932b0590df18d886/rpds_py-2026.6.3-cp315-cp315-win32.whl", hash = "sha256:d483fe17f01ad64b7bf7cc38fcefff1ca9fb83f8c2b2542b68f97ffe0611b369", size = 202864, upload-time = "2026-06-30T07:17:05.746Z" }, + { url = "https://files.pythonhosted.org/packages/eb/62/b577562de0edbb55b2be85ce5fd09c33e386b9b13eee09833af4240fd5c4/rpds_py-2026.6.3-cp315-cp315-win_amd64.whl", hash = "sha256:67e3a721ffc5d8d2210d3671872298c4a84e4b8035cfe42ffd7cde35d772b146", size = 220430, upload-time = "2026-06-30T07:17:07.471Z" }, + { url = "https://files.pythonhosted.org/packages/c8/95/d6d0b2509825141eef60669a5739eec88dbc6a48053d6c92993a5704defe/rpds_py-2026.6.3-cp315-cp315-win_arm64.whl", hash = "sha256:6e84adbcf4bf841aed8116a8264b9f50b4cb3e7bd89b516122e616ac56ca269e", size = 215877, upload-time = "2026-06-30T07:17:09.008Z" }, + { url = "https://files.pythonhosted.org/packages/b7/bf/f3ea278f0afd615c1d0f19cb69043a41526e2bb600c2b536eb192218eb27/rpds_py-2026.6.3-cp315-cp315t-macosx_10_12_x86_64.whl", hash = "sha256:ae6dd8f10bd17aad820876d24caec9efdafd80a318d16c0a48edb5e136902c6b", size = 346933, upload-time = "2026-06-30T07:17:10.762Z" }, + { url = "https://files.pythonhosted.org/packages/9d/29/9907bdf1c5346763cf10b7f6852aad86652168c259def904cbe0082c5864/rpds_py-2026.6.3-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:bdbd97738551fca3917c1bd7188bec1920bb520104f28e7e1007f9ceb17b7690", size = 340274, upload-time = "2026-06-30T07:17:12.266Z" }, + { url = "https://files.pythonhosted.org/packages/6f/2c/8e03767b5778ef25cebf74a7a91a2c3806f8eced4c92cb7406bbe060756d/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b95977e7211527ab0ba576e286d023389fbeeb32a6b7b771665d333c60e5342", size = 370763, upload-time = "2026-06-30T07:17:14.107Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e1/df2a7e1ba2efd796af26194250b8d42c821b46592311595162af9ef0528d/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15fde0e6fb0d88a60d221204873743e5d9f0b7d29165e62cd86d0413ad74ba6", size = 376467, upload-time = "2026-06-30T07:17:15.76Z" }, + { url = "https://files.pythonhosted.org/packages/6b/de/8a0814d1946af29cb068fb259aa8622f856df1d0bab58429448726b537f5/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a136d453475ac0fcbda502ef1e6504bd28d6d904700915d278deeab0d00fe140", size = 496689, upload-time = "2026-06-30T07:17:17.308Z" }, + { url = "https://files.pythonhosted.org/packages/df/f3/f19e0c852ba13694f5a79f3b719331051573cb5693feacf8a88ffffc3a71/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f826877d462181e5eb1c26a0026b8d0cab05d99844ecb6d8bf3627a2ca0c0442", size = 385340, upload-time = "2026-06-30T07:17:18.928Z" }, + { url = "https://files.pythonhosted.org/packages/e2/ae/7ec3a9d2d4351f99e37bcb06b6b6f954512646bfdbf9742e1de727865daf/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79486287de1730dbaff3dbd124d0ca4d2ef7f9d29bf2544f1f93c09b5bcbbd12", size = 372179, upload-time = "2026-06-30T07:17:20.539Z" }, + { url = "https://files.pythonhosted.org/packages/d3/ac/9cee911dff2aaa9a5a8354f6610bf2e6a616de9197c5fff4f54f82585f1e/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_31_riscv64.whl", hash = "sha256:808345f53cb952433ca2816f1604ff3515608a81784954f38d4452acfe8e61d5", size = 379993, upload-time = "2026-06-30T07:17:22.212Z" }, + { url = "https://files.pythonhosted.org/packages/83/6b/7c2a07ba88d1e9a936612f7a5d067467ed03d971d5a06f7d309dff044a7e/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1967debc37f64f2c4dc90a7f563aec558b471966e12adcac4e1c4240496b6ebf", size = 398909, upload-time = "2026-06-30T07:17:23.66Z" }, + { url = "https://files.pythonhosted.org/packages/97/0b/776ffcb66783637b0031f6d58d6fb55913c8b5abf00aeecd46bf933fb477/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:f0840b5b17057f7fd918b76183a4b5a0635f43e14eb2ce60dce1d4ee4707ea00", size = 546584, upload-time = "2026-06-30T07:17:25.264Z" }, + { url = "https://files.pythonhosted.org/packages/55/33/ba3bc04d7092bd553c9b2b195624992d2cc4f3de1f380b7b93cbee67bd79/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:faa679d19a6696fd54259ad321251ad77a13e70e03dd834daa762a44fb6196ef", size = 614357, upload-time = "2026-06-30T07:17:26.888Z" }, + { url = "https://files.pythonhosted.org/packages/8b/71/14edf065f04630b1a8472f7653cad03f6c478bcf95ea0e6aed55451e33ea/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:23a439f31ccbeff1574e24889128821d1f7917470e830cf6544dced1c662262a", size = 576533, upload-time = "2026-06-30T07:17:28.546Z" }, + { url = "https://files.pythonhosted.org/packages/ba/76/65002b08596c389105720a8c0d22298b8dc25a4baf89b2ce431343c8b1de/rpds_py-2026.6.3-cp315-cp315t-win32.whl", hash = "sha256:913ca42ccad3f8cc6e292b587ae8ae49c8c823e5dce51a736252fc7c7cdfa577", size = 201204, upload-time = "2026-06-30T07:17:30.193Z" }, + { url = "https://files.pythonhosted.org/packages/8c/97/d855d6b3c322d1f27e26f5241c42016b56cf01377ea8ed348285f54652f0/rpds_py-2026.6.3-cp315-cp315t-win_amd64.whl", hash = "sha256:ae3d4fe8c0b9213624fdce7279d70e3b148b682ca20719ebd193a23ebfa47324", size = 220719, upload-time = "2026-06-30T07:17:31.788Z" }, + { url = "https://files.pythonhosted.org/packages/b4/9c/f0d19ac587fd0e4ab6b72cda355e9c5a6166b01ef7e064e437aef8eb9fef/rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:4cf2d36a2357e4d07bb5a4f98801265327b48256867816cfd2ceb001e9754a8f", size = 349791, upload-time = "2026-06-30T07:17:33.315Z" }, + { url = "https://files.pythonhosted.org/packages/38/c7/1d49d204c9fd2ee6c537601dc4c1ba921e03363ca576bfab94a00254ac9a/rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:30c6dc199b24a5e3e81d50da0f00858c5bbdb2617a750395687f4339c5818171", size = 352842, upload-time = "2026-06-30T07:17:34.897Z" }, + { url = "https://files.pythonhosted.org/packages/ac/e5/c0b5dc93cd0d4c06ce1f438907649514e2ea077bcd911e3154a51e96c38e/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9891e594296ab9dada6551c8e7b387b2721f27a67eecd528412e8906247a7b90", size = 382094, upload-time = "2026-06-30T07:17:36.514Z" }, + { url = "https://files.pythonhosted.org/packages/0d/54/ec0e907b4ca8d541112db352409bd15f871c9b243e0c92c9b5a46ae96f01/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5c2dc92304aa48a4a60443b548bb12f12e119d4b72f314015e67b9e1be97fca", size = 388662, upload-time = "2026-06-30T07:17:38.235Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f4/921c22a4fd0f1c1ac13a3996ffbf0aa67951e2c8ad0d1d9574938a2932e8/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:127e08c0642d880cf32ca47ec2a4a77b901f7e2dd1ad9762adb13955d72ffcc9", size = 504896, upload-time = "2026-06-30T07:17:39.689Z" }, + { url = "https://files.pythonhosted.org/packages/0b/1b/a114b972cefa1ab1cdb3c7bb177cd3844a12826c507c722d3a73516dbbaf/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8bb68f03f395eb793220b45c097bd4d8c32944393da0fad8b999efac0868fc8c", size = 391545, upload-time = "2026-06-30T07:17:41.336Z" }, + { url = "https://files.pythonhosted.org/packages/4e/98/af9b3db77d47fcbe6c8c1f36e2c2147ec70292819e99c325f871584a1c11/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3450b693fde92133e9f51060568a4c31fcca76d5e53bbd611e689ca446517e9", size = 380059, upload-time = "2026-06-30T07:17:42.857Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ba/0efd8668b97c1d26a61566386c636a7a7a09829e474fdf807caa15a2c844/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:5e8d07bddee435a2ff6f1920e18feff28d0bc4533e42f4bf6927fbd073312c41", size = 393235, upload-time = "2026-06-30T07:17:44.637Z" }, + { url = "https://files.pythonhosted.org/packages/62/90/8c139ee9690f73b0829f32647de6f40d826f8f443af6fa72644f96351aac/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3a83ae6c67b7676b9878378547ca8e93ed77a580037bcbcd1d32f739e1e6089c", size = 413008, upload-time = "2026-06-30T07:17:46.225Z" }, + { url = "https://files.pythonhosted.org/packages/9c/97/0043896fdd7828ce09a1d9a8b06433714d0960fc4ff3fc4aa72b666b764e/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2bfd04c19ddbd6640de0b51894d764bd2758854d5b75bd102d2ef10cb9c293a9", size = 558118, upload-time = "2026-06-30T07:17:47.759Z" }, + { url = "https://files.pythonhosted.org/packages/f6/40/02355f0e134f783a8f9814c4680a1bd311d37671577a5964ea838573ff37/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:ca6546b66be9dc4738b1b043d5ebd5488c66c578c5ff0fd0e8065313fe3afb76", size = 623138, upload-time = "2026-06-30T07:17:49.355Z" }, + { url = "https://files.pythonhosted.org/packages/10/85/48f0abdcef5cce4e034c7a5b0ceeceba0b01bf0d942824f4bb720afe2dec/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8e65860d238379ed982fd9ba690579b5e95af2f4840f99c772816dbe573cb826", size = 586486, upload-time = "2026-06-30T07:17:51.141Z" }, +] + +[[package]] +name = "ruff" +version = "0.15.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/dc/35b341fc554ba02f217fc10da57d1a75168cfbcf75b0ef2202176d4c4f2d/ruff-0.15.20.tar.gz", hash = "sha256:1416eb04349192646b54de98f146c4f59afe37d0decfc02c3cbbf396f3a28566", size = 4755489, upload-time = "2026-06-25T17:20:37.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/d9/2d5014f0253ba541d2061d9fa7193f48e941c8b21bb88a7ff9bbe0bd0596/ruff-0.15.20-py3-none-linux_armv6l.whl", hash = "sha256:00e188c53e499c3c1637f73c91dcf2fb56d576cab76ce1be50a27c4e80e37078", size = 10839665, upload-time = "2026-06-25T17:19:44.702Z" }, + { url = "https://files.pythonhosted.org/packages/c6/d3/ac1798ba64f670698867fcfc591d50e7e421bef137db564858f619a30fcf/ruff-0.15.20-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9ebd1fd9b9c95fc0bd7b2761aebec1f030013d2e193a2901b224af68fe47251b", size = 11208649, upload-time = "2026-06-25T17:19:48.787Z" }, + { url = "https://files.pythonhosted.org/packages/47/47/d3ac899991202095dfcf3d5176be4272642be3cf981a2f1a30f72a2afb95/ruff-0.15.20-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5b16cdd67ca108185cd36dce98c576350c03b1660a751de725fb049193a0632", size = 10622638, upload-time = "2026-06-25T17:19:51.354Z" }, + { url = "https://files.pythonhosted.org/packages/33/13/4e043fe30aa94d4ff5213a9881fc296d12960f5971b234a5263fdc225312/ruff-0.15.20-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3413bb3c3d2ca6a8208f1f4809cd2dca3c6de6d0b491c0e70847672bde6e6efd", size = 10984227, upload-time = "2026-06-25T17:19:54.044Z" }, + { url = "https://files.pythonhosted.org/packages/76/e6/92e7bf40388bc5800073b96564f56264f7e48bfd1a498f5ced6ae6d5a769/ruff-0.15.20-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd7ec42b3bb3da066488db093308a69c4ac5ee6d2af333a86ba6e2eb2e7dd44b", size = 10622882, upload-time = "2026-06-25T17:19:57.037Z" }, + { url = "https://files.pythonhosted.org/packages/13/7a/43460be3f24495a3aa46d4b16873e2c4941b3b5f0b00cf88c03b7b94b339/ruff-0.15.20-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1a36ad0eb77fba9aabfb69ede54de6f376d04ac18ebea022847046d340a8267", size = 11474808, upload-time = "2026-06-25T17:20:00.357Z" }, + { url = "https://files.pythonhosted.org/packages/27/a0/f37077884873221c6b33b4ab49eb18f9f88e54a16a25a5bca59bef46dd66/ruff-0.15.20-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6df3b1e4610432f0386dba04d853b5f08cbbc903410c6fcc02f620f05aff53c", size = 12293094, upload-time = "2026-06-25T17:20:03.446Z" }, + { url = "https://files.pythonhosted.org/packages/a6/74/165545b60256a9704c21ac0ec4a0d07933b320812f9584836c9f4aca4292/ruff-0.15.20-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e89f198a1ea6ef0d727c1cf16088bc91a6cb0ab947dedc966715691647186eae", size = 11526176, upload-time = "2026-06-25T17:20:06.301Z" }, + { url = "https://files.pythonhosted.org/packages/86/b1/a976a136d40ade83ce743578399865f57001003a409acadc0ecbb3051082/ruff-0.15.20-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309809086c2acb67624950a3c8133e80f32d0d3e27106c0cd60ff26657c9f24b", size = 11520767, upload-time = "2026-06-25T17:20:09.191Z" }, + { url = "https://files.pythonhosted.org/packages/19/0f/f032696cb01c9b54c0263fa393474d7758f1cdc021a01b04e3cbc2500999/ruff-0.15.20-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2d2374caa2f2c2f9e2b7da0a50802cfb8b79f55a9b5e49379f564544fbf56487", size = 11500132, upload-time = "2026-06-25T17:20:13.602Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f4/51b1a14bc69e8c224b15dab9cce8e99b425e0455d462caa2b3c9be2b6a8e/ruff-0.15.20-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a1ed17b65293e0c2f22fc387bc13198a5de94bf4429589b0ff6946b0feaf21a3", size = 10943828, upload-time = "2026-06-25T17:20:16.635Z" }, + { url = "https://files.pythonhosted.org/packages/71/4b/fe267640783cd02bf6c5cc290b1df1051be2ec294c678b5c15fe19e52343/ruff-0.15.20-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f701305e66b38ea6c91882490eb73459796808e4c6362a1b765255e0cdcd4053", size = 10645418, upload-time = "2026-06-25T17:20:19.4Z" }, + { url = "https://files.pythonhosted.org/packages/b0/c0/a65aa4ec2f5e87a1df32dc3ec1fede434fe3dfd5cbcf3b503cafc676ab54/ruff-0.15.20-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b9c0c367ad8e5d0d5b5b8537864c469a0a0e55417aadfbeca41fa61333be9f4", size = 11211770, upload-time = "2026-06-25T17:20:22.033Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a4/0caa331d954ae2723d729d351c989cb4ca8b6077d5c6c2cb6de75e98c041/ruff-0.15.20-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:01cc00dd58f0df339d0e902219dd53990ea99996a0344e5d9cc8d45d5307e460", size = 11618698, upload-time = "2026-06-25T17:20:25.259Z" }, + { url = "https://files.pythonhosted.org/packages/10/9b/5f14927848d2fd4aa891fd88d883788c5a7baba561c7874732364045708c/ruff-0.15.20-py3-none-win32.whl", hash = "sha256:ed65ef510e43a137207e0f01cfcf998aeddb1aeeda5c9d35023e910284d7cf21", size = 10857322, upload-time = "2026-06-25T17:20:28.612Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f0/fe47c501f9dea92a26d788ff98bb5d92ed4cb4c88792c5c88af6b697dc8e/ruff-0.15.20-py3-none-win_amd64.whl", hash = "sha256:a525c81c70fb0380344dd1d8745d8cc1c890b7fc94a58d5a07bd8eb9557b8415", size = 11993274, upload-time = "2026-06-25T17:20:31.871Z" }, + { url = "https://files.pythonhosted.org/packages/d7/2b/9555445e1201d92b3195f45cdb153a0b68f24e0a4273f6e3d5ab46e212bb/ruff-0.15.20-py3-none-win_arm64.whl", hash = "sha256:2f5b2a6d614e8700388806a14996c40fab2c47b819ef57d790a34878858ed9ca", size = 11343498, upload-time = "2026-06-25T17:20:35.03Z" }, +] + +[[package]] +name = "secretstorage" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography", marker = "(python_full_version < '3.11' and sys_platform == 'emscripten') or (python_full_version < '3.11' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32')" }, + { name = "jeepney", marker = "(python_full_version < '3.11' and sys_platform == 'emscripten') or (python_full_version < '3.11' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl", hash = "sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137", size = 15554, upload-time = "2025-11-23T19:02:51.545Z" }, +] + +[[package]] +name = "sgmllib3k" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9e/bd/3704a8c3e0942d711c1299ebf7b9091930adae6675d7c8f476a7ce48653c/sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9", size = 5750, upload-time = "2010-08-24T14:33:52.445Z" } + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "snowballstemmer" +version = "3.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/f8/0a71edf031f03c40db17503cb8ca78a69a171254e568e7db241b0ab57ea1/snowballstemmer-3.1.1.tar.gz", hash = "sha256:e07bbc54a0d798fe6010a12398422e62a8bfbba95c394fd0956ef58cb4d3e260", size = 123314, upload-time = "2026-06-03T00:56:40.194Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4c/07/2ebca9b11fb9be7340a818d8d6f63feaebb146be2c4afbd6061701d6df6e/snowballstemmer-3.1.1-py3-none-any.whl", hash = "sha256:7e207fa178741da09cdee59d3ecec3827ad5f92b1fc5c9ff3755b639f71f5752", size = 104164, upload-time = "2026-06-03T00:56:38.614Z" }, +] + +[[package]] +name = "sse-starlette" +version = "3.4.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "starlette" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6c/10/a34c656829ffc1c4b22ef36d70d9ebb6b99c020e2aeb17cee5485099f028/sse_starlette-3.4.6.tar.gz", hash = "sha256:725f8a1bd6d26ae1b2c9610c0ef5065dfdd496f3988d28adcf8c4b49dc25c627", size = 32542, upload-time = "2026-07-20T14:16:32.201Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/36/e10c1d1b7ca881d2625db2ec28508578499187bb1c389952c398474e1834/sse_starlette-3.4.6-py3-none-any.whl", hash = "sha256:56217ab4c9a9f9c5db7b21e08732d3e7c2b807f45231ad23de0551a24c4a41f6", size = 16516, upload-time = "2026-07-20T14:16:30.978Z" }, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pure-eval" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, +] + +[[package]] +name = "starlette" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/e3/7c1dc7381d9f8ab7d854328ebfa884e62cb3f3d8549ddfd37c7814f42afa/starlette-1.3.1.tar.gz", hash = "sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0", size = 2703240, upload-time = "2026-06-12T09:23:11.602Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/bb/2799cc2ede3ed41131f8975621e7213dfc7ef4acbbaadfa440f32500c370/starlette-1.3.1-py3-none-any.whl", hash = "sha256:c7372aae11c3c3f26a42df7bd626cec2f47d03483d261d369516a615a53714c6", size = 73632, upload-time = "2026-06-12T09:23:10.017Z" }, +] + +[[package]] +name = "time-machine" +version = "2.19.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/a4/1b5fdd165f61b67f445fac2a7feb0c655118edef429cd09ff5a8067f7f1d/time_machine-2.19.0.tar.gz", hash = "sha256:7c5065a8b3f2bbb449422c66ef71d114d3f909c276a6469642ecfffb6a0fcd29", size = 14576, upload-time = "2025-08-19T17:22:08.402Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/8f/19125611ebbcb3a14da14cd982b9eb4573e2733db60c9f1fbf6a39534f40/time_machine-2.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b5169018ef47206997b46086ce01881cd3a4666fd2998c9d76a87858ca3e49e9", size = 19659, upload-time = "2025-08-19T17:20:30.062Z" }, + { url = "https://files.pythonhosted.org/packages/74/da/9b0a928321e7822a3ff96dbd1eae089883848e30e9e1b149b85fb96ba56b/time_machine-2.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:85bb7ed440fccf6f6d0c8f7d68d849e7c3d1f771d5e0b2cdf871fa6561da569f", size = 15157, upload-time = "2025-08-19T17:20:31.931Z" }, + { url = "https://files.pythonhosted.org/packages/36/ff/d7e943422038f5f2161fe2c2d791e64a45be691ef946020b20f3a6efc4d4/time_machine-2.19.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a3b12028af1cdc09ccd595be2168b7b26f206c1e190090b048598fbe278beb8e", size = 32860, upload-time = "2025-08-19T17:20:33.241Z" }, + { url = "https://files.pythonhosted.org/packages/fc/80/2b0f1070ed9808ee7da7a6da62a4a0b776957cb4d861578348f86446e778/time_machine-2.19.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c261f073086cf081d1443cbf7684148c662659d3d139d06b772bfe3fe7cc71a6", size = 34510, upload-time = "2025-08-19T17:20:34.221Z" }, + { url = "https://files.pythonhosted.org/packages/ef/b4/48038691c8d89924b36c83335a73adeeb68c884f5a1da08a5b17b8a956f3/time_machine-2.19.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:011954d951230a9f1079f22b39ed1a3a9abb50ee297dfb8c557c46351659d94d", size = 36204, upload-time = "2025-08-19T17:20:35.163Z" }, + { url = "https://files.pythonhosted.org/packages/37/2e/60e8adb541df195e83cb74b720b2cfb1f22ed99c5a7f8abf2a9ab3442cb5/time_machine-2.19.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b0f83308b29c7872006803f2e77318874eb84d0654f2afe0e48e3822e7a2e39b", size = 34936, upload-time = "2025-08-19T17:20:36.61Z" }, + { url = "https://files.pythonhosted.org/packages/5e/72/e8cee59c6cd99dd3b25b8001a0253e779a286aa8f44d5b40777cbd66210b/time_machine-2.19.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:39733ef844e2984620ec9382a42d00cccc4757d75a5dd572be8c2572e86e50b9", size = 32932, upload-time = "2025-08-19T17:20:37.901Z" }, + { url = "https://files.pythonhosted.org/packages/2c/eb/83f300d93c1504965d944e03679f1c943a923bce2d0fdfadef0e2e22cc13/time_machine-2.19.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f8db99f6334432e9ffbf00c215caf2ae9773f17cec08304d77e9e90febc3507b", size = 34010, upload-time = "2025-08-19T17:20:39.202Z" }, + { url = "https://files.pythonhosted.org/packages/e1/77/f35f2500e04daac5033a22fbfd17e68467822b8406ee77966bf222ccaa26/time_machine-2.19.0-cp310-cp310-win32.whl", hash = "sha256:72bf66cd19e27ffd26516b9cbe676d50c2e0b026153289765dfe0cf406708128", size = 17121, upload-time = "2025-08-19T17:20:40.108Z" }, + { url = "https://files.pythonhosted.org/packages/db/df/32d3e0404be1760a64a44caab2af34b07e952bfe00a23134fea9ddba3e8a/time_machine-2.19.0-cp310-cp310-win_amd64.whl", hash = "sha256:46f1c945934ce3d6b4f388b8e581fce7f87ec891ea90d7128e19520e434f96f0", size = 17957, upload-time = "2025-08-19T17:20:41.079Z" }, + { url = "https://files.pythonhosted.org/packages/66/df/598a71a1afb4b509a4587273b76590b16d9110a3e9106f01eedc68d02bb2/time_machine-2.19.0-cp310-cp310-win_arm64.whl", hash = "sha256:fb4897c7a5120a4fd03f0670f332d83b7e55645886cd8864a71944c4c2e5b35b", size = 16821, upload-time = "2025-08-19T17:20:41.967Z" }, + { url = "https://files.pythonhosted.org/packages/1d/ed/4815ebcc9b6c14273f692b9be38a9b09eae52a7e532407cc61a51912b121/time_machine-2.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5ee91664880434d98e41585c3446dac7180ec408c786347451ddfca110d19296", size = 19342, upload-time = "2025-08-19T17:20:43.207Z" }, + { url = "https://files.pythonhosted.org/packages/ee/08/154cce8b11b60d8238b0b751b8901d369999f4e8f7c3a5f917caa5d95b0b/time_machine-2.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ed3732b83a893d1c7b8cabde762968b4dc5680ee0d305b3ecca9bb516f4e3862", size = 14978, upload-time = "2025-08-19T17:20:44.134Z" }, + { url = "https://files.pythonhosted.org/packages/c7/b7/b689d8c8eeca7af375cfcd64973e49e83aa817cc00f80f98548d42c0eb50/time_machine-2.19.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6ba0303e9cc9f7f947e344f501e26bedfb68fab521e3c2729d370f4f332d2d55", size = 30964, upload-time = "2025-08-19T17:20:45.366Z" }, + { url = "https://files.pythonhosted.org/packages/80/91/38bf9c79674e95ce32e23c267055f281dff651eec77ed32a677db3dc011a/time_machine-2.19.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2851825b524a988ee459c37c1c26bdfaa7eff78194efb2b562ea497a6f375b0a", size = 32606, upload-time = "2025-08-19T17:20:46.693Z" }, + { url = "https://files.pythonhosted.org/packages/19/4a/e9222d85d4de68975a5e799f539a9d32f3a134a9101fca0a61fa6aa33d68/time_machine-2.19.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:68d32b09ecfd7fef59255c091e8e7c24dd117f882c4880b5c7ab8c5c32a98f89", size = 34405, upload-time = "2025-08-19T17:20:48.032Z" }, + { url = "https://files.pythonhosted.org/packages/14/e2/09480d608d42d6876f9ff74593cfc9197a7eb2c31381a74fb2b145575b65/time_machine-2.19.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60c46ab527bf2fa144b530f639cc9e12803524c9e1f111dc8c8f493bb6586eeb", size = 33181, upload-time = "2025-08-19T17:20:48.937Z" }, + { url = "https://files.pythonhosted.org/packages/84/64/f9359e000fad32d9066305c48abc527241d608bcdf77c19d67d66e268455/time_machine-2.19.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:56f26ab9f0201c453d18fe76bb7d1cf05fe58c1b9d9cb0c7d243d05132e01292", size = 31036, upload-time = "2025-08-19T17:20:50.276Z" }, + { url = "https://files.pythonhosted.org/packages/71/0d/fab2aacec71e3e482bd7fce0589381f9414a4a97f8766bddad04ad047b7b/time_machine-2.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6c806cf3c1185baa1d807b7f51bed0db7a6506832c961d5d1b4c94c775749bc0", size = 32145, upload-time = "2025-08-19T17:20:51.449Z" }, + { url = "https://files.pythonhosted.org/packages/44/fb/faeba2405fb27553f7b28db441a500e2064ffdb2dcba001ee315fdd2c121/time_machine-2.19.0-cp311-cp311-win32.whl", hash = "sha256:b30039dfd89855c12138095bee39c540b4633cbc3684580d684ef67a99a91587", size = 17004, upload-time = "2025-08-19T17:20:52.38Z" }, + { url = "https://files.pythonhosted.org/packages/2f/84/87e483d660ca669426192969280366635c845c3154a9fe750be546ed3afc/time_machine-2.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:13ed8b34430f1de79905877f5600adffa626793ab4546a70a99fb72c6a3350d8", size = 17822, upload-time = "2025-08-19T17:20:53.348Z" }, + { url = "https://files.pythonhosted.org/packages/41/f4/ebf7bbf5047854a528adaf54a5e8780bc5f7f0104c298ab44566a3053bf8/time_machine-2.19.0-cp311-cp311-win_arm64.whl", hash = "sha256:cc29a50a0257d8750b08056b66d7225daab47606832dea1a69e8b017323bf511", size = 16680, upload-time = "2025-08-19T17:20:54.26Z" }, + { url = "https://files.pythonhosted.org/packages/9b/aa/7e00614d339e4d687f6e96e312a1566022528427d237ec639df66c4547bc/time_machine-2.19.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c85cf437dc3c07429456d8d6670ac90ecbd8241dcd0fbf03e8db2800576f91ff", size = 19308, upload-time = "2025-08-19T17:20:55.25Z" }, + { url = "https://files.pythonhosted.org/packages/ab/3c/bde3c757394f5bca2fbc1528d4117960a26c38f9b160bf471b38d2378d8f/time_machine-2.19.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d9238897e8ef54acdf59f5dff16f59ca0720e7c02d820c56b4397c11db5d3eb9", size = 15019, upload-time = "2025-08-19T17:20:56.204Z" }, + { url = "https://files.pythonhosted.org/packages/c8/e0/8ca916dd918018352d377f1f5226ee071cfbeb7dbbde2b03d14a411ac2b1/time_machine-2.19.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e312c7d5d6bfffb96c6a7b39ff29e3046de100d7efaa3c01552654cfbd08f14c", size = 33079, upload-time = "2025-08-19T17:20:57.166Z" }, + { url = "https://files.pythonhosted.org/packages/48/69/184a0209f02dd0cb5e01e8d13cd4c97a5f389c4e3d09b95160dd676ad1e7/time_machine-2.19.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:714c40b2c90d1c57cc403382d5a9cf16e504cb525bfe9650095317da3c3d62b5", size = 34925, upload-time = "2025-08-19T17:20:58.117Z" }, + { url = "https://files.pythonhosted.org/packages/43/42/4bbf4309e8e57cea1086eb99052d97ff6ddecc1ab6a3b07aa4512f8bf963/time_machine-2.19.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2eaa1c675d500dc3ccae19e9fb1feff84458a68c132bbea47a80cc3dd2df7072", size = 36384, upload-time = "2025-08-19T17:20:59.108Z" }, + { url = "https://files.pythonhosted.org/packages/b1/af/9f510dc1719157348c1a2e87423aed406589070b54b503cb237d9bf3a4fe/time_machine-2.19.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e77a414e9597988af53b2b2e67242c9d2f409769df0d264b6d06fda8ca3360d4", size = 34881, upload-time = "2025-08-19T17:21:00.116Z" }, + { url = "https://files.pythonhosted.org/packages/ca/28/61764a635c70cc76c76ba582dfdc1a84834cddaeb96789023af5214426b2/time_machine-2.19.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cd93996970e11c382b04d4937c3cd0b0167adeef14725ece35aae88d8a01733c", size = 32931, upload-time = "2025-08-19T17:21:01.095Z" }, + { url = "https://files.pythonhosted.org/packages/b6/e0/f028d93b266e6ade8aca5851f76ebbc605b2905cdc29981a2943b43e1a6c/time_machine-2.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8e20a6d8d6e23174bd7e931e134d9610b136db460b249d07e84ecdad029ec352", size = 34241, upload-time = "2025-08-19T17:21:02.052Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a6/36d1950ed1d3f613158024cf1dcc73db1d9ef0b9117cf51ef2e37dc06499/time_machine-2.19.0-cp312-cp312-win32.whl", hash = "sha256:95afc9bc65228b27be80c2756799c20b8eb97c4ef382a9b762b6d7888bc84099", size = 17021, upload-time = "2025-08-19T17:21:03.374Z" }, + { url = "https://files.pythonhosted.org/packages/b1/0d/e2dce93355abda3cac69e77fe96566757e98b8fe7fdcbddce89c9ced3f5f/time_machine-2.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:e84909af950e2448f4e2562ea5759c946248c99ab380d2b47d79b62bd76fa236", size = 17857, upload-time = "2025-08-19T17:21:04.331Z" }, + { url = "https://files.pythonhosted.org/packages/eb/28/50ae6fb83b7feeeca7a461c0dc156cf7ef5e6ef594a600d06634fde6a2cb/time_machine-2.19.0-cp312-cp312-win_arm64.whl", hash = "sha256:0390a1ea9fa7e9d772a39b7c61b34fdcca80eb9ffac339cc0441c6c714c81470", size = 16677, upload-time = "2025-08-19T17:21:05.39Z" }, + { url = "https://files.pythonhosted.org/packages/a9/b8/24ebce67aa531bae2cbe164bb3f4abc6467dc31f3aead35e77f5a075ea3e/time_machine-2.19.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5e172866753e6041d3b29f3037dc47c20525176a494a71bbd0998dfdc4f11f2f", size = 19373, upload-time = "2025-08-19T17:21:06.701Z" }, + { url = "https://files.pythonhosted.org/packages/53/a5/c9a5240fd2f845d3ff9fa26f8c8eaa29f7239af9d65007e61d212250f15b/time_machine-2.19.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f70f68379bd6f542ae6775cce9a4fa3dcc20bf7959c42eaef871c14469e18097", size = 15056, upload-time = "2025-08-19T17:21:07.667Z" }, + { url = "https://files.pythonhosted.org/packages/b9/92/66cce5d2fb2a5e68459aca85fd18a7e2d216f725988940cd83f96630f2f1/time_machine-2.19.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e69e0b0f694728a00e72891ef8dd00c7542952cb1c87237db594b6b27d504a96", size = 33172, upload-time = "2025-08-19T17:21:08.619Z" }, + { url = "https://files.pythonhosted.org/packages/ae/20/b499e9ab4364cd466016c33dcdf4f56629ca4c20b865bd4196d229f31d92/time_machine-2.19.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3ae0a8b869574301ec5637e32c270c7384cca5cd6e230f07af9d29271a7fa293", size = 35042, upload-time = "2025-08-19T17:21:09.622Z" }, + { url = "https://files.pythonhosted.org/packages/41/32/b252d3d32791eb16c07d553c820dbc33d9c7fa771de3d1c602190bded2b7/time_machine-2.19.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:554e4317de90e2f7605ff80d153c8bb56b38c0d0c0279feb17e799521e987b8c", size = 36535, upload-time = "2025-08-19T17:21:10.571Z" }, + { url = "https://files.pythonhosted.org/packages/98/cf/4d0470062b9742e1b040ab81bad04d1a5d1de09806507bb6188989cfa1a7/time_machine-2.19.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6567a5ec5538ed550539ac29be11b3cb36af1f9894e2a72940cba0292cc7c3c9", size = 34945, upload-time = "2025-08-19T17:21:11.538Z" }, + { url = "https://files.pythonhosted.org/packages/24/71/2f741b29d98b1c18f6777a32236497c3d3264b6077e431cea4695684c8a1/time_machine-2.19.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82e9ffe8dfff07b0d810a2ad015a82cd78c6a237f6c7cf185fa7f747a3256f8a", size = 33014, upload-time = "2025-08-19T17:21:12.858Z" }, + { url = "https://files.pythonhosted.org/packages/e8/83/ca8dba6106562843fd99f672e5aaf95badbc10f4f13f7cfe8d8640a7019d/time_machine-2.19.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7e1c4e578cdd69b3531d8dd3fbcb92a0cd879dadb912ee37af99c3a9e3c0d285", size = 34350, upload-time = "2025-08-19T17:21:13.923Z" }, + { url = "https://files.pythonhosted.org/packages/21/7f/34fe540450e18d0a993240100e4b86e8d03d831b92af8bb6ddb2662dc6fc/time_machine-2.19.0-cp313-cp313-win32.whl", hash = "sha256:72dbd4cbc3d96dec9dd281ddfbb513982102776b63e4e039f83afb244802a9e5", size = 17047, upload-time = "2025-08-19T17:21:14.874Z" }, + { url = "https://files.pythonhosted.org/packages/bf/5d/c8be73df82c7ebe7cd133279670e89b8b110af3ce1412c551caa9d08e625/time_machine-2.19.0-cp313-cp313-win_amd64.whl", hash = "sha256:e17e3e089ac95f9a145ce07ff615e3c85674f7de36f2d92aaf588493a23ffb4b", size = 17868, upload-time = "2025-08-19T17:21:15.819Z" }, + { url = "https://files.pythonhosted.org/packages/92/13/2dfd3b8fb285308f61cd7aa9bfa96f46ddf916e3549a0f0afd094c556599/time_machine-2.19.0-cp313-cp313-win_arm64.whl", hash = "sha256:149072aff8e3690e14f4916103d898ea0d5d9c95531b6aa0995251c299533f7b", size = 16710, upload-time = "2025-08-19T17:21:16.748Z" }, + { url = "https://files.pythonhosted.org/packages/05/c1/deebb361727d2c5790f9d4d874be1b19afd41f4375581df465e6718b46a2/time_machine-2.19.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f3589fee1ed0ab6ee424a55b0ea1ec694c4ba64cc26895bcd7d99f3d1bc6a28a", size = 20053, upload-time = "2025-08-19T17:21:17.704Z" }, + { url = "https://files.pythonhosted.org/packages/45/e8/fe3376951e6118d8ec1d1f94066a169b791424fe4a26c7dfc069b153ee08/time_machine-2.19.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7887e85275c4975fe54df03dcdd5f38bd36be973adc68a8c77e17441c3b443d6", size = 15423, upload-time = "2025-08-19T17:21:18.668Z" }, + { url = "https://files.pythonhosted.org/packages/9c/c7/f88d95cd1a87c650cf3749b4d64afdaf580297aa18ad7f4b44ec9d252dfc/time_machine-2.19.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ce0be294c209928563fcce1c587963e60ec803436cf1e181acd5bc1e425d554b", size = 39630, upload-time = "2025-08-19T17:21:19.645Z" }, + { url = "https://files.pythonhosted.org/packages/cc/5d/65a5c48a65357e56ec6f032972e4abd1c02d4fca4b0717a3aaefd19014d4/time_machine-2.19.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a62fd1ab380012c86f4c042010418ed45eb31604f4bf4453e17c9fa60bc56a29", size = 41242, upload-time = "2025-08-19T17:21:20.979Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f9/fe5209e1615fde0a8cad6c4e857157b150333ed1fe31a7632b08cfe0ebdd/time_machine-2.19.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b25ec853a4530a5800731257f93206b12cbdee85ede964ebf8011b66086a7914", size = 44278, upload-time = "2025-08-19T17:21:21.984Z" }, + { url = "https://files.pythonhosted.org/packages/4a/3a/a5e5fe9c5d614cde0a9387ff35e8dfd12c5ef6384e4c1a21b04e6e0b905d/time_machine-2.19.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a430e4d0e0556f021a9c78e9b9f68e5e8910bdace4aa34ed4d1a73e239ed9384", size = 42321, upload-time = "2025-08-19T17:21:23.755Z" }, + { url = "https://files.pythonhosted.org/packages/a1/c5/56eca774e9162bc1ce59111d2bd69140dc8908c9478c92ec7bd15d547600/time_machine-2.19.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2415b7495ec4364c8067071e964fbadfe746dd4cdb43983f2f0bd6ebed13315c", size = 39270, upload-time = "2025-08-19T17:21:26.009Z" }, + { url = "https://files.pythonhosted.org/packages/9b/69/5dd0c420667578169a12acc8c8fd7452e8cfb181e41c9b4ac7e88fa36686/time_machine-2.19.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dbfc6b90c10f288594e1bf89a728a98cc0030791fd73541bbdc6b090aff83143", size = 40193, upload-time = "2025-08-19T17:21:27.054Z" }, + { url = "https://files.pythonhosted.org/packages/75/a7/de974d421bd55c9355583427c2a38fb0237bb5fd6614af492ba89dacb2f9/time_machine-2.19.0-cp313-cp313t-win32.whl", hash = "sha256:16f5d81f650c0a4d117ab08036dc30b5f8b262e11a4a0becc458e7f1c011b228", size = 17542, upload-time = "2025-08-19T17:21:28.674Z" }, + { url = "https://files.pythonhosted.org/packages/76/0a/aa0d05becd5d06ae8d3f16d657dc8cc9400c8d79aef80299de196467ff12/time_machine-2.19.0-cp313-cp313t-win_amd64.whl", hash = "sha256:645699616ec14e147094f601e6ab9553ff6cea37fad9c42720a6d7ed04bcd5dc", size = 18703, upload-time = "2025-08-19T17:21:29.663Z" }, + { url = "https://files.pythonhosted.org/packages/1f/c0/f785a4c7c73aa176510f7c48b84b49c26be84af0d534deb222e0327f750e/time_machine-2.19.0-cp313-cp313t-win_arm64.whl", hash = "sha256:b32daa965d13237536ea3afaa5ad61ade2b2d9314bc3a20196a0d2e1d7b57c6a", size = 17020, upload-time = "2025-08-19T17:21:30.653Z" }, + { url = "https://files.pythonhosted.org/packages/ed/97/c5fb51def06c0b2b6735332ad118ab35b4d9b85368792e5b638e99b1b686/time_machine-2.19.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:31cb43c8fd2d961f31bed0ff4e0026964d2b35e5de9e0fabbfecf756906d3612", size = 19360, upload-time = "2025-08-19T17:21:31.94Z" }, + { url = "https://files.pythonhosted.org/packages/2d/4e/2d795f7d6b7f5205ffe737a05bb1cf19d8038233b797062b2ef412b8512b/time_machine-2.19.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:bdf481a75afc6bff3e520db594501975b652f7def21cd1de6aa971d35ba644e6", size = 15033, upload-time = "2025-08-19T17:21:32.934Z" }, + { url = "https://files.pythonhosted.org/packages/dd/32/9bad501e360b4e758c58fae616ca5f8c7ad974b343f2463a15b2bf77a366/time_machine-2.19.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:00bee4bb950ac6a08d62af78e4da0cf2b4fc2abf0de2320d0431bf610db06e7c", size = 33379, upload-time = "2025-08-19T17:21:33.925Z" }, + { url = "https://files.pythonhosted.org/packages/a3/45/eda0ca4d793dfd162478d6163759b1c6ce7f6e61daa7fd7d62b31f21f87f/time_machine-2.19.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9f02199490906582302ce09edd32394fb393271674c75d7aa76c7a3245f16003", size = 35123, upload-time = "2025-08-19T17:21:34.945Z" }, + { url = "https://files.pythonhosted.org/packages/f0/5a/97e16325442ae5731fcaac794f0a1ef9980eff8a5491e58201d7eb814a34/time_machine-2.19.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e35726c7ba625f844c13b1fc0d4f81f394eefaee1d3a094a9093251521f2ef15", size = 36588, upload-time = "2025-08-19T17:21:35.975Z" }, + { url = "https://files.pythonhosted.org/packages/e8/9d/bf0b2ccc930cc4a316f26f1c78d3f313cd0fa13bb7480369b730a8f129db/time_machine-2.19.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:304315023999cd401ff02698870932b893369e1cfeb2248d09f6490507a92e97", size = 35013, upload-time = "2025-08-19T17:21:37.017Z" }, + { url = "https://files.pythonhosted.org/packages/f0/5a/39ac6a3078174f9715d88364871348b249631f12e76de1b862433b3f8862/time_machine-2.19.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9765d4f003f263ea8bfd90d2d15447ca4b3dfa181922cf6cf808923b02ac180a", size = 33303, upload-time = "2025-08-19T17:21:38.352Z" }, + { url = "https://files.pythonhosted.org/packages/b3/ac/d8646baf9f95f2e792a6d7a7b35e92fca253c4a992afff801beafae0e5c2/time_machine-2.19.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7837ef3fd5911eb9b480909bb93d922737b6bdecea99dfcedb0a03807de9b2d3", size = 34440, upload-time = "2025-08-19T17:21:39.382Z" }, + { url = "https://files.pythonhosted.org/packages/ce/8b/8b6568c5ae966d80ead03ab537be3c6acf2af06fb501c2d466a3162c6295/time_machine-2.19.0-cp314-cp314-win32.whl", hash = "sha256:4bb5bd43b1bdfac3007b920b51d8e761f024ed465cfeec63ac4296922a4ec428", size = 17162, upload-time = "2025-08-19T17:21:40.381Z" }, + { url = "https://files.pythonhosted.org/packages/46/a5/211c1ab4566eba5308b2dc001b6349e3a032e3f6afa67ca2f27ea6b27af5/time_machine-2.19.0-cp314-cp314-win_amd64.whl", hash = "sha256:f583bbd0aa8ab4a7c45a684bf636d9e042d466e30bcbae1d13e7541e2cbe7207", size = 18040, upload-time = "2025-08-19T17:21:41.363Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fc/4c2fb705f6371cb83824da45a8b967514a922fc092a0ef53979334d97a70/time_machine-2.19.0-cp314-cp314-win_arm64.whl", hash = "sha256:f379c6f8a6575a8284592179cf528ce89373f060301323edcc44f1fa1d37be12", size = 16752, upload-time = "2025-08-19T17:21:42.336Z" }, + { url = "https://files.pythonhosted.org/packages/79/ab/6437d18f31c666b5116c97572a282ac2590a82a0a9867746a6647eaf4613/time_machine-2.19.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:a3b8981f9c663b0906b05ab4d0ca211fae4b63b47c6ec26de5374fe56c836162", size = 20057, upload-time = "2025-08-19T17:21:43.35Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a2/e03639ec2ba7200328bbcad8a2b2b1d5fccca9cceb9481b164a1cabdcb33/time_machine-2.19.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8e9c6363893e7f52c226afbebb23e825259222d100e67dfd24c8a6d35f1a1907", size = 15430, upload-time = "2025-08-19T17:21:44.725Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ff/39e63a48e840f3e36ce24846ee51dd99c6dba635659b1750a2993771e88e/time_machine-2.19.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:206fcd6c9a6f00cac83db446ad1effc530a8cec244d2780af62db3a2d0a9871b", size = 39622, upload-time = "2025-08-19T17:21:45.821Z" }, + { url = "https://files.pythonhosted.org/packages/9a/2e/ee5ac79c4954768705801e54817c7d58e07e25a0bb227e775f501f3e2122/time_machine-2.19.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bf33016a1403c123373ffaeff25e26e69d63bf2c63b6163932efed94160db7ef", size = 41235, upload-time = "2025-08-19T17:21:46.783Z" }, + { url = "https://files.pythonhosted.org/packages/3a/3e/9af5f39525e779185c77285b8bbae15340eeeaa0afb33d458bc8b47d459b/time_machine-2.19.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9247c4bb9bbd3ff584ef4efbdec8efd9f37aa08bcfc4728bde1e489c2cb445bd", size = 44276, upload-time = "2025-08-19T17:21:47.759Z" }, + { url = "https://files.pythonhosted.org/packages/59/fe/572c7443cc27140bbeae3947279bbd4a120f9e8622253a20637f260b7813/time_machine-2.19.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:77f9bb0b86758d1f2d9352642c874946ad5815df53ef4ca22eb9d532179fe50d", size = 42330, upload-time = "2025-08-19T17:21:48.881Z" }, + { url = "https://files.pythonhosted.org/packages/cf/24/1a81c2e08ee7dae13ec8ceed27a29afa980c3d63852e42f1e023bf0faa03/time_machine-2.19.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0b529e262df3b9c449f427385f4d98250828c879168c2e00eec844439f40b370", size = 39281, upload-time = "2025-08-19T17:21:49.907Z" }, + { url = "https://files.pythonhosted.org/packages/d2/60/6f0d6e5108978ca1a2a4ffb4d1c7e176d9199bb109fd44efe2680c60b52a/time_machine-2.19.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9199246e31cdc810e5d89cb71d09144c4d745960fdb0824da4994d152aca3303", size = 40201, upload-time = "2025-08-19T17:21:50.953Z" }, + { url = "https://files.pythonhosted.org/packages/73/b9/3ea4951e8293b0643feb98c0b9a176fa822154f1810835db3f282968ab10/time_machine-2.19.0-cp314-cp314t-win32.whl", hash = "sha256:0fe81bae55b7aefc2c2a34eb552aa82e6c61a86b3353a3c70df79b9698cb02ca", size = 17743, upload-time = "2025-08-19T17:21:51.948Z" }, + { url = "https://files.pythonhosted.org/packages/e4/8b/cd802884ca8a98e2b6cdc2397d57dd12ff8a7d1481e06fc3fad3d4e7e5ff/time_machine-2.19.0-cp314-cp314t-win_amd64.whl", hash = "sha256:7253791b8d7e7399fbeed7a8193cb01bc004242864306288797056badbdaf80b", size = 18956, upload-time = "2025-08-19T17:21:52.997Z" }, + { url = "https://files.pythonhosted.org/packages/c6/49/cabb1593896082fd55e34768029b8b0ca23c9be8b2dc127e0fc14796d33e/time_machine-2.19.0-cp314-cp314t-win_arm64.whl", hash = "sha256:536bd1ac31ab06a1522e7bf287602188f502dc19d122b1502c4f60b1e8efac79", size = 17068, upload-time = "2025-08-19T17:21:54.064Z" }, +] + +[[package]] +name = "tomli" +version = "2.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454, upload-time = "2026-03-25T20:21:12.036Z" }, + { url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561, upload-time = "2026-03-25T20:21:13.098Z" }, + { url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824, upload-time = "2026-03-25T20:21:14.569Z" }, + { url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227, upload-time = "2026-03-25T20:21:15.712Z" }, + { url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859, upload-time = "2026-03-25T20:21:17.001Z" }, + { url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204, upload-time = "2026-03-25T20:21:18.079Z" }, + { url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084, upload-time = "2026-03-25T20:21:18.978Z" }, + { url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285, upload-time = "2026-03-25T20:21:20.309Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924, upload-time = "2026-03-25T20:21:21.626Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018, upload-time = "2026-03-25T20:21:23.002Z" }, + { url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948, upload-time = "2026-03-25T20:21:24.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341, upload-time = "2026-03-25T20:21:25.177Z" }, + { url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159, upload-time = "2026-03-25T20:21:26.364Z" }, + { url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290, upload-time = "2026-03-25T20:21:27.46Z" }, + { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" }, + { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" }, + { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" }, + { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" }, + { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" }, + { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" }, + { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" }, + { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" }, + { url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726, upload-time = "2026-03-25T20:21:42.23Z" }, + { url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859, upload-time = "2026-03-25T20:21:43.386Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713, upload-time = "2026-03-25T20:21:44.474Z" }, + { url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084, upload-time = "2026-03-25T20:21:45.62Z" }, + { url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973, upload-time = "2026-03-25T20:21:46.937Z" }, + { url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223, upload-time = "2026-03-25T20:21:48.467Z" }, + { url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973, upload-time = "2026-03-25T20:21:49.526Z" }, + { url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082, upload-time = "2026-03-25T20:21:50.506Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490, upload-time = "2026-03-25T20:21:51.474Z" }, + { url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263, upload-time = "2026-03-25T20:21:52.543Z" }, + { url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736, upload-time = "2026-03-25T20:21:53.674Z" }, + { url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717, upload-time = "2026-03-25T20:21:55.129Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461, upload-time = "2026-03-25T20:21:56.228Z" }, + { url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855, upload-time = "2026-03-25T20:21:57.653Z" }, + { url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144, upload-time = "2026-03-25T20:21:59.089Z" }, + { url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683, upload-time = "2026-03-25T20:22:00.214Z" }, + { url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196, upload-time = "2026-03-25T20:22:01.169Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393, upload-time = "2026-03-25T20:22:02.137Z" }, + { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" }, +] + +[[package]] +name = "tomli-w" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/75/241269d1da26b624c0d5e110e8149093c759b7a286138f4efd61a60e75fe/tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021", size = 7184, upload-time = "2025-01-15T12:07:24.262Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z" }, +] + +[[package]] +name = "tomlkit" +version = "0.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/51/db/03eaf4331631ef6b27d6e3c9b68c54dc6f0d63d87201fed600cc409307fd/tomlkit-0.15.0.tar.gz", hash = "sha256:7d1a9ecba3086638211b13814ea79c90dd54dd11993564376f3aa92271f5c7a3", size = 161875, upload-time = "2026-05-10T07:38:22.245Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/43/8bd850ee71a191bf072e31302c73a66be413fecdd98fdcd111ecbcce13ca/tomlkit-0.15.0-py3-none-any.whl", hash = "sha256:4dbc8f0fc024412b57ced8757ac7461305126a648ff8c2c807fcb8e133a78738", size = 41328, upload-time = "2026-05-10T07:38:23.517Z" }, +] + +[[package]] +name = "tornado" +version = "6.5.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/64/24/95ec527ad67b76d59299e5465b3935d05e4294b7e0290a3924b7487df30b/tornado-6.5.7.tar.gz", hash = "sha256:66c513a76cda70d53907bc27cf1447557699c2e95aa48ba27a442ff61c3ddfc2", size = 519252, upload-time = "2026-06-08T17:34:51.232Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/dc/c7043cab6fed8ae159fc1923ce829ada35c4dbd797d408a43858ffaf9639/tornado-6.5.7-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:148b2eb15c2c765a50796172c1e499649b35f30d2e3c3d3e15913cfa56bfb163", size = 448543, upload-time = "2026-06-08T17:34:38.052Z" }, + { url = "https://files.pythonhosted.org/packages/92/4f/090b1431e5a43df696feceffc268c5383cc079ecb5f08ce58f917109aafe/tornado-6.5.7-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9da38de27f1da3b78a966f0dae12b5a1ea9afe72ca805d84ff06508272ddf100", size = 446707, upload-time = "2026-06-08T17:34:39.594Z" }, + { url = "https://files.pythonhosted.org/packages/37/d8/ef374952fd5da67d4463122c2b8e5a96536ec10b4b339254c6dcde81d01c/tornado-6.5.7-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8d759e71906ee783f8867b93bf26a265743da4c1e2f4a018464c1ba019862972", size = 449774, upload-time = "2026-06-08T17:34:41.204Z" }, + { url = "https://files.pythonhosted.org/packages/35/37/d434c73f4c6e014b745b9b37085f34f40c022f007efff3d7fe65991899f3/tornado-6.5.7-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a46347a18f23fb92b396beebe0fb78f61dda0cc302445202c16203d8a18848b", size = 450745, upload-time = "2026-06-08T17:34:42.531Z" }, + { url = "https://files.pythonhosted.org/packages/b6/2b/56b9aff361d7f1ab728a805ec7d7ea835f8807afa9f5cc690ea0e630efb9/tornado-6.5.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7778b30bef919231265e91c69963ce0f49a1e9c07ac900bbe75b19ce2575ba92", size = 450578, upload-time = "2026-06-08T17:34:43.787Z" }, + { url = "https://files.pythonhosted.org/packages/02/30/a7444fb23aa76860a14198fab96ac79f1866b0a6e19e26c4381b0938e50f/tornado-6.5.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e726f0c75da7726eec023aa62751ff8878bd2737e34fbdd33b1ae5897d2200f5", size = 449985, upload-time = "2026-06-08T17:34:45.326Z" }, + { url = "https://files.pythonhosted.org/packages/5c/42/5f0e56c01e8d9d36f4e23f367b85ae6cae0c1ecddd5e6977d8388ad27488/tornado-6.5.7-cp39-abi3-win32.whl", hash = "sha256:f8de3bf12d3efdd0cbe7c8887868198f8a91415e3f29fcf258d9b8eb7b1d9ae4", size = 451047, upload-time = "2026-06-08T17:34:46.784Z" }, + { url = "https://files.pythonhosted.org/packages/c9/a4/b393076ffb21b469eec5b328a0534cf03a3b90bfc6b1f09507cdd075d938/tornado-6.5.7-cp39-abi3-win_amd64.whl", hash = "sha256:de942f843533a039ef9fa3d9c88c7cd8a7c94553fb5ad0154270989b3d99a2c4", size = 451485, upload-time = "2026-06-08T17:34:48.248Z" }, + { url = "https://files.pythonhosted.org/packages/71/2e/7b1c769803121b809112cf9a00681c472eae1d80e32d7ec0e0bd61d0d0e1/tornado-6.5.7-cp39-abi3-win_arm64.whl", hash = "sha256:ff934fce95643af5f11efdae618eaa73d469dc588641e5c8d19295a0c65c4796", size = 450506, upload-time = "2026-06-08T17:34:49.702Z" }, +] + +[[package]] +name = "tox" +version = "4.56.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cachetools" }, + { name = "colorama" }, + { name = "filelock" }, + { name = "packaging" }, + { name = "platformdirs" }, + { name = "pluggy" }, + { name = "pyproject-api" }, + { name = "python-discovery" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "tomli-w" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/81/b75cc8da0c83eb78fe9fcefb572ecd6f3ebdf5af46b9a04114c81f02db94/tox-4.56.3.tar.gz", hash = "sha256:6eaaf5258114e736cca7ca8423e84234fce910b7889ea0fb92b1df28cb4c31aa", size = 286614, upload-time = "2026-07-08T17:02:21.726Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/7c/b32ea539fb2e3948f09c32c0c7b06543afd5c4a454b73cb31e11e90be461/tox-4.56.3-py3-none-any.whl", hash = "sha256:d3274970e82f8ec3e3a9d5acfa19ee507574193ead81f01d177e7f78edbe7746", size = 217461, upload-time = "2026-07-08T17:02:19.979Z" }, +] + +[[package]] +name = "traitlets" +version = "5.15.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/a9/a2584b8313b89f94869ddb3c4074617a691de1812a614d2d50e32ca5a7a6/traitlets-5.15.1.tar.gz", hash = "sha256:7b1c07854fe25acb39e009bae49f11b79ff6cbb2f27999104e9110e7a6b53722", size = 163344, upload-time = "2026-06-03T12:26:06.181Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/8d/1080ee4c231f361b6ce4470d556c8c435b67c7e0753aaa641497ee92f88b/traitlets-5.15.1-py3-none-any.whl", hash = "sha256:770a53705f84b81ac107e83a1b3328ff2dae16094d8fc3cfc004e4b22dfd8e92", size = 85858, upload-time = "2026-06-03T12:26:04.395Z" }, +] + +[[package]] +name = "ty" +version = "0.0.57" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/16/d01c968d405acae51c07872e80f30f3a586235bdf52c9847ca0917a230a3/ty-0.0.57.tar.gz", hash = "sha256:bc058f564868690283a0420d09c269ec8be21e8e43b4b49ee975a17623092e44", size = 6100787, upload-time = "2026-07-08T11:33:59.904Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3e/9c/a7948b05f2a3f43d511f88ef5c4f56d7edb8acc8caa5f56d7c5831f52c84/ty-0.0.57-py3-none-linux_armv6l.whl", hash = "sha256:cb6d3371dd8c78950b75bee31a36b94564a54a1f0eecafbbf05715ac1a5287d6", size = 11760058, upload-time = "2026-07-08T11:33:18.671Z" }, + { url = "https://files.pythonhosted.org/packages/6e/92/3776380decba3965bcaa1ea2b56f5b133aa3ef549bfbe4b79eb122dcc15d/ty-0.0.57-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e58b90491a48ec757bd50f512f3eb92c1c64b7d46a4db83677e9b60222e1d2bb", size = 11492105, upload-time = "2026-07-08T11:33:21.267Z" }, + { url = "https://files.pythonhosted.org/packages/13/be/912f8422d06fd1e29805a7c781e3ce4c821917e0e3d00f0cf176c0529469/ty-0.0.57-py3-none-macosx_11_0_arm64.whl", hash = "sha256:dbb8207f75122c658ca21bf405cea8202e490240440461ae3e0c5a6f67ae668f", size = 11078675, upload-time = "2026-07-08T11:33:23.804Z" }, + { url = "https://files.pythonhosted.org/packages/06/86/6ed526df554b491ce3d07bbec04f7a10304243bc994ab989352c85134b1e/ty-0.0.57-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:651243f391809de80b01be1729c5d0cecc7b952d7d22cfbf56f0b4f069703195", size = 11614379, upload-time = "2026-07-08T11:33:26.041Z" }, + { url = "https://files.pythonhosted.org/packages/0d/95/78af20f309abce31fa616e0142f85756e665a9965669b823181ff695ffec/ty-0.0.57-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:28c5392bbd7c4d6a4c1b1646a709231db675dc094f49bf71b7de83757125e93b", size = 11563854, upload-time = "2026-07-08T11:33:28.144Z" }, + { url = "https://files.pythonhosted.org/packages/88/dc/bf9231d5563b9e61a1eec9782184a4055afaa87259644cd9ed1376a7dc5c/ty-0.0.57-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d981535094ab492aaef6f71d9348bcf90e42e6de4cb50de2dd7fbabd8378360", size = 12229897, upload-time = "2026-07-08T11:33:30.262Z" }, + { url = "https://files.pythonhosted.org/packages/c0/dd/012008190a997097ebe500b9704baaad9135bfa033b9530a9b8f69f1d11f/ty-0.0.57-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:719b41fd6df61352866cad952d7bfb4873c893a70e806d37d0f1d30ad4f26cd5", size = 12816002, upload-time = "2026-07-08T11:33:32.747Z" }, + { url = "https://files.pythonhosted.org/packages/f4/2f/0e42c361e38e04747ed2b3d3299512edd4ea6060d8e3124e3c6f2d2465a1/ty-0.0.57-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a1641a609b025e13f44115c7071b39b02675044a78fbfedef239a5f7da50b393", size = 12323420, upload-time = "2026-07-08T11:33:35.426Z" }, + { url = "https://files.pythonhosted.org/packages/c6/01/18f1e03108d1ae8e515c92fb304994a66eaafd47037f928fd42fd3a1e29d/ty-0.0.57-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a33f96a9dd6919fe8b1d3512cd99f16be4a51388f265de135fea2c2fbf0b4317", size = 12119481, upload-time = "2026-07-08T11:33:37.808Z" }, + { url = "https://files.pythonhosted.org/packages/6a/48/570b73fb3e32554ff03aa9f6650b33a504cdfa027a8b50a5ab087e56b20d/ty-0.0.57-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:f0a1014a922b2b7f79a46e5cdbaa6feb7403a444631292b8666382a98a04de20", size = 12427299, upload-time = "2026-07-08T11:33:39.964Z" }, + { url = "https://files.pythonhosted.org/packages/b7/37/76b27f6a92e12525d09cd65d3c3b5aea419cf4782b13320db95ac3d310f0/ty-0.0.57-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d73aaed84023bf682819f871377b255fae9098898c50475426ac9bdfcd986872", size = 11562292, upload-time = "2026-07-08T11:33:42.392Z" }, + { url = "https://files.pythonhosted.org/packages/84/8b/d0c398147b00f336595e1a00a5895b3924251205c11b8d73cb0668281f1c/ty-0.0.57-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f3e2104704063c00ab8a757af3e95378b32624a3e8d8149aad5251877bf82959", size = 11565833, upload-time = "2026-07-08T11:33:44.778Z" }, + { url = "https://files.pythonhosted.org/packages/3e/74/dab9745e977ef38751ec710f74e40d21fddbd04a80338dd5597c98899eed/ty-0.0.57-py3-none-musllinux_1_2_i686.whl", hash = "sha256:07ad760763646d8f1567ea5d899e6d217212acd8539b7afed5a370d93693553b", size = 11864967, upload-time = "2026-07-08T11:33:47.36Z" }, + { url = "https://files.pythonhosted.org/packages/a2/57/350812143b49dac7aa655f40a1f45d4821ca9b56b75d9b68d5e603269044/ty-0.0.57-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b4a6e1f0fee7df3e65fb0b9cbe9f99a4be39198558ed9aacc31a98d210ad7bcc", size = 12239054, upload-time = "2026-07-08T11:33:49.586Z" }, + { url = "https://files.pythonhosted.org/packages/a4/d0/b3e3d9c6cce3debda6247aa435e81d18ec62fabfec13f35f6c6957066f47/ty-0.0.57-py3-none-win32.whl", hash = "sha256:f8d488c0535a8f0386dbe2c9bcb31d467ae0c68d0c9945113018937828ebaabb", size = 11225353, upload-time = "2026-07-08T11:33:52.569Z" }, + { url = "https://files.pythonhosted.org/packages/77/db/6ce240ee31413f9dc7467e31377553e92e2664252ee7d33aa9290a7a94bb/ty-0.0.57-py3-none-win_amd64.whl", hash = "sha256:de9529a7dcc3e529b08c14634dc4e7066ebea5cd55006afc02bde8033efe7c91", size = 12272419, upload-time = "2026-07-08T11:33:54.889Z" }, + { url = "https://files.pythonhosted.org/packages/44/de/48662fa2c42289f309eeb8b5539cbe840e10002b65ac0700cb7889e92532/ty-0.0.57-py3-none-win_arm64.whl", hash = "sha256:7f3352777ce40c4906145f3c3e10b71716d8d35c0c9e3a0070d84f61dda0755f", size = 11686309, upload-time = "2026-07-08T11:33:57.246Z" }, +] + +[[package]] +name = "types-python-dateutil" +version = "2.9.0.20260518" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8d/e8/c01bdf0d7c3659428c091fbd693177093639565bcbc86bc20098e6d37cc6/types_python_dateutil-2.9.0.20260518.tar.gz", hash = "sha256:51f02dc03b61c7f6a07df45797d4dfe8a1aa47f0b7db9ad89f6fd3a1a70e1b51", size = 17082, upload-time = "2026-05-18T06:05:24.508Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/22/169273273ca34e9ab0ae2f387ba72ed7e09faaaf834da01d6b89c2bea71a/types_python_dateutil-2.9.0.20260518-py3-none-any.whl", hash = "sha256:d6a9c5bd0de61460c8fdef8ab2b400f956a1a1075cce08d4e2b4434e478c50b8", size = 18431, upload-time = "2026-05-18T06:05:23.641Z" }, +] + +[[package]] +name = "types-requests" +version = "2.33.0.20260518" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e0/01/c5a19253fe1ac159159ddf9a3a07cec8bb5e486ec4d9002ad2821da0e5d2/types_requests-2.33.0.20260518.tar.gz", hash = "sha256:df7bd3bfe0ca8402dfb841e7d9be714bb5578203283d66d7dc4ef69343449a5e", size = 24752, upload-time = "2026-05-18T06:07:37.966Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/bc/b139710a3b6018f7fb2b9508b35c8af564e61bf2bf4fa619d088f3e16f85/types_requests-2.33.0.20260518-py3-none-any.whl", hash = "sha256:626d697d1adaaff76e2044dc8c5c051d8f21abc157bdfe204a75558076fe0bf0", size = 21391, upload-time = "2026-05-18T06:07:37.044Z" }, +] + +[[package]] +name = "types-toml" +version = "0.10.8.20260518" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4b/11/6ece999e91f2ccb848ab4420f3f4816e78ac0541f739e6864affdaaa5737/types_toml-0.10.8.20260518.tar.gz", hash = "sha256:80e10facd24fdeda9d5c672187d72be3ac284843788d67f5aae59e3e016db6fe", size = 9419, upload-time = "2026-05-18T06:02:16.719Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/25/489751806bf5c95e4007f8e17409199c54d31e49ffbea07c5729b1286c8e/types_toml-0.10.8.20260518-py3-none-any.whl", hash = "sha256:0e564ab05f6fde62a315b3b5a9b6624fda569399795d30a37e64705a70459303", size = 9669, upload-time = "2026-05-18T06:02:15.86Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, +] + +[[package]] +name = "tzdata" +version = "2026.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/19/1b9b0e29f30c6d35cb345486df41110984ea67ae69dddbc0e8a100999493/tzdata-2026.2.tar.gz", hash = "sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10", size = 198254, upload-time = "2026-04-24T15:22:08.651Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7", size = 349321, upload-time = "2026-04-24T15:22:05.876Z" }, +] + +[[package]] +name = "uncalled-for" +version = "0.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b5/82/345cc927f7fbdae6065e7768759932fcc827fc20b29b45dfbafa2f1f7da4/uncalled_for-0.3.2.tar.gz", hash = "sha256:89f5dbcd71e2b8f47c030b1fa302e6cce2ec795d1ac565eeb6525c5fe55cb8a2", size = 50032, upload-time = "2026-05-06T13:38:25.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/25/2c87754f3a9e692315f7b811244090e68f362979fc8886b3fbd2985a1d8c/uncalled_for-0.3.2-py3-none-any.whl", hash = "sha256:0ff60b142c7d1f8070bde9d42afaa70aedc77dcc10998c227687e9c15713418e", size = 11444, upload-time = "2026-05-06T13:38:24.025Z" }, +] + +[[package]] +name = "urllib3" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, +] + +[[package]] +name = "uuid7" +version = "0.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/19/7472bd526591e2192926247109dbf78692e709d3e56775792fec877a7720/uuid7-0.1.0.tar.gz", hash = "sha256:8c57aa32ee7456d3cc68c95c4530bc571646defac01895cfc73545449894a63c", size = 14052, upload-time = "2021-12-29T01:38:21.897Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b5/77/8852f89a91453956582a85024d80ad96f30a41fed4c2b3dce0c9f12ecc7e/uuid7-0.1.0-py2.py3-none-any.whl", hash = "sha256:5e259bb63c8cb4aded5927ff41b444a80d0c7124e8a0ced7cf44efa1f5cccf61", size = 7477, upload-time = "2021-12-29T01:38:20.418Z" }, +] + +[[package]] +name = "uvicorn" +version = "0.51.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a2/65/b7c6c443ccc58678c91e1e973bbe2a878591538655d6e1d47f24ba1c51f3/uvicorn-0.51.0.tar.gz", hash = "sha256:f6f4b69b657c312f516dd2d268ab9ae6f254b11e4bac504f37b2ab58b24dd0b0", size = 94412, upload-time = "2026-07-08T10:59:05.962Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/ec/dbb7e5a6b91f86bfb9eb7d2988a2730907b6a729875b949c7f022e8b88fa/uvicorn-0.51.0-py3-none-any.whl", hash = "sha256:5d38af6cd620f2ae3849fb44fd4879e0890aa1febe8d47eb355fb45d93fe6a5b", size = 73219, upload-time = "2026-07-08T10:59:04.44Z" }, +] + +[[package]] +name = "vcrpy" +version = "8.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/39/d5/8a1f8eb603e2d35fbb0ecd1e309d0c5c18a0ecfc8c0a8f04088bbc8f833b/vcrpy-8.3.0.tar.gz", hash = "sha256:46d64e77e8d95e5c76c7d9a94ff05d8b38b2ae4e1d4869eb0235024b6fcb5212", size = 96117, upload-time = "2026-07-04T14:27:01.608Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/77/cb4219be91508399cbcb6143bad89462cfb16f6c638458f454a5d46ac95a/vcrpy-8.3.0-py3-none-any.whl", hash = "sha256:bd66e6143746778157f00e2a922527a8d96b2fdc350be8988a45a29c843815b9", size = 46530, upload-time = "2026-07-04T14:27:00.546Z" }, +] + +[[package]] +name = "virtualenv" +version = "21.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, + { name = "python-discovery" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/65/ec1d92091671e6407d3e7c1f5801413bb7b2b57630a50cae7750456ba0ed/virtualenv-21.6.0.tar.gz", hash = "sha256:e18a4d750f2b64dea73e72ffde3922f3c52365fabdc8157ebd3da20d031c4734", size = 5526111, upload-time = "2026-07-06T22:49:56.972Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/e7/2fbd0cc1653c53eed8f10670538bb547de2b3e37aacad283faa82a71094b/virtualenv-21.6.0-py3-none-any.whl", hash = "sha256:bce9d097950fef9d81129b333babfb7767072850c2f1acce0ec536708401bfd1", size = 5506216, upload-time = "2026-07-06T22:49:54.941Z" }, +] + +[[package]] +name = "watchfiles" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cd/41/5e1a4bb12aac5f1493fa1bdc11154eca3b258ca4eba65d39c473fe19d8e9/watchfiles-1.2.0.tar.gz", hash = "sha256:c995fba777f1ea992f090f9236e9284cf7a5d1a0130dd5a3d82c598cacd76838", size = 108252, upload-time = "2026-05-18T04:32:04.251Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/5a/2bf22ecb24916983bf1cc0095e7dea2741d14d6553b0d6a2ac8bc96eca93/watchfiles-1.2.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:bb68bf4df85abebe5efddc53cf2075520f243a59868d9b3973278b23e76962a9", size = 400471, upload-time = "2026-05-18T04:31:08.908Z" }, + { url = "https://files.pythonhosted.org/packages/55/70/dea1f6a0e76607841a60fb51af150e70124864673f61704abb62b90cdcc7/watchfiles-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c16cb06dd17d43b9d185094268459eac92c9538356f050e55b54e82cf700e1d4", size = 394599, upload-time = "2026-05-18T04:30:19.845Z" }, + { url = "https://files.pythonhosted.org/packages/18/52/752dcc7dc817baef5e89518732925795ce52e36a683a9a3c9fb68b21504e/watchfiles-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77a0feab9af4c021c581f695258c642b3d10c5fd4c676e33a0d8606425d82631", size = 455458, upload-time = "2026-05-18T04:30:29.126Z" }, + { url = "https://files.pythonhosted.org/packages/12/48/366ebbb22fcc504c2f72b45f0b7e72f40a18795cc01752c16066d597b67a/watchfiles-1.2.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a16ffe19bf5cf9f5edaa1ad1dd830c5a816e8feec430c522302ab55483a4b994", size = 460513, upload-time = "2026-05-18T04:31:40.85Z" }, + { url = "https://files.pythonhosted.org/packages/ad/44/1f9e1b15e7a729062e0d0c3d0d7225ea4ab98b2267ef87287153be2495fc/watchfiles-1.2.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204f299afcbd65918ab78dbc52626b0ae45e9d8cef403fdbf33ecf9e40eac66e", size = 493616, upload-time = "2026-05-18T04:30:58.47Z" }, + { url = "https://files.pythonhosted.org/packages/7e/55/8b1086dcc8a1d6a697a62767bd7ea368e74c61c6fd171683cfe24a3fe5d2/watchfiles-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11743adfa510bfffebe97659fb280182b5c9b238708f667e866f308c3430dc19", size = 573154, upload-time = "2026-05-18T04:30:37.903Z" }, + { url = "https://files.pythonhosted.org/packages/14/7a/242f400cc77fafa7b18d53d19d9cb64fc6a6f61f28c55913bae7c674d92a/watchfiles-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eb72919d93e3a16fc451d3aa3d4b1698423daca1b382d3d959c9ac51297c12a8", size = 467046, upload-time = "2026-05-18T04:30:41.869Z" }, + { url = "https://files.pythonhosted.org/packages/02/c8/79eee650c62d2c186598489814468e389b5def0ebe755399ff645b35b1b2/watchfiles-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62f042afde2dde21ec1d2c1a74361e804673df86f51e418a999c9acfe671b07", size = 457100, upload-time = "2026-05-18T04:31:13.064Z" }, + { url = "https://files.pythonhosted.org/packages/81/36/519f6dbb7a95e4fe7c1513ed25b1520295ef9905a27f1f2226a73892bfb7/watchfiles-1.2.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:027ae72bfdfd254862065d8b3e2a815c6ab9b1853ce41e6648ece84afd34a551", size = 467038, upload-time = "2026-05-18T04:30:32.915Z" }, + { url = "https://files.pythonhosted.org/packages/2f/12/951af6b9f89097e02511122258402cb3578443021930b70cf968d6310dc0/watchfiles-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e1cfd51e97e13ff3bd047c140764d277fc9b95b7cb5da59e46a47d167adab310", size = 632563, upload-time = "2026-05-18T04:30:11.539Z" }, + { url = "https://files.pythonhosted.org/packages/28/cc/0cba1f0a6117b7ec117271bdc3cb3a5a252005959755a2c09a745e0942cc/watchfiles-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:24b2405c0a46738dd9e1cf7135aa5dbdb9d42d024628651b3b13d5117e99f8df", size = 660851, upload-time = "2026-05-18T04:31:53.186Z" }, + { url = "https://files.pythonhosted.org/packages/d0/f2/26347558cc8bf6877845e66b315f644d03c173906aa09e233a3f4fd23928/watchfiles-1.2.0-cp310-cp310-win32.whl", hash = "sha256:8c520725602756229f045b032a1ff33d7ef0f7404189d62f6c2438cb6d8ef6a1", size = 277023, upload-time = "2026-05-18T04:30:18.825Z" }, + { url = "https://files.pythonhosted.org/packages/6d/68/a5e67b6b68e94f4c1511d61c46c55eba0737583620b6febf194c7b9cc23f/watchfiles-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:03b14855c6f35539e2d95c442ae9530a75762f1e26567152b9ed05f96534a74d", size = 290107, upload-time = "2026-05-18T04:32:09.677Z" }, + { url = "https://files.pythonhosted.org/packages/fc/3d/8024c801df84d1587740d0359e7fdd80afeae3d159011f3d5376dd82f18e/watchfiles-1.2.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:704fd259e332e01f9b9c178f4bce9e49027e5587cc2600eeeaf8e76e1c846201", size = 400242, upload-time = "2026-05-18T04:31:19.014Z" }, + { url = "https://files.pythonhosted.org/packages/87/5b/f4dfd45323e949984a3a7f9dc31d1cbb049921e7d98253488dda72ccdaa9/watchfiles-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6543cf55d170003296d185c0af981f3e1311564907e1f4e08671fc7693a890a5", size = 394562, upload-time = "2026-05-18T04:30:08.46Z" }, + { url = "https://files.pythonhosted.org/packages/98/d8/19483ef075d601c409bce8bcbb5c0f81a10876fff870400568f08ce484a1/watchfiles-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89d8c2394a065ca86f5d2910ff263ae67c127e1376ccc4f9fc35c71db879f80a", size = 456611, upload-time = "2026-05-18T04:30:45.723Z" }, + { url = "https://files.pythonhosted.org/packages/b1/6a/cc81fbe7ee42f2f22e661a6e12def7807e01b14b2f39e0ff83fd373fd307/watchfiles-1.2.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:772b80df316480d894a0e3165fdd19cf77f5d17f9a787f94029465ad0e3529d1", size = 461379, upload-time = "2026-05-18T04:31:29.292Z" }, + { url = "https://files.pythonhosted.org/packages/b1/57/7e669002082c0a0f4fb5113bb70125f7110124b846b0a11bc5ae8e90eac1/watchfiles-1.2.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d158cd89df6053823533e06fb1d73c549133bff5f0396170c0e53d9559340717", size = 493556, upload-time = "2026-05-18T04:30:05.44Z" }, + { url = "https://files.pythonhosted.org/packages/45/7d/f60a2b19807b21fe8281f3a8da4f59eef0d5f96825ac4680ba2d4f2ebf91/watchfiles-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d516b3283a758e087841aedb8031549fb41ced08f3db10aa6d2bf32dc042525b", size = 575255, upload-time = "2026-05-18T04:30:40.568Z" }, + { url = "https://files.pythonhosted.org/packages/bd/49/77f5b5e6efbcd57482f74948ebb1b97e5c0046d6b61475042d830c84b3ff/watchfiles-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:53b2290c92e0506d102cd448fbc610d87079553f86caa39d67440856a8b8bba5", size = 467052, upload-time = "2026-05-18T04:31:17.942Z" }, + { url = "https://files.pythonhosted.org/packages/ee/5a/73e2959af1b97fd5d556f9a8bdba017be23ceeef731869d5eaa0a753d5a3/watchfiles-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a711b51aec4370d0dcda5b6c09463206f133a5759341d7744b953a7b62e1100e", size = 456858, upload-time = "2026-05-18T04:30:30.182Z" }, + { url = "https://files.pythonhosted.org/packages/50/57/1bc8c27fad7e6c19bddee15d276dbb6ab72480ec01c127afff1673aee417/watchfiles-1.2.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:e2ca07fa7d89195ec0865d3d285666286740bfa83d83e5cee204043a31ecc165", size = 467579, upload-time = "2026-05-18T04:32:15.897Z" }, + { url = "https://files.pythonhosted.org/packages/09/6c/3c2e44edba3553c5e3c3b8c8a2a6dee6b9e12ae2cf4bd2378bebf9dc3038/watchfiles-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e0618518f282c4ebff60f5e5b1247b6d91bb8b9f4476947563a1e74acc66f3c6", size = 633253, upload-time = "2026-05-18T04:31:37.123Z" }, + { url = "https://files.pythonhosted.org/packages/30/c2/d8c84a882ab39bbefcc4915ab3e91830b7a7e990c5570b0b69075aba3faf/watchfiles-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0d191c054d0715c3c95c99df9b8dbf6fd096d8c1e021e8f212e1bd8bc444ccb5", size = 660713, upload-time = "2026-05-18T04:31:24.62Z" }, + { url = "https://files.pythonhosted.org/packages/a9/07/f97736a5fc605364fe67b25e9fa4a6965dfd4840d50c406ada507e9d735f/watchfiles-1.2.0-cp311-cp311-win32.whl", hash = "sha256:9342472aff9b093c5acd4f6d8f70ae0937964ab56542502bcf5579782da69ae8", size = 277222, upload-time = "2026-05-18T04:31:21.131Z" }, + { url = "https://files.pythonhosted.org/packages/cf/99/2b04981977fc2608afd60360d928c6aecf6b950292ca221d98f4005f6694/watchfiles-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:dbd6c97045dad81227c8d040173da044c1de08de64a5ea8b555da4aee1d5fa22", size = 290274, upload-time = "2026-05-18T04:31:45.966Z" }, + { url = "https://files.pythonhosted.org/packages/3c/74/f7f58a7075ee9cf612b0cfcddb78b8cd8234f0742d6f0075cf0da2dde1c6/watchfiles-1.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:57a2d9fa4fb4c2ecae57b13dfff2c7ab53e21a2ba674fe9f05506680fcdcc0d7", size = 283460, upload-time = "2026-05-18T04:31:39.126Z" }, + { url = "https://files.pythonhosted.org/packages/b8/2f/e42c992d2afda3108ea1c02acecc991b9f31d05c14adc2a7cee9ee211fc4/watchfiles-1.2.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:bc13eb17538be00c874699dc0abe4ee2bc8d50bb1166a6b9e175ef3fd7eb8f26", size = 400115, upload-time = "2026-05-18T04:32:02.06Z" }, + { url = "https://files.pythonhosted.org/packages/5f/8f/6af2ea19065c91d8b0ea3516fdfc8c0d349f407e8e9fbf4e5a17360de8ad/watchfiles-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d95ddc1eb6914154253d239089900813f6a767e174b8e6a50e7fdacb7e4236c", size = 393659, upload-time = "2026-05-18T04:30:50.951Z" }, + { url = "https://files.pythonhosted.org/packages/13/01/b32a967c56fb3e3e5be3db52c3d3b87fa4513aa367d8ed1ad96d42952e5f/watchfiles-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f70d8b291ef6e88d19b1f297a6905ddb978888d9272b0d05e6f53309856bcfc", size = 453207, upload-time = "2026-05-18T04:31:04.231Z" }, + { url = "https://files.pythonhosted.org/packages/04/98/97557a812180338cb1abd32e1cffcc4588f59b5f23e0cb006b2ba95ba64a/watchfiles-1.2.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:56d8641cf834c2836922899105bd3ce3d0dfc69291d52edf0b4d0436829b34c0", size = 459273, upload-time = "2026-05-18T04:31:50.377Z" }, + { url = "https://files.pythonhosted.org/packages/e8/a8/b4b08dcb7653b8087c6586f7ce649505900e866bbcfe40dc9587af02e686/watchfiles-1.2.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2581a94056e55d7d0a31a823ea92bf73749c489ca2285bfdc0fbe6b2bb49d50c", size = 489927, upload-time = "2026-05-18T04:31:42.485Z" }, + { url = "https://files.pythonhosted.org/packages/50/94/3dceea03545d2e5ddfd839f0ddd5e1cecbf1697b5a428d5ba11cef6af95d/watchfiles-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41bc1199f7523b3f82843c88cbb979180c949caef0342cf90968f178e5d49b01", size = 570476, upload-time = "2026-05-18T04:31:03.071Z" }, + { url = "https://files.pythonhosted.org/packages/cc/f2/d39a5450c3532092b91f81d274360e613c2371bc874a89c7a1a3c5e8d138/watchfiles-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7571e4464cb6e434958f867f7f730b8ab0b75e3f8e5eac0499168486ab3c33a8", size = 465650, upload-time = "2026-05-18T04:30:12.701Z" }, + { url = "https://files.pythonhosted.org/packages/22/24/ed72f68cbc1333ca9b9f2200aa048bb6658ae41709bc1caad4310f4bdffd/watchfiles-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e53a384f76b631c3ae5334ce6a52f0baa3a911eb94a4eac7f160079868b716d5", size = 456398, upload-time = "2026-05-18T04:30:13.784Z" }, + { url = "https://files.pythonhosted.org/packages/0d/64/982ef4a4e5bab5b6e5b6becc8cd5e732f6130a78b855f0abec6439a9a135/watchfiles-1.2.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:d20029a60a71a052a24c4db7673bc4de39ab89adbaccbfb5d67987c5d73f424d", size = 465140, upload-time = "2026-05-18T04:31:52.111Z" }, + { url = "https://files.pythonhosted.org/packages/a0/0c/95282abf4ed680b6096010bcfc30c5fa7a041fc5aa5a2ad17a2cc6c75bba/watchfiles-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2cb93af48550faf1cea04c303107c8b75833de7013e57ce27d3b8d21d8d0f58c", size = 630259, upload-time = "2026-05-18T04:31:25.676Z" }, + { url = "https://files.pythonhosted.org/packages/30/45/607c1de1530c4bdcf2cf1d1ecc2505ddba5d96bd43ba9f2b0e79876f850f/watchfiles-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2995c176de7692b86a2e4c58d9ec718f753150a979cb4a754e2b4ffa38e70906", size = 659859, upload-time = "2026-05-18T04:30:24.333Z" }, + { url = "https://files.pythonhosted.org/packages/fa/08/d9e2e0f9e8e6791d33aefc694ad7eefa7f901f63caff84a81ded38692f9c/watchfiles-1.2.0-cp312-cp312-win32.whl", hash = "sha256:7a2cffd17d27d2ecbb310c2b1d8174f222a5495b1a721894afa88ec11e25b898", size = 275480, upload-time = "2026-05-18T04:30:31.307Z" }, + { url = "https://files.pythonhosted.org/packages/1c/e6/9d42569c0102645cc8cea5d8c7d8a1e9d4ada2cb7f05f75e554b8aa2202a/watchfiles-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:f155b3a1b2a5fc89cdc70d47ee5d54e3b75e88efa34982028a35daef9ba00379", size = 288718, upload-time = "2026-05-18T04:32:10.745Z" }, + { url = "https://files.pythonhosted.org/packages/0a/26/88e0dc6ee3898169d7fa22bb6a69cabf2502d2ee25cb8c876d1262d204f8/watchfiles-1.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:8fa585ede612ee9f9e91b18bebf9ba11b9ae29a4e3a0d0cf6fca3e382133f0d5", size = 281026, upload-time = "2026-05-18T04:30:22.23Z" }, + { url = "https://files.pythonhosted.org/packages/d1/4d/70a7feced9f87e2ff26dba42667290f41694fc64646c67261fbb8cab5d5c/watchfiles-1.2.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:01ea8d66f0693b9b60a6541c8d10263091ca9a9060d242f3c1f3143f9aad2c98", size = 399730, upload-time = "2026-05-18T04:31:38.162Z" }, + { url = "https://files.pythonhosted.org/packages/31/3a/0da302f2307aee316922806ebd5726c542cbd787c938271cf14a074c7daf/watchfiles-1.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7ba0480b9a74af058f43b337e937a451e109295c420916d68ad24e3dc02f5e44", size = 392842, upload-time = "2026-05-18T04:30:27.051Z" }, + { url = "https://files.pythonhosted.org/packages/db/ef/d5bdb705c224dbc256aa0c1ec47bf4e61ec52558f2afb44a71a1fe4d7015/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f34e26a19f91f710c08e0183429f0d1d15df734e6bc78c31e77b9ea9c433658", size = 452989, upload-time = "2026-05-18T04:31:11.945Z" }, + { url = "https://files.pythonhosted.org/packages/71/29/5495f2c1661949ef7a35e4d71111d129cfe7606414a26887a919d0a55406/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b4e77f6a55f858504069abd35d336a637555c09bca453dde1ee1e5ada8a6a1fb", size = 458978, upload-time = "2026-05-18T04:30:52.606Z" }, + { url = "https://files.pythonhosted.org/packages/d5/8c/7f9c07c433811c2fffd93e13fdfb7135de9aab5f2ae41be08960fa0047dc/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0cb4d80e212f116474a545c21c912b445f16bb0cef9e6a73a498164223e14e2f", size = 490248, upload-time = "2026-05-18T04:31:36.003Z" }, + { url = "https://files.pythonhosted.org/packages/3c/11/d93632febc52fbc21be90231bb7c17fd5387f46c9076fd40a5f9c2ae6910/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b974946a10af379d425e2eef5b62f5c6ebeaccf91d45eaad6f5b27ecd4f91aa0", size = 571847, upload-time = "2026-05-18T04:31:10.862Z" }, + { url = "https://files.pythonhosted.org/packages/55/b4/383173e73aabb07ad1d9c7aa859d95437ac46a6d6a1e11005facda0c9d19/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86bc13c25a8d1fcd70b51d0ce7c9b65e90de5666fcbfd3e34957cc73ee19aeb5", size = 465974, upload-time = "2026-05-18T04:30:17.006Z" }, + { url = "https://files.pythonhosted.org/packages/a7/6c/89b1a230a78f57c52dd8893adb1f92f94411721b6ec12596c56d98c74356/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca148d73dea36c9763aaa351e4d7a51780ec1584217c45276f4fe8239c768b71", size = 454782, upload-time = "2026-05-18T04:30:35.656Z" }, + { url = "https://files.pythonhosted.org/packages/24/62/1732118367cfff0a9fce3bf62ff4bfded09ef5df21d9d446b858b3f70a96/watchfiles-1.2.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:c525543d91961c6955b2636b308569e84a1d1c5f5f2932041ab9ef46422f43e3", size = 465182, upload-time = "2026-05-18T04:30:20.846Z" }, + { url = "https://files.pythonhosted.org/packages/28/96/716f7e5f51339bf22963f3345f9f27d7f3b30e2eadc597e257c881dd3c53/watchfiles-1.2.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a204794696ffb8f9b10fba6f7cb5216d42f3b2b71860ccac6b6e42f5f10973b0", size = 629841, upload-time = "2026-05-18T04:31:05.397Z" }, + { url = "https://files.pythonhosted.org/packages/4c/fe/c40783950fd771ccf66ab3ec2722d188a9af1c7f96c6e811f36e40c6e03f/watchfiles-1.2.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:10d86db20695afe7997ac9e1717637d6714a8d0220458c33f3d2061f54cec427", size = 658028, upload-time = "2026-05-18T04:31:48.22Z" }, + { url = "https://files.pythonhosted.org/packages/71/72/4508db1856d1d87fcbb3b63f4839bab1b5682cb0e8d224d122263c09654a/watchfiles-1.2.0-cp313-cp313-win32.whl", hash = "sha256:eb283ee99e21ad6443c8cdb06ac5b34b1308c329cbdf03fa02b445363714c799", size = 275183, upload-time = "2026-05-18T04:30:59.57Z" }, + { url = "https://files.pythonhosted.org/packages/f9/36/14b76ca57652e5cc5fd1c11f32a261292c08a0d19a00351013c2549cbfb2/watchfiles-1.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:a0f27f01bee51861392bb6b7c4fdb290b27d1eb194e9e28788d68102a0e898d9", size = 288059, upload-time = "2026-05-18T04:32:07.937Z" }, + { url = "https://files.pythonhosted.org/packages/1b/8d/0a85e395398d8d20fadfe5c5d32c726eee17a519e78fb356f2cf7531bffe/watchfiles-1.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:3651aa7058595e9cfb75d35dd5ada2bf9f48a5b8a0f3562821d3e210c507e077", size = 280186, upload-time = "2026-05-18T04:31:54.484Z" }, + { url = "https://files.pythonhosted.org/packages/37/68/36db056f1fdcc5f07302f56e631774d6835bcd6fa3ace402304621d5f9e5/watchfiles-1.2.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:faea288b6f0ab1902ef08f4ca6de005dccf856c4e0c4f21b8c5fce02d90a1b08", size = 399031, upload-time = "2026-05-18T04:30:44.576Z" }, + { url = "https://files.pythonhosted.org/packages/c1/64/01a9d6f66a82a5c101ce939274106cc72759d62427e153f01edd2b9f87c2/watchfiles-1.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:01859b11fd9fbca670f4d5da00fbac282cfea9bd67a2125d8b2833a3b5617ea9", size = 391205, upload-time = "2026-05-18T04:30:25.413Z" }, + { url = "https://files.pythonhosted.org/packages/84/2c/0a44fe058cb4bb7b8ede6b6670698bbb7c0400740e378d00022189b7b31d/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fff610d7bb2256a317bb1e96f0d7862c7aa8076733ee5df0fd41bbe76a24a4f4", size = 451892, upload-time = "2026-05-18T04:32:14.005Z" }, + { url = "https://files.pythonhosted.org/packages/67/a1/351e0d56cd35e6488b5c8b4fb11a809a5bc923e8fe8fed9faf8920be0c89/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b141a4891c995a039cd89e9a49e62df1dc8a559a5d1a6e4c7106d16c12777a55", size = 458867, upload-time = "2026-05-18T04:31:22.279Z" }, + { url = "https://files.pythonhosted.org/packages/d5/7d/9d09605187f1b838998624049fcf8bf47b73c1a3b76901fcac1782f62277/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f22943b7770483f6ea0721c6b11d022947a98eb0acae14694de034f4d0d38925", size = 490217, upload-time = "2026-05-18T04:31:43.657Z" }, + { url = "https://files.pythonhosted.org/packages/60/5d/a17a16eccb182f04188cd308ec24b1a71a9b5c4e7098269cf35d9fa56d02/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1bc6195825b7dcd217968bb1f801a60fd4c16e8eeab5bedc7fe917d7d5995ab4", size = 571458, upload-time = "2026-05-18T04:32:11.875Z" }, + { url = "https://files.pythonhosted.org/packages/d3/3d/4dd457062083ab1938e5dfd45032eb425cee2ac817287ca8ff4356183e5d/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4a4b147f5dca2a5d325a06a832fb43f345751adfbc63204aec30e0d9ca965a2", size = 464707, upload-time = "2026-05-18T04:30:43.492Z" }, + { url = "https://files.pythonhosted.org/packages/c6/71/ea8c57b128f5383de74d0c7d2d9c57ad7c9a65a930c451bd25d524b295b7/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4543579a9bdb0c9560039b4ffddbdb39545707659fbc430ce4c10f3f68d557f9", size = 454663, upload-time = "2026-05-18T04:30:16.061Z" }, + { url = "https://files.pythonhosted.org/packages/53/fd/2e812bf938406d7db351f0703ddd3fc6c061cf30d96153a77bc79a943a44/watchfiles-1.2.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:20aa0e708b920bde876a4aa82dc7dd6ebea228a63a67cda6632c2fc87b787efa", size = 463537, upload-time = "2026-05-18T04:31:44.9Z" }, + { url = "https://files.pythonhosted.org/packages/86/56/d17a7f1dd1bc3035f1072694a551301272f1739c2d8e319c927cb9e29b38/watchfiles-1.2.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:d413349d565dab74297f2a63e84a097936be69bf8f3b3801f27f380e32040f44", size = 629194, upload-time = "2026-05-18T04:31:14.141Z" }, + { url = "https://files.pythonhosted.org/packages/be/06/f1ff66bf5cae50aa4062779a0ecd0bbaf15e466195719074078947d9a17d/watchfiles-1.2.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:f28b2725eb8cce327b9b3ab02415c853011dc55c95832fe90de6bc56f5315f72", size = 656194, upload-time = "2026-05-18T04:31:47.14Z" }, + { url = "https://files.pythonhosted.org/packages/e7/54/a9c7ea9a82a4ac65e7004c0a03920b5cdd2f9c3b678757d9cd425aa51d53/watchfiles-1.2.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:b8c8358484d5fa12ef34f05b7f4168eaf1932f408725ff6d023c33ec17bd79d4", size = 400205, upload-time = "2026-05-18T04:32:05.153Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5d/c9ab3534374a4a67450696905d6ef16a04405448b8dc52bd752ae50423d4/watchfiles-1.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f04b092229ad2c50126dd3c922c8822e51e605993764a33058d4a791ab42281", size = 392508, upload-time = "2026-05-18T04:30:54.849Z" }, + { url = "https://files.pythonhosted.org/packages/26/ca/1ad30103535cf0cecd7b993e8d50edc5351b1820e38f2d22e3df58962feb/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a7ce236284f002a156f70add88efe5c70879cccbb658be0822c54b1306fc09d", size = 452448, upload-time = "2026-05-18T04:30:53.727Z" }, + { url = "https://files.pythonhosted.org/packages/37/a1/ceee2cdf2afbd715fa07758d39c9859513eae411b23196f7fd039e5feedd/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b9909cc2b48468b575eefa944919e1fe8a36c5849d5c7c168f80a8c1db69398e", size = 459605, upload-time = "2026-05-18T04:30:23.312Z" }, + { url = "https://files.pythonhosted.org/packages/e8/f6/421e30fd1cb3907a84ed92ab3f1983e37ba2dca015e9a894a048418417a2/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a37faaed405c67e28e6be45a1fa4f206ef5a2860f27c237db9fa30704c38242", size = 490757, upload-time = "2026-05-18T04:30:47.358Z" }, + { url = "https://files.pythonhosted.org/packages/41/b0/55ed1b97ed08be7bba6f9a541cac15f2a858e1d74d2b07b6da70a82aab00/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9649193aa27bd9ff2e80ff29bfaa93085496c7a3a377592823cc58b77ee88add", size = 568672, upload-time = "2026-05-18T04:30:38.915Z" }, + { url = "https://files.pythonhosted.org/packages/d1/cf/d8ae8a80dd7bafab395ea7681c10237311bbf34d37704a8c744e7cf31fc7/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e4ff8e37f99cf1da89e255e07c9c4b37c214038c4283707bdec308cb1b0ea1f", size = 464197, upload-time = "2026-05-18T04:30:09.914Z" }, + { url = "https://files.pythonhosted.org/packages/7c/8a/3076c496ca8dafe0e8cd03fcebdfc47be4b1174b4e5b24ff6e396e6b3af2/watchfiles-1.2.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:054dc20fd2e3132b4c3883b4a00d72fd6e1f56fdaf89fccd12e8057d74cd74d7", size = 453181, upload-time = "2026-05-18T04:30:14.829Z" }, + { url = "https://files.pythonhosted.org/packages/e5/10/9745e17c98e7b8a86454df0a3c7b5686bd650383f1e9f26e4ebcbd6cc0c0/watchfiles-1.2.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:e140ed30ebde76796b686e67c182cff10ea2fbab186fafd1560f74bb5a473a6e", size = 465109, upload-time = "2026-05-18T04:30:28.123Z" }, + { url = "https://files.pythonhosted.org/packages/8f/95/8ef4a95481d3e0cb52d62a06fa6e972e81424be2d9698b91a2fecca9904c/watchfiles-1.2.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:bb7e52ecf68ba46d22df23467b87cffeb2146908aa523ebfe803019618cfda06", size = 630653, upload-time = "2026-05-18T04:31:49.304Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e4/3b3bf36b0f829b50c6ebcb8d031583863c59f923d6a6af3d485e470d0fac/watchfiles-1.2.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:23282a321c8baf9b3a3c4afff673f9fe65eb7fdc2338d765ccad9d3d1916a5ba", size = 657838, upload-time = "2026-05-18T04:31:06.497Z" }, + { url = "https://files.pythonhosted.org/packages/21/b1/6cbbb50c1f3002ab568777d44aa21206dfb8807a840990c4037523b51812/watchfiles-1.2.0-cp314-cp314-win32.whl", hash = "sha256:c0db965c5f79aa49fe672d297cf1febc5ad149b658594944f49a54a2b96270a7", size = 275108, upload-time = "2026-05-18T04:30:06.891Z" }, + { url = "https://files.pythonhosted.org/packages/92/45/190ce6db8dcb4536682cf75d3889ff1a27182a58cb519d343cb6d9ea63d8/watchfiles-1.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:71283b39fd17e5408eb123bd37aeecfd9d54c81fc184421943208aadb879d103", size = 288441, upload-time = "2026-05-18T04:32:12.901Z" }, + { url = "https://files.pythonhosted.org/packages/74/0d/3eae1c2313ab08378431d907c3f8095ecca00f3eda33111cf4f0f2591799/watchfiles-1.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:c5c19526f4e54a00f2666a6c0e9e40d582c09e865055ea7378bf0009aab857b3", size = 280684, upload-time = "2026-05-18T04:31:26.902Z" }, + { url = "https://files.pythonhosted.org/packages/b1/75/fb64e6c25d6b5ca636d03df34ffb1c6e9873303e76d27967e045f8df088f/watchfiles-1.2.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:d73a585accffa5ae39c17264c36ec3166d2fad7000c780f5ef83b2722afb9dd2", size = 398857, upload-time = "2026-05-18T04:32:17.108Z" }, + { url = "https://files.pythonhosted.org/packages/73/4e/9f7adf01754cbf81843722ccfec169d8f26c69778281a302855cecd2ee08/watchfiles-1.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ae99b14c5f21e026e0e9d96f40e07d8570ebee6cafd9d8fc318354606daa7a28", size = 392413, upload-time = "2026-05-18T04:31:07.911Z" }, + { url = "https://files.pythonhosted.org/packages/47/c8/bec626bcc2d69f44b9acb24ce7d60ed7b16b73628eea747fcbd169d8edda/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4429f3b105524a10b72c3a819b091c495d2811d419c1e1e8df773a5a5974f831", size = 452409, upload-time = "2026-05-18T04:31:20.142Z" }, + { url = "https://files.pythonhosted.org/packages/00/b7/b6362068e81e7c556d155a34c35d40ac3ef42d747b06d7f6e5bf58e359c2/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:43d818978d06062d9b22c4fab2ebe44cf5213d42dc8e62bda8c2760cfa2eeb33", size = 458827, upload-time = "2026-05-18T04:32:06.219Z" }, + { url = "https://files.pythonhosted.org/packages/67/f8/9a813fa42afb1e0b4625e75f0479826644d3ee8dc287e093799bc01f390c/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b9f732dc58b2dbe69e464ccf8fff7a03b0dd0be439da4c0720d3558527d3d6b4", size = 490104, upload-time = "2026-05-18T04:31:56.034Z" }, + { url = "https://files.pythonhosted.org/packages/2f/bf/27dfb6094ca4c9aad21298b5525b6c53cb36121ee454331d05161e58d130/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f200104103feb097de4cab8fe4f5dd18a2026934c7dea98c55a2f5fd6d5a33b", size = 571360, upload-time = "2026-05-18T04:31:57.133Z" }, + { url = "https://files.pythonhosted.org/packages/fb/39/44a096d67270ea93df91d33877dbe91fbda3aa4f8ec2edf799d93eda8736/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:63ac26eefbf4af1741247d6fb68b11c49a25b2f7413fbd318a83a12aaa9cf666", size = 464644, upload-time = "2026-05-18T04:30:57.33Z" }, + { url = "https://files.pythonhosted.org/packages/0e/80/c7472203bad6268e3ef1ad260739704847898938ad7ea8b63a5131f46b50/watchfiles-1.2.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c4997d4e4a55f0d02b6cde327322daf3a0400e5df6c6b15948994bf72497925", size = 454771, upload-time = "2026-05-18T04:30:48.736Z" }, + { url = "https://files.pythonhosted.org/packages/51/cf/3b10b268b4b7f0fc26e9debb5eef1998b515887840f444cd3ec80c688755/watchfiles-1.2.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:4c887eba18b7945ac73067a8b4a66f21cd46c2539b2bc68588f7be6c7eb6d26b", size = 463494, upload-time = "2026-05-18T04:31:33.826Z" }, + { url = "https://files.pythonhosted.org/packages/3d/3e/a4302545cd589262a0dc7d140e86f7688eba3f9c72776c27f7e23b8864c4/watchfiles-1.2.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:3416ff151bb6b5a8d8d11664974fbef4d9305b9b2957839ab5a270468fd8df30", size = 629383, upload-time = "2026-05-18T04:31:15.596Z" }, + { url = "https://files.pythonhosted.org/packages/db/99/d5649df0a9a410d45b7c882304d0b790903ac9b6e8f2cfd12114e0c6b9f2/watchfiles-1.2.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:0e831a271c035d89789cffc386b6aa1375f39f1cd25eb7ca0997e4970d152fc5", size = 656093, upload-time = "2026-05-18T04:31:58.707Z" }, + { url = "https://files.pythonhosted.org/packages/92/b9/362702539275019a54dd2e94511b31a9b89c5f9e6a21966de7eb692549fc/watchfiles-1.2.0-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:37a6721cdf3f65dbb13aa9503510ccb4451603ac837e44d265d7992a597e1374", size = 400109, upload-time = "2026-05-18T04:31:16.879Z" }, + { url = "https://files.pythonhosted.org/packages/8f/75/71d5ba62db781e5587bded1d944c675374bc4aa37ff33d5018d98e8b6538/watchfiles-1.2.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2b37d10b5a63bd4d87e18472d80fa525bd670586fae62e5dd580452764879b65", size = 392167, upload-time = "2026-05-18T04:31:28.058Z" }, + { url = "https://files.pythonhosted.org/packages/3c/01/c66dd95d0423fe30d31820e2d1d5bda773764131bbb6ac0cb1cf303ac328/watchfiles-1.2.0-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a105bc2283f67e8fbec74253ec2d94925de92ed72c0393f1206bf326b7b7b69", size = 452372, upload-time = "2026-05-18T04:31:00.836Z" }, + { url = "https://files.pythonhosted.org/packages/91/15/2fe99557e72f85627c6a8eed50d889e8d101623e060a22ad75b875cb932d/watchfiles-1.2.0-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5327989a465505f05cfe06f04fa9d0c2fd5432bb243e10e6f012b1bdca3c8579", size = 459596, upload-time = "2026-05-18T04:31:34.96Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/d4acfa0023367428ed48351b3b9b267893037b6cadae55620c61c24bcfd4/watchfiles-1.2.0-cp315-cp315-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ecb47f183a8025b2aa18b546725c3657e542112ae9c0613a2af79b4fa8d04ad7", size = 490869, upload-time = "2026-05-18T04:31:59.923Z" }, + { url = "https://files.pythonhosted.org/packages/a4/5f/3164cbdce06c9fb95c4f7b9e2f9760b5e2797af43a9ecc317ef42a23a278/watchfiles-1.2.0-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8520a4ab0e37f770afc34459c4f8f7019e153f9124dc101c15538365875d1ab2", size = 571641, upload-time = "2026-05-18T04:32:00.948Z" }, + { url = "https://files.pythonhosted.org/packages/41/e6/85d3731c55e65cd7690f3f803d24c139588aaf863e4bf2148fe7a7fa1a19/watchfiles-1.2.0-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:71cd71740ed2c15211ebb237ced4e39a1cdf6f80566e5fe95428da1626f4fde6", size = 464444, upload-time = "2026-05-18T04:30:34.298Z" }, + { url = "https://files.pythonhosted.org/packages/f4/7d/562641012b8b09872742c3b8adf9629ec479fd78f8d68ae4a0c13da8add6/watchfiles-1.2.0-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f88af53d6ddaf72179ef613ddc905e6f4785f712b49b80b3bef9f3525e6194b4", size = 453593, upload-time = "2026-05-18T04:31:23.464Z" }, + { url = "https://files.pythonhosted.org/packages/56/fe/cb8ef3d6f929d14158fdaaad9925985b7310abc9384dcd4d82dd0016fb59/watchfiles-1.2.0-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:cee9d5efd929efdac5f7e58f72b3376f676b64050a91c5b99a7094c5b2317488", size = 465096, upload-time = "2026-05-18T04:31:30.384Z" }, + { url = "https://files.pythonhosted.org/packages/25/91/80908e835e100527a9267147b08c0eee1fa6ab0ffec15edc04d1d44885f7/watchfiles-1.2.0-cp315-cp315-musllinux_1_1_aarch64.whl", hash = "sha256:b718bf356bbc15e559bd8ef41782b573b8ae0e3f177ab244b440568d7ea02cfb", size = 630638, upload-time = "2026-05-18T04:30:49.89Z" }, + { url = "https://files.pythonhosted.org/packages/46/4b/95ab2f256bb4af3cb2eb23b9317bda984ee6e0f11733a5c004a6c95b06e3/watchfiles-1.2.0-cp315-cp315-musllinux_1_1_x86_64.whl", hash = "sha256:922c0e019fe68b3ae392965a766b02a71ba1168c932cebc3733cd52c5fe5b377", size = 657684, upload-time = "2026-05-18T04:31:32.027Z" }, + { url = "https://files.pythonhosted.org/packages/23/f4/7513ef1e85fc4c6331b59479d6d72661fc391fbe543678052ac72c8b6c19/watchfiles-1.2.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:4674d49eb94706dfe666c069fc0a1b646ffcf920473492e209f6d5f60d3f0cc2", size = 403050, upload-time = "2026-05-18T04:30:36.753Z" }, + { url = "https://files.pythonhosted.org/packages/27/0b/a54103cfd732bb703c7a749222011a0483ef3705948dae3b203158601119/watchfiles-1.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:094b9b70103d4e963499bdea001ee3c2697b144cd9ae6218a62c0f89ec9e31db", size = 396629, upload-time = "2026-05-18T04:32:03.268Z" }, + { url = "https://files.pythonhosted.org/packages/5e/2c/73f31a3b893886206c3f54d73e8ad8dee58cdb2f69ad2622e0a8a9e07f4e/watchfiles-1.2.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0ef001f8c25ad0fa9529f914c1600647ecd0f542d11c19b7894768c67b6acb7", size = 457318, upload-time = "2026-05-18T04:31:01.932Z" }, + { url = "https://files.pythonhosted.org/packages/e9/f9/45d021e4a5cc7b9dd567f7cbb06d3b75f751a690063fb6cc7ec60f4e46b7/watchfiles-1.2.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a88fc94e647bc4eec523f1caa540258eb71d14278b9daf72fa1e2658a98df0f0", size = 457771, upload-time = "2026-05-18T04:30:56.331Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.8.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/34/74/c6428f875774288bec1396f5bfcbc2d925700a4dad61727fd5f2b12f249d/wcwidth-0.8.2.tar.gz", hash = "sha256:91fbef97204b96a3d4d421609b80340b760cf33e26da123ff243d76b1fda8dda", size = 1466253, upload-time = "2026-06-29T18:11:11.601Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/42/3e5985a0a7e57de470b320c6d6a1a67c844f6737a587f3d44dd13d1819e7/wcwidth-0.8.2-py3-none-any.whl", hash = "sha256:d63947694a0539a1d51e01eda7caf800c291020e6cdd7e28ad7b14dd33ad4f85", size = 323166, upload-time = "2026-06-29T18:11:09.888Z" }, +] + +[[package]] +name = "websockets" +version = "16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346, upload-time = "2026-01-10T09:23:47.181Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/74/221f58decd852f4b59cc3354cccaf87e8ef695fede361d03dc9a7396573b/websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a", size = 177343, upload-time = "2026-01-10T09:22:21.28Z" }, + { url = "https://files.pythonhosted.org/packages/19/0f/22ef6107ee52ab7f0b710d55d36f5a5d3ef19e8a205541a6d7ffa7994e5a/websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0", size = 175021, upload-time = "2026-01-10T09:22:22.696Z" }, + { url = "https://files.pythonhosted.org/packages/10/40/904a4cb30d9b61c0e278899bf36342e9b0208eb3c470324a9ecbaac2a30f/websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957", size = 175320, upload-time = "2026-01-10T09:22:23.94Z" }, + { url = "https://files.pythonhosted.org/packages/9d/2f/4b3ca7e106bc608744b1cdae041e005e446124bebb037b18799c2d356864/websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72", size = 183815, upload-time = "2026-01-10T09:22:25.469Z" }, + { url = "https://files.pythonhosted.org/packages/86/26/d40eaa2a46d4302becec8d15b0fc5e45bdde05191e7628405a19cf491ccd/websockets-16.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde", size = 185054, upload-time = "2026-01-10T09:22:27.101Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ba/6500a0efc94f7373ee8fefa8c271acdfd4dca8bd49a90d4be7ccabfc397e/websockets-16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3", size = 184565, upload-time = "2026-01-10T09:22:28.293Z" }, + { url = "https://files.pythonhosted.org/packages/04/b4/96bf2cee7c8d8102389374a2616200574f5f01128d1082f44102140344cc/websockets-16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3", size = 183848, upload-time = "2026-01-10T09:22:30.394Z" }, + { url = "https://files.pythonhosted.org/packages/02/8e/81f40fb00fd125357814e8c3025738fc4ffc3da4b6b4a4472a82ba304b41/websockets-16.0-cp310-cp310-win32.whl", hash = "sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9", size = 178249, upload-time = "2026-01-10T09:22:32.083Z" }, + { url = "https://files.pythonhosted.org/packages/b4/5f/7e40efe8df57db9b91c88a43690ac66f7b7aa73a11aa6a66b927e44f26fa/websockets-16.0-cp310-cp310-win_amd64.whl", hash = "sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35", size = 178685, upload-time = "2026-01-10T09:22:33.345Z" }, + { url = "https://files.pythonhosted.org/packages/f2/db/de907251b4ff46ae804ad0409809504153b3f30984daf82a1d84a9875830/websockets-16.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8", size = 177340, upload-time = "2026-01-10T09:22:34.539Z" }, + { url = "https://files.pythonhosted.org/packages/f3/fa/abe89019d8d8815c8781e90d697dec52523fb8ebe308bf11664e8de1877e/websockets-16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad", size = 175022, upload-time = "2026-01-10T09:22:36.332Z" }, + { url = "https://files.pythonhosted.org/packages/58/5d/88ea17ed1ded2079358b40d31d48abe90a73c9e5819dbcde1606e991e2ad/websockets-16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d", size = 175319, upload-time = "2026-01-10T09:22:37.602Z" }, + { url = "https://files.pythonhosted.org/packages/d2/ae/0ee92b33087a33632f37a635e11e1d99d429d3d323329675a6022312aac2/websockets-16.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe", size = 184631, upload-time = "2026-01-10T09:22:38.789Z" }, + { url = "https://files.pythonhosted.org/packages/c8/c5/27178df583b6c5b31b29f526ba2da5e2f864ecc79c99dae630a85d68c304/websockets-16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b", size = 185870, upload-time = "2026-01-10T09:22:39.893Z" }, + { url = "https://files.pythonhosted.org/packages/87/05/536652aa84ddc1c018dbb7e2c4cbcd0db884580bf8e95aece7593fde526f/websockets-16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5", size = 185361, upload-time = "2026-01-10T09:22:41.016Z" }, + { url = "https://files.pythonhosted.org/packages/6d/e2/d5332c90da12b1e01f06fb1b85c50cfc489783076547415bf9f0a659ec19/websockets-16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64", size = 184615, upload-time = "2026-01-10T09:22:42.442Z" }, + { url = "https://files.pythonhosted.org/packages/77/fb/d3f9576691cae9253b51555f841bc6600bf0a983a461c79500ace5a5b364/websockets-16.0-cp311-cp311-win32.whl", hash = "sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6", size = 178246, upload-time = "2026-01-10T09:22:43.654Z" }, + { url = "https://files.pythonhosted.org/packages/54/67/eaff76b3dbaf18dcddabc3b8c1dba50b483761cccff67793897945b37408/websockets-16.0-cp311-cp311-win_amd64.whl", hash = "sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac", size = 178684, upload-time = "2026-01-10T09:22:44.941Z" }, + { url = "https://files.pythonhosted.org/packages/84/7b/bac442e6b96c9d25092695578dda82403c77936104b5682307bd4deb1ad4/websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00", size = 177365, upload-time = "2026-01-10T09:22:46.787Z" }, + { url = "https://files.pythonhosted.org/packages/b0/fe/136ccece61bd690d9c1f715baaeefd953bb2360134de73519d5df19d29ca/websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79", size = 175038, upload-time = "2026-01-10T09:22:47.999Z" }, + { url = "https://files.pythonhosted.org/packages/40/1e/9771421ac2286eaab95b8575b0cb701ae3663abf8b5e1f64f1fd90d0a673/websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39", size = 175328, upload-time = "2026-01-10T09:22:49.809Z" }, + { url = "https://files.pythonhosted.org/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c", size = 184915, upload-time = "2026-01-10T09:22:51.071Z" }, + { url = "https://files.pythonhosted.org/packages/97/bb/21c36b7dbbafc85d2d480cd65df02a1dc93bf76d97147605a8e27ff9409d/websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f", size = 186152, upload-time = "2026-01-10T09:22:52.224Z" }, + { url = "https://files.pythonhosted.org/packages/4a/34/9bf8df0c0cf88fa7bfe36678dc7b02970c9a7d5e065a3099292db87b1be2/websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1", size = 185583, upload-time = "2026-01-10T09:22:53.443Z" }, + { url = "https://files.pythonhosted.org/packages/47/88/4dd516068e1a3d6ab3c7c183288404cd424a9a02d585efbac226cb61ff2d/websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2", size = 184880, upload-time = "2026-01-10T09:22:55.033Z" }, + { url = "https://files.pythonhosted.org/packages/91/d6/7d4553ad4bf1c0421e1ebd4b18de5d9098383b5caa1d937b63df8d04b565/websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89", size = 178261, upload-time = "2026-01-10T09:22:56.251Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f0/f3a17365441ed1c27f850a80b2bc680a0fa9505d733fe152fdf5e98c1c0b/websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea", size = 178693, upload-time = "2026-01-10T09:22:57.478Z" }, + { url = "https://files.pythonhosted.org/packages/cc/9c/baa8456050d1c1b08dd0ec7346026668cbc6f145ab4e314d707bb845bf0d/websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9", size = 177364, upload-time = "2026-01-10T09:22:59.333Z" }, + { url = "https://files.pythonhosted.org/packages/7e/0c/8811fc53e9bcff68fe7de2bcbe75116a8d959ac699a3200f4847a8925210/websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230", size = 175039, upload-time = "2026-01-10T09:23:01.171Z" }, + { url = "https://files.pythonhosted.org/packages/aa/82/39a5f910cb99ec0b59e482971238c845af9220d3ab9fa76dd9162cda9d62/websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c", size = 175323, upload-time = "2026-01-10T09:23:02.341Z" }, + { url = "https://files.pythonhosted.org/packages/bd/28/0a25ee5342eb5d5f297d992a77e56892ecb65e7854c7898fb7d35e9b33bd/websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5", size = 184975, upload-time = "2026-01-10T09:23:03.756Z" }, + { url = "https://files.pythonhosted.org/packages/f9/66/27ea52741752f5107c2e41fda05e8395a682a1e11c4e592a809a90c6a506/websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82", size = 186203, upload-time = "2026-01-10T09:23:05.01Z" }, + { url = "https://files.pythonhosted.org/packages/37/e5/8e32857371406a757816a2b471939d51c463509be73fa538216ea52b792a/websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8", size = 185653, upload-time = "2026-01-10T09:23:06.301Z" }, + { url = "https://files.pythonhosted.org/packages/9b/67/f926bac29882894669368dc73f4da900fcdf47955d0a0185d60103df5737/websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f", size = 184920, upload-time = "2026-01-10T09:23:07.492Z" }, + { url = "https://files.pythonhosted.org/packages/3c/a1/3d6ccdcd125b0a42a311bcd15a7f705d688f73b2a22d8cf1c0875d35d34a/websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a", size = 178255, upload-time = "2026-01-10T09:23:09.245Z" }, + { url = "https://files.pythonhosted.org/packages/6b/ae/90366304d7c2ce80f9b826096a9e9048b4bb760e44d3b873bb272cba696b/websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156", size = 178689, upload-time = "2026-01-10T09:23:10.483Z" }, + { url = "https://files.pythonhosted.org/packages/f3/1d/e88022630271f5bd349ed82417136281931e558d628dd52c4d8621b4a0b2/websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0", size = 177406, upload-time = "2026-01-10T09:23:12.178Z" }, + { url = "https://files.pythonhosted.org/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904", size = 175085, upload-time = "2026-01-10T09:23:13.511Z" }, + { url = "https://files.pythonhosted.org/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4", size = 175328, upload-time = "2026-01-10T09:23:14.727Z" }, + { url = "https://files.pythonhosted.org/packages/63/bc/d3e208028de777087e6fb2b122051a6ff7bbcca0d6df9d9c2bf1dd869ae9/websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e", size = 185044, upload-time = "2026-01-10T09:23:15.939Z" }, + { url = "https://files.pythonhosted.org/packages/ad/6e/9a0927ac24bd33a0a9af834d89e0abc7cfd8e13bed17a86407a66773cc0e/websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4", size = 186279, upload-time = "2026-01-10T09:23:17.148Z" }, + { url = "https://files.pythonhosted.org/packages/b9/ca/bf1c68440d7a868180e11be653c85959502efd3a709323230314fda6e0b3/websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1", size = 185711, upload-time = "2026-01-10T09:23:18.372Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f8/fdc34643a989561f217bb477cbc47a3a07212cbda91c0e4389c43c296ebf/websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3", size = 184982, upload-time = "2026-01-10T09:23:19.652Z" }, + { url = "https://files.pythonhosted.org/packages/dd/d1/574fa27e233764dbac9c52730d63fcf2823b16f0856b3329fc6268d6ae4f/websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8", size = 177915, upload-time = "2026-01-10T09:23:21.458Z" }, + { url = "https://files.pythonhosted.org/packages/8a/f1/ae6b937bf3126b5134ce1f482365fde31a357c784ac51852978768b5eff4/websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d", size = 178381, upload-time = "2026-01-10T09:23:22.715Z" }, + { url = "https://files.pythonhosted.org/packages/06/9b/f791d1db48403e1f0a27577a6beb37afae94254a8c6f08be4a23e4930bc0/websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244", size = 177737, upload-time = "2026-01-10T09:23:24.523Z" }, + { url = "https://files.pythonhosted.org/packages/bd/40/53ad02341fa33b3ce489023f635367a4ac98b73570102ad2cdd770dacc9a/websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e", size = 175268, upload-time = "2026-01-10T09:23:25.781Z" }, + { url = "https://files.pythonhosted.org/packages/74/9b/6158d4e459b984f949dcbbb0c5d270154c7618e11c01029b9bbd1bb4c4f9/websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641", size = 175486, upload-time = "2026-01-10T09:23:27.033Z" }, + { url = "https://files.pythonhosted.org/packages/e5/2d/7583b30208b639c8090206f95073646c2c9ffd66f44df967981a64f849ad/websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8", size = 185331, upload-time = "2026-01-10T09:23:28.259Z" }, + { url = "https://files.pythonhosted.org/packages/45/b0/cce3784eb519b7b5ad680d14b9673a31ab8dcb7aad8b64d81709d2430aa8/websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e", size = 186501, upload-time = "2026-01-10T09:23:29.449Z" }, + { url = "https://files.pythonhosted.org/packages/19/60/b8ebe4c7e89fb5f6cdf080623c9d92789a53636950f7abacfc33fe2b3135/websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944", size = 186062, upload-time = "2026-01-10T09:23:31.368Z" }, + { url = "https://files.pythonhosted.org/packages/88/a8/a080593f89b0138b6cba1b28f8df5673b5506f72879322288b031337c0b8/websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206", size = 185356, upload-time = "2026-01-10T09:23:32.627Z" }, + { url = "https://files.pythonhosted.org/packages/c2/b6/b9afed2afadddaf5ebb2afa801abf4b0868f42f8539bfe4b071b5266c9fe/websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6", size = 178085, upload-time = "2026-01-10T09:23:33.816Z" }, + { url = "https://files.pythonhosted.org/packages/9f/3e/28135a24e384493fa804216b79a6a6759a38cc4ff59118787b9fb693df93/websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd", size = 178531, upload-time = "2026-01-10T09:23:35.016Z" }, + { url = "https://files.pythonhosted.org/packages/72/07/c98a68571dcf256e74f1f816b8cc5eae6eb2d3d5cfa44d37f801619d9166/websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d", size = 174947, upload-time = "2026-01-10T09:23:36.166Z" }, + { url = "https://files.pythonhosted.org/packages/7e/52/93e166a81e0305b33fe416338be92ae863563fe7bce446b0f687b9df5aea/websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03", size = 175260, upload-time = "2026-01-10T09:23:37.409Z" }, + { url = "https://files.pythonhosted.org/packages/56/0c/2dbf513bafd24889d33de2ff0368190a0e69f37bcfa19009ef819fe4d507/websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da", size = 176071, upload-time = "2026-01-10T09:23:39.158Z" }, + { url = "https://files.pythonhosted.org/packages/a5/8f/aea9c71cc92bf9b6cc0f7f70df8f0b420636b6c96ef4feee1e16f80f75dd/websockets-16.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c", size = 176968, upload-time = "2026-01-10T09:23:41.031Z" }, + { url = "https://files.pythonhosted.org/packages/9a/3f/f70e03f40ffc9a30d817eef7da1be72ee4956ba8d7255c399a01b135902a/websockets-16.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767", size = 178735, upload-time = "2026-01-10T09:23:42.259Z" }, + { url = "https://files.pythonhosted.org/packages/6f/28/258ebab549c2bf3e64d2b0217b973467394a9cea8c42f70418ca2c5d0d2e/websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec", size = 171598, upload-time = "2026-01-10T09:23:45.395Z" }, +] + +[[package]] +name = "wrapt" +version = "2.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/a4/282c8e64300a59fc834518a54bf0afabb4ff9218b5fa76958b450459a844/wrapt-2.2.2.tar.gz", hash = "sha256:0788e321027c999bf221b667bd4a54aaefd1a36283749a860ac3eb77daed0302", size = 129068, upload-time = "2026-06-20T23:49:44.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/8b/59781d0fe7b0adfbea37f600857de4be68921e454aeecf1a11bda35cdccc/wrapt-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:055e6fcfaa28e58c6a8c247d48b92be9d56f818b7068aa4f22b15b3343a09931", size = 80556, upload-time = "2026-06-20T23:47:28.473Z" }, + { url = "https://files.pythonhosted.org/packages/94/dc/66c61aca927230c9cf97a3cb005c803971a1076ff9f7d61085d035c20085/wrapt-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8374eb6b1a58809211e84ff835a182bb17ab2807a5bfef23204c8cff38178a00", size = 81648, upload-time = "2026-06-20T23:47:30.504Z" }, + { url = "https://files.pythonhosted.org/packages/23/1b/545eee1c18f3af4cf140bb5822b6ef81ebe569df0a63ac109973103a30a5/wrapt-2.2.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:656593bb3f5529f03d27af4136c4d7b11990e470bcbc6fefa5ef218695bece55", size = 152956, upload-time = "2026-06-20T23:47:31.867Z" }, + { url = "https://files.pythonhosted.org/packages/44/a7/6f42a3d03e44dc612a5dcff324e7366075a7857f0be2d49a8cb8a68279b8/wrapt-2.2.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dfb00cb7bb22099e2f64b7340fb96113639aa7260c0972af3797ace2297b936c", size = 154771, upload-time = "2026-06-20T23:47:33.352Z" }, + { url = "https://files.pythonhosted.org/packages/bf/55/4d76175aaa97523c38f1d28f79d18ab41a1b116814158a818bc0eba00571/wrapt-2.2.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e7f10ee0bd53673bfd52b67cbce83336fe6cad90d2377b03baf66491d2bbfb91", size = 149460, upload-time = "2026-06-20T23:47:34.712Z" }, + { url = "https://files.pythonhosted.org/packages/84/9b/12e23264d8f4735e8483262f95c5a6b03c3665fd2a84bdf99a45b6a2f4ec/wrapt-2.2.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4402f57c5f0d0579599858ffbdd9bf4e3f0972f51096f2bd6cc7dab6b76ee49e", size = 153648, upload-time = "2026-06-20T23:47:36.092Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a3/bcd5ec37289dcd85ecd4d15395a6a6063d60bc45ff94a9d77814e1e54d64/wrapt-2.2.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:3a4eb7964ff4643d333c84f880bcf554652b2a1050aebc54ae696327f61acfaf", size = 148502, upload-time = "2026-06-20T23:47:37.623Z" }, + { url = "https://files.pythonhosted.org/packages/f2/be/716d708f607fa70f8a6eb47dff8ee945d5278dfc89ffeeff33039d052e63/wrapt-2.2.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e542b7c5af91e2123a8aabf19894319d5ec4268d2a9ffd2f239386133fc47746", size = 152238, upload-time = "2026-06-20T23:47:39.118Z" }, + { url = "https://files.pythonhosted.org/packages/b5/c0/1a48e7e54501274f5d906f18372221b13183b0afbb5b8bb4c7ca0392c0b4/wrapt-2.2.2-cp310-cp310-win32.whl", hash = "sha256:6e7e45b43d3c774d244fe7264378f5a3f0f383bc55a54a9866434e524540110f", size = 77278, upload-time = "2026-06-20T23:47:40.476Z" }, + { url = "https://files.pythonhosted.org/packages/b0/82/9cd69a1af288fbdedf01a10e3c8a0b6890b08c7f3f96d36a213699dbcd94/wrapt-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:955f1d6e72a352e478de8d8b503abe301c5e139a141b62eb0923bd694995025f", size = 80131, upload-time = "2026-06-20T23:47:41.785Z" }, + { url = "https://files.pythonhosted.org/packages/7f/73/8db7e27daef37ae70a53ea62bef7fe80cc51a8b5e9e9181a8be6eb9a999c/wrapt-2.2.2-cp310-cp310-win_arm64.whl", hash = "sha256:b89d8d73c82db2bb7e6090b3afd7973f980d24e905cc34394eab60b884b3bf67", size = 79615, upload-time = "2026-06-20T23:47:43.109Z" }, + { url = "https://files.pythonhosted.org/packages/27/15/0c2d55168707465abfc41f33c0b23d792a5fa9b65c26983606940900a120/wrapt-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f1a2ff355ece6a111ca7a20dc86df6659c9205d3fcee674ca34f2a2854fd4e73", size = 80782, upload-time = "2026-06-20T23:47:44.367Z" }, + { url = "https://files.pythonhosted.org/packages/7d/b5/5c0b093eb48f8a062ef6267d3cb36e9bb1b88440181f6545a383c60efdf8/wrapt-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:55b9a899e6fff5444f229d30aa6e9ac92d2216d9d60f33c771b5d76a760d5f8e", size = 81678, upload-time = "2026-06-20T23:47:45.857Z" }, + { url = "https://files.pythonhosted.org/packages/34/f3/de70937472dd3e8a4e6811192f9c6075efdffd4a2cd9b4596bf160f89668/wrapt-2.2.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a2d78c363f97d8bd718ee40432c66395685e9e98528ccaa423c3355d1715a26d", size = 159671, upload-time = "2026-06-20T23:47:47.345Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ec/40aed2330e7f02ecf74386ffcfef9ccb7108c6a430f15b6a252b663b1bed/wrapt-2.2.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d619e1eed9bd4f6ed9f24cd61971aa086fa86505289628d464bcf8a2c2e3f328", size = 160785, upload-time = "2026-06-20T23:47:48.759Z" }, + { url = "https://files.pythonhosted.org/packages/45/04/aa5309beed5344b00220ae6b3b24055852192656194c27947bee1736306a/wrapt-2.2.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:518b0c5e323511ec56a38894802ddd5e1222626484e68efe63f201854ad788e5", size = 153699, upload-time = "2026-06-20T23:47:50.177Z" }, + { url = "https://files.pythonhosted.org/packages/01/df/2def7e99d1fe87eea413f95f671924cdddcb08823b1ffd212748dfa6d062/wrapt-2.2.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4bccea5cdecffa9dd70e343741f0e41e0a16619313d04b72f78bb525162ebcd0", size = 159695, upload-time = "2026-06-20T23:47:51.602Z" }, + { url = "https://files.pythonhosted.org/packages/c7/f6/a906d01a2ce12157bad2404957b3e2140da354b8a70b2fa48bbf282871c0/wrapt-2.2.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:209112cafd963710a05d199aae431d79a28bc76eb8e6d1bbbb8ad24340722cae", size = 152813, upload-time = "2026-06-20T23:47:53.03Z" }, + { url = "https://files.pythonhosted.org/packages/02/49/bc0086292d239575b4c08f4cf8a4079fa58abbad58ec23abf84833a283ed/wrapt-2.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e5a5290e4bf2f332fc29ce72ffb9a2fff678aaac047e2e9f5f7165cd7792e099", size = 158809, upload-time = "2026-06-20T23:47:54.391Z" }, + { url = "https://files.pythonhosted.org/packages/55/83/8fbd034de1f3e907edaa18786d5dd8f6932874edee0826c7cecb5cab03a1/wrapt-2.2.2-cp311-cp311-win32.whl", hash = "sha256:5499236ad1dc116012e2a5dd943f3f31af12fce452128e2bbcbd55a7d3d4d14c", size = 77414, upload-time = "2026-06-20T23:47:55.882Z" }, + { url = "https://files.pythonhosted.org/packages/7e/9c/23695baa331c6de4e874c3d78b8e0bed92e1d2a274e665b29858f6841672/wrapt-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:8636809939152be6ae20a6cef0fed9fe60f411b47847d0426a826884b469e971", size = 80368, upload-time = "2026-06-20T23:47:57.237Z" }, + { url = "https://files.pythonhosted.org/packages/08/49/40cefc342bf89b234a4490d741290fce781774b831aefb39c25471da96c9/wrapt-2.2.2-cp311-cp311-win_arm64.whl", hash = "sha256:5d0a142f7af07caeb5e5da87493162a7b8efa19ba919e550a746f7446e13fb30", size = 79489, upload-time = "2026-06-20T23:47:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/2a/85/180b40628b23772692a0c76e8030114e1c0ae068470ed531919f0a5f2a4a/wrapt-2.2.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8417fd3c674d3c8023d080292d29301531a12daf8bd938dd419710dd2f464f2b", size = 81484, upload-time = "2026-06-20T23:47:59.924Z" }, + { url = "https://files.pythonhosted.org/packages/94/f2/21c90f2a16689702e2aaff45795b11018dff2c9b1242bac10d225483f676/wrapt-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e7070c7472582e31af3dfc2622b2381a0df7435110a9388ed8db5ffbce67efb", size = 82151, upload-time = "2026-06-20T23:48:01.303Z" }, + { url = "https://files.pythonhosted.org/packages/5f/b3/7e6e9fcf4fe7e1b69a49fe6cc5a44e8224bab6283c5233c97e132f14908e/wrapt-2.2.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2e096c9d39a59b35b63c9aacfbbbec2088ff51ff1fc31051acc60a07f42f273a", size = 169828, upload-time = "2026-06-20T23:48:02.719Z" }, + { url = "https://files.pythonhosted.org/packages/0b/43/894f132d857ed5a9904d937baf368badcbe5ea9e436e2f1930fe21c9f1f0/wrapt-2.2.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d1a6050405bf334be33bf66296f113563622972a34900ae6fa60fd283a1a900", size = 171544, upload-time = "2026-06-20T23:48:04.266Z" }, + { url = "https://files.pythonhosted.org/packages/29/de/3c833e03725b477e9ea34028224dd21a48781830101e4e036f77e8b6b102/wrapt-2.2.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:10adb01371408c6de504a6658b9886480f1a4919a83752748a387a504a21df79", size = 160663, upload-time = "2026-06-20T23:48:05.708Z" }, + { url = "https://files.pythonhosted.org/packages/33/be/27edce350b24e3054d9d047f65f16d4c4d4c1f3f31c4278a1f8a95c723c8/wrapt-2.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3442eee2a5798f9b451f1b2cd7518ce8b7e28a2a364696c414460a0e295c012a", size = 169387, upload-time = "2026-06-20T23:48:07.243Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c4/9fd9679af8bf38e146652c7f47b6b352c3e5795b4ad1c0b7f94e15ac2aa7/wrapt-2.2.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:6c99012a22f735a85eed7c4b86a3e99c30fdd57d9e115b2b45f796264b58d0bf", size = 158849, upload-time = "2026-06-20T23:48:08.91Z" }, + { url = "https://files.pythonhosted.org/packages/bc/c2/aa6c0c2206803068c6859dabe01f8c84c43744da93d4c67b8946d21655ee/wrapt-2.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3b686cfc008776a3952d6213cb296ed7f45d782a8453936406faa89eac0835ab", size = 168147, upload-time = "2026-06-20T23:48:10.374Z" }, + { url = "https://files.pythonhosted.org/packages/42/63/3eb25da41049d20ae18fcab2dd8b056e02387c4bfa626cbdfb7c3b872e4f/wrapt-2.2.2-cp312-cp312-win32.whl", hash = "sha256:ef2cce266b5b0b07e19fa82e59673b81142b7a3607c8ed1254113d048ed668da", size = 77734, upload-time = "2026-06-20T23:48:11.769Z" }, + { url = "https://files.pythonhosted.org/packages/da/09/0390e008a305360948fa9ce69507d041ac12cb2ee5d28e34467e2ee79391/wrapt-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:abf8c20a2d72ee69e16328b3c91342c446e723bfe48bfcc4dded3b9722ac027f", size = 80585, upload-time = "2026-06-20T23:48:13.117Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b3/84c445c66969f2d3457276b183a48c91097d59bbef9af6c075366b0f8c36/wrapt-2.2.2-cp312-cp312-win_arm64.whl", hash = "sha256:c6c64c5d02578bc4c4bca4f0aef1504de933c1d5b4ac2710b9131111459506c8", size = 79553, upload-time = "2026-06-20T23:48:14.5Z" }, + { url = "https://files.pythonhosted.org/packages/43/fc/f32f4b22c6511173c11d9e541ab4e7d8467a0f1b3455acaf784115d31ff8/wrapt-2.2.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9e8b648270c613720a202d9a45ebabc33261b22c3a839b115ac5bce8c0bb0d69", size = 81296, upload-time = "2026-06-20T23:48:15.881Z" }, + { url = "https://files.pythonhosted.org/packages/72/06/4d117d5d77a9344776c0248b24dae3d3dd2f58e5f765fa08cf887072e719/wrapt-2.2.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6fb7e94e8fe3e4c3067bb1653a91cce7c5e83acc119fdd41501b1bf74654617", size = 81841, upload-time = "2026-06-20T23:48:17.262Z" }, + { url = "https://files.pythonhosted.org/packages/15/ff/63ad96f98eb58a742b1a20d80f21da88924405910149950b912368150468/wrapt-2.2.2-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb18fc51e813df0d9c98049e3bf2298a5495a648602040e21fa3c7329371159e", size = 167882, upload-time = "2026-06-20T23:48:18.764Z" }, + { url = "https://files.pythonhosted.org/packages/20/1f/8bb62d8933df7acf3247194e6e9fc68edf9d2fa203252c89c94b319dd472/wrapt-2.2.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94b00b00f806eb3ef2abe9049ed45994a81ee9284884d96e6b8314927c6cea3d", size = 167411, upload-time = "2026-06-20T23:48:20.315Z" }, + { url = "https://files.pythonhosted.org/packages/17/09/8789dcb09ee1de715727db7521aabbb68ffa68dfade3a49468440cfced49/wrapt-2.2.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:62415fd095bc590b842b6d092f2b5d9ccbaeb7e0b28535c03dcea2718b48636b", size = 158607, upload-time = "2026-06-20T23:48:21.728Z" }, + { url = "https://files.pythonhosted.org/packages/9c/20/66e02562d53ee67d841f175e38e3c993c2d78a3e104c576cad61c028b43c/wrapt-2.2.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a41e758d80dc0ab8c210f641ac892009d356cf1f955d97db544c8dd317b4d14c", size = 166367, upload-time = "2026-06-20T23:48:23.177Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a3/832ac4e41222fb263b3042d42c2f08d305db7d0f0c9b1d3a271a9eede8f6/wrapt-2.2.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b84cd4058001c9727b0e9980b7a9e66325b5ca748b1b578e822cade1bc6b304f", size = 157176, upload-time = "2026-06-20T23:48:24.711Z" }, + { url = "https://files.pythonhosted.org/packages/b7/01/1bd5e4d2df9c0178989ac8da9186543465388588ee2ef153e2591accebef/wrapt-2.2.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:26fc73a1b15e0946d2942b9a4426d162b51676338327dc067ccd8d2d76385f94", size = 167025, upload-time = "2026-06-20T23:48:26.118Z" }, + { url = "https://files.pythonhosted.org/packages/1c/69/583ed25291ab53e1ec117135fb1c33425e2f46d2bc8f29c17f7a94cf4274/wrapt-2.2.2-cp313-cp313-win32.whl", hash = "sha256:3c4095803491f6ef72128914c28ec05bbad9758433bb35f6715a3e9c8e46fb2d", size = 77605, upload-time = "2026-06-20T23:48:27.643Z" }, + { url = "https://files.pythonhosted.org/packages/29/68/e69fc6d06e1523c68e0d00f95c9aed1158ce9908ee41603f7f2eae3d5db6/wrapt-2.2.2-cp313-cp313-win_amd64.whl", hash = "sha256:2cb07f414fab25dbe6b5c7398e1491423a5c81a6209533639969a6c928d474a4", size = 80508, upload-time = "2026-06-20T23:48:29.013Z" }, + { url = "https://files.pythonhosted.org/packages/55/21/fe7a393d9e5dc0923bed8f5d857e9dcff210f1fa0888c02cc8f3ffaa55aa/wrapt-2.2.2-cp313-cp313-win_arm64.whl", hash = "sha256:1fc7691f070220215cccb2a20836b9adbaecb8ff22ad47abe63de5f110994fac", size = 79565, upload-time = "2026-06-20T23:48:30.429Z" }, + { url = "https://files.pythonhosted.org/packages/b6/e5/c120d13bf5091164f68c3c1657e84f16f57e71d978421b626393ac5bd7eb/wrapt-2.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ec8f83949028366531383603139403cac7a826e4011955813cdd640017845ce5", size = 83264, upload-time = "2026-06-20T23:48:31.807Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b0/d4a1eb97e0e286625bdf21bc7f702637f9607787ffbbdb5ec14d50c79dbf/wrapt-2.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4b481fb0c40d9fd90a5809911208da700987d373a20a4709dc9e3944af7a6bec", size = 83791, upload-time = "2026-06-20T23:48:33.482Z" }, + { url = "https://files.pythonhosted.org/packages/18/1e/f060df47755e87b57684cee7bfc1362b204df55fac96ffebc0631b697b79/wrapt-2.2.2-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0065a3b657cec06813b4241d2462ccec287f6863103d7445b725fb3a889736f9", size = 203399, upload-time = "2026-06-20T23:48:34.97Z" }, + { url = "https://files.pythonhosted.org/packages/c4/de/2316a757a1abb6453700b79d83e532146dcef2611348282d4d8889792161/wrapt-2.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:30f7424af5c5c345b7f26490e097f74a2ef45b3d08b664dc33571aee3bd3b56c", size = 210461, upload-time = "2026-06-20T23:48:36.569Z" }, + { url = "https://files.pythonhosted.org/packages/ed/29/d1160785ae18ca2495a6d82a21154103d74f656c9fd457fb35f6b11b965a/wrapt-2.2.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:07fdcb012821859168641acf68afad61ef9783cf37100af85f152550e9677194", size = 195313, upload-time = "2026-06-20T23:48:38.175Z" }, + { url = "https://files.pythonhosted.org/packages/f5/2d/7caa9598ae61a9cf0989cc501739cbeeb7d650ab3193cca1407b9af0c6ab/wrapt-2.2.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f90038ab58fafb584801ca62d72384d7d5225d93c76f7b773c22fae545bd8066", size = 206116, upload-time = "2026-06-20T23:48:39.804Z" }, + { url = "https://files.pythonhosted.org/packages/ac/02/281ea1088b8650d865f311b35cf86fd21df89128e2909714f1161e01c9d0/wrapt-2.2.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:c5d7825491bfa2d08b97e9557768987952c7b9ae687d06c3320b40a37ccb7f20", size = 192668, upload-time = "2026-06-20T23:48:41.346Z" }, + { url = "https://files.pythonhosted.org/packages/be/7d/976e2d5b4b5c5babda40974edd54d0a5585cb60132ed86b46f4b80239b16/wrapt-2.2.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0ad520e6daa9bbf136f14de735474dbec7dcc0891f718e1d274ce8dc92e645af", size = 198891, upload-time = "2026-06-20T23:48:43.056Z" }, + { url = "https://files.pythonhosted.org/packages/59/b7/e47651797c097f75a37e2ce86dcf04048ff576f3a674f7c558df7b5e9622/wrapt-2.2.2-cp313-cp313t-win32.whl", hash = "sha256:25904acb9475f46c24fe0423dbc8fda8cc5fbc282ab3dc6e72e919748c53f4e9", size = 78537, upload-time = "2026-06-20T23:48:44.509Z" }, + { url = "https://files.pythonhosted.org/packages/d1/6f/9fa5d59fb06d890defb5a8f727ce6a14d2932c8760153f96956628559fee/wrapt-2.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:305d4c247d61c4115794a169141823c62f719525ddb90b23aa332741c77d2c28", size = 82005, upload-time = "2026-06-20T23:48:46.391Z" }, + { url = "https://files.pythonhosted.org/packages/15/80/4c7bd9873d1f9f7d138d93556b500469dbe24f42710b877519c2b9eb380d/wrapt-2.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:c20279cd1a29800815d7b2d6338b60a6c6e78263f9d6e62e0eda251ba9cae2d0", size = 80762, upload-time = "2026-06-20T23:48:47.964Z" }, + { url = "https://files.pythonhosted.org/packages/24/05/7fd9c3f83b2c74cbfc572a0b88aa37431e04bd8aed70d2c0efd3464206de/wrapt-2.2.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:0e64826f920c42d9d9f87e8cc09ffae66c51ede12d59061a5a426deb9aa71745", size = 81341, upload-time = "2026-06-20T23:48:49.39Z" }, + { url = "https://files.pythonhosted.org/packages/4b/68/1bfa43100dd90d4ef74a05897b86275cf57e1313ca14aae2545bc9f872c9/wrapt-2.2.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dcaa5e1451bd8751d7bd1568dfa3321c78092a52a7ecb5d1a0f18a5791e1fd00", size = 81921, upload-time = "2026-06-20T23:48:50.986Z" }, + { url = "https://files.pythonhosted.org/packages/74/eb/df7b7f0b631dbbc750f39be27d8b55f65777d8ac86da80e12be41a644c4b/wrapt-2.2.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0abfd648dac9ac9c5b3aa9b523d27f1789046640b58dcd5652a720ddb325e1fc", size = 167713, upload-time = "2026-06-20T23:48:52.598Z" }, + { url = "https://files.pythonhosted.org/packages/4d/9a/d1bd36f6d088c8e652a9383cabbd49af30b8c576302a7eccddbab6963e3f/wrapt-2.2.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f4bfd8d1eb438153eff8b8cfe87f032ba65731e1ce06138b5090f745a33f6f95", size = 166779, upload-time = "2026-06-20T23:48:54.33Z" }, + { url = "https://files.pythonhosted.org/packages/4c/ae/24ffacd4187fac2740a1972093929e836dea092d42c87d728cd98fee11a6/wrapt-2.2.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c427c9d06d859848a69f0d928fe28b5c33a941b2265d10a0e1f15cd244f1ee33", size = 158407, upload-time = "2026-06-20T23:48:55.944Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ed/974427668249a356051e8d67d47fa54ef6c777f0fcf3bae9d292c047d4b6/wrapt-2.2.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4250b43d1a129d947e083c4dc6baf333c9bb34edd26f912d5b0457841fc858ab", size = 166594, upload-time = "2026-06-20T23:48:57.617Z" }, + { url = "https://files.pythonhosted.org/packages/fb/5f/e1d7c6e4523f78db2fbd7826babd0348da1d5e0834c4f918b9ab5757dfae/wrapt-2.2.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:173e5bb5ca350a6e0abab60b7ec7cdd7992a814cb14b4de670a28f067f105663", size = 157068, upload-time = "2026-06-20T23:48:59.171Z" }, + { url = "https://files.pythonhosted.org/packages/1e/c1/7ebd1027f00700c0b0233b20aceef2b4784294ed64971424c4a78e069e34/wrapt-2.2.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:aa14b01804bce36c6d63d7b6a4f55df390f29f8648cc13a1f40b166f4d54680d", size = 166470, upload-time = "2026-06-20T23:49:00.737Z" }, + { url = "https://files.pythonhosted.org/packages/99/eb/974e471a6a978b8180186b8a9dc5ae3361ce269a967190b709b8ce17abfb/wrapt-2.2.2-cp314-cp314-win32.whl", hash = "sha256:58f9f8d637c9a6e245c6ef5b109b67ec187d2faed23d1405656b51d96e0a5b56", size = 78062, upload-time = "2026-06-20T23:49:02.327Z" }, + { url = "https://files.pythonhosted.org/packages/49/ec/e1281156cdc7a66693838ad7a0865ad641c74abd337a957d668b575aaffb/wrapt-2.2.2-cp314-cp314-win_amd64.whl", hash = "sha256:385cb1866f20479e83299af585375bfa0a4b0c6c9907a981483ea782ea8ae406", size = 80832, upload-time = "2026-06-20T23:49:03.837Z" }, + { url = "https://files.pythonhosted.org/packages/45/7d/1b6b5ddd94005a2dac97a4490c9838f3154977850d633abcb65b30089437/wrapt-2.2.2-cp314-cp314-win_arm64.whl", hash = "sha256:8ffbeaea6771a6eba6e6eeb09767864995726bc8240bb54baf88a9bb1db34d5c", size = 80029, upload-time = "2026-06-20T23:49:05.237Z" }, + { url = "https://files.pythonhosted.org/packages/b0/33/9ebcf8aafe91c601127cbd93708c16aa8f688f34a10bf004046803ecdc4f/wrapt-2.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:09f811d43f6f33ec7515f0be76b159569f4057ab54d3e079c3204dddb90afa2a", size = 83357, upload-time = "2026-06-20T23:49:06.632Z" }, + { url = "https://files.pythonhosted.org/packages/39/38/ec45b635153327b52e52732a0ea980e5f00b7efba65f9e018828f1e69daa/wrapt-2.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a795d3c06e5fbf9ea2f13196180b77aeab1b4685917256ee0d014cc163d90063", size = 83794, upload-time = "2026-06-20T23:49:08.098Z" }, + { url = "https://files.pythonhosted.org/packages/4e/ea/1a89e6d3b7a83c3affe5c09cde77792c947e63e4bc85ad84cd5bb9abb0d8/wrapt-2.2.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:45c2f2768e790c9f8db90f239ef23a2af8e7570f25a35619ef902df4a738447f", size = 203362, upload-time = "2026-06-20T23:49:09.811Z" }, + { url = "https://files.pythonhosted.org/packages/19/d8/3b58763d9863b5a73771c0d97110f9595d248db454009e07e1535ee905a4/wrapt-2.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bbf00ee0cb55ec24e2b0995a71942b85b21a066db8f3f46e1dbfdb9433ffba81", size = 210449, upload-time = "2026-06-20T23:49:11.521Z" }, + { url = "https://files.pythonhosted.org/packages/2d/6f/17fd9e053103d8be148d20d5d7505facc72d5fe1f9127973904ceaed79cf/wrapt-2.2.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2252f77663651b89255895f58cc6ac08fcb206d4371813e5af61bb62d4f7689c", size = 195349, upload-time = "2026-06-20T23:49:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/ef/04/d0d1ccaaa12cb7dccf28a23f0279a608ba498f71e81d949d5ed54bcfd5c1/wrapt-2.2.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2cd7181ab1c31192ff5219269830744b5a62020b3a6d433588c4f1c95b8f8bff", size = 206099, upload-time = "2026-06-20T23:49:15.051Z" }, + { url = "https://files.pythonhosted.org/packages/44/b3/e8aa07b619890a2aa6cde1931b1887abb08820721b564a5f80b7ca3f3aa0/wrapt-2.2.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:6fe35fd51b74867d8b80174c277bd6bbf6a73e443f908129dc531c4b688a20d5", size = 192728, upload-time = "2026-06-20T23:49:16.854Z" }, + { url = "https://files.pythonhosted.org/packages/b7/f0/1819fb50f0d3c9bd758d8a83b56f1b470dee8b5b8eac8702b7c137cea9d4/wrapt-2.2.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:11d95fc2fbad3163596c39d440e6f21ca9fccece74b56e30a37ac2fca786a07c", size = 198842, upload-time = "2026-06-20T23:49:18.504Z" }, + { url = "https://files.pythonhosted.org/packages/67/7c/e88313f16a99930b899ef970d91c281544a470749a359decad994483bbda/wrapt-2.2.2-cp314-cp314t-win32.whl", hash = "sha256:d8a15813215f33fa83667bfc978b300e35669ea8bb424e970a1426bcb7bc6cca", size = 79059, upload-time = "2026-06-20T23:49:20.107Z" }, + { url = "https://files.pythonhosted.org/packages/a0/4f/ac12fda57a55068a094ec42851fb0a40e8489d8941863d517452de62e507/wrapt-2.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:d09db0f7e8357060d3c38fc22a018aba683a796bf184360fd1a58f6fc180dc77", size = 82462, upload-time = "2026-06-20T23:49:21.631Z" }, + { url = "https://files.pythonhosted.org/packages/48/a7/df732dac86d9b2027c56bd163dbc883e037b16c3469614752e148d219c61/wrapt-2.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:f32fe639c39561ccc187bcae17e9271be0eb45f1c2952510d2f29b33ab577347", size = 81182, upload-time = "2026-06-20T23:49:23.199Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d2/6317eb6d4554855bbf12d61857774af34747bf88a42c19bf306de67e2fa3/wrapt-2.2.2-py3-none-any.whl", hash = "sha256:5bad217350f19ce99ca5b5e71d406765ea86fe541628426772b657375ee1c048", size = 61460, upload-time = "2026-06-20T23:49:42.966Z" }, +] + +[[package]] +name = "xlrd" +version = "2.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/07/5a/377161c2d3538d1990d7af382c79f3b2372e880b65de21b01b1a2b78691e/xlrd-2.0.2.tar.gz", hash = "sha256:08b5e25de58f21ce71dc7db3b3b8106c1fa776f3024c54e45b45b374e89234c9", size = 100167, upload-time = "2025-06-14T08:46:39.039Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/62/c8d562e7766786ba6587d09c5a8ba9f718ed3fa8af7f4553e8f91c36f302/xlrd-2.0.2-py2.py3-none-any.whl", hash = "sha256:ea762c3d29f4cca48d82df517b6d89fbce4db3107f9d78713e48cd321d5c9aa9", size = 96555, upload-time = "2025-06-14T08:46:37.766Z" }, +] + +[[package]] +name = "yarl" +version = "1.24.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "multidict" }, + { name = "propcache" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/79/12/1e8f37460ea0f7eb59c221fdaf0ed75e7ac43e97f8093b9c6f411df50a78/yarl-1.24.2.tar.gz", hash = "sha256:9ac374123c6fd7abf64d1fec93962b0bd4ee2c19751755a762a72dd96c0378f8", size = 210798, upload-time = "2026-05-19T21:31:05.599Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/df/f1c7a3de0831cd83194f1a85c5bb431b13f81e6b45079314c86d1c4ef3f2/yarl-1.24.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5249a113065c2b7a958bc699759e359cd61cfc81e3069662208f48f191b7ed12", size = 129057, upload-time = "2026-05-19T21:27:47.564Z" }, + { url = "https://files.pythonhosted.org/packages/48/41/7daafb32dd7562bf45b1ce56562e7e1a9146f6479b6456873eb8a3413c40/yarl-1.24.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f4425fa244fbf530b006d0c5f79ce920114cfff5b4f5f6056e669f8e160fdc0", size = 91545, upload-time = "2026-05-19T21:27:50.089Z" }, + { url = "https://files.pythonhosted.org/packages/a8/8f/7b3ec212f1ea0683f55f978e3246bc313c38818664edfc97a9f349a4901e/yarl-1.24.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15c0b5e49d3c44e2a0b93e6a49476c5edad0a7686b92c395765a7ea775572a75", size = 91380, upload-time = "2026-05-19T21:27:51.953Z" }, + { url = "https://files.pythonhosted.org/packages/8a/1b/8bafab7db23b0567ae9db749099b329d91e3b82bc6028b2050ba583e116c/yarl-1.24.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:246d32a53a947c8f0189f5d699cbd4c7036de45d9359e13ba238d1239678c727", size = 105957, upload-time = "2026-05-19T21:27:53.98Z" }, + { url = "https://files.pythonhosted.org/packages/7f/77/21030c2f8d21d21559719beafc772ada2014be933418ed1eaed9cc800e42/yarl-1.24.2-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:64480fb3e4d4ed9ed71c48a91a477384fc342a50ca30071d2f8a88d51d9c9413", size = 97242, upload-time = "2026-05-19T21:27:55.981Z" }, + { url = "https://files.pythonhosted.org/packages/50/d8/f9ea63d1b6aa910a866e089d871fff6cbd49caab29b86b35221a62dfa0d5/yarl-1.24.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:349de4701dc3760b6e876628423a8f147ef4f5599d10aba1e10702075d424ed9", size = 114719, upload-time = "2026-05-19T21:27:58.037Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a3/04e0ee98ac58a249ea7ed75223f5f901ba81a834f0b4921b58e5cec11757/yarl-1.24.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d162677af8d5d3d6ebab8394b021f4d041ac107a4b705873148a77a49dc9e1b2", size = 112140, upload-time = "2026-05-19T21:27:59.618Z" }, + { url = "https://files.pythonhosted.org/packages/02/ad/0b9cc9f38a7324a7eb1d80f834eaa5283d17e9271bbda3186e598dddaeac/yarl-1.24.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f5f5c6ec23a9043f2d139cc072f53dd23168d202a334b9b2fda8de4c3e890d90", size = 106721, upload-time = "2026-05-19T21:28:02.586Z" }, + { url = "https://files.pythonhosted.org/packages/65/e7/a52478ebfc66ec989e085c6ae038b9f1bfa4190baa193b133b669c709e2f/yarl-1.24.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:60de6742447fbbf697f16f070b8a443f1b5fe6ca3826fbef9fe70ecd5328e643", size = 106478, upload-time = "2026-05-19T21:28:04.523Z" }, + { url = "https://files.pythonhosted.org/packages/04/d8/5508530fea8472542de00013ae280765fc938ee196fc4030c43a498afb36/yarl-1.24.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:acf93187c3710e422368eb768aee98db551ec7c85adc250207a95c16548ab7ac", size = 105423, upload-time = "2026-05-19T21:28:06.515Z" }, + { url = "https://files.pythonhosted.org/packages/84/f1/ece28505e9628e8b756e11bb4f28864a17cc33b6b44db4d2aaf0622bf630/yarl-1.24.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:f4b0352fd41fd34b6651934606268816afd6914d09626f9bcbbf018edb0afb3f", size = 99878, upload-time = "2026-05-19T21:28:08.637Z" }, + { url = "https://files.pythonhosted.org/packages/3f/52/fb5d34529b46dd84013afcfb30b8d2bc2832ed03d412736f577d604fa393/yarl-1.24.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:6b208bb939099b4b297438da4e9b25357f0b1c791888669b963e45b203ea9f36", size = 114025, upload-time = "2026-05-19T21:28:10.64Z" }, + { url = "https://files.pythonhosted.org/packages/43/f0/ff9d31aaab024f7a251c0ed308a98ae29bf9f7dc344e78f28b1322431ca2/yarl-1.24.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4b85b8825e631295ff4bc8943f7471d54c533a9360bbe15ebb38e018b555bb8a", size = 105613, upload-time = "2026-05-19T21:28:12.784Z" }, + { url = "https://files.pythonhosted.org/packages/31/7d/3296fb3f3ecd52bf9ae6c16b0895c1cda7e9170a2083861552b683f70264/yarl-1.24.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e26acf20c26cb4fefc631fdb75aca2a6b8fa8b7b5d7f204fb6a8f1e63c706f53", size = 111665, upload-time = "2026-05-19T21:28:14.393Z" }, + { url = "https://files.pythonhosted.org/packages/1a/74/77aa6ddaca4fbf42e45e675a465c43956dd40702281049975a2aa04eae59/yarl-1.24.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:819ca24f8eafcfb683c1bd5f44f2f488cea1274eb8944731ffd2e1f10f619342", size = 106914, upload-time = "2026-05-19T21:28:15.893Z" }, + { url = "https://files.pythonhosted.org/packages/d8/02/7611f22cd1d4ed7373eb7f9ee21fde1046edba2e7c0e514880d760352f48/yarl-1.24.2-cp310-cp310-win_amd64.whl", hash = "sha256:5cb0f995a901c36be096ccbf4c673591c2faabbe96279598ffaec8c030f85bf4", size = 92658, upload-time = "2026-05-19T21:28:17.471Z" }, + { url = "https://files.pythonhosted.org/packages/91/00/671d0add79938127292839ae44506ce2f7fe8909c72d5a931864f128fd0b/yarl-1.24.2-cp310-cp310-win_arm64.whl", hash = "sha256:f408eace7e22a68b467a0562e0d27d322f91fe3eaaa6f466b962c6cfaea9fa39", size = 87887, upload-time = "2026-05-19T21:28:19.021Z" }, + { url = "https://files.pythonhosted.org/packages/c5/c5/1ce244152ff2839645e7cae92f90e7bafcb2c52bea7ff586ac714f14f5df/yarl-1.24.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:36348bebb147b83818b9d7e673ea4debc75970afc6ffdc7e3975ad05ce5a58c1", size = 128971, upload-time = "2026-05-19T21:28:20.543Z" }, + { url = "https://files.pythonhosted.org/packages/87/5a/00f36967203ed89cb3acd2c8ed526cc3fed9418eb70ce128160a911c8499/yarl-1.24.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a97e42c8a2233f2f279ecadd9e4a037bcb5d813b78435e8eedd4db5a9e9708c", size = 91507, upload-time = "2026-05-19T21:28:22.556Z" }, + { url = "https://files.pythonhosted.org/packages/31/d0/1fb0c1cd27288f39f6974da4318c32768d72c9890984541fdf1e2e32a51d/yarl-1.24.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8d027d56f1035e339d1001ac33eceab5b2ec8e42e449787bb75e289fb9a5cd1d", size = 91343, upload-time = "2026-05-19T21:28:24.092Z" }, + { url = "https://files.pythonhosted.org/packages/03/ce/d4a646508bed2f8dec6435b40166fe9308dd191262033d3f307b2bbcaecd/yarl-1.24.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a6377060e7927187a42b7eb202090cbe2b34933a4eeaf90e3bd9e33432e5cae", size = 105704, upload-time = "2026-05-19T21:28:25.872Z" }, + { url = "https://files.pythonhosted.org/packages/4b/07/b3278e82d8bc41485bcf6d856cd0433262593de615b1d3dc43bd3f5bead4/yarl-1.24.2-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:17076578bce0049a5ce57d14ad1bded391b68a3b213e9b81b0097b090244999a", size = 97281, upload-time = "2026-05-19T21:28:27.352Z" }, + { url = "https://files.pythonhosted.org/packages/17/5b/4cee6e7c92e487bebe7afc797da0aa54a248ab4e776a68fe369ec29665a5/yarl-1.24.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:50713f1d4d6be6375bb178bb43d140ee1acb8abe589cd723320b7925a275be1e", size = 114020, upload-time = "2026-05-19T21:28:29.458Z" }, + { url = "https://files.pythonhosted.org/packages/5c/82/111076571545a7d4f9cca3fbd5c6f40615af58642be09f12328f48022468/yarl-1.24.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:34263e2fa8fb5bb63a0d97706cda38edbad62fddb58c7f12d6acbc092812aa50", size = 111450, upload-time = "2026-05-19T21:28:31.262Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ec/08f671f69a444d704aeecebf92af659b67b97a869942411d0a578b08c334/yarl-1.24.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49016d82f032b1bd1e10b01078a7d29ae71bf468eeae0ea22df8bab691e60003", size = 106384, upload-time = "2026-05-19T21:28:32.856Z" }, + { url = "https://files.pythonhosted.org/packages/e5/86/ce41e7a7a199340b2330d52b60f25c4074b6636dd0e60b1a80d31a9db042/yarl-1.24.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3f6d2c216318f8f32038ca3f72501ba08536f0fd18a36e858836b121b2deed9f", size = 106153, upload-time = "2026-05-19T21:28:35.222Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5d/31be8a729531ab3e55ac3e7e5c800be8c89ea98947f418b2f6ea259fb6ee/yarl-1.24.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:08d3a33218e0c64393e7610284e770409a9c31c429b078bcb24096ed0a783b8f", size = 105322, upload-time = "2026-05-19T21:28:36.642Z" }, + { url = "https://files.pythonhosted.org/packages/47/9b/b57afb22b386ae87ac9940f09878b98d8c333f89113e6fc96fcf4ca9eb64/yarl-1.24.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:5d699376c4ca3cba49bbfae3a05b5b70ded572937171ce1e0b8d87118e2ba294", size = 99057, upload-time = "2026-05-19T21:28:38.386Z" }, + { url = "https://files.pythonhosted.org/packages/a3/4f/06348c27c8389256c313e8a57d796808fc0264c915dd5e7cfd3c0e314dc7/yarl-1.24.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a1cab588b4fa14bea2e55ebea27478adfb05372f47573738e1acc4a36c0b05d2", size = 113502, upload-time = "2026-05-19T21:28:40.091Z" }, + { url = "https://files.pythonhosted.org/packages/5f/1c/284f307b298e4a17b7943b07d9d7ecc4151537f8d137ba51f3bb6c31ca20/yarl-1.24.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:ec87ccc31bd21db7ad009d8572c127c1000f268517618a4cc09adba3c2a7f21c", size = 105253, upload-time = "2026-05-19T21:28:41.987Z" }, + { url = "https://files.pythonhosted.org/packages/c8/bf/0de123bec8619e45c80cbded9085f61b5b4a9eddb8abe6d25d28ee1ec866/yarl-1.24.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d1dd47a22843b212baa8d74f37796815d43bd046b42a0f41e9da433386c3136b", size = 111345, upload-time = "2026-05-19T21:28:43.93Z" }, + { url = "https://files.pythonhosted.org/packages/90/af/0248eb065e51129d2a9b2436cd1b5c772c19a6b04e5b6a186955671e3319/yarl-1.24.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7b54b9c67c2b06bd7b9a77253d242124b9c95d2c02def5a1144001ee547dd9d5", size = 106558, upload-time = "2026-05-19T21:28:45.806Z" }, + { url = "https://files.pythonhosted.org/packages/21/3c/f960d7a65ef97d8ba9b424fb5128796a4bc710fc6df2ddbbd7dfdc3bbd20/yarl-1.24.2-cp311-cp311-win_amd64.whl", hash = "sha256:f8fdbcff8b2c7c9284e60c196f693588598ddcee31e11c18e14949ce44519d45", size = 92808, upload-time = "2026-05-19T21:28:48.465Z" }, + { url = "https://files.pythonhosted.org/packages/03/1a/49fb03750e4de4d2284cd5b885a383133c34eef45bd59631b2bb8b7e81e8/yarl-1.24.2-cp311-cp311-win_arm64.whl", hash = "sha256:b32c37a7a337e90822c45797bf3d79d60875cfcccd3ecc80e9f453d87026c122", size = 87610, upload-time = "2026-05-19T21:28:50.07Z" }, + { url = "https://files.pythonhosted.org/packages/f0/da/866bcb01076ba49d2b42b309867bed3826421f1c479655eb7a607b44f20b/yarl-1.24.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b975866c184564c827e0877380f0dae57dcca7e52782128381b72feff6dfceb8", size = 129957, upload-time = "2026-05-19T21:28:51.695Z" }, + { url = "https://files.pythonhosted.org/packages/bf/1d/fcefb70922ea2268a8971d8e5874d9a8218644200fb8465f1dcad55e6851/yarl-1.24.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3b075301a2836a0e297b1b658cb6d6135df535d62efefdd60366bd589c2c82f2", size = 92164, upload-time = "2026-05-19T21:28:53.242Z" }, + { url = "https://files.pythonhosted.org/packages/29/b6/170e2b8d4e3bc30e6bfdcca53556537f5bf595e938632dfcb059311f3ff6/yarl-1.24.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ae44649b00947634ab0dab2a374a638f52923a6e67083f2c156cd5cbd1a881d", size = 91688, upload-time = "2026-05-19T21:28:54.865Z" }, + { url = "https://files.pythonhosted.org/packages/fe/a5/c9f655d5553ea0b99fdac9d6a99ad3f9b3e73b8e5758bb46f58c9831f74c/yarl-1.24.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:507cc19f0b45454e2d6dcd62ff7d062b9f77a2812404e62dbdaec05b50faa035", size = 102902, upload-time = "2026-05-19T21:28:56.963Z" }, + { url = "https://files.pythonhosted.org/packages/5d/bc/6b9664d815d79af4ee553337f9d606c56bbf269186ada9172de45f1b5f60/yarl-1.24.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c4c17bad5a530912d2111825d3f05e89bab2dd376aaa8cbc77e449e6db63e576", size = 97931, upload-time = "2026-05-19T21:28:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/98/ec/32ba48acae30fecd60928f5791188b80a9d6ee3840507ffda29fecd37b71/yarl-1.24.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f5f0cbb112838a4a293985b6ed73948a547dadcc1ba6d2089938e7abdedceef8", size = 111030, upload-time = "2026-05-19T21:29:00.148Z" }, + { url = "https://files.pythonhosted.org/packages/82/5a/6f4cd081e5f4934d2ae3a8ef4abe3afacc010d26f0035ee91b35cd7d7c37/yarl-1.24.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ec8356b8a6afcf81fc7aeeef13b1ff7a49dec00f313394bbb9e83830d32ccd7", size = 110392, upload-time = "2026-05-19T21:29:02.155Z" }, + { url = "https://files.pythonhosted.org/packages/7a/da/323a01c349bd5fb01bb6652e314d9bb218cee630a736bdb810ad50e4013f/yarl-1.24.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e7ebcdef69dec6c6451e616f32b622a6d4a2e92b445c992f7c8e5274a6bbc4c", size = 105612, upload-time = "2026-05-19T21:29:04.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/80/264ab684f181e1a876389374519ff05d10248725535ae2ac4e8ac4e563d6/yarl-1.24.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:47a55d6cf6db2f401017a9e96e5288844e5051911fb4e0c8311a3980f5e59a7d", size = 104487, upload-time = "2026-05-19T21:29:06.491Z" }, + { url = "https://files.pythonhosted.org/packages/41/07/efabe5df87e96d7ad5959760b888344be48cd6884db127b407c6b5503adc/yarl-1.24.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3065657c80a2321225e804048597ad55658a7e76b32d6f5ee4074d04c50401db", size = 102333, upload-time = "2026-05-19T21:29:08.267Z" }, + { url = "https://files.pythonhosted.org/packages/44/0c/bcf7c42603e1009295f586d8890f2ba032c8b53310e815adf0a202c73d9f/yarl-1.24.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cb84b80d88e19ede158619b80813968713d8d008b0e2497a576e6a0557d50712", size = 99025, upload-time = "2026-05-19T21:29:10.682Z" }, + { url = "https://files.pythonhosted.org/packages/4f/82/84482ab1a57a0f21a08afe6a7004c61d741f8f2ecc3b05c321577c612164/yarl-1.24.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:990de4f680b1c217e77ff0d6aa0029f9eb79889c11fb3e9a3942c7eba29c1996", size = 110507, upload-time = "2026-05-19T21:29:12.954Z" }, + { url = "https://files.pythonhosted.org/packages/c4/8d/a546ba1dfe1b0f290e05fef145cd07614c0f15df1a707195e512d1e39d1d/yarl-1.24.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:abb8ec0323b80161e3802da3150ef660b41d0e9be2048b76a363d93eee992c2b", size = 103719, upload-time = "2026-05-19T21:29:14.893Z" }, + { url = "https://files.pythonhosted.org/packages/1a/b6/267f2a09213138473adfce6b8a6e17791d7fee70bd4d9003218e4dec58b0/yarl-1.24.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e7977781f83638a4c73e0f88425563d70173e0dfd90ac006a45c65036293ee3c", size = 110438, upload-time = "2026-05-19T21:29:16.485Z" }, + { url = "https://files.pythonhosted.org/packages/48/2d/1c8d89c7c5f9cad9fb2902445d94e2ab1d7aa35de029afbb8ae95c42d00f/yarl-1.24.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e30dd55825dc554ec5b66a94953b8eda8745926514c5089dfcacecb9c99b5bd1", size = 105719, upload-time = "2026-05-19T21:29:18.367Z" }, + { url = "https://files.pythonhosted.org/packages/a7/25/722e3b93bd687009afb2d59a35e13d30ddd8f80571445bb0c4e4ce26ec66/yarl-1.24.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dafe10c12ddd4d120d528c4b5599c953bd7b12845347d507b95451195bb6cad", size = 92901, upload-time = "2026-05-19T21:29:20.014Z" }, + { url = "https://files.pythonhosted.org/packages/39/47/4486ccfb674c04854a1ef8aa77868b6a6f765feaf69633409d7ca4f02cb8/yarl-1.24.2-cp312-cp312-win_arm64.whl", hash = "sha256:044a09d8401fcf8681977faef6d286b8ade1e2d2e9dceda175d1cfa5ca496f30", size = 87229, upload-time = "2026-05-19T21:29:22.1Z" }, + { url = "https://files.pythonhosted.org/packages/82/62/fcf0ce677f17e5c471c06311dd25964be38a4c586993632910d2e75278bc/yarl-1.24.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:491ac9141decf49ee8030199e1ee251cdff0e131f25678817ff6aa5f837a3536", size = 128978, upload-time = "2026-05-19T21:29:23.83Z" }, + { url = "https://files.pythonhosted.org/packages/d3/58/8e63299bb71ed61a834121d9d3fe6c9fcf2a6a5d09754ff4f20f2d20baf5/yarl-1.24.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e89418f65eda18f99030386305bd44d7d504e328a7945db1ead514fbe03a0607", size = 91733, upload-time = "2026-05-19T21:29:25.375Z" }, + { url = "https://files.pythonhosted.org/packages/c1/24/16748d5dab6daec8b0ed81ccec639a1cded0f18dcc62a4f696b4fe366c37/yarl-1.24.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cdfcce633b4a4bb8281913c57fcafd4b5933fbc19111a5e3930bbd299d6102f1", size = 91113, upload-time = "2026-05-19T21:29:26.928Z" }, + { url = "https://files.pythonhosted.org/packages/1b/66/b63fff7b71211e866624b21432d5943cbb633eb0c2872d9ee3070648f22c/yarl-1.24.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:863297ddede92ee49024e9a9b11ecb59f310ca85b60d8537f56bed9bbb5b1986", size = 103899, upload-time = "2026-05-19T21:29:28.842Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ac/ba1974b8533909636f7733fe86cf677e3619527c3c2fa913e0ea89c48757/yarl-1.24.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:374423f70754a2c96942ede36a29d37dc6b0cb8f92f8d009ddf3ed78d3da5488", size = 97862, upload-time = "2026-05-19T21:29:31.086Z" }, + { url = "https://files.pythonhosted.org/packages/1b/a5/123ac993b5c2ba6f554a140305620cb8f150fa543711bbc49be3ec0a65a4/yarl-1.24.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:33a29b5d00ccbf3219bb3e351d7875739c19481e030779f48cc46a7a71681a9b", size = 111060, upload-time = "2026-05-19T21:29:32.657Z" }, + { url = "https://files.pythonhosted.org/packages/23/37/c472d3af3509688392134a88a825276770a187f1daa4de3f6dc0a327a751/yarl-1.24.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a9532c57211730c515341af11fef6e9b61d157487272a096d0c04da445642592", size = 110613, upload-time = "2026-05-19T21:29:34.379Z" }, + { url = "https://files.pythonhosted.org/packages/df/88/09c28dad91e662ccfaa1b78f1c57badde74fc9d0b23e74aef644750ecd73/yarl-1.24.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:91e72cf093fd833483a97ee648e0c053c7c629f51ff4a0e7edd84f806b0c5617", size = 107012, upload-time = "2026-05-19T21:29:36.216Z" }, + { url = "https://files.pythonhosted.org/packages/07/ab/9d4f69d571a94f4d112fa7e2e007200f5a54d319f58c82ac7b7baa61f5c6/yarl-1.24.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b3177bc0a768ef3bacceb4f272632990b7bea352f1b2f1eee9d6d6ff16516f92", size = 105887, upload-time = "2026-05-19T21:29:38.746Z" }, + { url = "https://files.pythonhosted.org/packages/8e/9a/000b2b66c0d772a499fc531d21dab92dfeb73b640a12eed6ba89f49bb2d0/yarl-1.24.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e196952aacaf3b232e265ff02980b64d483dc0972bd49bcb061171ff22ac203a", size = 103620, upload-time = "2026-05-19T21:29:40.368Z" }, + { url = "https://files.pythonhosted.org/packages/41/7c/7c1050f73450fbdaa3f0c72017059f00ce5e13366692f3dba25275a1083d/yarl-1.24.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:204e7a61ce99919c0de1bf904ab5d7aa188a129ea8f690a8f76cfb6e2844dc44", size = 100599, upload-time = "2026-05-19T21:29:42.66Z" }, + { url = "https://files.pythonhosted.org/packages/ec/b1/29e5756b3926705f5f6089bd5b9f50a56eaac550da6e260bf713ead44d04/yarl-1.24.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b156914620f0b9d78dc1adb3751141daee561cfec796088abb89ed49d220f1a", size = 110604, upload-time = "2026-05-19T21:29:44.632Z" }, + { url = "https://files.pythonhosted.org/packages/a3/4b/8415bc96e9b150cde942fbac9a8182985e58f40ce5c54c34ed015407d3ee/yarl-1.24.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:8372a2b976cf70654b2be6619ab6068acabb35f724c0fda7b277fbf53d66a5cf", size = 105161, upload-time = "2026-05-19T21:29:46.755Z" }, + { url = "https://files.pythonhosted.org/packages/8b/d4/cde059abfa229553b7298a2eadde2752e723d50aeedaef86ce59da2718ee/yarl-1.24.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f9a1e9b622ca284143aab5d885848686dcd85453bb1ca9abcdb7503e64dc0056", size = 110619, upload-time = "2026-05-19T21:29:48.972Z" }, + { url = "https://files.pythonhosted.org/packages/e7/2c/d6a6c9a61549f7b6c7e6dc6937d195bcf069582b47b7200dcd0e7b256acf/yarl-1.24.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:810e19b685c8c3c5862f6a38160a1f4e4c0916c9390024ec347b6157a45a0992", size = 107362, upload-time = "2026-05-19T21:29:51Z" }, + { url = "https://files.pythonhosted.org/packages/92/dd/3ae5fe417e9d1c353a548553326eb9935e76b6b727161563b424cc296df3/yarl-1.24.2-cp313-cp313-win_amd64.whl", hash = "sha256:7d37fb7c38f2b6edab0f845c4f85148d4c44204f52bc127021bd2bc9fdbf1656", size = 92667, upload-time = "2026-05-19T21:29:52.743Z" }, + { url = "https://files.pythonhosted.org/packages/10/cc/a7beb239f78f27fca1b053c8e8595e4179c02e62249b4687ec218c370c50/yarl-1.24.2-cp313-cp313-win_arm64.whl", hash = "sha256:1e831894be7c2954240e49791fa4b50c05a0dc881de2552cfe3ffd8631c7f461", size = 87069, upload-time = "2026-05-19T21:29:54.442Z" }, + { url = "https://files.pythonhosted.org/packages/40/0e/e08087695fc12789263821c5dc0f8dc52b5b17efd0887cacf419f8a43ba3/yarl-1.24.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:f9312b3c02d9b3d23840f67952913c9c8721d7f1b7db305289faefa878f364c2", size = 129670, upload-time = "2026-05-19T21:29:56.631Z" }, + { url = "https://files.pythonhosted.org/packages/3a/98/ab4b5ed1b1b5cd973c8a3eb994c3a6aefb6ce6d399e21bb5f0316c33815c/yarl-1.24.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a4f4d6cd615823bfc7fb7e9b5987c3f41666371d870d51058f77e2680fbe9630", size = 91916, upload-time = "2026-05-19T21:29:58.645Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b1/5297bb6a7df4782f7605bffc43b31f5044070935fbbcaa6c705a07e6ac65/yarl-1.24.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0c3063e5c0a8e8e62fae6c2596fa01da1561e4cd1da6fec5789f5cf99a8aefd8", size = 91625, upload-time = "2026-05-19T21:30:00.412Z" }, + { url = "https://files.pythonhosted.org/packages/02/a7/45baabfff76829264e623b185cff0c340d7e11bf3e1cd9ea37e7d17934bd/yarl-1.24.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fecd17873a096036c1c87ab3486f1aef7f269ada7f23f7f856f93b1cc7744f14", size = 104574, upload-time = "2026-05-19T21:30:02.544Z" }, + { url = "https://files.pythonhosted.org/packages/f3/40/3a5ab144d3d650ca37d4f4b57e56169be8af3ca34c448793e064b30baaed/yarl-1.24.2-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a46d1ab4ba4d32e6dc80daf8a28ce0bd83d08df52fbc32f3e288663427734535", size = 97534, upload-time = "2026-05-19T21:30:04.319Z" }, + { url = "https://files.pythonhosted.org/packages/9c/b5/5658fef3681fb5776b4513b052bec750009f47b3a592251c705d75375798/yarl-1.24.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73e68edf6dfd5f73f9ca127d84e2a6f9213c65bdffb736bda19524c0564fcd14", size = 111481, upload-time = "2026-05-19T21:30:05.988Z" }, + { url = "https://files.pythonhosted.org/packages/4c/06/fdcd7dde037f00866dce123ed4ba23dba94beb56fc4cf561668d27be37f2/yarl-1.24.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a296ca617f2d25fbceafb962b88750d627e5984e75732c712154d058ae8d79a3", size = 111529, upload-time = "2026-05-19T21:30:07.738Z" }, + { url = "https://files.pythonhosted.org/packages/c2/53/d81269aaafccea0d33396c03035de997b743f11e648e6e27a0df99c72980/yarl-1.24.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51b2cf5ec89a8b8470177641ed62a3ba22d74e1e898e06ad53aa77972487208", size = 107338, upload-time = "2026-05-19T21:30:09.713Z" }, + { url = "https://files.pythonhosted.org/packages/ae/04/23049463f729bd899df203a7960505a75333edd499cda8aa1d5a82b64df5/yarl-1.24.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:310fc687f7b2044ec54e372c8cbe923bb88f5c37bded0d3079e5791c2fc3cf50", size = 106147, upload-time = "2026-05-19T21:30:11.365Z" }, + { url = "https://files.pythonhosted.org/packages/14/18/04a4b5830b43ed5e4c5015b40e9f6241ad91487d71611061b4e111d6ac80/yarl-1.24.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:297a2fe352ecf858b30a98f87948746ec16f001d279f84aebdbd3bd965e2f1bd", size = 104272, upload-time = "2026-05-19T21:30:12.978Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f7/8cffdf319aee7a7c1dbd07b61d91c3e3fda460c7a93b5f93e445f3806c4c/yarl-1.24.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2a263e76b97bc42bdcd7c5f4953dec1f7cd62a1112fa7f869e57255229390d67", size = 99962, upload-time = "2026-05-19T21:30:15.001Z" }, + { url = "https://files.pythonhosted.org/packages/d7/39/b3cce3b7dbef64ac700ad4cea156a207d01bede0f507587616c364b5468e/yarl-1.24.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:822519b64cf0b474f1a0aaef1dc621438ea46bb77c94df97a5b4d213a7d8a8b1", size = 111063, upload-time = "2026-05-19T21:30:16.683Z" }, + { url = "https://files.pythonhosted.org/packages/a1/ea/100818505e7ebf165c7242ff17fdf7d9fee79e27234aeca871c1082920d7/yarl-1.24.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:b6067060d9dc594899ba83e6db6c48c68d1e494a6dab158156ed86977ca7bcb1", size = 105438, upload-time = "2026-05-19T21:30:18.769Z" }, + { url = "https://files.pythonhosted.org/packages/8f/d2/e075a0b32aa6625087de9e653087df0759fed5de4a435fef594181102a77/yarl-1.24.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:0063adad533e57171b79db3943b229d40dfafeeee579767f96541f106bac5f1b", size = 111458, upload-time = "2026-05-19T21:30:21.024Z" }, + { url = "https://files.pythonhosted.org/packages/e6/5c/ceea7ba98b65c8eb8d947fdc52f9bedfcd43c6a57c9e3c90c17be8f324a3/yarl-1.24.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ee8e3fb34513e8dc082b586ef4910c98335d43a6fab688cd44d4851bacfce3e8", size = 107589, upload-time = "2026-05-19T21:30:23.412Z" }, + { url = "https://files.pythonhosted.org/packages/fa/d9/5582d57e2b2db9b85eb6663a22efdd78e08805f3f5389566e9fcad254d1b/yarl-1.24.2-cp314-cp314-win_amd64.whl", hash = "sha256:afb00d7fd8e0f285ca29a44cc50df2d622ff2f7a6d933fa641577b5f9d5f3db0", size = 94424, upload-time = "2026-05-19T21:30:25.425Z" }, + { url = "https://files.pythonhosted.org/packages/92/10/7dc07a0e22806a9280f42a57361395506e800c64e22737cd7b0886feab42/yarl-1.24.2-cp314-cp314-win_arm64.whl", hash = "sha256:68cf6eacd6028ef1142bc4b48376b81566385ca6f9e7dde3b0fa91be08ffcb57", size = 88690, upload-time = "2026-05-19T21:30:27.623Z" }, + { url = "https://files.pythonhosted.org/packages/9e/13/d5b8e2c8667db955bcb3de233f18798fefe7edf1d7429c2c9d4f9c401114/yarl-1.24.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:221ce1dd921ac4f603957f17d7c18c5cc0797fbb52f156941f92e04605d1d67b", size = 136248, upload-time = "2026-05-19T21:30:29.297Z" }, + { url = "https://files.pythonhosted.org/packages/de/46/a4a97c05c9c9b8fd266bb2a0df12992c7fbd02391eb9640583411b6dab32/yarl-1.24.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5f3224db28173a00d7afacdee07045cc4673dfab2b15492c7ae10deddbece761", size = 95084, upload-time = "2026-05-19T21:30:31.031Z" }, + { url = "https://files.pythonhosted.org/packages/95/b2/845cf2074a015e6fe0d0808cf1a2d9e868386c4220d657ebd8302b199043/yarl-1.24.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c557165320d6244ebe3a02431b2a201a20080e02f41f0cfa0ccc47a183765da8", size = 95272, upload-time = "2026-05-19T21:30:33.062Z" }, + { url = "https://files.pythonhosted.org/packages/fe/16/e69d4aa244aef45235ddfebc0e04036a6829842bc5a6a795aedc6c998d23/yarl-1.24.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:904065e6e85b1fa54d0d87438bd58c14c0bad97aad654ad1077fd9d87e8478ed", size = 101497, upload-time = "2026-05-19T21:30:34.842Z" }, + { url = "https://files.pythonhosted.org/packages/15/94/c07107715d621076863ee88b3ddf183fa5e9d4aba5769623c9979828410a/yarl-1.24.2-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8cec2a38d70edc10e0e856ceda886af5327a017ccbde8e1de1bd44d300357543", size = 94002, upload-time = "2026-05-19T21:30:37.724Z" }, + { url = "https://files.pythonhosted.org/packages/a9/35/fc1bbdd895b5e4010b8fdd037f7ed3aa289d3863e08231b30231ca9a0815/yarl-1.24.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e7484b9361ed222ee1ca5b4337aa4cbdcc4618ce5aff57d9ef1582fd95893fc0", size = 106524, upload-time = "2026-05-19T21:30:40.196Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f2/32b66d0a4ba47c296cf86d03e2c67bff58399fe6d6d84d5205c04c66cc6d/yarl-1.24.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:84f9670b89f34db07f81e53aee83e0b938a3412329d51c8f922488be7fcc4024", size = 106165, upload-time = "2026-05-19T21:30:41.888Z" }, + { url = "https://files.pythonhosted.org/packages/95/47/37cb5ff50c5e825d4d38e81bb04d1b7e96bf960f7ab89f9850b162f3f114/yarl-1.24.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:abb2759733d63a28b4956500a5dd57140f26486c92b2caedfb964ab7d9b79dbf", size = 103010, upload-time = "2026-05-19T21:30:43.985Z" }, + { url = "https://files.pythonhosted.org/packages/6f/d2/4597912315096f7bb359e46e13bf8b60994fcbb2db29b804c0902ef4eff5/yarl-1.24.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:081c2bf54efe03774d0311172bc04fedf9ca01e644d4cd8c805688e527209bdc", size = 101128, upload-time = "2026-05-19T21:30:46.291Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d5/c8e86e120521e646013d02a8e3b8884392e28494be8f392366e50d208efc/yarl-1.24.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:86746bef442aa479107fe28132e1277237f9c24c2f00b0b0cf22b3ee0904f2bb", size = 101382, upload-time = "2026-05-19T21:30:48.085Z" }, + { url = "https://files.pythonhosted.org/packages/fa/98/70b229236118f89dbeb739b76f10225bbf53b5497725502594c9a01d699a/yarl-1.24.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:2d07d21d0bc4b17558e8de0b02fbfdf1e347d3bb3699edd00bb92e7c57925420", size = 95964, upload-time = "2026-05-19T21:30:49.785Z" }, + { url = "https://files.pythonhosted.org/packages/87/f8/56c386981e3c8648d279fdef2397ffec577e8320fd5649745e34d54faeb7/yarl-1.24.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:4fb1ac3fc5fecd8ae7453ea237e4d22b49befa70266dfe1629924245c21a0c7f", size = 106204, upload-time = "2026-05-19T21:30:51.862Z" }, + { url = "https://files.pythonhosted.org/packages/1a/1e/765afe97811ca35933e2a7de70ac57b1997ea2e4ee895719ee7a231fb7e5/yarl-1.24.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:4da31a5512ed1729ca8d8aacde3f7faeb8843cde3165d6bcf7f88f74f17bb8aa", size = 101510, upload-time = "2026-05-19T21:30:53.62Z" }, + { url = "https://files.pythonhosted.org/packages/ee/78/393913f4b9039e1edd09ae8a9bbb9d539be909a8abf6d8a2084585bed4b7/yarl-1.24.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:533ded4dceb5f1f3da7906244f4e82cf46cfd40d84c69a1faf5ac506aa65ecbe", size = 105584, upload-time = "2026-05-19T21:30:55.962Z" }, + { url = "https://files.pythonhosted.org/packages/78/87/deb17b7049bbe74ea11a713b86f8f27800cc1c8648b0b797243ebb4830ba/yarl-1.24.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7b3a85525f6e7eeabcfdd372862b21ee1915db1b498a04e8bf0e389b607ff0bd", size = 103410, upload-time = "2026-05-19T21:30:57.962Z" }, + { url = "https://files.pythonhosted.org/packages/8f/be/f9f7594e23b5b93affff0318e4593c1920331bcaefda326cabcad94296a1/yarl-1.24.2-cp314-cp314t-win_amd64.whl", hash = "sha256:a7624b1ca46ca5d7b864ef0d2f8efe3091454085ee1855b4e992314529972215", size = 102980, upload-time = "2026-05-19T21:30:59.735Z" }, + { url = "https://files.pythonhosted.org/packages/65/a4/ba80dccd3593ff1f01051a818694d07b58cb8232677ee9a22a5a1f93a9fc/yarl-1.24.2-cp314-cp314t-win_arm64.whl", hash = "sha256:e434a45ce2e7a947f951fc5a8944c8cc080b7e59f9c50ae80fd39107cf88126d", size = 91219, upload-time = "2026-05-19T21:31:01.934Z" }, + { url = "https://files.pythonhosted.org/packages/fd/4d/4b880086bd0d3e034d25647be1d830afc3e3f610e98c4ab3490af6b1b6d5/yarl-1.24.2-py3-none-any.whl", hash = "sha256:2783d9226db8797636cd6896e4de81feed252d1db72265686c9558d97a4d94b9", size = 53576, upload-time = "2026-05-19T21:31:03.909Z" }, +] + +[[package]] +name = "zipp" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b9/d8/eab98a517c14134c0b2eb4e2387bc5f457334293ec5d2dd3857ec2966802/zipp-4.1.0.tar.gz", hash = "sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602", size = 26214, upload-time = "2026-05-18T20:08:57.967Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/13/547360d81e6d88d58492968ffda9f9542854f11310ee556fef14260cc886/zipp-4.1.0-py3-none-any.whl", hash = "sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f", size = 10238, upload-time = "2026-05-18T20:08:57.045Z" }, +]