[Feature] EconDB Provider Extension With New Economy Endpoints. (#6313)

* economy router

* router endpoints

* update available_indicators

* add econdb provider extension

* black

* fetcher test

* country description

* recapture tests and router examples

* black

* codespell

* codespell skip

* codespell skip...?

* use . instead of * in codespell.skip?

* this is supposed to skip the file from codespell

* try another thing for codespell

* unused import

* pylint

* doc page example - df.filter needs axis

* unused argument

* more pylint

* mypy

* insert image to doc page

* recapture test

* description

* mypy

* Update .codespell.skip

* black

* linting..

* more linters

* black

* init docstring

* static files

---------

Co-authored-by: Igor Radovanovic <74266147+IgorWounds@users.noreply.github.com>
This commit is contained in:
Danglewood
2024-04-22 09:45:56 -07:00
committed by GitHub
parent f18680a5c2
commit ee422419d0
36 changed files with 16017 additions and 387 deletions

1
.codespell.ignore vendored
View File

@@ -34,6 +34,7 @@ shold
shs
statics
te
tha
toke
vai
varian

View File

@@ -0,0 +1,43 @@
"""Available Indicators Standard Model."""
from typing import Optional
from pydantic import Field
from openbb_core.provider.abstract.data import Data
from openbb_core.provider.abstract.query_params import QueryParams
from openbb_core.provider.utils.descriptions import DATA_DESCRIPTIONS
class AvailableIndicesQueryParams(QueryParams):
"""Available Indicators Query."""
class AvailableIndicatorsData(Data):
"""Available Indicators Data.
Returns the list of available economic indicators from a provider.
"""
symbol_root: Optional[str] = Field(
default=None, description="The root symbol representing the indicator."
)
symbol: Optional[str] = Field(
default=None,
description=DATA_DESCRIPTIONS.get("symbol", "")
+ " The root symbol with additional codes.",
)
country: Optional[str] = Field(
default=None,
description="The name of the country, region, or entity represented by the symbol.",
)
iso: Optional[str] = Field(
default=None,
description="The ISO code of the country, region, or entity represented by the symbol.",
)
description: Optional[str] = Field(
default=None, description="The description of the indicator."
)
frequency: Optional[str] = Field(
default=None, description="The frequency of the indicator data."
)

View File

@@ -0,0 +1,89 @@
"""Country Profile Standard Model."""
from typing import Optional
from pydantic import Field, field_validator
from openbb_core.provider.abstract.data import Data
from openbb_core.provider.abstract.query_params import QueryParams
from openbb_core.provider.utils.descriptions import (
DATA_DESCRIPTIONS,
QUERY_DESCRIPTIONS,
)
class CountryProfileQueryParams(QueryParams):
"""Country Profile Query."""
country: str = Field(description=QUERY_DESCRIPTIONS.get("country", ""))
@field_validator("country", mode="before", check_fields=False)
@classmethod
def to_lower(cls, v: str) -> str:
"""Convert the country to lowercase."""
return v.lower().replace(" ", "_")
class CountryProfileData(Data):
"""Country Profile Data."""
country: str = Field(description=DATA_DESCRIPTIONS.get("country", ""))
population: Optional[int] = Field(default=None, description="Population.")
gdp_usd: Optional[float] = Field(
default=None, description="Gross Domestic Product, in billions of USD."
)
gdp_qoq: Optional[float] = Field(
default=None,
description="GDP growth quarter-over-quarter change, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
gdp_yoy: Optional[float] = Field(
default=None,
description="GDP growth year-over-year change, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
cpi_yoy: Optional[float] = Field(
default=None,
description="Consumer Price Index year-over-year change, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
core_yoy: Optional[float] = Field(
default=None,
description="Core Consumer Price Index year-over-year change, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
retail_sales_yoy: Optional[float] = Field(
default=None,
description="Retail Sales year-over-year change, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
industrial_production_yoy: Optional[float] = Field(
default=None,
description="Industrial Production year-over-year change, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
policy_rate: Optional[float] = Field(
default=None,
description="Short term policy rate, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
yield_10y: Optional[float] = Field(
default=None,
description="10-year government bond yield, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
govt_debt_gdp: Optional[float] = Field(
default=None,
description="Government debt as a percent (normalized) of GDP.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
current_account_gdp: Optional[float] = Field(
default=None,
description="Current account balance as a percent (normalized) of GDP.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)
jobless_rate: Optional[float] = Field(
default=None,
description="Unemployment rate, as a normalized percent.",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)

View File

@@ -0,0 +1,57 @@
"""Economic Indicators Standard Model."""
from datetime import date as dateType
from typing import Optional, Union
from pydantic import Field, field_validator
from openbb_core.provider.abstract.data import Data
from openbb_core.provider.abstract.query_params import QueryParams
from openbb_core.provider.utils.descriptions import (
DATA_DESCRIPTIONS,
QUERY_DESCRIPTIONS,
)
class EconomicIndicatorsQueryParams(QueryParams):
"""Economic Indicators Query."""
symbol: str = Field(
description=QUERY_DESCRIPTIONS.get("symbol", "")
+ " The base symbol for the indicator (e.g. GDP, CPI, etc.).",
)
country: Optional[str] = Field(
default=None,
description=QUERY_DESCRIPTIONS.get("country", "")
+ " The country represented by the indicator, if available.",
)
start_date: Optional[dateType] = Field(
description=QUERY_DESCRIPTIONS.get("start_date", ""), default=None
)
end_date: Optional[dateType] = Field(
description=QUERY_DESCRIPTIONS.get("end_date", ""), default=None
)
@field_validator("symbol", mode="before", check_fields=False)
@classmethod
def to_upper(cls, v: str) -> str:
"""Convert field to uppercase."""
return v.upper()
class EconomicIndicatorsData(Data):
"""Economic Indicators Data."""
date: dateType = Field(description=DATA_DESCRIPTIONS.get("date", ""))
symbol_root: Optional[str] = Field(
default=None, description="The root symbol for the indicator (e.g. GDP)."
)
symbol: Optional[str] = Field(
default=None, description=DATA_DESCRIPTIONS.get("symbol", "")
)
country: Optional[str] = Field(
default=None, description="The country represented by the data."
)
value: Optional[Union[int, float]] = Field(
default=None, description=DATA_DESCRIPTIONS.get("value", "")
)

View File

@@ -18,6 +18,7 @@ openbb-devtools = { path = "./extensions/devtools", develop = true }
openbb-core = { path = "./core", develop = true }
openbb-benzinga = { path = "./providers/benzinga", develop = true }
openbb-econdb = { path = "./providers/econdb", develop = true }
openbb-federal-reserve = { path = "./providers/federal_reserve", develop = true }
openbb-fmp = { path = "./providers/fmp", develop = true }
openbb-fred = { path = "./providers/fred", develop = true }

View File

@@ -562,3 +562,74 @@ def test_economy_fred_regional(params, headers):
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@parametrize(
"params",
[
(
{
"provider": "econdb",
"country": "us,uk,jp",
"symbol": "GDP,GDEBT",
"transform": None,
"start_date": "2022-01-01",
"end_date": "2024-01-01",
"use_cache": False,
}
),
],
)
@pytest.mark.integration
def test_economy_indicators(params, headers):
"""Test the economy indicators."""
params = {p: v for p, v in params.items() if v}
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/indicators?{query_str}"
result = requests.get(url, headers=headers, timeout=20)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@parametrize(
"params",
[
({"provider": "econdb", "use_cache": False}),
],
)
@pytest.mark.integration
def test_economy_available_indicators(params, headers):
"""Test the economy available indicators."""
params = {p: v for p, v in params.items() if v}
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/available_indicators?{query_str}"
result = requests.get(url, headers=headers, timeout=5)
assert isinstance(result, requests.Response)
assert result.status_code == 200
@parametrize(
"params",
[
(
{
"provider": "econdb",
"country": "us,uk,jp",
"latest": True,
"use_cache": False,
}
),
],
)
@pytest.mark.integration
def test_economy_country_profile(params, headers):
"""Test the economy country profile."""
params = {p: v for p, v in params.items() if v}
query_str = get_querystring(params, [])
url = f"http://0.0.0.0:8000/api/v1/economy/country_profile?{query_str}"
result = requests.get(url, headers=headers, timeout=30)
assert isinstance(result, requests.Response)
assert result.status_code == 200

View File

@@ -510,3 +510,71 @@ def test_economy_fred_regional(params, obb):
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@parametrize(
"params",
[
(
{
"provider": "econdb",
"country": "us,uk,jp",
"latest": True,
"use_cache": False,
}
),
],
)
@pytest.mark.integration
def test_economy_country_profile(params, obb):
"""Test economy country profile."""
params = {p: v for p, v in params.items() if v}
result = obb.economy.country_profile(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@parametrize(
"params",
[
({"provider": "econdb", "use_cache": False}),
],
)
@pytest.mark.integration
def test_economy_available_indicators(params, obb):
"""Test economy available indicators."""
params = {p: v for p, v in params.items() if v}
result = obb.economy.available_indicators(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0
@parametrize(
"params",
[
(
{
"provider": "econdb",
"country": "us,uk,jp",
"symbol": "GDP,GDEBT",
"transform": None,
"start_date": "2022-01-01",
"end_date": "2024-01-01",
"use_cache": False,
}
),
],
)
@pytest.mark.integration
def test_economy_indicators(params, obb):
"""Test economy indicators."""
params = {p: v for p, v in params.items() if v}
result = obb.economy.indicators(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0

View File

@@ -306,3 +306,69 @@ async def fred_regional(
The series group ID is found by using `fred_search` and the `series_id` parameter.
"""
return await OBBject.from_query(Query(**locals()))
@router.command(
model="CountryProfile",
examples=[
APIEx(parameters={"provider": "econdb", "country": "united_kingdom"}),
APIEx(
description="Enter the country as the full name, or iso code."
+ " If `latest` is False, the complete history for each series is returned.",
parameters={
"country": "united_states,jp",
"latest": False,
"provider": "econdb",
},
),
],
)
async def country_profile(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject:
"""Get a profile of country statistics and economic indicators."""
return await OBBject.from_query(Query(**locals()))
@router.command(
model="AvailableIndicators",
examples=[
APIEx(parameters={"provider": "econdb"}),
],
)
async def available_indicators(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject:
"""Get the available economic indicators for a provider."""
return await OBBject.from_query(Query(**locals()))
@router.command(
model="EconomicIndicators",
examples=[
APIEx(parameters={"provider": "econdb", "symbol": "PCOCO"}),
APIEx(
description="Enter the country as the full name, or iso code."
+ " Use `available_indicators()` to get a list of supported indicators from EconDB.",
parameters={
"symbol": "CPI",
"country": "united_states,jp",
"provider": "econdb",
},
),
],
)
async def indicators(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject:
"""Get economic indicators by country and indicator."""
return await OBBject.from_query(Query(**locals()))

View File

@@ -20,6 +20,7 @@
],
"openbb_provider_extension": [
"benzinga@1.1.5",
"econdb@1.0.0",
"federal_reserve@1.1.5",
"fmp@1.1.5",
"fred@1.1.5",
@@ -1416,14 +1417,14 @@
},
{
"name": "min_value",
"type": "Union[float, int]",
"type": "Union[int, float]",
"description": "The inclusive minimum total value for the unusual activity.",
"default": null,
"optional": true
},
{
"name": "max_value",
"type": "Union[float, int]",
"type": "Union[int, float]",
"description": "The inclusive maximum total value for the unusual activity.",
"default": null,
"optional": true
@@ -3605,7 +3606,7 @@
},
{
"name": "value",
"type": "Union[float, int]",
"type": "Union[int, float]",
"description": "The obersvation value. The units are defined in the search results by series ID.",
"default": null,
"optional": true
@@ -3621,6 +3622,476 @@
},
"model": "FredRegional"
},
"/economy/country_profile": {
"deprecated": {
"flag": null,
"message": null
},
"description": "Get a profile of country statistics and economic indicators.",
"examples": "\nExamples\n--------\n\n```python\nfrom openbb import obb\nobb.economy.country_profile(provider='econdb', country='united_kingdom')\n# Enter the country as the full name, or iso code. If `latest` is False, the complete history for each series is returned.\nobb.economy.country_profile(country='united_states,jp', latest=False, provider='econdb')\n```\n\n",
"parameters": {
"standard": [
{
"name": "country",
"type": "Union[str, List[str]]",
"description": "The country to get data. Multiple items allowed for provider(s): econdb.",
"default": "",
"optional": false
},
{
"name": "provider",
"type": "Literal['econdb']",
"description": "The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'econdb' if there is no default.",
"default": "econdb",
"optional": true
}
],
"econdb": [
{
"name": "latest",
"type": "bool",
"description": "If True, return only the latest data. If False, return all available data for each indicator.",
"default": true,
"optional": true
},
{
"name": "use_cache",
"type": "bool",
"description": "If True, the request will be cached for one day.Using cache is recommended to avoid needlessly requesting the same data.",
"default": true,
"optional": true
}
]
},
"returns": {
"OBBject": [
{
"name": "results",
"type": "List[CountryProfile]",
"description": "Serializable results."
},
{
"name": "provider",
"type": "Optional[Literal['econdb']]",
"description": "Provider name."
},
{
"name": "warnings",
"type": "Optional[List[Warning_]]",
"description": "List of warnings."
},
{
"name": "chart",
"type": "Optional[Chart]",
"description": "Chart object."
},
{
"name": "extra",
"type": "Dict[str, Any]",
"description": "Extra info."
}
]
},
"data": {
"standard": [
{
"name": "country",
"type": "str",
"description": "",
"default": "",
"optional": false
},
{
"name": "population",
"type": "int",
"description": "Population.",
"default": null,
"optional": true
},
{
"name": "gdp_usd",
"type": "float",
"description": "Gross Domestic Product, in billions of USD.",
"default": null,
"optional": true
},
{
"name": "gdp_qoq",
"type": "float",
"description": "GDP growth quarter-over-quarter change, as a normalized percent.",
"default": null,
"optional": true
},
{
"name": "gdp_yoy",
"type": "float",
"description": "GDP growth year-over-year change, as a normalized percent.",
"default": null,
"optional": true
},
{
"name": "cpi_yoy",
"type": "float",
"description": "Consumer Price Index year-over-year change, as a normalized percent.",
"default": null,
"optional": true
},
{
"name": "core_yoy",
"type": "float",
"description": "Core Consumer Price Index year-over-year change, as a normalized percent.",
"default": null,
"optional": true
},
{
"name": "retail_sales_yoy",
"type": "float",
"description": "Retail Sales year-over-year change, as a normalized percent.",
"default": null,
"optional": true
},
{
"name": "industrial_production_yoy",
"type": "float",
"description": "Industrial Production year-over-year change, as a normalized percent.",
"default": null,
"optional": true
},
{
"name": "policy_rate",
"type": "float",
"description": "Short term policy rate, as a normalized percent.",
"default": null,
"optional": true
},
{
"name": "yield_10y",
"type": "float",
"description": "10-year government bond yield, as a normalized percent.",
"default": null,
"optional": true
},
{
"name": "govt_debt_gdp",
"type": "float",
"description": "Government debt as a percent (normalized) of GDP.",
"default": null,
"optional": true
},
{
"name": "current_account_gdp",
"type": "float",
"description": "Current account balance as a percent (normalized) of GDP.",
"default": null,
"optional": true
},
{
"name": "jobless_rate",
"type": "float",
"description": "Unemployment rate, as a normalized percent.",
"default": null,
"optional": true
}
],
"econdb": []
},
"model": "CountryProfile"
},
"/economy/available_indicators": {
"deprecated": {
"flag": null,
"message": null
},
"description": "Get the available economic indicators for a provider.",
"examples": "\nExamples\n--------\n\n```python\nfrom openbb import obb\nobb.economy.available_indicators(provider='econdb')\n```\n\n",
"parameters": {
"standard": [
{
"name": "provider",
"type": "Literal['econdb']",
"description": "The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'econdb' if there is no default.",
"default": "econdb",
"optional": true
}
],
"econdb": [
{
"name": "use_cache",
"type": "bool",
"description": "Whether to use cache or not, by default is True The cache of indicator symbols will persist for one week.",
"default": true,
"optional": true
}
]
},
"returns": {
"OBBject": [
{
"name": "results",
"type": "List[AvailableIndicators]",
"description": "Serializable results."
},
{
"name": "provider",
"type": "Optional[Literal['econdb']]",
"description": "Provider name."
},
{
"name": "warnings",
"type": "Optional[List[Warning_]]",
"description": "List of warnings."
},
{
"name": "chart",
"type": "Optional[Chart]",
"description": "Chart object."
},
{
"name": "extra",
"type": "Dict[str, Any]",
"description": "Extra info."
}
]
},
"data": {
"standard": [
{
"name": "symbol_root",
"type": "str",
"description": "The root symbol representing the indicator.",
"default": null,
"optional": true
},
{
"name": "symbol",
"type": "str",
"description": "Symbol representing the entity requested in the data. The root symbol with additional codes.",
"default": null,
"optional": true
},
{
"name": "country",
"type": "str",
"description": "The name of the country, region, or entity represented by the symbol.",
"default": null,
"optional": true
},
{
"name": "iso",
"type": "str",
"description": "The ISO code of the country, region, or entity represented by the symbol.",
"default": null,
"optional": true
},
{
"name": "description",
"type": "str",
"description": "The description of the indicator.",
"default": null,
"optional": true
},
{
"name": "frequency",
"type": "str",
"description": "The frequency of the indicator data.",
"default": null,
"optional": true
}
],
"econdb": [
{
"name": "currency",
"type": "str",
"description": "The currency, or unit, the data is based in.",
"default": null,
"optional": true
},
{
"name": "scale",
"type": "str",
"description": "The scale of the data.",
"default": null,
"optional": true
},
{
"name": "multiplier",
"type": "int",
"description": "The multiplier of the data to arrive at whole units.",
"default": "",
"optional": false
},
{
"name": "transformation",
"type": "str",
"description": "Transformation type.",
"default": "",
"optional": false
},
{
"name": "source",
"type": "str",
"description": "The original source of the data.",
"default": null,
"optional": true
},
{
"name": "first_date",
"type": "date",
"description": "The first date of the data.",
"default": null,
"optional": true
},
{
"name": "last_date",
"type": "date",
"description": "The last date of the data.",
"default": null,
"optional": true
},
{
"name": "last_insert_timestamp",
"type": "datetime",
"description": "The time of the last update. Data is typically reported with a lag.",
"default": null,
"optional": true
}
]
},
"model": "AvailableIndicators"
},
"/economy/indicators": {
"deprecated": {
"flag": null,
"message": null
},
"description": "Get economic indicators by country and indicator.",
"examples": "\nExamples\n--------\n\n```python\nfrom openbb import obb\nobb.economy.indicators(provider='econdb', symbol='PCOCO')\n# Enter the country as the full name, or iso code. Use `available_indicators()` to get a list of supported indicators from EconDB.\nobb.economy.indicators(symbol='CPI', country='united_states,jp', provider='econdb')\n```\n\n",
"parameters": {
"standard": [
{
"name": "symbol",
"type": "Union[str, List[str]]",
"description": "Symbol to get data for. The base symbol for the indicator (e.g. GDP, CPI, etc.). Multiple items allowed for provider(s): econdb.",
"default": "",
"optional": false
},
{
"name": "country",
"type": "Union[str, List[str]]",
"description": "The country to get data. The country represented by the indicator, if available. Multiple items allowed for provider(s): econdb.",
"default": null,
"optional": true
},
{
"name": "start_date",
"type": "Union[date, str]",
"description": "Start date of the data, in YYYY-MM-DD format.",
"default": null,
"optional": true
},
{
"name": "end_date",
"type": "Union[date, str]",
"description": "End date of the data, in YYYY-MM-DD format.",
"default": null,
"optional": true
},
{
"name": "provider",
"type": "Literal['econdb']",
"description": "The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'econdb' if there is no default.",
"default": "econdb",
"optional": true
}
],
"econdb": [
{
"name": "transform",
"type": "Literal['toya', 'tpop', 'tusd', 'tpgp']",
"description": "The transformation to apply to the data, default is None. tpop: Change from previous period toya: Change from one year ago tusd: Values as US dollars tpgp: Values as a percent of GDP Only 'tpop' and 'toya' are applicable to all indicators. Applying transformations across multiple indicators/countries may produce unexpected results. This is because not all indicators are compatible with all transformations, and the original units and scale differ between entities. `tusd` should only be used where values are currencies.",
"default": null,
"optional": true
},
{
"name": "use_cache",
"type": "bool",
"description": "If True, the request will be cached for one day.Using cache is recommended to avoid needlessly requesting the same data.",
"default": true,
"optional": true
}
]
},
"returns": {
"OBBject": [
{
"name": "results",
"type": "List[EconomicIndicators]",
"description": "Serializable results."
},
{
"name": "provider",
"type": "Optional[Literal['econdb']]",
"description": "Provider name."
},
{
"name": "warnings",
"type": "Optional[List[Warning_]]",
"description": "List of warnings."
},
{
"name": "chart",
"type": "Optional[Chart]",
"description": "Chart object."
},
{
"name": "extra",
"type": "Dict[str, Any]",
"description": "Extra info."
}
]
},
"data": {
"standard": [
{
"name": "date",
"type": "date",
"description": "The date of the data.",
"default": "",
"optional": false
},
{
"name": "symbol_root",
"type": "str",
"description": "The root symbol for the indicator (e.g. GDP).",
"default": null,
"optional": true
},
{
"name": "symbol",
"type": "str",
"description": "Symbol representing the entity requested in the data.",
"default": null,
"optional": true
},
{
"name": "country",
"type": "str",
"description": "The country represented by the data.",
"default": null,
"optional": true
},
{
"name": "value",
"type": "Union[int, float]",
"description": "",
"default": null,
"optional": true
}
],
"econdb": []
},
"model": "EconomicIndicators"
},
"/equity/calendar/ipo": {
"deprecated": {
"flag": null,
@@ -16864,7 +17335,7 @@
},
{
"name": "underlying_shares",
"type": "Union[float, int]",
"type": "Union[int, float]",
"description": "Number of underlying shares related to this derivative transaction.",
"default": null,
"optional": true
@@ -17528,14 +17999,14 @@
},
{
"name": "volume",
"type": "Union[float, int]",
"type": "Union[int, float]",
"description": "The trading volume.",
"default": null,
"optional": true
},
{
"name": "exchange_volume",
"type": "Union[float, int]",
"type": "Union[int, float]",
"description": "Volume of shares exchanged during the trading day on the specific exchange.",
"default": null,
"optional": true
@@ -18114,7 +18585,7 @@
},
{
"name": "volume",
"type": "Union[float, int]",
"type": "Union[int, float]",
"description": "The trading volume.",
"default": null,
"optional": true
@@ -20442,7 +20913,7 @@
},
{
"name": "volume",
"type": "Union[float, int]",
"type": "Union[int, float]",
"description": "The trading volume.",
"default": null,
"optional": true
@@ -22650,7 +23121,7 @@
},
{
"name": "balance",
"type": "Union[float, int]",
"type": "Union[int, float]",
"description": "The number of units of the security held, if available.",
"default": null,
"optional": true
@@ -23566,7 +24037,7 @@
},
{
"name": "market_value",
"type": "Union[float, int]",
"type": "Union[int, float]",
"description": "The market value of the equity position in the ETF.",
"default": null,
"optional": true

View File

@@ -33,6 +33,7 @@ Extensions:
- regulators@1.1.5
- benzinga@1.1.5
- econdb@1.0.0
- federal_reserve@1.1.5
- fmp@1.1.5
- fred@1.1.5

View File

@@ -13,13 +13,16 @@ from typing_extensions import Annotated
class ROUTER_economy(Container):
"""/economy
available_indicators
calendar
composite_leading_indicator
country_profile
cpi
fred_regional
fred_search
fred_series
/gdp
indicators
long_term_interest_rate
money_measures
risk_premium
@@ -30,6 +33,95 @@ class ROUTER_economy(Container):
def __repr__(self) -> str:
return self.__doc__ or ""
@exception_handler
@validate
def available_indicators(
self,
provider: Annotated[
Optional[Literal["econdb"]],
OpenBBField(
description="The provider to use for the query, by default None.\n If None, the provider specified in defaults is selected or 'econdb' if there is\n no default."
),
] = None,
**kwargs
) -> OBBject:
"""Get the available economic indicators for a provider.
Parameters
----------
provider : Optional[Literal['econdb']]
The provider to use for the query, by default None.
If None, the provider specified in defaults is selected or 'econdb' if there is
no default.
use_cache : bool
Whether to use cache or not, by default is True The cache of indicator symbols will persist for one week. (provider: econdb)
Returns
-------
OBBject
results : List[AvailableIndicators]
Serializable results.
provider : Optional[Literal['econdb']]
Provider name.
warnings : Optional[List[Warning_]]
List of warnings.
chart : Optional[Chart]
Chart object.
extra : Dict[str, Any]
Extra info.
AvailableIndicators
-------------------
symbol_root : Optional[str]
The root symbol representing the indicator.
symbol : Optional[str]
Symbol representing the entity requested in the data. The root symbol with additional codes.
country : Optional[str]
The name of the country, region, or entity represented by the symbol.
iso : Optional[str]
The ISO code of the country, region, or entity represented by the symbol.
description : Optional[str]
The description of the indicator.
frequency : Optional[str]
The frequency of the indicator data.
currency : Optional[str]
The currency, or unit, the data is based in. (provider: econdb)
scale : Optional[str]
The scale of the data. (provider: econdb)
multiplier : Optional[int]
The multiplier of the data to arrive at whole units. (provider: econdb)
transformation : Optional[str]
Transformation type. (provider: econdb)
source : Optional[str]
The original source of the data. (provider: econdb)
first_date : Optional[date]
The first date of the data. (provider: econdb)
last_date : Optional[date]
The last date of the data. (provider: econdb)
last_insert_timestamp : Optional[datetime]
The time of the last update. Data is typically reported with a lag. (provider: econdb)
Examples
--------
>>> from openbb import obb
>>> obb.economy.available_indicators(provider='econdb')
""" # noqa: E501
return self._run(
"/economy/available_indicators",
**filter_inputs(
provider_choices={
"provider": self._get_provider(
provider,
"/economy/available_indicators",
("econdb",),
)
},
standard_params={},
extra_params=kwargs,
)
)
@exception_handler
@validate
def calendar(
@@ -238,6 +330,110 @@ class ROUTER_economy(Container):
)
)
@exception_handler
@validate
def country_profile(
self,
country: Annotated[
Union[str, List[str]],
OpenBBField(
description="The country to get data. Multiple comma separated items allowed for provider(s): econdb."
),
],
provider: Annotated[
Optional[Literal["econdb"]],
OpenBBField(
description="The provider to use for the query, by default None.\n If None, the provider specified in defaults is selected or 'econdb' if there is\n no default."
),
] = None,
**kwargs
) -> OBBject:
"""Get a profile of country statistics and economic indicators.
Parameters
----------
country : Union[str, List[str]]
The country to get data. Multiple comma separated items allowed for provider(s): econdb.
provider : Optional[Literal['econdb']]
The provider to use for the query, by default None.
If None, the provider specified in defaults is selected or 'econdb' if there is
no default.
latest : bool
If True, return only the latest data. If False, return all available data for each indicator. (provider: econdb)
use_cache : bool
If True, the request will be cached for one day.Using cache is recommended to avoid needlessly requesting the same data. (provider: econdb)
Returns
-------
OBBject
results : List[CountryProfile]
Serializable results.
provider : Optional[Literal['econdb']]
Provider name.
warnings : Optional[List[Warning_]]
List of warnings.
chart : Optional[Chart]
Chart object.
extra : Dict[str, Any]
Extra info.
CountryProfile
--------------
country : str
population : Optional[int]
Population.
gdp_usd : Optional[float]
Gross Domestic Product, in billions of USD.
gdp_qoq : Optional[float]
GDP growth quarter-over-quarter change, as a normalized percent.
gdp_yoy : Optional[float]
GDP growth year-over-year change, as a normalized percent.
cpi_yoy : Optional[float]
Consumer Price Index year-over-year change, as a normalized percent.
core_yoy : Optional[float]
Core Consumer Price Index year-over-year change, as a normalized percent.
retail_sales_yoy : Optional[float]
Retail Sales year-over-year change, as a normalized percent.
industrial_production_yoy : Optional[float]
Industrial Production year-over-year change, as a normalized percent.
policy_rate : Optional[float]
Short term policy rate, as a normalized percent.
yield_10y : Optional[float]
10-year government bond yield, as a normalized percent.
govt_debt_gdp : Optional[float]
Government debt as a percent (normalized) of GDP.
current_account_gdp : Optional[float]
Current account balance as a percent (normalized) of GDP.
jobless_rate : Optional[float]
Unemployment rate, as a normalized percent.
Examples
--------
>>> from openbb import obb
>>> obb.economy.country_profile(provider='econdb', country='united_kingdom')
>>> # Enter the country as the full name, or iso code. If `latest` is False, the complete history for each series is returned.
>>> obb.economy.country_profile(country='united_states,jp', latest=False, provider='econdb')
""" # noqa: E501
return self._run(
"/economy/country_profile",
**filter_inputs(
provider_choices={
"provider": self._get_provider(
provider,
"/economy/country_profile",
("econdb",),
)
},
standard_params={
"country": country,
},
extra_params=kwargs,
info={"country": {"multiple_items_allowed": ["econdb"]}},
)
)
@exception_handler
@validate
def cpi(
@@ -528,7 +724,7 @@ class ROUTER_economy(Container):
The name of the region. (provider: fred)
code : Optional[Union[int, str]]
The code of the region. (provider: fred)
value : Optional[Union[float, int]]
value : Optional[Union[int, float]]
The obersvation value. The units are defined in the search results by series ID. (provider: fred)
series_id : Optional[str]
The individual series ID for the region. (provider: fred)
@@ -839,6 +1035,127 @@ class ROUTER_economy(Container):
return economy_gdp.ROUTER_economy_gdp(command_runner=self._command_runner)
@exception_handler
@validate
def indicators(
self,
symbol: Annotated[
Union[str, List[str]],
OpenBBField(
description="Symbol to get data for. The base symbol for the indicator (e.g. GDP, CPI, etc.). Multiple comma separated items allowed for provider(s): econdb."
),
],
country: Annotated[
Union[str, None, List[Optional[str]]],
OpenBBField(
description="The country to get data. The country represented by the indicator, if available. Multiple comma separated items allowed for provider(s): econdb."
),
] = None,
start_date: Annotated[
Union[datetime.date, None, str],
OpenBBField(description="Start date of the data, in YYYY-MM-DD format."),
] = None,
end_date: Annotated[
Union[datetime.date, None, str],
OpenBBField(description="End date of the data, in YYYY-MM-DD format."),
] = None,
provider: Annotated[
Optional[Literal["econdb"]],
OpenBBField(
description="The provider to use for the query, by default None.\n If None, the provider specified in defaults is selected or 'econdb' if there is\n no default."
),
] = None,
**kwargs
) -> OBBject:
"""Get economic indicators by country and indicator.
Parameters
----------
symbol : Union[str, List[str]]
Symbol to get data for. The base symbol for the indicator (e.g. GDP, CPI, etc.). Multiple comma separated items allowed for provider(s): econdb.
country : Union[str, None, List[Optional[str]]]
The country to get data. The country represented by the indicator, if available. Multiple comma separated items allowed for provider(s): econdb.
start_date : Union[datetime.date, None, str]
Start date of the data, in YYYY-MM-DD format.
end_date : Union[datetime.date, None, str]
End date of the data, in YYYY-MM-DD format.
provider : Optional[Literal['econdb']]
The provider to use for the query, by default None.
If None, the provider specified in defaults is selected or 'econdb' if there is
no default.
transform : Literal['toya', 'tpop', 'tusd', 'tpgp']
The transformation to apply to the data, default is None.
tpop: Change from previous period
toya: Change from one year ago
tusd: Values as US dollars
tpgp: Values as a percent of GDP
Only 'tpop' and 'toya' are applicable to all indicators. Applying transformations across multiple indicators/countries may produce unexpected results.
This is because not all indicators are compatible with all transformations, and the original units and scale differ between entities.
`tusd` should only be used where values are currencies. (provider: econdb)
use_cache : bool
If True, the request will be cached for one day.Using cache is recommended to avoid needlessly requesting the same data. (provider: econdb)
Returns
-------
OBBject
results : List[EconomicIndicators]
Serializable results.
provider : Optional[Literal['econdb']]
Provider name.
warnings : Optional[List[Warning_]]
List of warnings.
chart : Optional[Chart]
Chart object.
extra : Dict[str, Any]
Extra info.
EconomicIndicators
------------------
date : date
The date of the data.
symbol_root : Optional[str]
The root symbol for the indicator (e.g. GDP).
symbol : Optional[str]
Symbol representing the entity requested in the data.
country : Optional[str]
The country represented by the data.
value : Optional[Union[int, float]]
Examples
--------
>>> from openbb import obb
>>> obb.economy.indicators(provider='econdb', symbol='PCOCO')
>>> # Enter the country as the full name, or iso code. Use `available_indicators()` to get a list of supported indicators from EconDB.
>>> obb.economy.indicators(symbol='CPI', country='united_states,jp', provider='econdb')
""" # noqa: E501
return self._run(
"/economy/indicators",
**filter_inputs(
provider_choices={
"provider": self._get_provider(
provider,
"/economy/indicators",
("econdb",),
)
},
standard_params={
"symbol": symbol,
"country": country,
"start_date": start_date,
"end_date": end_date,
},
extra_params=kwargs,
info={
"symbol": {"multiple_items_allowed": ["econdb"]},
"country": {"multiple_items_allowed": ["econdb"]},
},
)
)
@exception_handler
@validate
def long_term_interest_rate(

807
openbb_platform/poetry.lock generated vendored
View File

@@ -2,87 +2,87 @@
[[package]]
name = "aiohttp"
version = "3.9.3"
version = "3.9.4"
description = "Async http client/server framework (asyncio)"
optional = false
python-versions = ">=3.8"
files = [
{file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"},
{file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"},
{file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"},
{file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"},
{file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"},
{file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"},
{file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"},
{file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"},
{file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"},
{file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"},
{file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"},
{file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"},
{file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"},
{file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"},
{file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"},
{file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"},
{file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"},
{file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"},
{file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"},
{file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"},
{file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"},
{file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"},
{file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"},
{file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"},
{file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"},
{file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"},
{file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"},
{file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"},
{file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"},
{file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"},
{file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"},
{file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"},
{file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"},
{file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"},
{file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"},
{file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"},
{file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"},
{file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"},
{file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"},
{file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"},
{file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"},
{file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"},
{file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"},
{file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"},
{file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"},
{file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"},
{file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"},
{file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"},
{file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"},
{file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"},
{file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"},
{file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"},
{file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"},
{file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"},
{file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"},
{file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"},
{file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"},
{file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"},
{file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"},
{file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"},
{file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"},
{file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"},
{file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"},
{file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"},
{file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"},
{file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"},
{file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"},
{file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"},
{file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"},
{file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"},
{file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"},
{file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"},
{file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"},
{file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"},
{file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"},
{file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"},
{file = "aiohttp-3.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:76d32588ef7e4a3f3adff1956a0ba96faabbdee58f2407c122dd45aa6e34f372"},
{file = "aiohttp-3.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:56181093c10dbc6ceb8a29dfeea1e815e1dfdc020169203d87fd8d37616f73f9"},
{file = "aiohttp-3.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7a5b676d3c65e88b3aca41816bf72831898fcd73f0cbb2680e9d88e819d1e4d"},
{file = "aiohttp-3.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1df528a85fb404899d4207a8d9934cfd6be626e30e5d3a5544a83dbae6d8a7e"},
{file = "aiohttp-3.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f595db1bceabd71c82e92df212dd9525a8a2c6947d39e3c994c4f27d2fe15b11"},
{file = "aiohttp-3.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c0b09d76e5a4caac3d27752027fbd43dc987b95f3748fad2b924a03fe8632ad"},
{file = "aiohttp-3.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:689eb4356649ec9535b3686200b231876fb4cab4aca54e3bece71d37f50c1d13"},
{file = "aiohttp-3.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3666cf4182efdb44d73602379a66f5fdfd5da0db5e4520f0ac0dcca644a3497"},
{file = "aiohttp-3.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b65b0f8747b013570eea2f75726046fa54fa8e0c5db60f3b98dd5d161052004a"},
{file = "aiohttp-3.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1885d2470955f70dfdd33a02e1749613c5a9c5ab855f6db38e0b9389453dce7"},
{file = "aiohttp-3.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0593822dcdb9483d41f12041ff7c90d4d1033ec0e880bcfaf102919b715f47f1"},
{file = "aiohttp-3.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:47f6eb74e1ecb5e19a78f4a4228aa24df7fbab3b62d4a625d3f41194a08bd54f"},
{file = "aiohttp-3.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c8b04a3dbd54de6ccb7604242fe3ad67f2f3ca558f2d33fe19d4b08d90701a89"},
{file = "aiohttp-3.9.4-cp310-cp310-win32.whl", hash = "sha256:8a78dfb198a328bfb38e4308ca8167028920fb747ddcf086ce706fbdd23b2926"},
{file = "aiohttp-3.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:e78da6b55275987cbc89141a1d8e75f5070e577c482dd48bd9123a76a96f0bbb"},
{file = "aiohttp-3.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c111b3c69060d2bafc446917534150fd049e7aedd6cbf21ba526a5a97b4402a5"},
{file = "aiohttp-3.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:efbdd51872cf170093998c87ccdf3cb5993add3559341a8e5708bcb311934c94"},
{file = "aiohttp-3.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7bfdb41dc6e85d8535b00d73947548a748e9534e8e4fddd2638109ff3fb081df"},
{file = "aiohttp-3.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd9d334412961125e9f68d5b73c1d0ab9ea3f74a58a475e6b119f5293eee7ba"},
{file = "aiohttp-3.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:35d78076736f4a668d57ade00c65d30a8ce28719d8a42471b2a06ccd1a2e3063"},
{file = "aiohttp-3.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:824dff4f9f4d0f59d0fa3577932ee9a20e09edec8a2f813e1d6b9f89ced8293f"},
{file = "aiohttp-3.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52b8b4e06fc15519019e128abedaeb56412b106ab88b3c452188ca47a25c4093"},
{file = "aiohttp-3.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eae569fb1e7559d4f3919965617bb39f9e753967fae55ce13454bec2d1c54f09"},
{file = "aiohttp-3.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:69b97aa5792428f321f72aeb2f118e56893371f27e0b7d05750bcad06fc42ca1"},
{file = "aiohttp-3.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4d79aad0ad4b980663316f26d9a492e8fab2af77c69c0f33780a56843ad2f89e"},
{file = "aiohttp-3.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:d6577140cd7db19e430661e4b2653680194ea8c22c994bc65b7a19d8ec834403"},
{file = "aiohttp-3.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:9860d455847cd98eb67897f5957b7cd69fbcb436dd3f06099230f16a66e66f79"},
{file = "aiohttp-3.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:69ff36d3f8f5652994e08bd22f093e11cfd0444cea310f92e01b45a4e46b624e"},
{file = "aiohttp-3.9.4-cp311-cp311-win32.whl", hash = "sha256:e27d3b5ed2c2013bce66ad67ee57cbf614288bda8cdf426c8d8fe548316f1b5f"},
{file = "aiohttp-3.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d6a67e26daa686a6fbdb600a9af8619c80a332556245fa8e86c747d226ab1a1e"},
{file = "aiohttp-3.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c5ff8ff44825736a4065d8544b43b43ee4c6dd1530f3a08e6c0578a813b0aa35"},
{file = "aiohttp-3.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d12a244627eba4e9dc52cbf924edef905ddd6cafc6513849b4876076a6f38b0e"},
{file = "aiohttp-3.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dcad56c8d8348e7e468899d2fb3b309b9bc59d94e6db08710555f7436156097f"},
{file = "aiohttp-3.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f7e69a7fd4b5ce419238388e55abd220336bd32212c673ceabc57ccf3d05b55"},
{file = "aiohttp-3.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4870cb049f10d7680c239b55428916d84158798eb8f353e74fa2c98980dcc0b"},
{file = "aiohttp-3.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b2feaf1b7031ede1bc0880cec4b0776fd347259a723d625357bb4b82f62687b"},
{file = "aiohttp-3.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:939393e8c3f0a5bcd33ef7ace67680c318dc2ae406f15e381c0054dd658397de"},
{file = "aiohttp-3.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d2334e387b2adcc944680bebcf412743f2caf4eeebd550f67249c1c3696be04"},
{file = "aiohttp-3.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e0198ea897680e480845ec0ffc5a14e8b694e25b3f104f63676d55bf76a82f1a"},
{file = "aiohttp-3.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e40d2cd22914d67c84824045861a5bb0fb46586b15dfe4f046c7495bf08306b2"},
{file = "aiohttp-3.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:aba80e77c227f4234aa34a5ff2b6ff30c5d6a827a91d22ff6b999de9175d71bd"},
{file = "aiohttp-3.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:fb68dc73bc8ac322d2e392a59a9e396c4f35cb6fdbdd749e139d1d6c985f2527"},
{file = "aiohttp-3.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f3460a92638dce7e47062cf088d6e7663adb135e936cb117be88d5e6c48c9d53"},
{file = "aiohttp-3.9.4-cp312-cp312-win32.whl", hash = "sha256:32dc814ddbb254f6170bca198fe307920f6c1308a5492f049f7f63554b88ef36"},
{file = "aiohttp-3.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:63f41a909d182d2b78fe3abef557fcc14da50c7852f70ae3be60e83ff64edba5"},
{file = "aiohttp-3.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c3770365675f6be220032f6609a8fbad994d6dcf3ef7dbcf295c7ee70884c9af"},
{file = "aiohttp-3.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:305edae1dea368ce09bcb858cf5a63a064f3bff4767dec6fa60a0cc0e805a1d3"},
{file = "aiohttp-3.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6f121900131d116e4a93b55ab0d12ad72573f967b100e49086e496a9b24523ea"},
{file = "aiohttp-3.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b71e614c1ae35c3d62a293b19eface83d5e4d194e3eb2fabb10059d33e6e8cbf"},
{file = "aiohttp-3.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:419f009fa4cfde4d16a7fc070d64f36d70a8d35a90d71aa27670bba2be4fd039"},
{file = "aiohttp-3.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b39476ee69cfe64061fd77a73bf692c40021f8547cda617a3466530ef63f947"},
{file = "aiohttp-3.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b33f34c9c7decdb2ab99c74be6443942b730b56d9c5ee48fb7df2c86492f293c"},
{file = "aiohttp-3.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c78700130ce2dcebb1a8103202ae795be2fa8c9351d0dd22338fe3dac74847d9"},
{file = "aiohttp-3.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:268ba22d917655d1259af2d5659072b7dc11b4e1dc2cb9662fdd867d75afc6a4"},
{file = "aiohttp-3.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:17e7c051f53a0d2ebf33013a9cbf020bb4e098c4bc5bce6f7b0c962108d97eab"},
{file = "aiohttp-3.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:7be99f4abb008cb38e144f85f515598f4c2c8932bf11b65add0ff59c9c876d99"},
{file = "aiohttp-3.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:d58a54d6ff08d2547656356eea8572b224e6f9bbc0cf55fa9966bcaac4ddfb10"},
{file = "aiohttp-3.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7673a76772bda15d0d10d1aa881b7911d0580c980dbd16e59d7ba1422b2d83cd"},
{file = "aiohttp-3.9.4-cp38-cp38-win32.whl", hash = "sha256:e4370dda04dc8951012f30e1ce7956a0a226ac0714a7b6c389fb2f43f22a250e"},
{file = "aiohttp-3.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:eb30c4510a691bb87081192a394fb661860e75ca3896c01c6d186febe7c88530"},
{file = "aiohttp-3.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:84e90494db7df3be5e056f91412f9fa9e611fbe8ce4aaef70647297f5943b276"},
{file = "aiohttp-3.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7d4845f8501ab28ebfdbeab980a50a273b415cf69e96e4e674d43d86a464df9d"},
{file = "aiohttp-3.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:69046cd9a2a17245c4ce3c1f1a4ff8c70c7701ef222fce3d1d8435f09042bba1"},
{file = "aiohttp-3.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b73a06bafc8dcc508420db43b4dd5850e41e69de99009d0351c4f3007960019"},
{file = "aiohttp-3.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:418bb0038dfafeac923823c2e63226179976c76f981a2aaad0ad5d51f2229bca"},
{file = "aiohttp-3.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:71a8f241456b6c2668374d5d28398f8e8cdae4cce568aaea54e0f39359cd928d"},
{file = "aiohttp-3.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:935c369bf8acc2dc26f6eeb5222768aa7c62917c3554f7215f2ead7386b33748"},
{file = "aiohttp-3.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74e4e48c8752d14ecfb36d2ebb3d76d614320570e14de0a3aa7a726ff150a03c"},
{file = "aiohttp-3.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:916b0417aeddf2c8c61291238ce25286f391a6acb6f28005dd9ce282bd6311b6"},
{file = "aiohttp-3.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9b6787b6d0b3518b2ee4cbeadd24a507756ee703adbac1ab6dc7c4434b8c572a"},
{file = "aiohttp-3.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:221204dbda5ef350e8db6287937621cf75e85778b296c9c52260b522231940ed"},
{file = "aiohttp-3.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:10afd99b8251022ddf81eaed1d90f5a988e349ee7d779eb429fb07b670751e8c"},
{file = "aiohttp-3.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2506d9f7a9b91033201be9ffe7d89c6a54150b0578803cce5cb84a943d075bc3"},
{file = "aiohttp-3.9.4-cp39-cp39-win32.whl", hash = "sha256:e571fdd9efd65e86c6af2f332e0e95dad259bfe6beb5d15b3c3eca3a6eb5d87b"},
{file = "aiohttp-3.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:7d29dd5319d20aa3b7749719ac9685fbd926f71ac8c77b2477272725f882072d"},
{file = "aiohttp-3.9.4.tar.gz", hash = "sha256:6ff71ede6d9a5a58cfb7b6fffc83ab5d4a63138276c771ac91ceaaddf5459644"},
]
[package.dependencies]
@@ -608,13 +608,13 @@ files = [
[[package]]
name = "ecdsa"
version = "0.18.0"
version = "0.19.0"
description = "ECDSA cryptographic signature library (pure python)"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.6"
files = [
{file = "ecdsa-0.18.0-py2.py3-none-any.whl", hash = "sha256:80600258e7ed2f16b9aa1d7c295bd70194109ad5a30fdee0eaeefef1d4c559dd"},
{file = "ecdsa-0.18.0.tar.gz", hash = "sha256:190348041559e21b22a1d65cee485282ca11a6f81d503fddb84d5017e9ed1e49"},
{file = "ecdsa-0.19.0-py2.py3-none-any.whl", hash = "sha256:2cea9b88407fdac7bbeca0833b189e4c9c53f2ef1e1eaa29f6224dbc809b707a"},
{file = "ecdsa-0.19.0.tar.gz", hash = "sha256:60eaad1199659900dd0af521ed462b793bbdf867432b3948e87416ae4caf6bf8"},
]
[package.dependencies]
@@ -754,47 +754,47 @@ python-dateutil = ">=2.7"
[[package]]
name = "frozendict"
version = "2.4.1"
version = "2.4.2"
description = "A simple immutable dictionary"
optional = false
python-versions = ">=3.6"
files = [
{file = "frozendict-2.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:992cc157b6cdf788c1f24ab9531ba37104aba2d21f1520949a03bf3f9af7935e"},
{file = "frozendict-2.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a571fbbe8c0cb0d0d31dce24b1026301013d3884b2fc3099741ba7a9bd5764df"},
{file = "frozendict-2.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c113eb12f0713b53f6d0bbf3bced19dd429e17cac1cf3c350bf05c82c573613d"},
{file = "frozendict-2.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53eb5d19ff5b71d3f7806620000e80c1d2478a22c481799ea7b16fb218d42923"},
{file = "frozendict-2.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5b64b5c6ac3542a4028a431c01d39c60bfb809316cdd8c940d252d084437787f"},
{file = "frozendict-2.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:107a9953272410cd05fcfba4dcf31f01825cd6b3c17f3cf616072e9611480034"},
{file = "frozendict-2.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:42b3906ac43cf2c77f1e69fe7bdd93347044d1a0bc15bf5b733d47c39bfe2e3a"},
{file = "frozendict-2.4.1-cp310-cp310-win_arm64.whl", hash = "sha256:ace99e4430802bb3d52969870a9432d68919cd33af18f9086ccd6a3a46ac6e7c"},
{file = "frozendict-2.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:971017c706db1b76abdd7db285592d9f232aff6e8f47dffbd1cd0a020873b164"},
{file = "frozendict-2.4.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dfeca22e383d64d92301378ca5d10265d7ef05d989501ea5f37520052a0c9fd"},
{file = "frozendict-2.4.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ccf4943a5276a99ff98000890fcbc76fcbc5f43f51250270ddab65da0ee61883"},
{file = "frozendict-2.4.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:2f7b202617b410f9b8d528ce82cdb4b16a7e80ccd58601d0d1d8e15231e49292"},
{file = "frozendict-2.4.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:4e8477396a166f5b8cfaaebd623ff05b7bacca830afa8e8d377ad3ed951a8bb2"},
{file = "frozendict-2.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:4d2d2987b280fae3b46a77cbc3d51394b671c8d8b7270ab2e6d767a42dac15b1"},
{file = "frozendict-2.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:eebe6b4c054f987d83477f797f24a149ed409e8dc1c11c1fedc98d721f6ea905"},
{file = "frozendict-2.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7cc4f1be80760080ca9ee83977c43ad202db91d0ee1e46e9f7c44ebcc05a3b81"},
{file = "frozendict-2.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f0172c1c3a52714b6530ec56621a6be2962776fa1a4638c4e40576b32e33355"},
{file = "frozendict-2.4.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4fc7b05120500e13a2f319ba4cbfba7f832c04441348ca20dbdcf776b5d2332f"},
{file = "frozendict-2.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d8312598598c9e79653da50c49315fc89d017dbaa4406160958c64d85a707edd"},
{file = "frozendict-2.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2fa000d16b1af7315b8d9fbc15e6929303e1c447a9f06c10bfef62b7c9ea266f"},
{file = "frozendict-2.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:accdebc212ef31e0de5b54fbeb275f79c5380e02b250b3d1c4341f6ccf73e876"},
{file = "frozendict-2.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:81ffbac40077c6f56355d47e18adb36e11816ae114ca9d9ee90b842b907d92f5"},
{file = "frozendict-2.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d6b51d2a726ecb169765261bd7e73f63669cf849e882d94d382d8ff682f0292"},
{file = "frozendict-2.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9030e487d0d433aeaf2d7f741a47d9b890e2572951588f80f29d0161cfd5553a"},
{file = "frozendict-2.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:42077b882ed0e117e1b7f9c7b00453aecddbe268a80f5ca1a73c163c79025dbb"},
{file = "frozendict-2.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0187974c3cfc0ac77dc20f9af272f69c8436d2e994dfce85eb7cca269f4d0b7a"},
{file = "frozendict-2.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:1b01ebe8772ab30ab593e72dfe3f06e5d97db508bfd72613c243fd08f5ba96e4"},
{file = "frozendict-2.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b06df1995b14fca1e9acc53b1423a4c2dca072517acd619c1576fc6b352428ec"},
{file = "frozendict-2.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d1b02f873866f5d245a4bc4f9f2647aacb0d5f9a4d47e1de52c46cf03368c8cc"},
{file = "frozendict-2.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5619bd7f092b1f7ab69163ddcdff674e6786b7a19aea1217a6a46b942430631"},
{file = "frozendict-2.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee12840600814adf4fb1fb84eafb8098bf1701d536949ead096158e3b11cf6f8"},
{file = "frozendict-2.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:884a3cbaff8cfd1b36f07a8749b48a6cfebd7fca196e13b9664d33df38b38d27"},
{file = "frozendict-2.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7bd5b958264646ca0c5589a4c82ec4be2bf7ff0d4d1202b9d9599f24be4d51c7"},
{file = "frozendict-2.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:de9f7194f4edbacdc609c66f49f583a658ec130e0f68e482fccae35d1befddaf"},
{file = "frozendict-2.4.1-cp39-cp39-win_arm64.whl", hash = "sha256:1ed0f607c73e6482e8a8080ea22d9d9f057f0624225e04e7e3e16a94ec215827"},
{file = "frozendict-2.4.1.tar.gz", hash = "sha256:1b32eb2f30bb734b7a699ee7003c86f81964f1c3b6e0e0f18efcbbdeb5b220bf"},
{file = "frozendict-2.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:19743495b1e92a7e4db56fcd6a5d36ea1d1b0f550822d6fd780e44d58f0b8c18"},
{file = "frozendict-2.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81efb4ea854a1c93d954a67389eaf78c508acb2d4768321a835cda2754ec5c01"},
{file = "frozendict-2.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5f1a4d9662b854dce52b560b60f51349905dc871826b8c6be20141a13067a53"},
{file = "frozendict-2.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1412aeb325e4a28cfe32106c66c046372bb7fd5a9af1748193549c5d01a9e9c1"},
{file = "frozendict-2.4.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f7ce0535f02eba9746e4e2cf0abef0f0f2051d20fdccf4af31bc3d1adecf5a71"},
{file = "frozendict-2.4.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:07153e6d2720fa1131bb180ce388c7042affb29561d8bcd1c0d6e683a8beaea2"},
{file = "frozendict-2.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f7a90ea6d5248617a1222daef07d22fb146ff07635a36db327e1ce114bf3e304"},
{file = "frozendict-2.4.2-cp310-cp310-win_arm64.whl", hash = "sha256:20a6f741c92fdeb3766924cde42b8ee445cf568e3be8aa983cb83e9fe5b61e63"},
{file = "frozendict-2.4.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:146129502cd9d96de64e0c8f7dc4c66422da3d4bfccf891dd80a3821b358a926"},
{file = "frozendict-2.4.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ac1f74ccf818977abbc1868090c06436b8f06534d306f808f15cffc304ae046"},
{file = "frozendict-2.4.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a8d2ea4f10505ad15f53ce3742420682d916d0c4d566edb8e1019756e7cea30"},
{file = "frozendict-2.4.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:4a5841681e70d2862ca153543f2912e0bab034bf29e2d3610e86ea42506121c2"},
{file = "frozendict-2.4.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d4a10119f17552cbeab48d4ae830ba091c6d47616589618adc31f251184579a7"},
{file = "frozendict-2.4.2-cp36-cp36m-win_amd64.whl", hash = "sha256:7d13ffe649e9db6f4bb5e107d9be7dfd23e13101bc69f97aa5fa6cbf6aecaadd"},
{file = "frozendict-2.4.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19e64630e164a297f83e9a1c69f1cd36fa4b3d1196c1f9fc006a0385aa198ea4"},
{file = "frozendict-2.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bedb0a6587bae53bd53727b92a87c4cf90ad7a7e0bd2db562d439beb6982712e"},
{file = "frozendict-2.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83cc9d063131fd8adbeb18a473d222b5dc8301cac9505cfe578158f9a9bf55a9"},
{file = "frozendict-2.4.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:92c46b155ea9eb9ecabc66ba2d9030f2634319f55c6448688965ece094f14b51"},
{file = "frozendict-2.4.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:f958d40637e0440bce2453019821c94fe86cfc5f3847ae11cd4f02c3548b1d1b"},
{file = "frozendict-2.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:ac954be447a907face9b652207fbd943b9b552212890db959ba653e8f1dc3f56"},
{file = "frozendict-2.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f7e0ff5e84742604a1b42c2de4f1e67630c0868cf52a5c585b54a99e06f6b453"},
{file = "frozendict-2.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:84c36bfa819cd8442f6e0bdb86413c7678b2822a46b1a22cfa0f0dd30d9e5c45"},
{file = "frozendict-2.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cead3bfe70c90c634a9b76807c9d7e75e6c5666ec96fa2cea8e7412ccf22a1f8"},
{file = "frozendict-2.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fc6e3158107b5431255978b954758b1041cc70a3b8e7657373110512eb528e3"},
{file = "frozendict-2.4.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4db1d6cc412bd865cab36723995208b82166a97bc6c724753bcd2b90cf24f164"},
{file = "frozendict-2.4.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ff6fb5831539fffb09d71cc0cc0462b1f27c0160cb6c6fa2d1f4c1bc7fffe52a"},
{file = "frozendict-2.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:79e1c94ad2a925ad5723d82a4134c6d851d5a7bc72b7e9da8b2087c42758a512"},
{file = "frozendict-2.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:34704f9ffb21448d4b5c0f9239f8f058c0efab4bfdbe2956c5be978fef0b929c"},
{file = "frozendict-2.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5280d685cd1659883a3010dec843afe3065416ae92e453498997d4474a898a39"},
{file = "frozendict-2.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ca09a376114172e4d9918e6d576f58244c45e21f5af1245085699fd3a171c47"},
{file = "frozendict-2.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55953aa2acf5bf183c664f3d0f540f8c8ac8f5fa97170f2098d413414318eb2b"},
{file = "frozendict-2.4.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:476e4857e1d87b05c9102dd5409216ce4716cb7df619e6657429bc99279303cc"},
{file = "frozendict-2.4.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4a8b298f39242d25770d029588ce9d4f524e9f4edc60d2d34b6178fb07c8a93e"},
{file = "frozendict-2.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:c157b8a92743a7905b341edb0663044fecdc7780f96c59a2843d3da68d694b90"},
{file = "frozendict-2.4.2-cp39-cp39-win_arm64.whl", hash = "sha256:cbab325c0a98b2f3ee291b36710623781b4977a3057f9103a7b0f11bcc23b177"},
{file = "frozendict-2.4.2.tar.gz", hash = "sha256:741779e1d1a2e6bb2c623f78423bd5d14aad35dc0c57e6ccc89e54eaab5f1b8a"},
]
[[package]]
@@ -928,13 +928,13 @@ lxml = ["lxml"]
[[package]]
name = "idna"
version = "3.6"
version = "3.7"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.5"
files = [
{file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"},
{file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"},
{file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
{file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
]
[[package]]
@@ -1020,13 +1020,13 @@ files = [
[[package]]
name = "joblib"
version = "1.3.2"
version = "1.4.0"
description = "Lightweight pipelining with Python functions"
optional = true
python-versions = ">=3.7"
python-versions = ">=3.8"
files = [
{file = "joblib-1.3.2-py3-none-any.whl", hash = "sha256:ef4331c65f239985f3f2220ecc87db222f08fd22097a3dd5698f693875f8cbb9"},
{file = "joblib-1.3.2.tar.gz", hash = "sha256:92f865e621e17784e7955080b6d042489e3b8e294949cc44c6eac304f59772b1"},
{file = "joblib-1.4.0-py3-none-any.whl", hash = "sha256:42942470d4062537be4d54c83511186da1fc14ba354961a2114da91efa9a4ed7"},
{file = "joblib-1.4.0.tar.gz", hash = "sha256:1eb0dc091919cd384490de890cb5dfd538410a6d4b3b54eef09fb8c50b409b1c"},
]
[[package]]
@@ -1144,124 +1144,166 @@ statsmodels = ">=0.11"
[[package]]
name = "lxml"
version = "5.2.0"
version = "5.2.1"
description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
optional = false
python-versions = ">=3.6"
files = [
{file = "lxml-5.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c54f8d6160080831a76780d850302fdeb0e8d0806f661777b0714dfb55d9a08a"},
{file = "lxml-5.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0e95ae029396382a0d2e8174e4077f96befcd4a2184678db363ddc074eb4d3b2"},
{file = "lxml-5.2.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5810fa80e64a0c689262a71af999c5735f48c0da0affcbc9041d1ef5ef3920be"},
{file = "lxml-5.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae69524fd6a68b288574013f8fadac23cacf089c75cd3fc5b216277a445eb736"},
{file = "lxml-5.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fadda215e32fe375d65e560b7f7e2a37c7f9c4ecee5315bb1225ca6ac9bf5838"},
{file = "lxml-5.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:f1f164e4cc6bc646b1fc86664c3543bf4a941d45235797279b120dc740ee7af5"},
{file = "lxml-5.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:3603a8a41097daf7672cae22cc4a860ab9ea5597f1c5371cb21beca3398b8d6a"},
{file = "lxml-5.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b3b4bb89a785f4fd60e05f3c3a526c07d0d68e3536f17f169ca13bf5b5dd75a5"},
{file = "lxml-5.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1effc10bf782f0696e76ecfeba0720ea02c0c31d5bffb7b29ba10debd57d1c3d"},
{file = "lxml-5.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b03531f6cd6ce4b511dcece060ca20aa5412f8db449274b44f4003f282e6272f"},
{file = "lxml-5.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7fac15090bb966719df06f0c4f8139783746d1e60e71016d8a65db2031ca41b8"},
{file = "lxml-5.2.0-cp310-cp310-win32.whl", hash = "sha256:92bb37c96215c4b2eb26f3c791c0bf02c64dd251effa532b43ca5049000c4478"},
{file = "lxml-5.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:b0181c22fdb89cc19e70240a850e5480817c3e815b1eceb171b3d7a3aa3e596a"},
{file = "lxml-5.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ada8ce9e6e1d126ef60d215baaa0c81381ba5841c25f1d00a71cdafdc038bd27"},
{file = "lxml-5.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3cefb133c859f06dab2ae63885d9f405000c4031ec516e0ed4f9d779f690d8e3"},
{file = "lxml-5.2.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ede2a7a86a977b0c741654efaeca0af7860a9b1ae39f9268f0936246a977ee0"},
{file = "lxml-5.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d46df6f0b1a0cda39d12c5c4615a7d92f40342deb8001c7b434d7c8c78352e58"},
{file = "lxml-5.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2259243ee734cc736e237719037efb86603c891fd363cc7973a2d0ac8a0e3f"},
{file = "lxml-5.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:c53164f29ed3c3868787144e8ea8a399ffd7d8215f59500a20173593c19e96eb"},
{file = "lxml-5.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:371aab9a397dcc76625ad3b02fa9b21be63406d69237b773156e7d1fc2ce0cae"},
{file = "lxml-5.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e08784288a179b59115b5e57abf6d387528b39abb61105fe17510a199a277a40"},
{file = "lxml-5.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4c232726f7b6df5143415a06323faaa998ef8abbe1c0ed00d718755231d76f08"},
{file = "lxml-5.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e4366e58c0508da4dee4c7c70cee657e38553d73abdffa53abbd7d743711ee11"},
{file = "lxml-5.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c84dce8fb2e900d4fb094e76fdad34a5fd06de53e41bddc1502c146eb11abd74"},
{file = "lxml-5.2.0-cp311-cp311-win32.whl", hash = "sha256:0947d1114e337dc2aae2fa14bbc9ed5d9ca1a0acd6d2f948df9926aef65305e9"},
{file = "lxml-5.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:1eace37a9f4a1bef0bb5c849434933fd6213008ec583c8e31ee5b8e99c7c8500"},
{file = "lxml-5.2.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f2cb157e279d28c66b1c27e0948687dc31dc47d1ab10ce0cd292a8334b7de3d5"},
{file = "lxml-5.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:53c0e56f41ef68c1ce4e96f27ecdc2df389730391a2fd45439eb3facb02d36c8"},
{file = "lxml-5.2.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:703d60e59ab45c17485c2c14b11880e4f7f0eab07134afa9007573fa5a779a5a"},
{file = "lxml-5.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaf5e308a5e50bc0548c4fdca0117a31ec9596f8cfc96592db170bcecc71a957"},
{file = "lxml-5.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af64df85fecd3cf3b2e792f0b5b4d92740905adfa8ce3b24977a55415f1a0c40"},
{file = "lxml-5.2.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:df7dfbdef11702fd22c2eaf042d7098d17edbc62d73f2199386ad06cbe466f6d"},
{file = "lxml-5.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:7250030a7835bfd5ba6ca7d1ad483ec90f9cbc29978c5e75c1cc3e031d3c4160"},
{file = "lxml-5.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:be5faa2d5c8c8294d770cfd09d119fb27b5589acc59635b0cf90f145dbe81dca"},
{file = "lxml-5.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:347ec08250d5950f5b016caa3e2e13fb2cb9714fe6041d52e3716fb33c208663"},
{file = "lxml-5.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:dc7b630c4fb428b8a40ddd0bfc4bc19de11bb3c9b031154f77360e48fe8b4451"},
{file = "lxml-5.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ae550cbd7f229cdf2841d9b01406bcca379a5fb327b9efb53ba620a10452e835"},
{file = "lxml-5.2.0-cp312-cp312-win32.whl", hash = "sha256:7c61ce3cdd6e6c9f4003ac118be7eb3036d0ce2afdf23929e533e54482780f74"},
{file = "lxml-5.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:f90c36ca95a44d2636bbf55a51ca30583b59b71b6547b88d954e029598043551"},
{file = "lxml-5.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:1cce2eaad7e38b985b0f91f18468dda0d6b91862d32bec945b0e46e2ffe7222e"},
{file = "lxml-5.2.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:60a3983d32f722a8422c01e4dc4badc7a307ca55c59e2485d0e14244a52c482f"},
{file = "lxml-5.2.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60847dfbdfddf08a56c4eefe48234e8c1ab756c7eda4a2a7c1042666a5516564"},
{file = "lxml-5.2.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bbe335f0d1a86391671d975a1b5e9b08bb72fba6b567c43bdc2e55ca6e6c086"},
{file = "lxml-5.2.0-cp36-cp36m-manylinux_2_28_aarch64.whl", hash = "sha256:3ac7c8a60b8ad51fe7bca99a634dd625d66492c502fd548dc6dc769ce7d94b6a"},
{file = "lxml-5.2.0-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:73e69762cf740ac3ae81137ef9d6f15f93095f50854e233d50b29e7b8a91dbc6"},
{file = "lxml-5.2.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:281ee1ffeb0ab06204dfcd22a90e9003f0bb2dab04101ad983d0b1773bc10588"},
{file = "lxml-5.2.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ba3a86b0d5a5c93104cb899dff291e3ae13729c389725a876d00ef9696de5425"},
{file = "lxml-5.2.0-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:356f8873b1e27b81793e30144229adf70f6d3e36e5cb7b6d289da690f4398953"},
{file = "lxml-5.2.0-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:2a34e74ffe92c413f197ff4967fb1611d938ee0691b762d062ef0f73814f3aa4"},
{file = "lxml-5.2.0-cp36-cp36m-win32.whl", hash = "sha256:6f0d2b97a5a06c00c963d4542793f3e486b1ed3a957f8c19f6006ed39d104bb0"},
{file = "lxml-5.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:35e39c6fd089ad6674eb52d93aa874d6027b3ae44d2381cca6e9e4c2e102c9c8"},
{file = "lxml-5.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5f6e4e5a62114ae76690c4a04c5108d067442d0a41fd092e8abd25af1288c450"},
{file = "lxml-5.2.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93eede9bcc842f891b2267c7f0984d811940d1bc18472898a1187fe560907a99"},
{file = "lxml-5.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ad364026c2cebacd7e01d1138bd53639822fefa8f7da90fc38cd0e6319a2699"},
{file = "lxml-5.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f06e4460e76468d99cc36d5b9bc6fc5f43e6662af44960e13e3f4e040aacb35"},
{file = "lxml-5.2.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:ca3236f31d565555139d5b00b790ed2a98ac6f0c4470c4032f8b5e5a5dba3c1a"},
{file = "lxml-5.2.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:a9b67b850ab1d304cb706cf71814b0e0c3875287083d7ec55ee69504a9c48180"},
{file = "lxml-5.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5261c858c390ae9a19aba96796948b6a2d56649cbd572968970dc8da2b2b2a42"},
{file = "lxml-5.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e8359fb610c8c444ac473cfd82dae465f405ff807cabb98a9b9712bbd0028751"},
{file = "lxml-5.2.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:f9e27841cddfaebc4e3ffbe5dbdff42891051acf5befc9f5323944b2c61cef16"},
{file = "lxml-5.2.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:641a8da145aca67671205f3e89bfec9815138cf2fe06653c909eab42e486d373"},
{file = "lxml-5.2.0-cp37-cp37m-win32.whl", hash = "sha256:931a3a13e0f574abce8f3152b207938a54304ccf7a6fd7dff1fdb2f6691d08af"},
{file = "lxml-5.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:246c93e2503c710cf02c7e9869dc0258223cbefe5e8f9ecded0ac0aa07fd2bf8"},
{file = "lxml-5.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:11acfcdf5a38cf89c48662123a5d02ae0a7d99142c7ee14ad90de5c96a9b6f06"},
{file = "lxml-5.2.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:200f70b5d95fc79eb9ed7f8c4888eef4e274b9bf380b829d3d52e9ed962e9231"},
{file = "lxml-5.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba4d02aed47c25be6775a40d55c5774327fdedba79871b7c2485e80e45750cb2"},
{file = "lxml-5.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e283b24c14361fe9e04026a1d06c924450415491b83089951d469509900d9f32"},
{file = "lxml-5.2.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:03e3962d6ad13a862dacd5b3a3ea60b4d092a550f36465234b8639311fd60989"},
{file = "lxml-5.2.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:6e45fd5213e5587a610b7e7c8c5319a77591ab21ead42df46bb342e21bc1418d"},
{file = "lxml-5.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:27877732946843f4b6bfc56eb40d865653eef34ad2edeed16b015d5c29c248df"},
{file = "lxml-5.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4d16b44ad0dd8c948129639e34c8d301ad87ebc852568ace6fe9a5ad9ce67ee1"},
{file = "lxml-5.2.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:b8f842df9ba26135c5414e93214e04fe0af259bb4f96a32f756f89467f7f3b45"},
{file = "lxml-5.2.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c74e77df9e36c8c91157853e6cd400f6f9ca7a803ba89981bfe3f3fc7e5651ef"},
{file = "lxml-5.2.0-cp38-cp38-win32.whl", hash = "sha256:1459a998c10a99711ac532abe5cc24ba354e4396dafef741c7797f8830712d56"},
{file = "lxml-5.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:a00f5931b7cccea775123c3c0a2513aee58afdad8728550cc970bff32280bdd2"},
{file = "lxml-5.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ddda5ba8831f258ac7e6364be03cb27aa62f50c67fd94bc1c3b6247959cc0369"},
{file = "lxml-5.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:56835b9e9a7767202fae06310c6b67478963e535fe185bed3bf9af5b18d2b67e"},
{file = "lxml-5.2.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25fef8794f0dc89f01bdd02df6a7fec4bcb2fbbe661d571e898167a83480185e"},
{file = "lxml-5.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32d44af078485c4da9a7ec460162392d49d996caf89516fa0b75ad0838047122"},
{file = "lxml-5.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f354d62345acdf22aa3e171bd9723790324a66fafe61bfe3873b86724cf6daaa"},
{file = "lxml-5.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:6a7e0935f05e1cf1a3aa1d49a87505773b04f128660eac2a24a5594ea6b1baa7"},
{file = "lxml-5.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:75a4117b43694c72a0d89f6c18a28dc57407bde4650927d4ef5fd384bdf6dcc7"},
{file = "lxml-5.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:57402d6cdd8a897ce21cf8d1ff36683583c17a16322a321184766c89a1980600"},
{file = "lxml-5.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:56591e477bea531e5e1854f5dfb59309d5708669bc921562a35fd9ca5182bdcd"},
{file = "lxml-5.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7efbce96719aa275d49ad5357886845561328bf07e1d5ab998f4e3066c5ccf15"},
{file = "lxml-5.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a3c39def0965e8fb5c8d50973e0c7b4ce429a2fa730f3f9068a7f4f9ce78410b"},
{file = "lxml-5.2.0-cp39-cp39-win32.whl", hash = "sha256:5188f22c00381cb44283ecb28c8d85c2db4a3035774dd851876c8647cb809c27"},
{file = "lxml-5.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:ed1fe80e1fcdd1205a443bddb1ad3c3135bb1cd3f36cc996a1f4aed35960fbe8"},
{file = "lxml-5.2.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d2b339fb790fc923ae2e9345c8633e3d0064d37ea7920c027f20c8ae6f65a91f"},
{file = "lxml-5.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06036d60fccb21e22dd167f6d0e422b9cbdf3588a7e999a33799f9cbf01e41a5"},
{file = "lxml-5.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a1611fb9de0a269c05575c024e6d8cdf2186e3fa52b364e3b03dcad82514d57"},
{file = "lxml-5.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:05fc3720250d221792b6e0d150afc92d20cb10c9cdaa8c8f93c2a00fbdd16015"},
{file = "lxml-5.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:11e41ffd3cd27b0ca1c76073b27bd860f96431d9b70f383990f1827ca19f2f52"},
{file = "lxml-5.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0382e6a3eefa3f6699b14fa77c2eb32af2ada261b75120eaf4fc028a20394975"},
{file = "lxml-5.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be5c8e776ecbcf8c1bce71a7d90e3a3680c9ceae516cac0be08b47e9fac0ca43"},
{file = "lxml-5.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da12b4efc93d53068888cb3b58e355b31839f2428b8f13654bd25d68b201c240"},
{file = "lxml-5.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f46f8033da364bacc74aca5e319509a20bb711c8a133680ca5f35020f9eaf025"},
{file = "lxml-5.2.0-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:50a26f68d090594477df8572babac64575cd5c07373f7a8319c527c8e56c0f99"},
{file = "lxml-5.2.0-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:57cbadf028727705086047994d2e50124650e63ce5a035b0aa79ab50f001989f"},
{file = "lxml-5.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:8aa11638902ac23f944f16ce45c9f04c9d5d57bb2da66822abb721f4efe5fdbb"},
{file = "lxml-5.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b7150e630b879390e02121e71ceb1807f682b88342e2ea2082e2c8716cf8bd93"},
{file = "lxml-5.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4add722393c99da4d51c8d9f3e1ddf435b30677f2d9ba9aeaa656f23c1b7b580"},
{file = "lxml-5.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd0f25a431cd16f70ec1c47c10b413e7ddfe1ccaaddd1a7abd181e507c012374"},
{file = "lxml-5.2.0-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:883e382695f346c2ea3ad96bdbdf4ca531788fbeedb4352be3a8fcd169fc387d"},
{file = "lxml-5.2.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:80cc2b55bb6e35d3cb40936b658837eb131e9f16357241cd9ba106ae1e9c5ecb"},
{file = "lxml-5.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:59ec2948385336e9901008fdf765780fe30f03e7fdba8090aafdbe5d1b7ea0cd"},
{file = "lxml-5.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ddbea6e58cce1a640d9d65947f1e259423fc201c9cf9761782f355f53b7f3097"},
{file = "lxml-5.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52d6cdea438eb7282c41c5ac00bd6d47d14bebb6e8a8d2a1c168ed9e0cacfbab"},
{file = "lxml-5.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c556bbf88a8b667c849d326dd4dd9c6290ede5a33383ffc12b0ed17777f909d"},
{file = "lxml-5.2.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:947fa8bf15d1c62c6db36c6ede9389cac54f59af27010251747f05bddc227745"},
{file = "lxml-5.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e6cb8f7a332eaa2d876b649a748a445a38522e12f2168e5e838d1505a91cdbb7"},
{file = "lxml-5.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:16e65223f34fd3d65259b174f0f75a4bb3d9893698e5e7d01e54cd8c5eb98d85"},
{file = "lxml-5.2.0.tar.gz", hash = "sha256:21dc490cdb33047bc7f7ad76384f3366fa8f5146b86cc04c4af45de901393b90"},
{file = "lxml-5.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1f7785f4f789fdb522729ae465adcaa099e2a3441519df750ebdccc481d961a1"},
{file = "lxml-5.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6cc6ee342fb7fa2471bd9b6d6fdfc78925a697bf5c2bcd0a302e98b0d35bfad3"},
{file = "lxml-5.2.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:794f04eec78f1d0e35d9e0c36cbbb22e42d370dda1609fb03bcd7aeb458c6377"},
{file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817d420c60a5183953c783b0547d9eb43b7b344a2c46f69513d5952a78cddf3"},
{file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2213afee476546a7f37c7a9b4ad4d74b1e112a6fafffc9185d6d21f043128c81"},
{file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b070bbe8d3f0f6147689bed981d19bbb33070225373338df755a46893528104a"},
{file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e02c5175f63effbd7c5e590399c118d5db6183bbfe8e0d118bdb5c2d1b48d937"},
{file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:3dc773b2861b37b41a6136e0b72a1a44689a9c4c101e0cddb6b854016acc0aa8"},
{file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:d7520db34088c96cc0e0a3ad51a4fd5b401f279ee112aa2b7f8f976d8582606d"},
{file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:bcbf4af004f98793a95355980764b3d80d47117678118a44a80b721c9913436a"},
{file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a2b44bec7adf3e9305ce6cbfa47a4395667e744097faed97abb4728748ba7d47"},
{file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1c5bb205e9212d0ebddf946bc07e73fa245c864a5f90f341d11ce7b0b854475d"},
{file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2c9d147f754b1b0e723e6afb7ba1566ecb162fe4ea657f53d2139bbf894d050a"},
{file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:3545039fa4779be2df51d6395e91a810f57122290864918b172d5dc7ca5bb433"},
{file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a91481dbcddf1736c98a80b122afa0f7296eeb80b72344d7f45dc9f781551f56"},
{file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2ddfe41ddc81f29a4c44c8ce239eda5ade4e7fc305fb7311759dd6229a080052"},
{file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a7baf9ffc238e4bf401299f50e971a45bfcc10a785522541a6e3179c83eabf0a"},
{file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:31e9a882013c2f6bd2f2c974241bf4ba68c85eba943648ce88936d23209a2e01"},
{file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0a15438253b34e6362b2dc41475e7f80de76320f335e70c5528b7148cac253a1"},
{file = "lxml-5.2.1-cp310-cp310-win32.whl", hash = "sha256:6992030d43b916407c9aa52e9673612ff39a575523c5f4cf72cdef75365709a5"},
{file = "lxml-5.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:da052e7962ea2d5e5ef5bc0355d55007407087392cf465b7ad84ce5f3e25fe0f"},
{file = "lxml-5.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:70ac664a48aa64e5e635ae5566f5227f2ab7f66a3990d67566d9907edcbbf867"},
{file = "lxml-5.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1ae67b4e737cddc96c99461d2f75d218bdf7a0c3d3ad5604d1f5e7464a2f9ffe"},
{file = "lxml-5.2.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f18a5a84e16886898e51ab4b1d43acb3083c39b14c8caeb3589aabff0ee0b270"},
{file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6f2c8372b98208ce609c9e1d707f6918cc118fea4e2c754c9f0812c04ca116d"},
{file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:394ed3924d7a01b5bd9a0d9d946136e1c2f7b3dc337196d99e61740ed4bc6fe1"},
{file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d077bc40a1fe984e1a9931e801e42959a1e6598edc8a3223b061d30fbd26bbc"},
{file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:764b521b75701f60683500d8621841bec41a65eb739b8466000c6fdbc256c240"},
{file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:3a6b45da02336895da82b9d472cd274b22dc27a5cea1d4b793874eead23dd14f"},
{file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:5ea7b6766ac2dfe4bcac8b8595107665a18ef01f8c8343f00710b85096d1b53a"},
{file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:e196a4ff48310ba62e53a8e0f97ca2bca83cdd2fe2934d8b5cb0df0a841b193a"},
{file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:200e63525948e325d6a13a76ba2911f927ad399ef64f57898cf7c74e69b71095"},
{file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dae0ed02f6b075426accbf6b2863c3d0a7eacc1b41fb40f2251d931e50188dad"},
{file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:ab31a88a651039a07a3ae327d68ebdd8bc589b16938c09ef3f32a4b809dc96ef"},
{file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:df2e6f546c4df14bc81f9498bbc007fbb87669f1bb707c6138878c46b06f6510"},
{file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5dd1537e7cc06efd81371f5d1a992bd5ab156b2b4f88834ca852de4a8ea523fa"},
{file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9b9ec9c9978b708d488bec36b9e4c94d88fd12ccac3e62134a9d17ddba910ea9"},
{file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:8e77c69d5892cb5ba71703c4057091e31ccf534bd7f129307a4d084d90d014b8"},
{file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a8d5c70e04aac1eda5c829a26d1f75c6e5286c74743133d9f742cda8e53b9c2f"},
{file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c94e75445b00319c1fad60f3c98b09cd63fe1134a8a953dcd48989ef42318534"},
{file = "lxml-5.2.1-cp311-cp311-win32.whl", hash = "sha256:4951e4f7a5680a2db62f7f4ab2f84617674d36d2d76a729b9a8be4b59b3659be"},
{file = "lxml-5.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:5c670c0406bdc845b474b680b9a5456c561c65cf366f8db5a60154088c92d102"},
{file = "lxml-5.2.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:abc25c3cab9ec7fcd299b9bcb3b8d4a1231877e425c650fa1c7576c5107ab851"},
{file = "lxml-5.2.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6935bbf153f9a965f1e07c2649c0849d29832487c52bb4a5c5066031d8b44fd5"},
{file = "lxml-5.2.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d793bebb202a6000390a5390078e945bbb49855c29c7e4d56a85901326c3b5d9"},
{file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd5562927cdef7c4f5550374acbc117fd4ecc05b5007bdfa57cc5355864e0a4"},
{file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0e7259016bc4345a31af861fdce942b77c99049d6c2107ca07dc2bba2435c1d9"},
{file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:530e7c04f72002d2f334d5257c8a51bf409db0316feee7c87e4385043be136af"},
{file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59689a75ba8d7ffca577aefd017d08d659d86ad4585ccc73e43edbfc7476781a"},
{file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f9737bf36262046213a28e789cc82d82c6ef19c85a0cf05e75c670a33342ac2c"},
{file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:3a74c4f27167cb95c1d4af1c0b59e88b7f3e0182138db2501c353555f7ec57f4"},
{file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:68a2610dbe138fa8c5826b3f6d98a7cfc29707b850ddcc3e21910a6fe51f6ca0"},
{file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f0a1bc63a465b6d72569a9bba9f2ef0334c4e03958e043da1920299100bc7c08"},
{file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c2d35a1d047efd68027817b32ab1586c1169e60ca02c65d428ae815b593e65d4"},
{file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:79bd05260359170f78b181b59ce871673ed01ba048deef4bf49a36ab3e72e80b"},
{file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:865bad62df277c04beed9478fe665b9ef63eb28fe026d5dedcb89b537d2e2ea6"},
{file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:44f6c7caff88d988db017b9b0e4ab04934f11e3e72d478031efc7edcac6c622f"},
{file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:71e97313406ccf55d32cc98a533ee05c61e15d11b99215b237346171c179c0b0"},
{file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:057cdc6b86ab732cf361f8b4d8af87cf195a1f6dc5b0ff3de2dced242c2015e0"},
{file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:f3bbbc998d42f8e561f347e798b85513ba4da324c2b3f9b7969e9c45b10f6169"},
{file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:491755202eb21a5e350dae00c6d9a17247769c64dcf62d8c788b5c135e179dc4"},
{file = "lxml-5.2.1-cp312-cp312-win32.whl", hash = "sha256:8de8f9d6caa7f25b204fc861718815d41cbcf27ee8f028c89c882a0cf4ae4134"},
{file = "lxml-5.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:f2a9efc53d5b714b8df2b4b3e992accf8ce5bbdfe544d74d5c6766c9e1146a3a"},
{file = "lxml-5.2.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:70a9768e1b9d79edca17890175ba915654ee1725975d69ab64813dd785a2bd5c"},
{file = "lxml-5.2.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c38d7b9a690b090de999835f0443d8aa93ce5f2064035dfc48f27f02b4afc3d0"},
{file = "lxml-5.2.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5670fb70a828663cc37552a2a85bf2ac38475572b0e9b91283dc09efb52c41d1"},
{file = "lxml-5.2.1-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:958244ad566c3ffc385f47dddde4145088a0ab893504b54b52c041987a8c1863"},
{file = "lxml-5.2.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6241d4eee5f89453307c2f2bfa03b50362052ca0af1efecf9fef9a41a22bb4f"},
{file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:2a66bf12fbd4666dd023b6f51223aed3d9f3b40fef06ce404cb75bafd3d89536"},
{file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:9123716666e25b7b71c4e1789ec829ed18663152008b58544d95b008ed9e21e9"},
{file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:0c3f67e2aeda739d1cc0b1102c9a9129f7dc83901226cc24dd72ba275ced4218"},
{file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:5d5792e9b3fb8d16a19f46aa8208987cfeafe082363ee2745ea8b643d9cc5b45"},
{file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:88e22fc0a6684337d25c994381ed8a1580a6f5ebebd5ad41f89f663ff4ec2885"},
{file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_ppc64le.whl", hash = "sha256:21c2e6b09565ba5b45ae161b438e033a86ad1736b8c838c766146eff8ceffff9"},
{file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_s390x.whl", hash = "sha256:afbbdb120d1e78d2ba8064a68058001b871154cc57787031b645c9142b937a62"},
{file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:627402ad8dea044dde2eccde4370560a2b750ef894c9578e1d4f8ffd54000461"},
{file = "lxml-5.2.1-cp36-cp36m-win32.whl", hash = "sha256:e89580a581bf478d8dcb97d9cd011d567768e8bc4095f8557b21c4d4c5fea7d0"},
{file = "lxml-5.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:59565f10607c244bc4c05c0c5fa0c190c990996e0c719d05deec7030c2aa8289"},
{file = "lxml-5.2.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:857500f88b17a6479202ff5fe5f580fc3404922cd02ab3716197adf1ef628029"},
{file = "lxml-5.2.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56c22432809085b3f3ae04e6e7bdd36883d7258fcd90e53ba7b2e463efc7a6af"},
{file = "lxml-5.2.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a55ee573116ba208932e2d1a037cc4b10d2c1cb264ced2184d00b18ce585b2c0"},
{file = "lxml-5.2.1-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:6cf58416653c5901e12624e4013708b6e11142956e7f35e7a83f1ab02f3fe456"},
{file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:64c2baa7774bc22dd4474248ba16fe1a7f611c13ac6123408694d4cc93d66dbd"},
{file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:74b28c6334cca4dd704e8004cba1955af0b778cf449142e581e404bd211fb619"},
{file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:7221d49259aa1e5a8f00d3d28b1e0b76031655ca74bb287123ef56c3db92f213"},
{file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3dbe858ee582cbb2c6294dc85f55b5f19c918c2597855e950f34b660f1a5ede6"},
{file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:04ab5415bf6c86e0518d57240a96c4d1fcfc3cb370bb2ac2a732b67f579e5a04"},
{file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:6ab833e4735a7e5533711a6ea2df26459b96f9eec36d23f74cafe03631647c41"},
{file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f443cdef978430887ed55112b491f670bba6462cea7a7742ff8f14b7abb98d75"},
{file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:9e2addd2d1866fe112bc6f80117bcc6bc25191c5ed1bfbcf9f1386a884252ae8"},
{file = "lxml-5.2.1-cp37-cp37m-win32.whl", hash = "sha256:f51969bac61441fd31f028d7b3b45962f3ecebf691a510495e5d2cd8c8092dbd"},
{file = "lxml-5.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:b0b58fbfa1bf7367dde8a557994e3b1637294be6cf2169810375caf8571a085c"},
{file = "lxml-5.2.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3e183c6e3298a2ed5af9d7a356ea823bccaab4ec2349dc9ed83999fd289d14d5"},
{file = "lxml-5.2.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:804f74efe22b6a227306dd890eecc4f8c59ff25ca35f1f14e7482bbce96ef10b"},
{file = "lxml-5.2.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:08802f0c56ed150cc6885ae0788a321b73505d2263ee56dad84d200cab11c07a"},
{file = "lxml-5.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f8c09ed18ecb4ebf23e02b8e7a22a05d6411911e6fabef3a36e4f371f4f2585"},
{file = "lxml-5.2.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3d30321949861404323c50aebeb1943461a67cd51d4200ab02babc58bd06a86"},
{file = "lxml-5.2.1-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:b560e3aa4b1d49e0e6c847d72665384db35b2f5d45f8e6a5c0072e0283430533"},
{file = "lxml-5.2.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:058a1308914f20784c9f4674036527e7c04f7be6fb60f5d61353545aa7fcb739"},
{file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:adfb84ca6b87e06bc6b146dc7da7623395db1e31621c4785ad0658c5028b37d7"},
{file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:417d14450f06d51f363e41cace6488519038f940676ce9664b34ebf5653433a5"},
{file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a2dfe7e2473f9b59496247aad6e23b405ddf2e12ef0765677b0081c02d6c2c0b"},
{file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bf2e2458345d9bffb0d9ec16557d8858c9c88d2d11fed53998512504cd9df49b"},
{file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:58278b29cb89f3e43ff3e0c756abbd1518f3ee6adad9e35b51fb101c1c1daaec"},
{file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:64641a6068a16201366476731301441ce93457eb8452056f570133a6ceb15fca"},
{file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:78bfa756eab503673991bdcf464917ef7845a964903d3302c5f68417ecdc948c"},
{file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:11a04306fcba10cd9637e669fd73aa274c1c09ca64af79c041aa820ea992b637"},
{file = "lxml-5.2.1-cp38-cp38-win32.whl", hash = "sha256:66bc5eb8a323ed9894f8fa0ee6cb3e3fb2403d99aee635078fd19a8bc7a5a5da"},
{file = "lxml-5.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:9676bfc686fa6a3fa10cd4ae6b76cae8be26eb5ec6811d2a325636c460da1806"},
{file = "lxml-5.2.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cf22b41fdae514ee2f1691b6c3cdeae666d8b7fa9434de445f12bbeee0cf48dd"},
{file = "lxml-5.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ec42088248c596dbd61d4ae8a5b004f97a4d91a9fd286f632e42e60b706718d7"},
{file = "lxml-5.2.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd53553ddad4a9c2f1f022756ae64abe16da1feb497edf4d9f87f99ec7cf86bd"},
{file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feaa45c0eae424d3e90d78823f3828e7dc42a42f21ed420db98da2c4ecf0a2cb"},
{file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddc678fb4c7e30cf830a2b5a8d869538bc55b28d6c68544d09c7d0d8f17694dc"},
{file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:853e074d4931dbcba7480d4dcab23d5c56bd9607f92825ab80ee2bd916edea53"},
{file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc4691d60512798304acb9207987e7b2b7c44627ea88b9d77489bbe3e6cc3bd4"},
{file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:beb72935a941965c52990f3a32d7f07ce869fe21c6af8b34bf6a277b33a345d3"},
{file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_ppc64le.whl", hash = "sha256:6588c459c5627fefa30139be4d2e28a2c2a1d0d1c265aad2ba1935a7863a4913"},
{file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_s390x.whl", hash = "sha256:588008b8497667f1ddca7c99f2f85ce8511f8f7871b4a06ceede68ab62dff64b"},
{file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b6787b643356111dfd4032b5bffe26d2f8331556ecb79e15dacb9275da02866e"},
{file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7c17b64b0a6ef4e5affae6a3724010a7a66bda48a62cfe0674dabd46642e8b54"},
{file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:27aa20d45c2e0b8cd05da6d4759649170e8dfc4f4e5ef33a34d06f2d79075d57"},
{file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:d4f2cc7060dc3646632d7f15fe68e2fa98f58e35dd5666cd525f3b35d3fed7f8"},
{file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff46d772d5f6f73564979cd77a4fffe55c916a05f3cb70e7c9c0590059fb29ef"},
{file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:96323338e6c14e958d775700ec8a88346014a85e5de73ac7967db0367582049b"},
{file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:52421b41ac99e9d91934e4d0d0fe7da9f02bfa7536bb4431b4c05c906c8c6919"},
{file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:7a7efd5b6d3e30d81ec68ab8a88252d7c7c6f13aaa875009fe3097eb4e30b84c"},
{file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0ed777c1e8c99b63037b91f9d73a6aad20fd035d77ac84afcc205225f8f41188"},
{file = "lxml-5.2.1-cp39-cp39-win32.whl", hash = "sha256:644df54d729ef810dcd0f7732e50e5ad1bd0a135278ed8d6bcb06f33b6b6f708"},
{file = "lxml-5.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:9ca66b8e90daca431b7ca1408cae085d025326570e57749695d6a01454790e95"},
{file = "lxml-5.2.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9b0ff53900566bc6325ecde9181d89afadc59c5ffa39bddf084aaedfe3b06a11"},
{file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd6037392f2d57793ab98d9e26798f44b8b4da2f2464388588f48ac52c489ea1"},
{file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b9c07e7a45bb64e21df4b6aa623cb8ba214dfb47d2027d90eac197329bb5e94"},
{file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:3249cc2989d9090eeac5467e50e9ec2d40704fea9ab72f36b034ea34ee65ca98"},
{file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f42038016852ae51b4088b2862126535cc4fc85802bfe30dea3500fdfaf1864e"},
{file = "lxml-5.2.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:533658f8fbf056b70e434dff7e7aa611bcacb33e01f75de7f821810e48d1bb66"},
{file = "lxml-5.2.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:622020d4521e22fb371e15f580d153134bfb68d6a429d1342a25f051ec72df1c"},
{file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efa7b51824aa0ee957ccd5a741c73e6851de55f40d807f08069eb4c5a26b2baa"},
{file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c6ad0fbf105f6bcc9300c00010a2ffa44ea6f555df1a2ad95c88f5656104817"},
{file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e233db59c8f76630c512ab4a4daf5a5986da5c3d5b44b8e9fc742f2a24dbd460"},
{file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6a014510830df1475176466b6087fc0c08b47a36714823e58d8b8d7709132a96"},
{file = "lxml-5.2.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d38c8f50ecf57f0463399569aa388b232cf1a2ffb8f0a9a5412d0db57e054860"},
{file = "lxml-5.2.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5aea8212fb823e006b995c4dda533edcf98a893d941f173f6c9506126188860d"},
{file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff097ae562e637409b429a7ac958a20aab237a0378c42dabaa1e3abf2f896e5f"},
{file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f5d65c39f16717a47c36c756af0fb36144069c4718824b7533f803ecdf91138"},
{file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:3d0c3dd24bb4605439bf91068598d00c6370684f8de4a67c2992683f6c309d6b"},
{file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e32be23d538753a8adb6c85bd539f5fd3b15cb987404327c569dfc5fd8366e85"},
{file = "lxml-5.2.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cc518cea79fd1e2f6c90baafa28906d4309d24f3a63e801d855e7424c5b34144"},
{file = "lxml-5.2.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a0af35bd8ebf84888373630f73f24e86bf016642fb8576fba49d3d6b560b7cbc"},
{file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8aca2e3a72f37bfc7b14ba96d4056244001ddcc18382bd0daa087fd2e68a354"},
{file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ca1e8188b26a819387b29c3895c47a5e618708fe6f787f3b1a471de2c4a94d9"},
{file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c8ba129e6d3b0136a0f50345b2cb3db53f6bda5dd8c7f5d83fbccba97fb5dcb5"},
{file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e998e304036198b4f6914e6a1e2b6f925208a20e2042563d9734881150c6c246"},
{file = "lxml-5.2.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d3be9b2076112e51b323bdf6d5a7f8a798de55fb8d95fcb64bd179460cdc0704"},
{file = "lxml-5.2.1.tar.gz", hash = "sha256:3f7765e69bbce0906a7c74d5fe46d2c7a7596147318dbc08e4a2431f3060e306"},
]
[package.extras]
@@ -1436,19 +1478,19 @@ six = "*"
[[package]]
name = "nbformat"
version = "5.10.3"
version = "5.10.4"
description = "The Jupyter Notebook format"
optional = true
python-versions = ">=3.8"
files = [
{file = "nbformat-5.10.3-py3-none-any.whl", hash = "sha256:d9476ca28676799af85385f409b49d95e199951477a159a576ef2a675151e5e8"},
{file = "nbformat-5.10.3.tar.gz", hash = "sha256:60ed5e910ef7c6264b87d644f276b1b49e24011930deef54605188ddeb211685"},
{file = "nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b"},
{file = "nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a"},
]
[package.dependencies]
fastjsonschema = "*"
fastjsonschema = ">=2.15"
jsonschema = ">=2.6"
jupyter-core = "*"
jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0"
traitlets = ">=5.1"
[package.extras]
@@ -1672,6 +1714,19 @@ files = [
openbb-core = ">=1.1.5,<2.0.0"
xmltodict = ">=0.13.0,<0.14.0"
[[package]]
name = "openbb-econdb"
version = "1.0.0"
description = "EconDB extension for OpenBB"
optional = false
python-versions = "*"
files = []
develop = true
[package.source]
type = "directory"
url = "providers/econdb"
[[package]]
name = "openbb-econometrics"
version = "1.1.4"
@@ -2417,18 +2472,18 @@ files = [
[[package]]
name = "pydantic"
version = "2.6.4"
version = "2.7.0"
description = "Data validation using Python type hints"
optional = false
python-versions = ">=3.8"
files = [
{file = "pydantic-2.6.4-py3-none-any.whl", hash = "sha256:cc46fce86607580867bdc3361ad462bab9c222ef042d3da86f2fb333e1d916c5"},
{file = "pydantic-2.6.4.tar.gz", hash = "sha256:b1704e0847db01817624a6b86766967f552dd9dbf3afba4004409f908dcc84e6"},
{file = "pydantic-2.7.0-py3-none-any.whl", hash = "sha256:9dee74a271705f14f9a1567671d144a851c675b072736f0a7b2608fd9e495352"},
{file = "pydantic-2.7.0.tar.gz", hash = "sha256:b5ecdd42262ca2462e2624793551e80911a1e989f462910bb81aef974b4bb383"},
]
[package.dependencies]
annotated-types = ">=0.4.0"
pydantic-core = "2.16.3"
pydantic-core = "2.18.1"
typing-extensions = ">=4.6.1"
[package.extras]
@@ -2436,90 +2491,90 @@ email = ["email-validator (>=2.0.0)"]
[[package]]
name = "pydantic-core"
version = "2.16.3"
description = ""
version = "2.18.1"
description = "Core functionality for Pydantic validation and serialization"
optional = false
python-versions = ">=3.8"
files = [
{file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"},
{file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"},
{file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"},
{file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"},
{file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"},
{file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"},
{file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"},
{file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"},
{file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"},
{file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"},
{file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"},
{file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"},
{file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"},
{file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"},
{file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"},
{file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"},
{file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"},
{file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"},
{file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"},
{file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"},
{file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"},
{file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"},
{file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"},
{file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"},
{file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"},
{file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"},
{file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"},
{file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"},
{file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"},
{file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"},
{file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"},
{file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"},
{file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"},
{file = "pydantic_core-2.18.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:ee9cf33e7fe14243f5ca6977658eb7d1042caaa66847daacbd2117adb258b226"},
{file = "pydantic_core-2.18.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6b7bbb97d82659ac8b37450c60ff2e9f97e4eb0f8a8a3645a5568b9334b08b50"},
{file = "pydantic_core-2.18.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df4249b579e75094f7e9bb4bd28231acf55e308bf686b952f43100a5a0be394c"},
{file = "pydantic_core-2.18.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d0491006a6ad20507aec2be72e7831a42efc93193d2402018007ff827dc62926"},
{file = "pydantic_core-2.18.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ae80f72bb7a3e397ab37b53a2b49c62cc5496412e71bc4f1277620a7ce3f52b"},
{file = "pydantic_core-2.18.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:58aca931bef83217fca7a390e0486ae327c4af9c3e941adb75f8772f8eeb03a1"},
{file = "pydantic_core-2.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1be91ad664fc9245404a789d60cba1e91c26b1454ba136d2a1bf0c2ac0c0505a"},
{file = "pydantic_core-2.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:667880321e916a8920ef49f5d50e7983792cf59f3b6079f3c9dac2b88a311d17"},
{file = "pydantic_core-2.18.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f7054fdc556f5421f01e39cbb767d5ec5c1139ea98c3e5b350e02e62201740c7"},
{file = "pydantic_core-2.18.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:030e4f9516f9947f38179249778709a460a3adb516bf39b5eb9066fcfe43d0e6"},
{file = "pydantic_core-2.18.1-cp310-none-win32.whl", hash = "sha256:2e91711e36e229978d92642bfc3546333a9127ecebb3f2761372e096395fc649"},
{file = "pydantic_core-2.18.1-cp310-none-win_amd64.whl", hash = "sha256:9a29726f91c6cb390b3c2338f0df5cd3e216ad7a938762d11c994bb37552edb0"},
{file = "pydantic_core-2.18.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:9ece8a49696669d483d206b4474c367852c44815fca23ac4e48b72b339807f80"},
{file = "pydantic_core-2.18.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7a5d83efc109ceddb99abd2c1316298ced2adb4570410defe766851a804fcd5b"},
{file = "pydantic_core-2.18.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7973c381283783cd1043a8c8f61ea5ce7a3a58b0369f0ee0ee975eaf2f2a1b"},
{file = "pydantic_core-2.18.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:54c7375c62190a7845091f521add19b0f026bcf6ae674bdb89f296972272e86d"},
{file = "pydantic_core-2.18.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd63cec4e26e790b70544ae5cc48d11b515b09e05fdd5eff12e3195f54b8a586"},
{file = "pydantic_core-2.18.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:561cf62c8a3498406495cfc49eee086ed2bb186d08bcc65812b75fda42c38294"},
{file = "pydantic_core-2.18.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68717c38a68e37af87c4da20e08f3e27d7e4212e99e96c3d875fbf3f4812abfc"},
{file = "pydantic_core-2.18.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d5728e93d28a3c63ee513d9ffbac9c5989de8c76e049dbcb5bfe4b923a9739d"},
{file = "pydantic_core-2.18.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f0f17814c505f07806e22b28856c59ac80cee7dd0fbb152aed273e116378f519"},
{file = "pydantic_core-2.18.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d816f44a51ba5175394bc6c7879ca0bd2be560b2c9e9f3411ef3a4cbe644c2e9"},
{file = "pydantic_core-2.18.1-cp311-none-win32.whl", hash = "sha256:09f03dfc0ef8c22622eaa8608caa4a1e189cfb83ce847045eca34f690895eccb"},
{file = "pydantic_core-2.18.1-cp311-none-win_amd64.whl", hash = "sha256:27f1009dc292f3b7ca77feb3571c537276b9aad5dd4efb471ac88a8bd09024e9"},
{file = "pydantic_core-2.18.1-cp311-none-win_arm64.whl", hash = "sha256:48dd883db92e92519201f2b01cafa881e5f7125666141a49ffba8b9facc072b0"},
{file = "pydantic_core-2.18.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b6b0e4912030c6f28bcb72b9ebe4989d6dc2eebcd2a9cdc35fefc38052dd4fe8"},
{file = "pydantic_core-2.18.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3202a429fe825b699c57892d4371c74cc3456d8d71b7f35d6028c96dfecad31"},
{file = "pydantic_core-2.18.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3982b0a32d0a88b3907e4b0dc36809fda477f0757c59a505d4e9b455f384b8b"},
{file = "pydantic_core-2.18.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25595ac311f20e5324d1941909b0d12933f1fd2171075fcff763e90f43e92a0d"},
{file = "pydantic_core-2.18.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14fe73881cf8e4cbdaded8ca0aa671635b597e42447fec7060d0868b52d074e6"},
{file = "pydantic_core-2.18.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca976884ce34070799e4dfc6fbd68cb1d181db1eefe4a3a94798ddfb34b8867f"},
{file = "pydantic_core-2.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:684d840d2c9ec5de9cb397fcb3f36d5ebb6fa0d94734f9886032dd796c1ead06"},
{file = "pydantic_core-2.18.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:54764c083bbe0264f0f746cefcded6cb08fbbaaf1ad1d78fb8a4c30cff999a90"},
{file = "pydantic_core-2.18.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:201713f2f462e5c015b343e86e68bd8a530a4f76609b33d8f0ec65d2b921712a"},
{file = "pydantic_core-2.18.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fd1a9edb9dd9d79fbeac1ea1f9a8dd527a6113b18d2e9bcc0d541d308dae639b"},
{file = "pydantic_core-2.18.1-cp312-none-win32.whl", hash = "sha256:d5e6b7155b8197b329dc787356cfd2684c9d6a6b1a197f6bbf45f5555a98d411"},
{file = "pydantic_core-2.18.1-cp312-none-win_amd64.whl", hash = "sha256:9376d83d686ec62e8b19c0ac3bf8d28d8a5981d0df290196fb6ef24d8a26f0d6"},
{file = "pydantic_core-2.18.1-cp312-none-win_arm64.whl", hash = "sha256:c562b49c96906b4029b5685075fe1ebd3b5cc2601dfa0b9e16c2c09d6cbce048"},
{file = "pydantic_core-2.18.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:3e352f0191d99fe617371096845070dee295444979efb8f27ad941227de6ad09"},
{file = "pydantic_core-2.18.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0295d52b012cbe0d3059b1dba99159c3be55e632aae1999ab74ae2bd86a33d7"},
{file = "pydantic_core-2.18.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56823a92075780582d1ffd4489a2e61d56fd3ebb4b40b713d63f96dd92d28144"},
{file = "pydantic_core-2.18.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dd3f79e17b56741b5177bcc36307750d50ea0698df6aa82f69c7db32d968c1c2"},
{file = "pydantic_core-2.18.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38a5024de321d672a132b1834a66eeb7931959c59964b777e8f32dbe9523f6b1"},
{file = "pydantic_core-2.18.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2ce426ee691319d4767748c8e0895cfc56593d725594e415f274059bcf3cb76"},
{file = "pydantic_core-2.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2adaeea59849ec0939af5c5d476935f2bab4b7f0335b0110f0f069a41024278e"},
{file = "pydantic_core-2.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9b6431559676a1079eac0f52d6d0721fb8e3c5ba43c37bc537c8c83724031feb"},
{file = "pydantic_core-2.18.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:85233abb44bc18d16e72dc05bf13848a36f363f83757541f1a97db2f8d58cfd9"},
{file = "pydantic_core-2.18.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:641a018af4fe48be57a2b3d7a1f0f5dbca07c1d00951d3d7463f0ac9dac66622"},
{file = "pydantic_core-2.18.1-cp38-none-win32.whl", hash = "sha256:63d7523cd95d2fde0d28dc42968ac731b5bb1e516cc56b93a50ab293f4daeaad"},
{file = "pydantic_core-2.18.1-cp38-none-win_amd64.whl", hash = "sha256:907a4d7720abfcb1c81619863efd47c8a85d26a257a2dbebdb87c3b847df0278"},
{file = "pydantic_core-2.18.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:aad17e462f42ddbef5984d70c40bfc4146c322a2da79715932cd8976317054de"},
{file = "pydantic_core-2.18.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:94b9769ba435b598b547c762184bcfc4783d0d4c7771b04a3b45775c3589ca44"},
{file = "pydantic_core-2.18.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80e0e57cc704a52fb1b48f16d5b2c8818da087dbee6f98d9bf19546930dc64b5"},
{file = "pydantic_core-2.18.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:76b86e24039c35280ceee6dce7e62945eb93a5175d43689ba98360ab31eebc4a"},
{file = "pydantic_core-2.18.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12a05db5013ec0ca4a32cc6433f53faa2a014ec364031408540ba858c2172bb0"},
{file = "pydantic_core-2.18.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:250ae39445cb5475e483a36b1061af1bc233de3e9ad0f4f76a71b66231b07f88"},
{file = "pydantic_core-2.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a32204489259786a923e02990249c65b0f17235073149d0033efcebe80095570"},
{file = "pydantic_core-2.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6395a4435fa26519fd96fdccb77e9d00ddae9dd6c742309bd0b5610609ad7fb2"},
{file = "pydantic_core-2.18.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2533ad2883f001efa72f3d0e733fb846710c3af6dcdd544fe5bf14fa5fe2d7db"},
{file = "pydantic_core-2.18.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b560b72ed4816aee52783c66854d96157fd8175631f01ef58e894cc57c84f0f6"},
{file = "pydantic_core-2.18.1-cp39-none-win32.whl", hash = "sha256:582cf2cead97c9e382a7f4d3b744cf0ef1a6e815e44d3aa81af3ad98762f5a9b"},
{file = "pydantic_core-2.18.1-cp39-none-win_amd64.whl", hash = "sha256:ca71d501629d1fa50ea7fa3b08ba884fe10cefc559f5c6c8dfe9036c16e8ae89"},
{file = "pydantic_core-2.18.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e178e5b66a06ec5bf51668ec0d4ac8cfb2bdcb553b2c207d58148340efd00143"},
{file = "pydantic_core-2.18.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:72722ce529a76a4637a60be18bd789d8fb871e84472490ed7ddff62d5fed620d"},
{file = "pydantic_core-2.18.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fe0c1ce5b129455e43f941f7a46f61f3d3861e571f2905d55cdbb8b5c6f5e2c"},
{file = "pydantic_core-2.18.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4284c621f06a72ce2cb55f74ea3150113d926a6eb78ab38340c08f770eb9b4d"},
{file = "pydantic_core-2.18.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a0c3e718f4e064efde68092d9d974e39572c14e56726ecfaeebbe6544521f47"},
{file = "pydantic_core-2.18.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:2027493cc44c23b598cfaf200936110433d9caa84e2c6cf487a83999638a96ac"},
{file = "pydantic_core-2.18.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:76909849d1a6bffa5a07742294f3fa1d357dc917cb1fe7b470afbc3a7579d539"},
{file = "pydantic_core-2.18.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ee7ccc7fb7e921d767f853b47814c3048c7de536663e82fbc37f5eb0d532224b"},
{file = "pydantic_core-2.18.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ee2794111c188548a4547eccc73a6a8527fe2af6cf25e1a4ebda2fd01cdd2e60"},
{file = "pydantic_core-2.18.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a139fe9f298dc097349fb4f28c8b81cc7a202dbfba66af0e14be5cfca4ef7ce5"},
{file = "pydantic_core-2.18.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d074b07a10c391fc5bbdcb37b2f16f20fcd9e51e10d01652ab298c0d07908ee2"},
{file = "pydantic_core-2.18.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c69567ddbac186e8c0aadc1f324a60a564cfe25e43ef2ce81bcc4b8c3abffbae"},
{file = "pydantic_core-2.18.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:baf1c7b78cddb5af00971ad5294a4583188bda1495b13760d9f03c9483bb6203"},
{file = "pydantic_core-2.18.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:2684a94fdfd1b146ff10689c6e4e815f6a01141781c493b97342cdc5b06f4d5d"},
{file = "pydantic_core-2.18.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:73c1bc8a86a5c9e8721a088df234265317692d0b5cd9e86e975ce3bc3db62a59"},
{file = "pydantic_core-2.18.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e60defc3c15defb70bb38dd605ff7e0fae5f6c9c7cbfe0ad7868582cb7e844a6"},
{file = "pydantic_core-2.18.1.tar.gz", hash = "sha256:de9d3e8717560eb05e28739d1b35e4eac2e458553a52a301e51352a7ffc86a35"},
]
[package.dependencies]
@@ -3144,18 +3199,18 @@ test = ["pytest"]
[[package]]
name = "setuptools"
version = "69.2.0"
version = "69.5.1"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = true
python-versions = ">=3.8"
files = [
{file = "setuptools-69.2.0-py3-none-any.whl", hash = "sha256:c21c49fb1042386df081cb5d86759792ab89efca84cf114889191cd09aacc80c"},
{file = "setuptools-69.2.0.tar.gz", hash = "sha256:0ff4183f8f42cd8fa3acea16c45205521a4ef28f73c6391d8a25e92893134f2e"},
{file = "setuptools-69.5.1-py3-none-any.whl", hash = "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32"},
{file = "setuptools-69.5.1.tar.gz", hash = "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987"},
]
[package.extras]
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
[[package]]
@@ -3360,13 +3415,13 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,
[[package]]
name = "typing-extensions"
version = "4.10.0"
version = "4.11.0"
description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
python-versions = ">=3.8"
files = [
{file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"},
{file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"},
{file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"},
{file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"},
]
[[package]]
@@ -3771,54 +3826,54 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
[[package]]
name = "zope-interface"
version = "6.2"
version = "6.3"
description = "Interfaces for Python"
optional = true
python-versions = ">=3.7"
files = [
{file = "zope.interface-6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:506f5410b36e5ba494136d9fa04c548eaf1a0d9c442b0b0e7a0944db7620e0ab"},
{file = "zope.interface-6.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b386b8b9d2b6a5e1e4eadd4e62335571244cb9193b7328c2b6e38b64cfda4f0e"},
{file = "zope.interface-6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abb0b3f2cb606981c7432f690db23506b1db5899620ad274e29dbbbdd740e797"},
{file = "zope.interface-6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de7916380abaef4bb4891740879b1afcba2045aee51799dfd6d6ca9bdc71f35f"},
{file = "zope.interface-6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b240883fb43160574f8f738e6d09ddbdbf8fa3e8cea051603d9edfd947d9328"},
{file = "zope.interface-6.2-cp310-cp310-win_amd64.whl", hash = "sha256:8af82afc5998e1f307d5e72712526dba07403c73a9e287d906a8aa2b1f2e33dd"},
{file = "zope.interface-6.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4d45d2ba8195850e3e829f1f0016066a122bfa362cc9dc212527fc3d51369037"},
{file = "zope.interface-6.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:76e0531d86523be7a46e15d379b0e975a9db84316617c0efe4af8338dc45b80c"},
{file = "zope.interface-6.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59f7374769b326a217d0b2366f1c176a45a4ff21e8f7cebb3b4a3537077eff85"},
{file = "zope.interface-6.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25e0af9663eeac6b61b231b43c52293c2cb7f0c232d914bdcbfd3e3bd5c182ad"},
{file = "zope.interface-6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14e02a6fc1772b458ebb6be1c276528b362041217b9ca37e52ecea2cbdce9fac"},
{file = "zope.interface-6.2-cp311-cp311-win_amd64.whl", hash = "sha256:02adbab560683c4eca3789cc0ac487dcc5f5a81cc48695ec247f00803cafe2fe"},
{file = "zope.interface-6.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8f5d2c39f3283e461de3655e03faf10e4742bb87387113f787a7724f32db1e48"},
{file = "zope.interface-6.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:75d2ec3d9b401df759b87bc9e19d1b24db73083147089b43ae748aefa63067ef"},
{file = "zope.interface-6.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa994e8937e8ccc7e87395b7b35092818905cf27c651e3ff3e7f29729f5ce3ce"},
{file = "zope.interface-6.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ede888382882f07b9e4cd942255921ffd9f2901684198b88e247c7eabd27a000"},
{file = "zope.interface-6.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2606955a06c6852a6cff4abeca38346ed01e83f11e960caa9a821b3626a4467b"},
{file = "zope.interface-6.2-cp312-cp312-win_amd64.whl", hash = "sha256:ac7c2046d907e3b4e2605a130d162b1b783c170292a11216479bb1deb7cadebe"},
{file = "zope.interface-6.2-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:febceb04ee7dd2aef08c2ff3d6f8a07de3052fc90137c507b0ede3ea80c21440"},
{file = "zope.interface-6.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fc711acc4a1c702ca931fdbf7bf7c86f2a27d564c85c4964772dadf0e3c52f5"},
{file = "zope.interface-6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:396f5c94654301819a7f3a702c5830f0ea7468d7b154d124ceac823e2419d000"},
{file = "zope.interface-6.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd374927c00764fcd6fe1046bea243ebdf403fba97a937493ae4be2c8912c2b"},
{file = "zope.interface-6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a3046e8ab29b590d723821d0785598e0b2e32b636a0272a38409be43e3ae0550"},
{file = "zope.interface-6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:de125151a53ecdb39df3cb3deb9951ed834dd6a110a9e795d985b10bb6db4532"},
{file = "zope.interface-6.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f444de0565db46d26c9fa931ca14f497900a295bd5eba480fc3fad25af8c763e"},
{file = "zope.interface-6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2fefad268ff5c5b314794e27e359e48aeb9c8bb2cbb5748a071757a56f6bb8f"},
{file = "zope.interface-6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97785604824981ec8c81850dd25c8071d5ce04717a34296eeac771231fbdd5cd"},
{file = "zope.interface-6.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7b2bed4eea047a949296e618552d3fed00632dc1b795ee430289bdd0e3717f3"},
{file = "zope.interface-6.2-cp38-cp38-win_amd64.whl", hash = "sha256:d54f66c511ea01b9ef1d1a57420a93fbb9d48a08ec239f7d9c581092033156d0"},
{file = "zope.interface-6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5ee9789a20b0081dc469f65ff6c5007e67a940d5541419ca03ef20c6213dd099"},
{file = "zope.interface-6.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af27b3fe5b6bf9cd01b8e1c5ddea0a0d0a1b8c37dc1c7452f1e90bf817539c6d"},
{file = "zope.interface-6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bce517b85f5debe07b186fc7102b332676760f2e0c92b7185dd49c138734b70"},
{file = "zope.interface-6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ae9793f114cee5c464cc0b821ae4d36e1eba961542c6086f391a61aee167b6f"},
{file = "zope.interface-6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e87698e2fea5ca2f0a99dff0a64ce8110ea857b640de536c76d92aaa2a91ff3a"},
{file = "zope.interface-6.2-cp39-cp39-win_amd64.whl", hash = "sha256:b66335bbdbb4c004c25ae01cc4a54fd199afbc1fd164233813c6d3c2293bb7e1"},
{file = "zope.interface-6.2.tar.gz", hash = "sha256:3b6c62813c63c543a06394a636978b22dffa8c5410affc9331ce6cdb5bfa8565"},
{file = "zope.interface-6.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f32010ffb87759c6a3ad1c65ed4d2e38e51f6b430a1ca11cee901ec2b42e021"},
{file = "zope.interface-6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e78a183a3c2f555c2ad6aaa1ab572d1c435ba42f1dc3a7e8c82982306a19b785"},
{file = "zope.interface-6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa0491a9f154cf8519a02026dc85a416192f4cb1efbbf32db4a173ba28b289a"},
{file = "zope.interface-6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62e32f02b3f26204d9c02c3539c802afc3eefb19d601a0987836ed126efb1f21"},
{file = "zope.interface-6.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c40df4aea777be321b7e68facb901bc67317e94b65d9ab20fb96e0eb3c0b60a1"},
{file = "zope.interface-6.3-cp310-cp310-win_amd64.whl", hash = "sha256:46034be614d1f75f06e7dcfefba21d609b16b38c21fc912b01a99cb29e58febb"},
{file = "zope.interface-6.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:600101f43a7582d5b9504a7c629a1185a849ce65e60fca0f6968dfc4b76b6d39"},
{file = "zope.interface-6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4d6b229f5e1a6375f206455cc0a63a8e502ed190fe7eb15e94a312dc69d40299"},
{file = "zope.interface-6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10cde8dc6b2fd6a1d0b5ca4be820063e46ddba417ab82bcf55afe2227337b130"},
{file = "zope.interface-6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40aa8c8e964d47d713b226c5baf5f13cdf3a3169c7a2653163b17ff2e2334d10"},
{file = "zope.interface-6.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d165d7774d558ea971cb867739fb334faf68fc4756a784e689e11efa3becd59e"},
{file = "zope.interface-6.3-cp311-cp311-win_amd64.whl", hash = "sha256:69dedb790530c7ca5345899a1b4cb837cc53ba669051ea51e8c18f82f9389061"},
{file = "zope.interface-6.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8d407e0fd8015f6d5dfad481309638e1968d70e6644e0753f229154667dd6cd5"},
{file = "zope.interface-6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:72d5efecad16c619a97744a4f0b67ce1bcc88115aa82fcf1dc5be9bb403bcc0b"},
{file = "zope.interface-6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:567d54c06306f9c5b6826190628d66753b9f2b0422f4c02d7c6d2b97ebf0a24e"},
{file = "zope.interface-6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:483e118b1e075f1819b3c6ace082b9d7d3a6a5eb14b2b375f1b80a0868117920"},
{file = "zope.interface-6.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb78c12c1ad3a20c0d981a043d133299117b6854f2e14893b156979ed4e1d2c"},
{file = "zope.interface-6.3-cp312-cp312-win_amd64.whl", hash = "sha256:ad4524289d8dbd6fb5aa17aedb18f5643e7d48358f42c007a5ee51a2afc2a7c5"},
{file = "zope.interface-6.3-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:a56fe1261230093bfeedc1c1a6cd6f3ec568f9b07f031c9a09f46b201f793a85"},
{file = "zope.interface-6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:014bb94fe6bf1786da1aa044eadf65bc6437bcb81c451592987e5be91e70a91e"},
{file = "zope.interface-6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22e8a218e8e2d87d4d9342aa973b7915297a08efbebea5b25900c73e78ed468e"},
{file = "zope.interface-6.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f95bebd0afe86b2adc074df29edb6848fc4d474ff24075e2c263d698774e108d"},
{file = "zope.interface-6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:d0e7321557c702bd92dac3c66a2f22b963155fdb4600133b6b29597f62b71b12"},
{file = "zope.interface-6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:187f7900b63845dcdef1be320a523dbbdba94d89cae570edc2781eb55f8c2f86"},
{file = "zope.interface-6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a058e6cf8d68a5a19cb5449f42a404f0d6c2778b897e6ce8fadda9cea308b1b0"},
{file = "zope.interface-6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8fa0fb05083a1a4216b4b881fdefa71c5d9a106e9b094cd4399af6b52873e91"},
{file = "zope.interface-6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26c9a37fb395a703e39b11b00b9e921c48f82b6e32cc5851ad5d0618cd8876b5"},
{file = "zope.interface-6.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b0c4c90e5eefca2c3e045d9f9ed9f1e2cdbe70eb906bff6b247e17119ad89a1"},
{file = "zope.interface-6.3-cp38-cp38-win_amd64.whl", hash = "sha256:5683aa8f2639016fd2b421df44301f10820e28a9b96382a6e438e5c6427253af"},
{file = "zope.interface-6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2c3cfb272bcb83650e6695d49ae0d14dd06dc694789a3d929f23758557a23d92"},
{file = "zope.interface-6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:01a0b3dd012f584afcf03ed814bce0fc40ed10e47396578621509ac031be98bf"},
{file = "zope.interface-6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4137025731e824eee8d263b20682b28a0bdc0508de9c11d6c6be54163e5b7c83"},
{file = "zope.interface-6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c8731596198198746f7ce2a4487a0edcbc9ea5e5918f0ab23c4859bce56055c"},
{file = "zope.interface-6.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf34840e102d1d0b2d39b1465918d90b312b1119552cebb61a242c42079817b9"},
{file = "zope.interface-6.3-cp39-cp39-win_amd64.whl", hash = "sha256:a1adc14a2a9d5e95f76df625a9b39f4709267a483962a572e3f3001ef90ea6e6"},
{file = "zope.interface-6.3.tar.gz", hash = "sha256:f83d6b4b22262d9a826c3bd4b2fbfafe1d0000f085ef8e44cd1328eea274ae6a"},
]
[package.dependencies]
setuptools = "*"
[package.extras]
docs = ["Sphinx", "repoze.sphinx.autointerface", "sphinx_rtd_theme"]
docs = ["Sphinx", "repoze.sphinx.autointerface", "sphinx-rtd-theme"]
test = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
@@ -3845,4 +3900,4 @@ wsj = ["openbb-wsj"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.8,<3.12"
content-hash = "0f0a6bfbe79eb6f9f646b1e413b5d875844f84a6f8a98396e77fa60482b9f656"
content-hash = "d2738ab8e908e13dddc4a6c9aabd5a38035da5410a824c3bc7084001e568215f"

View File

@@ -0,0 +1,16 @@
# OpenBB EconDB Provider
This extension integrates the [EconDB](https://econdb.com/) data provider into the OpenBB Platform.
## Installation
To install the extension:
```bash
pip install openbb-econdb
```
For development please check [Contribution Guidelines](https://github.com/OpenBB-finance/OpenBBTerminal/blob/develop/openbb_platform/CONTRIBUTING.md).
Documentation available [here](https://docs.openbb.co/platform).

View File

@@ -0,0 +1 @@
""" The ECB provider."""

View File

@@ -0,0 +1,20 @@
"""EconDB provider module."""
from openbb_core.provider.abstract.provider import Provider
from openbb_econdb.models.available_indicators import EconDbAvailableIndicatorsFetcher
from openbb_econdb.models.country_profile import EconDbCountryProfileFetcher
from openbb_econdb.models.economic_indicators import EconDbEconomicIndicatorsFetcher
econdb_provider = Provider(
name="EconDB",
website="https://econdb.com/",
description="""EconDB is a provider of data.""",
credentials=[
"api_key"
], # Can be left as None, an attempt to use a temporaray token will be made.
fetcher_dict={
"AvailableIndicators": EconDbAvailableIndicatorsFetcher,
"CountryProfile": EconDbCountryProfileFetcher,
"EconomicIndicators": EconDbEconomicIndicatorsFetcher,
},
)

View File

@@ -0,0 +1 @@
"""EconDB Models."""

View File

@@ -0,0 +1,101 @@
"""EconDB Available Indicators."""
# pylint: disable=unused-argument
from datetime import (
date as dateType,
datetime,
)
from typing import Any, Dict, List, Optional
from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.available_indicators import (
AvailableIndicatorsData,
AvailableIndicesQueryParams,
)
from openbb_core.provider.utils.errors import EmptyDataError
from openbb_econdb.utils.helpers import download_indicators
from pydantic import Field
class EconDbAvailableIndicatorsQueryParams(AvailableIndicesQueryParams):
"""EconDB Available Indicators Query Parameters."""
use_cache: bool = Field(
default=True,
description="Whether to use cache or not, by default is True"
+ " The cache of indicator symbols will persist for one week.",
)
class EconDbAvailableIndicatorsData(AvailableIndicatorsData):
"""EconDB Available Indicators Data."""
__alias_dict__ = {
"symbol": "short_ticker",
"country": "entity",
}
currency: Optional[str] = Field(
default=None,
description="The currency, or unit, the data is based in.",
)
scale: Optional[str] = Field(
default=None,
description="The scale of the data.",
)
multiplier: Optional[int] = Field(
description="The multiplier of the data to arrive at whole units.",
)
transformation: str = Field(
description="Transformation type.",
)
source: Optional[str] = Field(
default=None,
description="The original source of the data.",
)
first_date: Optional[dateType] = Field(
default=None,
description="The first date of the data.",
)
last_date: Optional[dateType] = Field(
default=None,
description="The last date of the data.",
)
last_insert_timestamp: Optional[datetime] = Field(
default=None,
description="The time of the last update. Data is typically reported with a lag.",
)
class EconDbAvailableIndicatorsFetcher(
Fetcher[EconDbAvailableIndicatorsQueryParams, List[EconDbAvailableIndicatorsData]]
):
"""EconDB Available Indicators Fetcher."""
require_credentials = False
@staticmethod
def transform_query(params: Dict[str, Any]) -> EconDbAvailableIndicatorsQueryParams:
"""Transform query."""
return EconDbAvailableIndicatorsQueryParams(**params)
@staticmethod
async def aextract_data(
query: EconDbAvailableIndicatorsQueryParams,
credentials: Optional[Dict[str, str]],
**kwargs: Any,
) -> List[Dict]:
"""Extract data."""
df = await download_indicators(query.use_cache)
if df.empty:
raise EmptyDataError("There was an error fetching the data.")
return df.sort_values(by="last_date", ascending=False).to_dict(orient="records")
@staticmethod
def transform_data(
query: EconDbAvailableIndicatorsQueryParams,
data: List[Dict],
**kwargs: Any,
) -> List[EconDbAvailableIndicatorsData]:
"""Transform data."""
return [EconDbAvailableIndicatorsData.model_validate(d) for d in data]

View File

@@ -0,0 +1,313 @@
"""EconDB Country Profile."""
# pylint: disable=unused-argument
import asyncio
from typing import Any, Dict, List, Optional
from warnings import warn
from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.country_profile import (
CountryProfileData,
CountryProfileQueryParams,
)
from openbb_core.provider.utils.errors import EmptyDataError
from openbb_econdb.utils.helpers import (
COUNTRY_GROUPS,
COUNTRY_MAP,
PROFILE_ORDER,
THREE_LETTER_ISO_MAP,
get_context,
parse_context,
)
from pandas import DataFrame, concat
from pydantic import Field, field_validator
class EconDbCountryProfileQueryParams(CountryProfileQueryParams):
"""Country Profile Query."""
__json_schema_extra__ = {"country": ["multiple_items_allowed"]}
latest: bool = Field(
default=True,
description="If True, return only the latest data."
+ " If False, return all available data for each indicator.",
)
use_cache: bool = Field(
default=True,
description="If True, the request will be cached for one day."
+ "Using cache is recommended to avoid needlessly requesting the same data.",
)
@field_validator("country", mode="before", check_fields=False)
@classmethod
def validate_country(cls, v):
"""Validate the country."""
country = v if isinstance(v, list) else v.split(",")
for c in country.copy():
if (
len(c) == 2
and c.upper() not in list(COUNTRY_MAP.values())
and c.lower() != "g7"
) or (
len(c) > 3 and c.lower() not in list(COUNTRY_MAP) + list(COUNTRY_GROUPS)
):
country.remove(c)
elif len(c) == 3 and c.lower() != "g20":
_c = THREE_LETTER_ISO_MAP.get(c.upper(), "")
if _c: # pylint: disable=R0801
country[country.index(c)] = _c
else:
warn(f"Error: {c} is not a valid country code.")
country.remove(c)
elif len(c) > 3 and c.lower() in COUNTRY_MAP:
country[country.index(c)] = COUNTRY_MAP[c.lower()].upper()
elif len(c) > 2 and c.lower() in COUNTRY_GROUPS:
country[country.index(c)] = ",".join(COUNTRY_GROUPS[c.lower()])
if len(country) == 0:
raise ValueError("No valid countries were supplied.")
return ",".join(country)
class EconDbCountryProfileData(CountryProfileData):
"""EconDB Country Profile Data."""
__alias_dict__ = {
"country": "Country",
"gdp_usd": "GDP ($B USD)",
"gdp_qoq": "GDP QoQ",
"gdp_yoy": "GDP YoY",
"cpi_yoy": "CPI YoY",
"core_yoy": "Core CPI YoY",
"retail_sales_yoy": "Retail Sales YoY",
"industrial_production_yoy": "Industrial Production YoY",
"policy_rate": "Policy Rate",
"yield_10y": "10Y Yield",
"govt_debt_gdp": "Govt Debt/GDP",
"current_account_gdp": "Current Account/GDP",
"jobless_rate": "Jobless Rate",
"population": "Population",
}
@field_validator(
"gdp_qoq",
"gdp_yoy",
"cpi_yoy",
"core_yoy",
"retail_sales_yoy",
"industrial_production_yoy",
"policy_rate",
"yield_10y",
"current_account_gdp",
"jobless_rate",
mode="before",
check_fields=False,
)
@classmethod
def normalize_percent(cls, v):
"""Normalize the percent values."""
return float(v) / 100 if v is not None else None
class EconDbCountryProfileFetcher(
Fetcher[EconDbCountryProfileQueryParams, List[EconDbCountryProfileData]]
):
"""EconDB Country Profile Fetcher."""
require_credentials = False
@staticmethod
def transform_query(params: Dict[str, Any]) -> EconDbCountryProfileQueryParams:
"""Transform the query parameters."""
return EconDbCountryProfileQueryParams(**params)
@staticmethod
async def aextract_data(
query: EconDbCountryProfileQueryParams,
credentials: Optional[Dict[str, str]],
**kwargs: Any,
) -> List[Dict]:
"""Extract the data."""
country = query.country.split(",")
latest = query.latest
use_cache = query.use_cache
results = []
async def get_one_country(_country): # pylint: disable=too-many-locals
"""Get the profile for one country."""
_country = _country.upper()
final_df = DataFrame()
(
gdp_response,
gdp_qoq_response,
gdp_yoy_response,
pop_response,
cpi_response,
core_response,
retail_response,
industrial_response,
policy_response,
y10y_response,
gdebt_response,
ca_response,
urate_response,
) = await asyncio.gather(
get_context("GDP", _country, "TUSD", use_cache),
get_context("RGDP", _country, "TPOP", use_cache),
get_context("RGDP", _country, "TOYA", use_cache),
get_context("POP", _country, None, use_cache),
get_context("CPI", _country, "TOYA", use_cache),
get_context("CORE", _country, "TOYA", use_cache),
get_context("RETA", _country, "TOYA", use_cache),
get_context("IP", _country, "TOYA", use_cache),
get_context("POLIR", _country, None, use_cache),
get_context("Y10YD", _country, None, use_cache),
get_context("GDEBT", _country, "TUSD", use_cache),
get_context("CA", _country, "TPGP", use_cache),
get_context("URATE", _country, None, use_cache),
)
gdp = parse_context(gdp_response, latest=latest).rename(columns={"GDP": "GDP ($B USD)"}) # type: ignore
gdp_qoq = parse_context(gdp_qoq_response, latest=latest).rename(columns={"RGDP": "GDP QoQ"}) # type: ignore
gdp_yoy = parse_context(gdp_yoy_response, latest=latest).rename(columns={"RGDP": "GDP YoY"}) # type: ignore
pop = parse_context(pop_response, latest=latest).rename(columns={"POP": "Population"}) # type: ignore
cpi = parse_context(cpi_response, latest=latest).rename(columns={"CPI": "CPI YoY"}) # type: ignore
core_cpi = parse_context(core_response, latest=latest).rename(columns={"CORE": "Core CPI YoY"}) # type: ignore
retail_sales = parse_context(retail_response, latest=latest).rename(columns={"RETA": "Retail Sales YoY"}) # type: ignore
industrial_production = parse_context(
industrial_response, latest=latest
).rename(
columns={"IP": "Industrial Production YoY"}
) # type: ignore
policy_rate = parse_context(policy_response, latest=latest).rename(columns={"POLIR": "Policy Rate"}) # type: ignore
y10y = parse_context(y10y_response, latest=latest).rename(columns={"Y10YD": "10Y Yield"}) # type: ignore
gdebt = parse_context(gdebt_response, latest=latest).rename(columns={"GDEBT": "Govt Debt/GDP"}) # type: ignore
ca = parse_context(ca_response, latest=latest).rename(columns={"CA": "Current Account/GDP"}) # type: ignore
urate = parse_context(urate_response, latest=latest).rename(columns={"URATE": "Jobless Rate"}) # type: ignore
# If returning a pivot table, we need to add the country as an index before concatenating.
if latest is False:
gdp = (
gdp.set_index("Country", append=True)
if "Country" in gdp.columns
else gdp
)
gdp_qoq = (
gdp_qoq.set_index("Country", append=True)
if "Country" in gdp_qoq.columns
else gdp_qoq
)
gdp_yoy = (
gdp_yoy.set_index("Country", append=True)
if "Country" in gdp_yoy.columns
else gdp_yoy
)
pop = (
pop.set_index("Country", append=True)
if "Country" in pop.columns
else pop
)
cpi = (
cpi.set_index("Country", append=True)
if "Country" in cpi.columns
else cpi
)
core_cpi = (
core_cpi.set_index("Country", append=True)
if "Country" in core_cpi.columns
else core_cpi
)
retail_sales = (
retail_sales.set_index("Country", append=True)
if "Country" in retail_sales.columns
else retail_sales
)
industrial_production = (
industrial_production.set_index("Country", append=True)
if "Country" in industrial_production.columns
else industrial_production
)
policy_rate = (
policy_rate.set_index("Country", append=True)
if "Country" in policy_rate.columns
else policy_rate
)
y10y = (
y10y.set_index("Country", append=True)
if "Country" in y10y.columns
else y10y
)
gdebt = (
gdebt.set_index("Country", append=True)
if "Country" in gdebt.columns
else gdebt
)
ca = (
ca.set_index("Country", append=True)
if "Country" in ca.columns
else ca
)
urate = (
urate.set_index("Country", append=True)
if "Country" in urate.columns
else urate
)
final_df = concat(
[
gdp,
gdp_qoq,
gdp_yoy,
cpi,
core_cpi,
retail_sales,
industrial_production,
policy_rate,
y10y,
gdebt,
ca,
urate,
pop,
],
axis=1,
)
# Here, calculating this ratio ourselves produces better results than directly transforming from the API.
if (
"Govt Debt/GDP" in final_df.columns
and "GDP ($B USD)" in final_df.columns
):
final_df["Govt Debt/GDP"] = (
final_df["Govt Debt/GDP"] / final_df["GDP ($B USD)"]
)
if "Current Account/GDP" in final_df.columns and _country == "US":
final_df["Current Account/GDP"] = final_df["Current Account/GDP"] * 4
if final_df.empty:
warn(f"Error: No data returned for {_country}.")
if not final_df.empty:
results.extend(final_df.reset_index().to_dict(orient="records"))
chunks = [country[i : i + 3] for i in range(0, len(country), 3)]
for chunk in chunks:
await asyncio.gather(*[get_one_country(c) for c in chunk])
if not results:
raise EmptyDataError("The request returned empty.")
return results
@staticmethod
def transform_data(
query: EconDbCountryProfileQueryParams,
data: List[Dict],
**kwargs: Any,
) -> List[EconDbCountryProfileData]:
"""Transform the data."""
output_df = (
DataFrame(data)
.filter(items=["date", "Country"] + PROFILE_ORDER, axis=1)
.sort_values("GDP ($B USD)", ascending=False)
.fillna("N/A")
.replace("N/A", None)
)
if "date" in output_df.columns:
output_df.sort_values(["date", "Country"], inplace=True)
return [
EconDbCountryProfileData.model_validate(d)
for d in output_df.to_dict(orient="records")
]

View File

@@ -0,0 +1,422 @@
"""EconDB Economic Indicators."""
# pylint: disable=unused-argument
from datetime import datetime, timedelta
from typing import Any, Dict, List, Literal, Optional
from warnings import warn
from openbb_core.provider.abstract.annotated_result import AnnotatedResult
from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.economic_indicators import (
EconomicIndicatorsData,
EconomicIndicatorsQueryParams,
)
from openbb_core.provider.utils.errors import EmptyDataError
from openbb_econdb.utils import helpers
from pandas import DataFrame, concat
from pydantic import Field, field_validator
INDICATORS = list(helpers.INDICATORS_DESCRIPTIONS)
class EconDbEconomicIndicatorsQueryParams(EconomicIndicatorsQueryParams):
"""EconDB Economic Indicators Query."""
__json_schema_extra__ = {
"symbol": ["multiple_items_allowed"],
"country": ["multiple_items_allowed"],
}
transform: Literal["toya", "tpop", "tusd", "tpgp"] = Field(
default=None,
description="The transformation to apply to the data, default is None."
+ "\n"
+ "\n tpop: Change from previous period"
+ "\n toya: Change from one year ago"
+ "\n tusd: Values as US dollars"
+ "\n tpgp: Values as a percent of GDP"
+ "\n"
+ "\n"
+ " Only 'tpop' and 'toya' are applicable to all indicators."
+ " Applying transformations across multiple indicators/countries"
+ " may produce unexpected results."
+ "\n This is because not all indicators are compatible with all transformations,"
+ " and the original units and scale differ between entities."
+ "\n `tusd` should only be used where values are currencies.",
)
use_cache: bool = Field(
default=True,
description="If True, the request will be cached for one day."
+ "Using cache is recommended to avoid needlessly requesting the same data.",
)
@field_validator("country", mode="before", check_fields=False)
@classmethod
def validate_countries(cls, v):
"""Validate each country and convert to a two-letter ISO code."""
if v:
country = v if isinstance(v, list) else v.split(",")
for c in country.copy():
c = "all" if c == "world" else c # noqa: PLW2901
if c == "all":
continue
if (
len(c) == 2
and c.upper() not in list(helpers.COUNTRY_MAP.values())
and c.lower() != "g7"
):
country.remove(c)
elif len(c) == 3 and c.lower() != "g20":
_c = helpers.THREE_LETTER_ISO_MAP.get(c.upper(), "")
if _c:
country[country.index(c)] = _c
else:
warn(f"Error: {c} is not a valid country code.")
country.remove(c)
elif len(c) > 3 and c.lower() in helpers.COUNTRY_MAP:
country[country.index(c)] = helpers.COUNTRY_MAP[c.lower()].upper()
elif len(c) > 2 and c.lower() in helpers.COUNTRY_GROUPS:
country[country.index(c)] = ",".join(
helpers.COUNTRY_GROUPS[c.lower()]
)
if len(country) == 0:
raise ValueError("No valid countries were supplied.")
return ",".join(country)
return None
@field_validator("symbol", mode="before", check_fields=False)
@classmethod
def validate_symbols(cls, v):
"""Validate each symbol to check if it is a valid indicator."""
symbols = v if isinstance(v, list) else v.split(",")
new_symbols: List[str] = []
for symbol in symbols:
if "_" in symbol:
new_symbols.append(symbol)
continue
if not any(
(
symbol.upper().startswith(indicator)
if len(symbol) >= len(indicator)
else symbol.upper() == indicator
)
for indicator in INDICATORS
):
warn(f"Invalid indicator: '{symbol}'.")
else:
new_symbols.append(symbol)
if not new_symbols:
raise ValueError(
"No valid indicators provided. Please choose from: "
+ ",".join(INDICATORS)
)
return ",".join(new_symbols)
class EconDbEconomicIndicatorsData(EconomicIndicatorsData):
"""EconDB Economic Indicators Data."""
class EconDbEconomicIndicatorsFetcher(
Fetcher[EconDbEconomicIndicatorsQueryParams, List[EconDbEconomicIndicatorsData]]
):
"""EconDB Economic Indicators Fetcher."""
require_credentials = False
@staticmethod
def transform_query(params: Dict[str, Any]) -> EconDbEconomicIndicatorsQueryParams:
"""Transform the query parameters."""
new_params = params.copy()
if new_params.get("start_date") is None:
new_params["start_date"] = (
datetime.today() - timedelta(weeks=52 * 11)
).date()
if new_params.get("end_date") is None:
new_params["end_date"] = datetime.today().date()
return EconDbEconomicIndicatorsQueryParams(**new_params)
@staticmethod
async def aextract_data( # pylint: disable=R0914.R0912,R0915
query: EconDbEconomicIndicatorsQueryParams,
credentials: Optional[Dict[str, str]],
**kwargs: Any,
) -> List[Dict]:
"""Extract the data."""
token = credentials.get("econdb_api_key", "") # type: ignore
# Attempt to create a temporary token if one is not supplied.
if not token:
token = await helpers.create_token(use_cache=query.use_cache)
credentials.update({"econdb_api_key": token}) # type: ignore
base_url = "https://www.econdb.com/api/series/?ticker="
data: List[Dict] = []
symbols = query.symbol.split(",")
countries = query.country.split(",") if query.country else []
new_symbols: List = []
# We need to join country, symbol, and transformation
# for every combination of country and symbol.
for symbol in symbols:
# We will assume that if the symbol has a '~' in it,
# the user knows what they are doing. We don't want to
# match this defined symbol with any supplied country, and we need to
# ignore the transform parameter because it has already been dictated by ~.
# We will check if the transform is valid,
# and return the symbol as 'level' if it is not.
# We will also check if the symbol should have a country,
# and if one was supplied.
if "~" in symbol:
_symbol = symbol.split("~")[0].upper()
_transform = symbol.split("~")[1].upper()
if (
helpers.HAS_COUNTRIES.get(_symbol) is True
and _symbol in helpers.SYMBOL_TO_INDICATOR.values()
):
message = f"Invalid symbol: '{symbol}'. It must have a two-letter country code."
if len(symbols) > 1:
warn(message)
continue
raise RuntimeError(message)
if _transform and _transform not in helpers.QUERY_TRANSFORMS:
message = f"Invalid transformation, '{_transform}', for symbol: '{_symbol}'."
if len(symbols) > 1:
warn(message)
new_symbols.append(_symbol)
else:
raise RuntimeError(message)
elif not _transform:
new_symbols.append(symbol.replace("~", ""))
else:
new_symbols.append(symbol)
# Else we need to wrap each symbol with each country code
# and check if the country is valid for that indicator.
elif countries and helpers.HAS_COUNTRIES.get(symbol) is True:
for country in countries:
_country = (
helpers.INDICATOR_COUNTRIES.get(symbol, [])
if country == "all"
else (
helpers.COUNTRY_GROUPS.get(country, [])
if country in helpers.COUNTRY_GROUPS
else (
[country.upper()]
if country.upper()
in helpers.INDICATOR_COUNTRIES.get(symbol, [])
else ""
)
)
)
if _country == "":
warn(
f"Invalid country code for indicator: {symbol}."
+ f" Skipping '{country}'. Valid countries are:"
+ f" {','.join(helpers.INDICATOR_COUNTRIES.get(symbol))}"
)
continue
new_symbol = [
symbol + d.upper()
for d in _country
if d in helpers.INDICATOR_COUNTRIES.get(symbol)
]
if query.transform:
new_symbol = [
d + "~" + query.transform.upper() for d in new_symbol
]
new_symbols.extend(new_symbol)
# If it is a commodity symbol, there will be no country associated with the indicator.
elif (
symbol in helpers.HAS_COUNTRIES
and helpers.HAS_COUNTRIES[symbol] is False
):
new_symbols.append(symbol)
if not new_symbols:
symbol_message = helpers.INDICATOR_COUNTRIES.get(query.symbol, "None")
error_message = (
"No valid combination of indicator symbols and countries were supplied."
+ f"\nValid countries for '{query.symbol}' are: {symbol_message}"
+ f"\nIf the symbol - {query.symbol} - is missing a country code."
+ " Please add the two-letter country code or use the country parameter."
+ "\nIf already included, add '~' to the end of the symbol."
)
raise ValueError(error_message)
url = base_url + f"%5B{','.join(new_symbols)}%5D&format=json&token={token}"
if query.start_date:
url += f"&from={query.start_date}"
if query.end_date:
url += f"&to={query.end_date}"
# If too many indicators and countries are supplied the request url will be too long.
# Instead of chunking we request the user reduce the number of indicators and countries.
# This might be able to nudge higher, but it is a safe limit for all operating systems.
if len(url) > 2000:
raise ValueError(
"The request has generated a url that is too long."
+ " Please reduce the number of symbols or countries and try again."
)
async def response_callback(response, session):
"""Response callback."""
if response.status != 200:
warn(f"Error: {response.status} - {response.reason}")
response = await response.json()
if response.get("results"):
data.extend(response["results"])
while response.get("next"):
response = await session.get(response["next"])
response = await response.json()
if response.get("results"):
data.extend(response["results"])
return data
if query.use_cache is True:
cache_dir = f"{helpers.get_user_cache_directory()}/http/econdb_indicators"
async with helpers.CachedSession(
cache=helpers.SQLiteBackend(
cache_dir, expire_after=3600 * 24, ignored_params=["token"]
)
) as session:
try:
data = await helpers.amake_request( # type: ignore
url,
session=session,
response_callback=response_callback,
timeout=20,
**kwargs,
)
finally:
await session.close()
else:
data = await helpers.amake_request( # type: ignore
url, response_callback=response_callback, timeout=20, **kwargs
)
if not data:
raise EmptyDataError()
return data
@staticmethod
def transform_data( # pylint: disable=R0914,R0915
query: EconDbEconomicIndicatorsQueryParams,
data: List[Dict],
**kwargs: Any,
) -> AnnotatedResult[List[EconDbEconomicIndicatorsData]]:
"""Transform the data."""
output = DataFrame()
metadata = {}
for d in data:
if "data" in d and not d["data"].get("values"):
warn(
f"Symbol Error: No data found for '{d.get('ticker', '')}'."
+ " The country has data, but not for the requested date range."
)
continue
# First we need to parse the metadata for the series.
title = d.get("description", "")
title = title.replace("All countries", "World")
_symbol = d.get("ticker", [])
symbol = _symbol.split("~")[0] if "~" in _symbol else _symbol
indicator = helpers.SYMBOL_TO_INDICATOR.get(symbol, "")
_transform = _symbol.split("~")[1] if "~" in _symbol else ""
transform = helpers.TRANSFORM_DICT.get(_transform, None)
country = d.get("geography", "")
country = country.replace("All countries", "World")
frequency = d.get("frequency", None)
dataset = d.get("dataset", None)
units = helpers.UNITS.get(symbol, "")
scale = (
"PERCENT"
if _transform in ["TPGP", "TPOP", "TOYA"]
else helpers.SCALES.get(symbol, None)
)
if symbol.startswith("Y10YD") or symbol.startswith("M3YD"):
scale = "Units"
units = "PERCENT"
add_info = d.get("additional_metadata", None) or d.get(
"additional_info", None
)
if _transform == "TUSD":
scale = "Units"
units = "USD"
if add_info:
if (
scale in ["Units", "PERCENT"]
and units == "DOMESTIC"
and "COMMODITY:Commodity" in add_info
):
units = "USD"
elif scale == "Units":
units = (
(
add_info["UNIT_MEASURE:UNIT_MEASURE"]
if "UNIT_MEASURE:UNIT_MEASURE" in add_info
else (
add_info["UNIT:Unit of measure"]
if "UNIT:Unit of measure" in add_info
else units
)
)
if units != "USD"
else units
)
units = units.replace("PC:Percentage", "PERCENT")
if ", " in units:
units = units.split(", ")[1]
multiplier = 1 if scale == "PERCENT" else helpers.MULTIPLIERS.get(symbol, 1)
# Special handling for the population multiplier
# because some values are buried elsewhere in the metadata.
if indicator == "POP" and country in helpers.POP_MULTIPLIER:
multiplier = helpers.POP_MULTIPLIER[country]
metadata.update(
{
_symbol: dict( # pylint: disable=R1735
title=title,
country=country,
frequency=frequency,
dataset=dataset,
transform=transform if transform else None,
units=units if units else None,
scale=scale if scale else None,
multiplier=multiplier if multiplier else None,
additional_info=add_info if add_info else None,
)
}
)
# Now we can get the data.
_result = d.get("data", [])
result = DataFrame(_result)
result = result.rename( # pylint: disable=E1136 # type: ignore
columns={"dates": "date", "values": "value"}
)[["date", "value"]].sort_values(by="date")
result["symbol_root"] = indicator
result["symbol"] = _symbol
result["country"] = country
# We can normalize the percent values here
# because we have accounted for transformation, if done.
if units == "PERCENT" or scale == "PERCENT":
result["value"] = result["value"].astype(float).div(100)
# Combine it with all the other series requested.
output = concat([output, result.dropna()], axis=0)
output = (
output.set_index(["date", "symbol_root", "country"])
.sort_index()
.reset_index()
)
if output.empty:
raise EmptyDataError(
"Error: The no data was found for the supplied symbols and countries: "
+ f"{query.symbol.split(',')} {query.country.split(',') if query.country else ''}"
)
records = (
output.fillna("N/A")
.replace("N/A", None)
.replace("nan", None)
.replace("", None)
.replace(0, None)
.to_dict("records")
)
return AnnotatedResult(
result=[
EconDbEconomicIndicatorsData.model_validate(r)
for r in records
if r["value"] is not None
],
metadata=metadata,
)

View File

@@ -0,0 +1 @@
"""EconDB Utilities."""

View File

@@ -0,0 +1,679 @@
"""EconDB Helpers"""
import asyncio
import json
from importlib.resources import files
from io import StringIO
from typing import Dict, List, Optional, Tuple, Union
import nest_asyncio
from aiohttp_client_cache import SQLiteBackend
from aiohttp_client_cache.session import CachedSession
from openbb_core.app.utils import get_user_cache_directory
from openbb_core.provider.utils.helpers import amake_request, amake_requests
from pandas import DataFrame, concat, read_csv
COUNTRY_MAP = {
"albania": "AL",
"argentina": "AR",
"australia": "AU",
"austria": "AT",
"azerbaijan": "AZ",
"bangladesh": "BD",
"belarus": "BY",
"belgium": "BE",
"bosnia_and_herzegovina": "BA",
"brazil": "BR",
"bulgaria": "BG",
"cambodia": "KH",
"canada": "CA",
"chile": "CL",
"china": "CN",
"colombia": "CO",
"costa rica": "CR",
"croatia": "HR",
"cyprus": "CY",
"czechia": "CZ",
"denmark": "DK",
"dominican republic": "DO",
"egypt": "EG",
"estonia": "EE",
"european_union": "EU",
"euro_area": "EA",
"finland": "FI",
"france": "FR",
"germany": "DE",
"greece": "GR",
"honduras": "HN",
"hong_kong": "HK",
"hungary": "HU",
"india": "IN",
"indonesia": "ID",
"iran": "IR",
"ireland": "IE",
"israel": "IL",
"italy": "IT",
"japan": "JP",
"jordan": "JO",
"kazakhstan": "KZ",
"laos": "LA",
"latvia": "LV",
"lithuania": "LT",
"luxembourg": "LU",
"macao": "MO",
"malaysia": "MY",
"mexico": "MX",
"mongolia": "MN",
"morocco": "MA",
"netherlands": "NL",
"new_zealand": "NZ",
"nigeria": "NG",
"norway": "NO",
"oman": "OM",
"pakistan": "PK",
"panama": "PA",
"peru": "PE",
"philippines": "PH",
"poland": "PL",
"portugal": "PT",
"romania": "RO",
"russia": "RU",
"saudi_arabia": "SA",
"serbia": "RS",
"singapore": "SG",
"slovakia": "SK",
"slovenia": "SI",
"south_africa": "ZA",
"south_korea": "KR",
"spain": "ES",
"sweden": "SE",
"switzerland": "CH",
"taiwan": "TW",
"thailand": "TH",
"tunisia": "TN",
"turkey": "TR",
"ukraine": "UA",
"united_arab_emirates": "AE",
"united_kingdom": "UK",
"united_states": "US",
"uzbekistan": "UZ",
"vietnam": "VN",
"world": "W00",
}
THREE_LETTER_ISO_MAP = {
"ALB": "AL",
"ARG": "AR",
"AUS": "AU",
"AUT": "AT",
"AZE": "AZ",
"BGD": "BD",
"BLR": "BY",
"BEL": "BE",
"BIH": "BA",
"BRA": "BR",
"BGR": "BG",
"KHM": "KH",
"CAN": "CA",
"CHL": "CL",
"CHN": "CN",
"COL": "CO",
"CRI": "CR",
"HRV": "HR",
"CYP": "CY",
"CZE": "CZ",
"DNK": "DK",
"DOM": "DO",
"EGY": "EG",
"EST": "EE",
"FIN": "FI",
"FRA": "FR",
"DEU": "DE",
"GRC": "GR",
"HND": "HN",
"HKG": "HK",
"HUN": "HU",
"IND": "IN",
"IDN": "ID",
"IRN": "IR",
"IRL": "IE",
"ISR": "IL",
"ITA": "IT",
"JPN": "JP",
"JOR": "JO",
"KAZ": "KZ",
"LAO": "LA",
"LVA": "LV",
"LTU": "LT",
"LUX": "LU",
"MAC": "MO",
"MYS": "MY",
"MEX": "MX",
"MNG": "MN",
"MAR": "MA",
"NLD": "NL",
"NZL": "NZ",
"NGA": "NG",
"NOR": "NO",
"OMN": "OM",
"PAK": "PK",
"PAN": "PA",
"PER": "PE",
"PHL": "PH",
"POL": "PL",
"PRT": "PT",
"ROU": "RO",
"RUS": "RU",
"SAU": "SA",
"SRB": "RS",
"SGP": "SG",
"SVK": "SK",
"SVN": "SI",
"ZAF": "ZA",
"KOR": "KR",
"ESP": "ES",
"SWE": "SE",
"CHE": "CH",
"TWN": "TW",
"THA": "TH",
"TUN": "TN",
"TUR": "TR",
"UKR": "UA",
"ARE": "AE",
"USA": "US",
"UZB": "UZ",
"VNM": "VN",
}
COUNTRY_GROUPS = {
"africa": ["ZA", "MA", "EG", "NG", "TN"],
"central_asia": ["AZ", "KZ", "MN", "UZ"],
"east_asia": ["CN", "HK", "JP", "KR", "MO", "TW"],
"europe": [
"AL",
"AT",
"BY",
"BE",
"BA",
"BG",
"HR",
"CY",
"CZ",
"DK",
"EE",
"FI",
"FR",
"DE",
"GR",
"HU",
"IE",
"IT",
"LV",
"LT",
"LU",
"NL",
"NO",
"PL",
"PT",
"RO",
"RU",
"RS",
"SK",
"SI",
"ES",
"SE",
"CH",
"TR",
"UA",
"UK",
],
"g7": ["US", "CA", "FR", "DE", "IT", "JP", "UK"],
"g20": [
"AR",
"AU",
"BR",
"CA",
"CN",
"FR",
"DE",
"EA",
"IN",
"ID",
"IT",
"JP",
"KR",
"MX",
"RU",
"SA",
"TR",
"US",
"UK",
"ZA",
],
"latin_america": ["AR", "BR", "CL", "CO", "CR", "DO", "HN", "PA", "PE"],
"middle_east": ["IR", "IL", "JO", "OM", "SA", "AE"],
"north_america": ["CA", "MX", "US"],
"oceania": ["AU", "NZ"],
"south_asia": ["BD", "IN", "PK"],
"southeast_asia": ["KH", "ID", "LA", "MY", "PH", "SG", "TH", "VN"],
}
INDICATORS_DESCRIPTIONS = json.load(
(files("openbb_econdb.utils") / "indicators_descriptions.json").open()
)
MULTIPLIERS = json.load((files("openbb_econdb.utils") / "multipliers.json").open())
SCALES = json.load((files("openbb_econdb.utils") / "scales.json").open())
UNITS = json.load((files("openbb_econdb.utils") / "units.json").open())
INDICATOR_COUNTRIES = json.load(
(files("openbb_econdb.utils") / "indicator_countries.json").open()
)
SYMBOL_TO_INDICATOR = json.load(
(files("openbb_econdb.utils") / "symbol_to_indicator.json").open()
)
HAS_COUNTRIES = {
d: INDICATOR_COUNTRIES.get(d) != ["W00"] for d in INDICATORS_DESCRIPTIONS
}
QUERY_TRANSFORMS = ["TOYA", "TPOP", "TUSD", "TPGP"]
TRANSFORM_DICT = {
"TOYA": "Change from one year ago",
"TPOP": "Change from previous period",
"TUSD": "Values as US dollars",
"TPGP": "Values as a percent of GDP",
"TNOR": "Indexed to 100",
}
POP_MULTIPLIER = {
"United States": 1000,
"China": 10000,
"Japan": 10000,
"Russian Federation": 1000000,
"Australia": 1000,
"Brazil": 1000,
"South Africa": 1000,
"Switzerland": 1000,
"Taiwan": 1000,
"Bangladesh": 1000000,
"Pakistan": 1000000,
"Panama": 1000,
"Honduras": 1000000,
"Vietnam": 1000,
"Malaysia": 1000,
"Laos": 1000,
}
PROFILE_ORDER = [
"Population",
"GDP ($B USD)",
"GDP QoQ",
"GDP YoY",
"CPI YoY",
"Core CPI YoY",
"Retail Sales YoY",
"Industrial Production YoY",
"Policy Rate",
"10Y Yield",
"Govt Debt/GDP",
"Current Account/GDP",
"Jobless Rate",
]
GDP_ADJUST = [
"United States",
"Canada",
"Mexico",
"South Africa",
"Argentina",
"Uzbekistan",
"Kazakhstan",
"Bosnia And Herzegovina",
]
def parse_symbols(
symbol,
transform: Optional[str] = None,
countries: Optional[Union[str, List[str]]] = None,
):
"""Parse the indicator symbol with the optional transformation for a list of countries. Returns a string list."""
symbols = []
if not countries:
if transform:
symbol += "~" + transform
symbols.append(symbol)
elif countries and HAS_COUNTRIES.get(symbol, False) is False:
raise RuntimeError(f"Indicator {symbol} does not have countries.")
elif countries and HAS_COUNTRIES.get(symbol, False) is True:
countries = countries if isinstance(countries, list) else countries.split(",")
for country in countries:
new_country = (
"EA19"
if country == "EA" and (symbol in ["URATE", "POP", "GDEBT"])
else country
)
new_symbol = symbol + new_country
if transform:
new_symbol += "~" + transform
symbols.append(new_symbol)
return ",".join(symbols)
def unit_multiplier(unit: str) -> int: # pylint: disable=R0911
"""Return the multiplier for a given unit measurement."""
if unit == "thousands":
return 1000
if unit in ["tens of thousands", "tens thousands"]:
return 10000
if unit in ["hundreds of thousands", "hundreds thousands"]:
return 100000
if unit in ["millions", "milions"]:
return 1000000
if unit in ["tens of millions", "tens millions"]:
return 10000000
if unit in ["hundreds of millions", "hundreds millions"]:
return 100000000
if unit == "billions":
return 1000000000
if unit == "trillions":
return 1000000000000
return 1
def get_indicator_countries(indicator: str) -> List[str]:
"""Get the list of countries for a given indicator."""
return INDICATOR_COUNTRIES.get(indicator, [])
async def create_token(use_cache: bool = True) -> str:
"""Create a temporary token for the EconDB API."""
async def _callback(response, session): # pylint: disable=W0613
"""Response callback function."""
try:
return await response.json()
except Exception as _:
raise RuntimeError(
"The temporary EconDB token could not be retrieved."
+ " Please try again later or provide your own token."
+ " Sign-up at: https://www.econdb.com/"
+ " Your IP address may have been flagged by Cloudflare."
) from _
url = "https://www.econdb.com/user/create_token/?reset=0"
if use_cache is True:
cache_dir = f"{get_user_cache_directory()}/http/econdb_indicators_temp_token"
async with CachedSession(
cache=SQLiteBackend(cache_dir, expire_after=3600 * 12)
) as session:
try:
response = await amake_request(
url, response_callback=_callback, session=session # type: ignore
)
finally:
await session.close()
else:
response = await amake_request(url, response_callback=_callback) # type: ignore
return response.get("api_key", "") # type: ignore
async def download_indicators(use_cache: bool = True) -> DataFrame:
"""Download the list of main indicators from the EconDB website."""
url = "http://econdb.com/static/help/main_tickers.csv"
async def callback(response, _) -> str:
"""Response callback to read the CSV response."""
return await response.text()
if use_cache is True:
cache_dir = f"{get_user_cache_directory()}/http/econdb_indicators"
async with CachedSession(
cache=SQLiteBackend(cache_dir, expire_after=3600 * 24 * 7)
) as session:
try:
response = await amake_request(url, session=session, response_callback=callback) # type: ignore
finally:
await session.close()
else:
response = await amake_request(url, response_callback=callback) # type: ignore
all_tickers = read_csv(StringIO(response)) # type: ignore
# Drop all the OECD stuff that is obsolete.
all_tickers = all_tickers[all_tickers.iso.astype(str) != "OECD"]
# Clear out some other known, bad data.
all_tickers = all_tickers[~all_tickers.short_ticker.isin(["POPNP", "M3CO"])]
all_tickers = all_tickers[~all_tickers.short_ticker.str.contains("_")]
country_indicators = all_tickers[all_tickers.iso.str.len() == 2].copy()
country_indicators.loc[:, "symbol_root"] = country_indicators.apply(
lambda row: (
row["short_ticker"][::-1].replace(row["iso"][::-1], "", 1)[::-1]
if row["short_ticker"].endswith(row["iso"])
else row["short_ticker"]
),
axis=1,
)
country_indicators = country_indicators.query(
"symbol_root != 'XUSD' and ~symbol_root.str.startswith('USD')"
" and symbol_root != 'EURUSD' and short_ticker != 'PPIAZ'"
)
commodity_indicators = all_tickers.query(
"iso == 'W00' and ~short_ticker.str.endswith('W00')"
).copy()
commodity_indicators["symbol_root"] = commodity_indicators["short_ticker"]
commodity_indicators["currency"] = "USD"
tickers = concat([country_indicators, commodity_indicators], axis=0)
tickers["multiplier"] = tickers.scale.astype(str).str.lower().apply(unit_multiplier)
# Fix a typo in the data.
tickers["scale"] = tickers.scale.astype(str).str.replace("Milions", "Millions")
# Fix a known incorrect value.
tickers.loc[tickers["short_ticker"] == "GDPPCNZ", "multiplier"] = 1
tickers.loc[tickers["short_ticker"] == "GDPPCNZ", "scale"] = "Units"
tickers.entity = tickers.entity.str.replace("All countries", "World")
tickers = tickers.fillna("N/A").replace("N/A", None).replace("nan", None)
return tickers.sort_values(by="last_date", ascending=False)
async def get_context(
symbol: str,
countries: Union[str, List[str]],
transform: Optional[str] = None,
use_cache: bool = True,
) -> List[Dict]:
"""Get the data for a symbol and a list of countries."""
urls = []
countries = countries if isinstance(countries, list) else countries.split(",")
# Multiple countries could be passed in a single request, but the request is prone
# to failure if there is a bad symbol. To avoid this, each country is requested individually.
# If one country does not return data, the request will still be successful.
for country in countries:
if country not in INDICATOR_COUNTRIES.get(symbol, []):
continue
symbols_string = parse_symbols(symbol, transform, country)
url = f"https://www.econdb.com/series/context/?tickers=[{symbols_string}]"
urls.append(url)
# Using cache is recommended to avoid needlessly requesting the same data.
if use_cache is True:
cache_dir = f"{get_user_cache_directory()}/http/econdb_context"
async with CachedSession(
cache=SQLiteBackend(cache_dir, expire_after=3600 * 24)
) as session:
try:
response = await amake_requests(urls, session=session)
finally:
await session.close()
else:
response = await amake_requests(urls)
return response
def parse_context( # pylint: disable=R0912, R0914, R0915
response: List[Dict], latest: bool = False, with_metadata: bool = False
) -> Union[DataFrame, Tuple[DataFrame, Dict]]:
"""Parse the output from `get_context()`, and optionally return the metadata."""
metadata = {}
results = DataFrame()
if response is None:
raise RuntimeError("No data was in the response")
if not isinstance(response, List):
raise RuntimeError(
"Expecting a list of dictionaries and received a dictionary."
)
for item in response:
symbol = item.get("id", "")
_symbol = symbol.split("~")[0].replace("19", "")
temp_unit = ""
temp_meta = item.get("td", {})
temp_data = item.get("dataarray", [])
temp_transform = symbol.split("~")[1] if "~" in symbol else ""
temp_country = item.get("geography", {}).get("name", "")
temp_country = temp_country.replace(" (19 countries)", "")
# We need the metadata to process the results.
if temp_meta:
temp_unit = temp_meta.get("units", "")
temp_scale = temp_meta.get("scale", "")
if temp_transform:
if temp_transform in ["TOYA", "TPOP", "TPGP"]:
temp_unit = "Percent"
if temp_transform == "TUSD":
temp_unit = "USD"
temp_transform = TRANSFORM_DICT.get(temp_transform, "")
temp_multiplier = (
1 if temp_unit == "Percent" else unit_multiplier(temp_scale.lower())
)
date_ranges = temp_meta.get("range", [])
# We store the metadata for each indicator.
metadata[_symbol] = dict( # pylint: disable=R1735
country=temp_country.title(),
title=item.get("verbose_title", None),
frequency=temp_meta.get("frequency", None),
transformation=temp_transform if temp_transform else None,
unit=temp_unit,
unit_multiplier=temp_multiplier,
scale=temp_unit if temp_unit == "Percent" else temp_scale,
description=temp_meta.get("descrip_long", None),
last_update=temp_meta.get("lastupdate", None),
next_release=temp_meta.get("next_release", None),
first_date=date_ranges[0] if date_ranges else None,
last_date=date_ranges[1] if date_ranges else None,
dataset=item.get("dataset", None),
)
if temp_data:
temp_series = (
DataFrame(temp_data).set_index("date").sort_index().get(symbol)
)
temp_series.name = _symbol
temp_series = temp_series.replace("nan", None).dropna()
temp_series.name = temp_series.name[:-2]
temp_series = temp_series.to_frame()
temp_series["Country"] = metadata[_symbol].get("country")
# To make the GDP data comparable across countries, it needs to be consistent.
# We scale everything to billions for GDP. The data needs to be annualized for most countries.
if "GDP" in symbol and temp_unit != "Percent":
temp_series[_symbol[:-2]] = (
temp_series[_symbol[:-2]].astype(float).dropna()
)
# For some countries, we need to annualize the GDP data.
if temp_country not in GDP_ADJUST:
temp_series[_symbol[:-2]] = (
temp_series[_symbol[:-2]].rolling(4).sum()
)
temp_series[_symbol[:-2]] = (
temp_series[_symbol[:-2]] * temp_multiplier
) / 1000000000
# Update the metadata to reflect the new scale.
metadata[_symbol]["unit_multiplier"] = 1000000000
metadata[_symbol]["scale"] = "Billions"
if "GDEBT" in symbol and temp_unit != "Percent":
# We apply the multiplier in the metadata to the data and then convert it to billions.
temp_series[_symbol[:-2]] = (
temp_series[_symbol[:-2]].astype(float) * temp_multiplier
) / 1000000000
if "POP" in symbol and temp_unit != "Percent":
temp_series[_symbol[:-2]] = (
temp_series[_symbol[:-2]].astype(int).dropna()
)
# We don't use the metadata multiplier here because it is not always accurate.
if temp_country in POP_MULTIPLIER:
temp_series[_symbol[:-2]] = (
temp_series[_symbol[:-2]] * POP_MULTIPLIER[temp_country]
)
metadata[_symbol]["unit_multiplier"] = POP_MULTIPLIER[
temp_country
]
# If we are just getting the latest data, clip it.
if latest is True:
temp_series = temp_series.set_index("Country").tail(1)
results = concat([results, temp_series], axis=0)
if with_metadata is True:
return results, metadata
return results
nest_asyncio.apply()
def update_json_files() -> None:
"""Update the static JSON files with fresh values from EconDB."""
loop = asyncio.get_event_loop()
indicators = loop.run_until_complete(download_indicators(use_cache=False))
def update_symbol_to_indicator() -> None:
"""Update the symbol to indicator mapping."""
with open(
files("openbb_econdb.utils") / "symbol_to_indicator.json",
"w", # type: ignore
encoding="utf-8",
) as f:
indicators.set_index("short_ticker").sort_index()["symbol_root"].to_json(f)
def update_multipliers() -> None:
"""Update the unit multipliers."""
with open( # type: ignore
files("openbb_econdb.utils") / "multipliers.json", "w", encoding="utf-8"
) as f:
indicators.set_index("short_ticker").sort_index()["multiplier"].to_json(f)
def update_scales() -> None:
"""Update the scales."""
with open( # type: ignore
files("openbb_econdb.utils") / "scales.json", "w", encoding="utf-8"
) as f:
indicators.set_index("short_ticker").sort_index()["scale"].to_json(f)
def update_units() -> None:
"""Update the units."""
with open( # type: ignore
files("openbb_econdb.utils") / "units.json", "w", encoding="utf-8"
) as f:
indicators.set_index("short_ticker").sort_index()["currency"].to_json(f)
def update_descriptions() -> None:
"""Update the indicator descriptions."""
descriptions_dict = dict(
zip(indicators["symbol_root"], indicators["description"])
)
descriptions_dict = {k: descriptions_dict[k] for k in sorted(descriptions_dict)}
with open( # type: ignore
files("openbb_econdb.utils") / "indicators_descriptions.json",
"w",
encoding="utf-8",
) as f:
json.dump(descriptions_dict, f)
def update_indicator_countries() -> None:
"""Update the indicator countries."""
with open( # type: ignore
files("openbb_econdb.utils") / "indicator_countries.json",
"w",
encoding="utf-8",
) as f:
indicators[indicators["symbol_root"] != "[W00]"].groupby("symbol_root")[
"iso"
].apply(lambda x: x.sort_values().unique().tolist()).to_json(f)
update_symbol_to_indicator()
update_multipliers()
update_scales()
update_units()
update_descriptions()
update_indicator_countries()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1478
openbb_platform/providers/econdb/poetry.lock generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
[tool.poetry]
name = "openbb-econdb"
version = "1.0.0"
description = "EconDB extension for OpenBB"
authors = ["OpenBB Team <hello@openbb.co>"]
readme = "README.md"
packages = [{ include = "openbb_econdb" }]
[tool.poetry.dependencies]
python = "^3.8"
openbb-core = "^1.1.5"
aiohttp-client-cache = "^0.10.0"
aiosqlite = "^0.19.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.poetry.plugins."openbb_provider_extension"]
econdb = "openbb_econdb:econdb_provider"

View File

@@ -0,0 +1 @@
""" Test the EconDB Provider."""

View File

@@ -0,0 +1,114 @@
interactions:
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
method: GET
uri: https://www.econdb.com/user/create_token/?reset=0
response:
body:
string: !!binary |
H4sIAAAAAAAAAxTLSwqAIBAA0KvIrBOcccbfZUJNQdpIbYro7tHbvwfyHOvebkgKkANVcjVTEZbY
ig0kgtYzY4ilmyBu6znDoqBdcxzt/BsZYm1Yo1dkk7FJEN4PAAD//wMAUDPkb1kAAAA=
headers:
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- 8757cfa3ad5f2d6c-YVR
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Tue, 16 Apr 2024 23:03:51 GMT
NEL:
- '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'
Referrer-Policy:
- same-origin
Report-To:
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=bzxJE5Y4WTu%2Fk8wzG0GOCRKkmLZ7g67rctpErrmfGGBuZYFkgaWqaJZZgfuahjfAptNMbO8MCpz%2FOf9DnkW%2FiXZo29EoouU69YyXacIHdhC2GnQJ4MyHdDm0%2BJoJ5xrOVOMZiqGAyVfMzaNG"}],"group":"cf-nel","max_age":604800}'
Server:
- cloudflare
Transfer-Encoding:
- chunked
Vary:
- Origin, Cookie
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
method: GET
uri: https://www.econdb.com/api/series/?format=json&from=2020-01-01&ticker=%5BGDPUS%5D&to=2024-01-01&token=MOCK_TOKEN
response:
body:
string: !!binary |
H4sIAAAAAAAAA8VUXW+rOBD9K4hnLrLHxjZ+45a0irSlbUJeqCrEDW4vWgJZPqqtqv73HUMbWXfv
40orRcT28Zk5M3Pg3T/2czf5mgb+uXox47LqzN941M1ti6eDeW36efzaD2ac2wm3j+/+1Bz/NIOv
/Zv0/rD3A78243FozlPTd3h66JrJ1N5+qiYzet+8m6EfR6/uT2ZEpnce+no+Tkh7Mf3LUJ1/vv1K
Qux5MH/Npjta7MGmqKZqNCjP/75Jyiy5IQRPZ2RdJFZ13VgJVVuezFRZhq/f/TTJkzK9u022mU7x
zEv7U9VYoRhFZ9VK8ZLj0pJFcHqPsXeb6zLZbRK9M89mQCnGW24Mb14/eNVgKit7r39Vvs3S7VWS
3+305th3/QlL3nZ1c6ym3vYsw+jlYZ/+O3Pw2an0q1P3a6cCL8MoeDPwDntE27YabKKru0OWb3b3
yS5fhV7ZMGY4V8P0G6llobN+8qrzuUUxP1qDIQ7ZNi9vD3/kSxXeCUfcILwMV+jbpm1Ros11vds8
6Gt3JvphxjxmaN/8j3U8ttmvVTtbNz0ClUREFAIax5RRzgOggkvBSQBAgEcEcCEIoQohBjEwgSdM
gYolLriIuCAI4cWYUoGLiHOwUBTHfImDD8XtHaEow1ABYE5GMClIQfFf4SJmSjF4WiQuynxMT74R
ij8sbN1wdyOdDSWXDXU51OVQl0NdDrgccDngcsDlMJfDXA5zOeyTg5WNaL15Ke3a2sSO63/5f7Kf
idbge1rW+KY+Lq/lf/fA8E03GjRdXdoPzeNleBDnlGsmNSMhI4rwuHCmyUgORDOhCQ+BUCFp4YwX
USo1ANJDIShc0GXeNvKKxqGMBFq6cAyAKEbmXEcqFJTFESscR3yiRJM4BCklgwtK8QLklGkKOopD
IqWKeOF4BuRSkdIMQkIiecm7mAiU5SJKIOQRCCkKx1UrClJzCJmKI6IKx2ZrZIIXaKgkjdgXd/Ed
iJxGmhBNWSi54pQVjhFXLmrmKlSC4DtbOM5EFKjtFdYrJQHJC8eqGNmisc0bMazoqxt8yRt9opSH
2Ef8chT+08fH08c/QxF3XKoGAAA=
headers:
Allow:
- GET, HEAD, OPTIONS
CF-Cache-Status:
- DYNAMIC
CF-RAY:
- 8757cfa49bec2db5-YVR
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Tue, 16 Apr 2024 23:03:51 GMT
NEL:
- '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'
Referrer-Policy:
- same-origin
Report-To:
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=DtYnXyxGPYd3xpC3hzdp9nGI23hFrYmMBTlGXUMtj0lsucYCQqy4fOonk9LaBWjFc8o5EVnLIuL4ke%2BRMAQu8%2FGqXHx%2F5K1CUg7gxtYM%2BXCpS9P4Qiqnl%2BvMvo2rHjKgj%2BZ0s35XHFGAUR5Y"}],"group":"cf-nel","max_age":604800}'
Server:
- cloudflare
Transfer-Encoding:
- chunked
Vary:
- Accept-Encoding
- Accept, Origin
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,60 @@
""" Test EconDB Fetchers. """
import datetime
import pytest
from openbb_core.app.service.user_service import UserService
from openbb_econdb.models.available_indicators import EconDbAvailableIndicatorsFetcher
from openbb_econdb.models.country_profile import EconDbCountryProfileFetcher
from openbb_econdb.models.economic_indicators import EconDbEconomicIndicatorsFetcher
test_credentials = UserService().default_user_settings.credentials.model_dump(
mode="json"
)
@pytest.fixture(scope="module")
def vcr_config():
"""VCR config."""
return {
"filter_headers": [("User-Agent", None)],
"filter_query_parameters": [
("token", "MOCK_TOKEN"),
],
}
@pytest.mark.record_http
def test_econdb_available_indicators_fetcher(credentials=test_credentials):
"""Test EconDB Available Indicators Fetcher."""
params = {"use_cache": False}
fetcher = EconDbAvailableIndicatorsFetcher()
result = fetcher.test(params, credentials)
assert result is None
@pytest.mark.record_http
def test_econdb_country_profile_fetcher(credentials=test_credentials):
"""Test EconDB Country Profile Fetcher."""
params = {"country": "us", "latest": True, "use_cache": False}
fetcher = EconDbCountryProfileFetcher()
result = fetcher.test(params, credentials)
assert result is None
@pytest.mark.record_http
def test_econdb_economic_indicators_fetcher(credentials=test_credentials):
"""Test EconDB Economic Indicators Fetcher."""
params = {
"country": "us",
"symbol": "GDP",
"start_date": datetime.date(2020, 1, 1),
"end_date": datetime.date(2024, 1, 1),
"use_cache": False,
}
fetcher = EconDbEconomicIndicatorsFetcher()
result = fetcher.test(params, credentials)
assert result is None

View File

@@ -11,6 +11,7 @@ python = ">=3.8,<3.12"
openbb-core = "^1.1.6"
openbb-benzinga = "^1.1.5"
openbb-econdb = "^1.0.0"
openbb-federal-reserve = "^1.1.5"
openbb-fmp = "^1.1.5"
openbb-fred = "^1.1.5"

View File

@@ -0,0 +1,707 @@
---
title: Economic Indicators
sidebar_position: 8
description: This page provides a tutorial for getting started using the `obb.economy.indicators` endpoint,
with the `openbb-econdb` provider extension. The command provides access to over 100 standardized indicator
symbols, covering countries around the world.
keywords:
- tutorial
- provider
- econdb
- economy
- usage
- indicators
- economic
- CPI
- CORE
- GDP
- transform
---
import HeadTitle from '@site/src/components/General/HeadTitle.tsx';
<HeadTitle title="Economic Indicators - Usage | OpenBB Platform Docs" />
This page provides a tutorial for getting started using the `obb.economy.indicators` endpoint, with the `openbb-econdb` provider extension.
The command provides access to over 100 standardized indicator symbols, covering countries around the world.
:::note
**OpenBB is not affiliated with EconDB. All service is provided "AS IS" and without warranty.**
:::
## Authorization
This command requires an API key. You can create an account [here](https://econdb.com), and enter the key assigned.
Leaving the key as None will attempt to retrieve a temporary token that is assigned when downloading the data as a CSV file from a browser.
This is a workaround and can be blocked by Cloudflare. In this instance, the temporary token can be viewed by opening any indicator in your browser,
then selecting 'Python' from the 'Export' drop-down.
![Temporary Token](https://github.com/OpenBB-finance/OpenBBTerminal/assets/85772166/d2d4c6a7-e8b1-4345-b28f-0693ddb8dcf1)
The best method is to support the service by registering an account.
```python
from openbb import obb
obb.user.credentials.econdb_api_key = REPLACE_WITH_KEY
```
See the [API keys](api_keys) page for more information on credentials.
## Important Considerations
**Carefully inspect data before conducting analysis and arriving at conclusions.**
EconDB sources data directly from national agencies, or other reputable sources such as the IMF, but the data itself may not be directly comparable between collections of countries. For example, some countries will have GDP data as 'annualized' (North America) while others report the values for the period.
These factors can be considered as "known-unknowns", the metadata will not contain this information.
:::important
- This function will not attempt to normalize the values for cross-country comparison. Some values should be manually adjusted, post-request, to accommodate.
- Transforming levels as USD, or % of GDP, may have unexpected results where values are not appropriate for this conversion. Do not attempt to apply these transformations universally.
- Values that are scaled to, or transformed as, a percent are returned as a normalized value - i.e, 1% = 0.01. It will have a multiplier value of 1, which is not indicative of display values.
- Contextual information is contained within metadata, returned under the "extra" attribute of the function response.
:::
## Available Indicators
EconDB has a list of "main" indicators, which are standardized base symbols across the available countries for each.
```python
from openbb import obb
indicators = obb.economy.available_indicators(provider="econdb").to_df()
indicators.iloc[0]
```
| symbol_root | POLIR |
|:----------------------|:---------------------------|
| symbol | POLIREA |
| country | Euro area |
| iso | EA |
| description | Policy rate - short term |
| frequency | D |
| currency | PERCENT |
| scale | Units |
| multiplier | 1 |
| transformation | Period level |
| source | European Central Bank |
| first_date | 1999-01-01 |
| last_date | 2024-04-08 |
| last_insert_timestamp | 2024-04-08 12:27:05.089860 |
:::tip
Metadata is returned in the command response to the 'extra' attribute.
:::
```python
data = obb.economy.indicators("POLIR", country="EA")
data.extra["results_metadata"]
```
```python
{'POLIREA': {'title': 'Euro area - Policy rate - short term',
'country': 'Euro area',
'frequency': 'D',
'dataset': 'ECBFM',
'transformation': None,
'units': 'PERCENT',
'scale': 'Units',
'multiplier': 1,
'additional_info': {'FREQ:Frequency': 'D:Daily',
'REF_AREA:Reference area': 'U2:Euro area (Member States and Institutions of the Euro Area) changing composition',
'CURRENCY:Currency': 'EUR:Euro',
'PROVIDER_FM:Financial market provider': '4F:ECB',
'INSTRUMENT_FM:Financial market instrument': 'KR:Key interest rate',
'PROVIDER_FM_ID:Financial market provider identifier': 'MRR_FR:ECB Main refinancing operations - fixed rate tenders (fixed rate) (date of changes)',
'DATA_TYPE_FM:Financial market data type': 'LEV:Level'}}}
```
### Basic Descriptions
Basic descriptions of the base symbols can be imported from within the extension module helpers.
```python
from openbb_econdb.utils.helpers import INDICATORS_DESCRIPTIONS
```
:::important
This list should not be considered as the absolute source of truth. The metadata for the indicator will be returned in the command response, under the `extras` attribute.
:::
| ACPOP | Active population |
|:----------|:---------------------------------------------------|
| CA | Current account balance |
| CAR | Passenger car sales |
| CBAL | Commercial balance (goods + services) |
| CI | Change in inventories |
| CKA | Net foreign investment |
| CLAIMS | Weekly unemployment insurance claims |
| CLI | OECD CLI |
| CON | Total consumption |
| CONF | Consumer confidence index |
| CORE | Core consumer price index |
| CP | Construction production |
| CPI | Consumer price index |
| CRED | Domestic credit |
| CREDEA | Domestic credit |
| DWPE | Dwelling permits |
| ELE | Production electricity |
| EMP | Total employment |
| EMRATIO | Employment to working age population |
| EQYCAP | Market capitalization |
| EXP | Exports of goods and services |
| EXPMON | Monthly exports |
| GASDEM | Gas demand |
| GASODEM | Gasoline demand |
| GASOPROD | Gasoline production |
| GASPROD | Gas production |
| GBAL | Government balance |
| GCF | Gross capital formation |
| GDEBT | Government debt |
| GDEBTN | Government net debt |
| GDP | Gross domestic product |
| GDPDEF | GDP deflator |
| GDPPC | GDP per capita |
| GFCF | Gross fixed capital formation |
| GREV | General government total revenue |
| GSPE | General government total expenditure |
| HHDIR | Household debt to income ratio |
| HHS | Household saving |
| HOU | House price |
| IBD1 | Interbank lending overnight rate |
| IIPA | International investment position: Assets |
| IIPL | International investment position: Liabilities |
| IMP | Imports of goods and services |
| IMPMON | Monthly imports |
| INVER | Investment rate |
| IP | Industrial production |
| JHR | Job hires rate |
| JLR | Job layoffs rate |
| JQR | Job quits rate |
| JVR | Job vacancy rate |
| KA | Capital account |
| LE00 | Life expectancy at birth |
| LMICS | Low and Middle Income Commodity Index (World Bank) |
| M3 | Money supply |
| M3YD | 3 month yield |
| MB | Monetary base |
| NCT | Net current transfers (Secondary Income) |
| NFCI | Non-financial corporations investment rate |
| NFCLOAN | Lending to non-financial corporations |
| NIIP | Net international investment position |
| NPL | Non performing loans |
| NY | Net income from abroad (Primary Income) |
| OILDEM | Oil demand |
| OILPROD | Oil production |
| PALUM | Aluminum |
| PAPPLE | Non-Citrus Fruit, Apple |
| PART | Participation rate |
| PBANSOP | Bananas |
| PBARL | Barley |
| PBEEF | Beef |
| PCE | Personal consumption expenditure price index |
| PCHANA | Legumes, Chickpea |
| PCHROM | Chromium |
| PCOALAU | Coal, Australia |
| PCOALSA | Coal, South Africa |
| PCOBA | Cobalt |
| PCOCO | Cocoa |
| PCOFFOTM | Coffee, Other Mild Arabica |
| PCOFFROB | Coffee, Robustas |
| PCOIL | Coconut Oil |
| PCOPP | Copper |
| PCOTTIND | Cotton |
| PDAP | Diammonium phosphate |
| PFSHMEAL | Fish Meal |
| PGASO | Gasoline |
| PGNUTS | Groundnuts |
| PGOLD | Gold |
| PHEATOIL | Heating Oil |
| PHIDE | Hides |
| PIORECR | Iron |
| PLAMB | Lamb |
| PLEAD | Lead |
| PLITH | Lithium |
| PLMMODY | Molybdenum |
| PLOGORE | Soft Logs |
| PLOGSK | Hard Logs, Import Price Japan |
| PMAIZMT | Corn |
| PMANGELE | Manganese |
| PMILK | Dairy Products, Milk |
| PNGASEU | Natural gas, EU |
| PNGASJP | LNG, Asia |
| PNGASUS | Natural Gas, US Henry Hub Gas |
| PNICK | Nickel |
| POATS | Oats |
| POILAPSP | APSP crude oil($/bbl) |
| POILBRE | Brent Crude |
| POILDUB | Dubai Crude |
| POILWTI | WTI Crude |
| POLIR | Policy rate - short term |
| POLVOIL | Olive Oil |
| POP | Population |
| PORANG | Orange |
| PPALLA | Palladium |
| PPI | Producer price index |
| PPLAT | Platinum |
| PPOIL | Palm Oil |
| PPORK | Swine |
| PPOTASH | Potassium Fertilizer |
| PPOULT | Poultry |
| PPROPANE | Propane |
| PRC | Private consumption |
| PREODOM | Rare Earth Elements |
| PRICENPQ | Rice, Thailand |
| PRIDEBT | Private debt |
| PROIL | Rapeseed Oil |
| PRUBB | Rubber |
| PSALM | Fish |
| PSAWMAL | Hard Sawnwood, Dark Red Meranti |
| PSAWORE | Soft Sawnwood, Average of Softwoods, |
| PSHRI | Shrimp |
| PSILLUMP | Silicon |
| PSILVER | Silver |
| PSMEA | Soybean Meal |
| PSOIL | Soybeans Oil |
| PSORG | Sorghum |
| PSOYB | Soybeans |
| PSUGAISA | Sugar, No. 11, World |
| PSUGAUSA | Sugar, No. 16, US |
| PSUNO | Sunflower Oil |
| PTEA | Tea, Kenyan |
| PTEAINDIA | Tea, Kolkata |
| PTEAMOM | Tea, Mombasa |
| PTEASL | Tea, Colombo |
| PTIN | Tin |
| PTOMATO | Vegetables, Tomato |
| PUC | Public consumption |
| PURAN | Uranium |
| PUREA | Urea |
| PVANPENT | Vanadium |
| PWHEAMT | Wheat |
| PWOOLC | Wool, Coarse |
| PWOOLF | Wool, Fine |
| PZINC | Zinc |
| RCI | Real change in inventories |
| RCON | Real total consumption |
| REER | Real effective exchange rate |
| REEREA | Real effective exchange rate |
| RETA | Retail trade |
| REXP | Real exports of goods and services |
| RGCF | Real gross capital formation |
| RGDP | Real gross domestic product |
| RGDPPC | Real GDP per capita |
| RGFCF | Real gross fixed capital formation |
| RIMP | Real imports of goods and services |
| RPRC | Real private consumption |
| RPUC | Real public consumption |
| SEI | Stock exchange index |
| SENT | Sentiment index |
| TB | Trade balance |
| URATE | Unemployment |
| UTIL | Utilization rate |
| WAGE | Wages/Earnings |
| WAGEMAN | Hourly wage manufacturing |
| Y10YD | Long term yield |
## Countries
The `country` parameter will accept the ISO country code, or the country name. Regional groups listed below are also valid:
- all
- africa
- central_asia
- east_asia
- europe
- g7
- g20
- latin_america
- middle_east
- north_america
- oceania
- south_asia
- southeast_asia
:::note
Some symbols do not have a country - e.g., commodity items - and they will ignore any supplied values to the parameter.
Not every indicator has data for every country. Items with no results will be communicated via the `warnings` attribute of the response object.
```python
obb.economy.indicators("POLIR", country="southeast_asia")
```
```console
OBBject
id: 0661ac07-ab9c-7ebf-8000-849fef1202bc
results: [{'date': datetime.date(2013, 4, 29), 'symbol': 'POLIRSG', 'country': 'Sin...
provider: econdb
warnings: [{'category': 'UserWarning', 'message': "Invalid country code for...
chart: None
extra: {'results_metadata': {'POLIRID': {'title': 'Indonesia - Policy rate - short ...
```
:::
### Countries By Indicator
In addition to filtering the `available_indicators` data locally, countries by indicator can be imported as a utility function from the `openbb_econdb.utils.helpers` module.
```python
from openbb_econdb.utils.helpers import get_indicator_countries
get_indicator_countries("GDPPC") # returns a list of two-letter ISO country codes
```
## How To Enter Symbols
The three parameters - symbol, country, transform - all work together.
- Symbol (base symbol)
- CPI, GDP, CORE, etc
- Multiple items allowed
- Country
- ISO country code, or name
- Multiple items allowed
- Transform
- `tpop`: Percent change from previous period
- `toya`: Percent change from year ago
- `tusd`: Values as US dollars
- `tpgp`: Values as a percent of GDP
The `transform` will apply to all combinations of `symbol` and `country`.
:::warning
If you attempt to pass a base symbol (excluding commodity and world indicators) with no country, it will raise an error.
:::
### Example - One Indicator & Country
M3 Money Supply
```python
data = obb.economy.indicators("M3", country="us")
data.to_df().tail(12)
```
| date | symbol_root | symbol | country | value |
|:-----------|:--------------|:---------|:--------------|--------:|
| 2023-03-01 | M3 | M3US | United States | 21027 |
| 2023-04-01 | M3 | M3US | United States | 20843 |
| 2023-05-01 | M3 | M3US | United States | 20711 |
| 2023-06-01 | M3 | M3US | United States | 20749 |
| 2023-07-01 | M3 | M3US | United States | 20724 |
| 2023-08-01 | M3 | M3US | United States | 20695 |
| 2023-09-01 | M3 | M3US | United States | 20669 |
| 2023-10-01 | M3 | M3US | United States | 20636 |
| 2023-11-01 | M3 | M3US | United States | 20723 |
| 2023-12-01 | M3 | M3US | United States | 20890 |
| 2024-01-01 | M3 | M3US | United States | 20862 |
| 2024-02-01 | M3 | M3US | United States | 20788 |
```python
data.extra.get("results_metadata")
```
```python
{'M3US': {'title': 'United States - Money supply',
'country': 'United States',
'frequency': 'M',
'dataset': 'FRB_H6_M2',
'transform': None,
'units': 'DOMESTIC',
'scale': 'Billions',
'multiplier': 1000000000,
'additional_info': {'ADJUSTED:Seasonal Adjustment': 'NSA:Not seasonally adjusted',
'CURRENCY:Currency': 'USD:United States / United States Dollar',
'FREQ:Frequency': '129:Monthly',
'SERIES_NAME:Series name (FRB)': 'M2_N.M:M2_N.M',
'UNIT:Units': 'CURRENCY:Currency'}}}
```
### Example - One Indicator & Country With Transform
US PPI - Change from one year ago.
```python
data = obb.economy.indicators("PPI", country="us", transform="toya")
data.to_df().tail(12)
```
| date | symbol_root | symbol | country | value |
|:-----------|:--------------|:-----------|:--------------|---------:|
| 2023-04-01 | PPI | PPIUS~TOYA | United States | 0.022995 |
| 2023-05-01 | PPI | PPIUS~TOYA | United States | 0.011822 |
| 2023-06-01 | PPI | PPIUS~TOYA | United States | 0.001912 |
| 2023-07-01 | PPI | PPIUS~TOYA | United States | 0.008722 |
| 2023-08-01 | PPI | PPIUS~TOYA | United States | 0.016003 |
| 2023-09-01 | PPI | PPIUS~TOYA | United States | 0.021542 |
| 2023-10-01 | PPI | PPIUS~TOYA | United States | 0.013481 |
| 2023-11-01 | PPI | PPIUS~TOYA | United States | 0.008465 |
| 2023-12-01 | PPI | PPIUS~TOYA | United States | 0.00948 |
| 2024-01-01 | PPI | PPIUS~TOYA | United States | 0.008222 |
| 2024-02-01 | PPI | PPIUS~TOYA | United States | 0.015153 |
| 2024-03-01 | PPI | PPIUS~TOYA | United States | 0.020896 |
```python
data.extra.get("results_metadata")
```
```
{'PPIUS~TOYA': {'title': 'United States - Producer price index',
'country': 'United States',
'frequency': 'M',
'dataset': 'BLS_PPI00',
'transform': 'Change from one year ago',
'units': 'INDEX',
'scale': 'PERCENT',
'multiplier': 1,
'additional_info': {'DATA_DOMAIN:Data Domain': 'PPI:Producer price indices',
'REF_AREA:Reference country or area': 'US:United States',
'INDICATOR:Economic Indicator': 'PPPI_SA_IX:Prices, Producer Price Index, All Commodities, Seasonally adjusted, Index',
'COUNTERPART_AREA:Counterpart country or area': '_Z:Not applicable',
'FREQ:Frequency': 'M:Monthly',
'UNIT_MULT:Unit multiplier': '0:Units'}}}
```
### Example - Commodity Indicator
Values are always in USD.
```python
lead = obb.economy.indicators("plead")
lead.to_df().tail(4)
```
| date | symbol_root | symbol | country | value |
|:-----------|:--------------|:---------|:----------|--------:|
| 2023-10-01 | PLEAD | PLEAD | World | 2131.4 |
| 2023-11-01 | PLEAD | PLEAD | World | 2188.5 |
| 2023-12-01 | PLEAD | PLEAD | World | 2027.2 |
| 2024-01-01 | PLEAD | PLEAD | World | 2087.4 |
```python
lead.extra["results_metadata"]
```
```python
{'PLEAD': {'title': 'World - Lead',
'country': 'World',
'frequency': 'M',
'dataset': 'IMF_PCPS',
'transform': None,
'units': 'USD',
'scale': 'Units',
'multiplier': 1,
'additional_info': {'FREQ:Frequency': 'M:Monthly',
'REF_AREA:Reference Area': 'W00:All Countries, excluding the IO',
'COMMODITY:Commodity': 'PLEAD:Primary Commodity Prices, Lead',
'UNIT_MEASURE:Unit of Measure': 'USD:US Dollars',
'UNIT_MULT:Scale': '0:Units'}}}
```
### Example - Multiple Indicators & Countries With Transform
```python
params = {"symbol": "core,cpi", "country": "us,de,jp", "transform": "toya"}
data = obb.economy.indicators(**params)
df = data.to_df().filter(like="2024", axis=0)
df
```
| date | symbol_root | symbol | country | value |
|:-----------|:--------------|:------------|:--------------|---------:|
| 2024-01-01 | CORE | COREDE~TOYA | Germany | 0.03394 |
| 2024-01-01 | CORE | COREJP~TOYA | Japan | 0.03523 |
| 2024-01-01 | CORE | COREUS~TOYA | United States | 0.03875 |
| 2024-01-01 | CPI | CPIDE~TOYA | Germany | 0.02887 |
| 2024-01-01 | CPI | CPIJP~TOYA | Japan | 0.021012 |
| 2024-01-01 | CPI | CPIUS~TOYA | United States | 0.03106 |
| 2024-02-01 | CORE | COREDE~TOYA | Germany | 0.03454 |
| 2024-02-01 | CORE | COREJP~TOYA | Japan | 0.03216 |
| 2024-02-01 | CORE | COREUS~TOYA | United States | 0.03762 |
| 2024-02-01 | CPI | CPIDE~TOYA | Germany | 0.02517 |
| 2024-02-01 | CPI | CPIJP~TOYA | Japan | 0.02788 |
| 2024-02-01 | CPI | CPIUS~TOYA | United States | 0.03166 |
| 2024-03-01 | CORE | COREUS~TOYA | United States | 0.03797 |
| 2024-03-01 | CPI | CPIDE~TOYA | Germany | 0.021533 |
| 2024-03-01 | CPI | CPIUS~TOYA | United States | 0.03475 |
### Example - All Countries
Setting the country to "all" will retrieve data for all available countries.
```python
data = obb.economy.indicators("ny", country="all", transform="tusd")
data.to_df().filter(like="2024", axis=0)
```
| date | symbol_root | symbol | country | value |
|:-----------|:--------------|:----------|:-----------|---------:|
| 2024-01-01 | NY | NYBE~TUSD | Belgium | 1132.6 |
| 2024-01-01 | NY | NYBG~TUSD | Bulgaria | -78.79 |
| 2024-01-01 | NY | NYHR~TUSD | Croatia | 31.99 |
| 2024-01-01 | NY | NYCZ~TUSD | Czechia | -676.3 |
| 2024-01-01 | NY | NYDK~TUSD | Denmark | 1323.6 |
| 2024-01-01 | NY | NYEE~TUSD | Estonia | -131.74 |
| 2024-01-01 | NY | NYFI~TUSD | Finland | 626.4 |
| 2024-01-01 | NY | NYFR~TUSD | France | 8570 |
| 2024-01-01 | NY | NYDE~TUSD | Germany | 13656 |
| 2024-01-01 | NY | NYGR~TUSD | Greece | 451.5 |
| 2024-01-01 | NY | NYHU~TUSD | Hungary | -528.7 |
| 2024-01-01 | NY | NYIT~TUSD | Italy | -509.5 |
| 2024-01-01 | NY | NYLV~TUSD | Latvia | 53.57 |
| 2024-01-01 | NY | NYLT~TUSD | Lithuania | -111.62 |
| 2024-01-01 | NY | NYLU~TUSD | Luxembourg | -3791 |
| 2024-01-01 | NY | NYMT~TUSD | Malta | -218.54 |
| 2024-01-01 | NY | NYPL~TUSD | Poland | -3029 |
| 2024-01-01 | NY | NYPT~TUSD | Portugal | 28.42 |
| 2024-01-01 | NY | NYRO~TUSD | Romania | -410.1 |
| 2024-01-01 | NY | NYSK~TUSD | Slovakia | -342.7 |
| 2024-01-01 | NY | NYSI~TUSD | Slovenia | -82.76 |
| 2024-01-01 | NY | NYSE~TUSD | Sweden | 2334.1 |
```python
data.extra.get("results_metadata")["NYSE~TUSD"]
```
```
{'title': 'Sweden - Net income from abroad (Primary Income)',
'country': 'Sweden',
'frequency': 'M',
'dataset': 'BOP_C6_M',
'transform': 'Values as US dollars',
'units': 'USD',
'scale': 'Units',
'multiplier': 1000000,
'additional_info': {'GEO:Geopolitical entity (reporting)': 'SE:Sweden',
'PARTNER:Geopolitical entity (partner)': 'WRL_REST:Rest of the world',
'SECTPART:Sector (ESA 2010)': 'S1:Total economy',
'SECTOR10:Sector (ESA 2010)': 'S1:Total economy',
'FREQ:Frequency': 'M:Monthly',
'STK_FLOW:Stock or flow': 'BAL:Balance',
'CURRENCY:Currency': 'MIO_NAC:Million units of national currency',
'BOP_ITEM:BOP_item': 'IN1:Primary income'}}
```
## Advanced Symbols
The grouping behaviour can be overridden. This will allow multiple transformations, or for a specific symbol to ignore the supplied `country` and `transform` parameters.
### Example - Bypass Group Parameters
The "~" character is used to separate the base symbol + 2-letter ISO country code, and the transformation.
It works as a flag to exclude from the other parameters.
```python
obb.economy.indicators("CPIUS~").to_df().tail(2)
```
| date | symbol_root | symbol | country | value |
|:-----------|:--------------|:---------|:--------------|--------:|
| 2024-02-01 | CPI | CPIUS | United States | 311.1 |
| 2024-03-01 | CPI | CPIUS | United States | 312.2 |
Without "~", symbols are assumed to be a base symbol, and require a country parameter. An error (or warning where at least one symbol supplied was valid) is raised if the condition is not met.
```python
obb.economy.indicators("CPIUS")
```
```console
OpenBBError: No valid combination of indicator symbols and countries were supplied.
Valid countries for 'CPIUS' are: None
If the symbol - CPIUS - is missing a country code. Please add the two-letter country code or use the country parameter.
If already included, add '~' to the end of the symbol.
```
This example bypasses the transformation for US data, applying it only to France.
```python
obb.economy.indicators(symbol=["CPIUS~","CPI"], country="fr", transform="toya").to_df().tail(2)
```
| date | symbol_root | symbol | country | value |
|:-----------|:--------------|:-----------|:--------------|-----------:|
| 2024-03-01 | CPI | CPIFR~TOYA | France | 0.022947 |
| 2024-03-01 | CPI | CPIUS | United States | 312.2 |
### Example - Non-Standard Symbols
The `symbol` parameter can also be used to access non-standard series. These are specific to reporting entities, like the Ministry of Finance, Japan.
These symbols are not searchable, but the structure will be familiar if you have worked with the particular source before.
For this purpose, enter each symbol ending with, "~".
:::important
Non-standard symbols will not have transformations, standardized metadata, or normalized percent values.
:::
Japan Yield Curve
```python
symbols = [
"MFJP_IR.1Y.D.JP~",
"MFJP_IR.2Y.D.JP~",
"MFJP_IR.3Y.D.JP~",
"MFJP_IR.4Y.D.JP~",
"MFJP_IR.5Y.D.JP~",
"MFJP_IR.6Y.D.JP~",
"MFJP_IR.7Y.D.JP~",
"MFJP_IR.8Y.D.JP~",
"MFJP_IR.9Y.D.JP~",
"MFJP_IR.10Y.D.JP~",
"MFJP_IR.15Y.D.JP~",
"MFJP_IR.20Y.D.JP~",
"MFJP_IR.25Y.D.JP~",
"MFJP_IR.30Y.D.JP~",
"MFJP_IR.40Y.D.JP~",
]
data = obb.economy.indicators(symbol=symbols)
curve = data.to_df().filter(like="2024-04-11", axis=0)
curve
```
| date | symbol_root | symbol | country | value |
|:-----------|:--------------|:-----------------|:----------|--------:|
| 2024-04-11 | | MFJP_IR.1Y.D.JP | Japan | 0.068 |
| 2024-04-11 | | MFJP_IR.2Y.D.JP | Japan | 0.27 |
| 2024-04-11 | | MFJP_IR.3Y.D.JP | Japan | 0.28 |
| 2024-04-11 | | MFJP_IR.4Y.D.JP | Japan | 0.37 |
| 2024-04-11 | | MFJP_IR.5Y.D.JP | Japan | 0.485 |
| 2024-04-11 | | MFJP_IR.6Y.D.JP | Japan | 0.508 |
| 2024-04-11 | | MFJP_IR.7Y.D.JP | Japan | 0.592 |
| 2024-04-11 | | MFJP_IR.8Y.D.JP | Japan | 0.68 |
| 2024-04-11 | | MFJP_IR.9Y.D.JP | Japan | 0.757 |
| 2024-04-11 | | MFJP_IR.10Y.D.JP | Japan | 0.854 |
| 2024-04-11 | | MFJP_IR.15Y.D.JP | Japan | 1.289 |
| 2024-04-11 | | MFJP_IR.20Y.D.JP | Japan | 1.625 |
| 2024-04-11 | | MFJP_IR.25Y.D.JP | Japan | 1.78 |
| 2024-04-11 | | MFJP_IR.30Y.D.JP | Japan | 1.907 |
| 2024-04-11 | | MFJP_IR.40Y.D.JP | Japan | 2.065 |
```python
data.extra["results_metadata"].get("MFJP_IR.5Y.D.JP")
```
```python
{'title': 'Japan - Japanese Government Bonds - 5Y yield',
'country': 'Japan',
'frequency': 'D',
'dataset': 'MFJP_IR',
'transform': None,
'units': None,
'scale': None,
'multiplier': 1,
'additional_info': {'3:Indicator': '8:Japanese Government Bonds - 5Y yield',
'GEO:None': '107:None'}}
```