mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-02 15:32:04 +00:00
[BugFix] Fix Some Bugs Before Release (#7101)
* fix some bugs before release * no-else
This commit is contained in:
@@ -13,7 +13,7 @@ from openbb_core.provider.utils.descriptions import (
|
||||
DATA_DESCRIPTIONS,
|
||||
QUERY_DESCRIPTIONS,
|
||||
)
|
||||
from pydantic import Field, PositiveFloat, field_validator
|
||||
from pydantic import Field, field_validator
|
||||
|
||||
|
||||
class CryptoHistoricalQueryParams(QueryParams):
|
||||
@@ -47,12 +47,14 @@ class CryptoHistoricalData(Data):
|
||||
date: Union[dateType, datetime] = Field(
|
||||
description=DATA_DESCRIPTIONS.get("date", "")
|
||||
)
|
||||
open: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("open", ""))
|
||||
high: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("high", ""))
|
||||
low: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("low", ""))
|
||||
close: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("close", ""))
|
||||
volume: float = Field(description=DATA_DESCRIPTIONS.get("volume", ""))
|
||||
vwap: Optional[PositiveFloat] = Field(
|
||||
open: float = Field(description=DATA_DESCRIPTIONS.get("open", ""))
|
||||
high: float = Field(description=DATA_DESCRIPTIONS.get("high", ""))
|
||||
low: float = Field(description=DATA_DESCRIPTIONS.get("low", ""))
|
||||
close: float = Field(description=DATA_DESCRIPTIONS.get("close", ""))
|
||||
volume: Optional[float] = Field(
|
||||
default=None, description=DATA_DESCRIPTIONS.get("volume", "")
|
||||
)
|
||||
vwap: Optional[float] = Field(
|
||||
default=None, description=DATA_DESCRIPTIONS.get("vwap", "")
|
||||
)
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ def get_engle_granger_two_step_cointegration_test(
|
||||
short_run_ols = sm.OLS(dependent_series.diff().iloc[1:], (z.shift().iloc[1:]))
|
||||
short_run_ols_fit = short_run_ols.fit()
|
||||
|
||||
alpha = short_run_ols_fit.params[0]
|
||||
alpha = short_run_ols_fit.params.iloc[0]
|
||||
|
||||
# NOTE: The p-value returned by the adfuller function assumes we do not estimate z
|
||||
# first, but test stationarity of an unestimated series directly. This assumption
|
||||
|
||||
@@ -2108,7 +2108,7 @@ def test_equity_fundamental_management_discussion_analysis(params, obb):
|
||||
@pytest.mark.integration
|
||||
def test_equity_calendar_events(params, obb):
|
||||
"""Test the equity calendar events endpoint."""
|
||||
result = obb.equity.calendar_events(**params)
|
||||
result = obb.equity.calendar.events(**params)
|
||||
assert result
|
||||
assert isinstance(result, OBBject)
|
||||
assert len(result.results) > 0
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Literal, Optional
|
||||
from warnings import warn
|
||||
from typing import Any, Literal, Optional
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from openbb_core.provider.abstract.fetcher import Fetcher
|
||||
@@ -17,12 +15,6 @@ from openbb_core.provider.utils.descriptions import (
|
||||
DATA_DESCRIPTIONS,
|
||||
QUERY_DESCRIPTIONS,
|
||||
)
|
||||
from openbb_core.provider.utils.errors import EmptyDataError
|
||||
from openbb_core.provider.utils.helpers import (
|
||||
amake_request,
|
||||
get_querystring,
|
||||
)
|
||||
from openbb_fmp.utils.helpers import get_interval
|
||||
from pydantic import Field
|
||||
|
||||
|
||||
@@ -69,13 +61,13 @@ class FMPCryptoHistoricalData(CryptoHistoricalData):
|
||||
class FMPCryptoHistoricalFetcher(
|
||||
Fetcher[
|
||||
FMPCryptoHistoricalQueryParams,
|
||||
List[FMPCryptoHistoricalData],
|
||||
list[FMPCryptoHistoricalData],
|
||||
]
|
||||
):
|
||||
"""Transform the query, extract and transform the data from the FMP endpoints."""
|
||||
|
||||
@staticmethod
|
||||
def transform_query(params: Dict[str, Any]) -> FMPCryptoHistoricalQueryParams:
|
||||
def transform_query(params: dict[str, Any]) -> FMPCryptoHistoricalQueryParams:
|
||||
"""Transform the query params. Start and end dates are set to 1 year interval."""
|
||||
transformed_params = params
|
||||
|
||||
@@ -91,10 +83,20 @@ class FMPCryptoHistoricalFetcher(
|
||||
@staticmethod
|
||||
async def aextract_data(
|
||||
query: FMPCryptoHistoricalQueryParams,
|
||||
credentials: Optional[Dict[str, str]],
|
||||
credentials: Optional[dict[str, str]],
|
||||
**kwargs: Any,
|
||||
) -> List[Dict]:
|
||||
) -> list[dict]:
|
||||
"""Return the raw data from the FMP endpoint."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import asyncio # noqa
|
||||
from openbb_core.provider.utils.errors import EmptyDataError
|
||||
from openbb_core.provider.utils.helpers import (
|
||||
amake_request,
|
||||
get_querystring,
|
||||
)
|
||||
from openbb_fmp.utils.helpers import get_interval, response_callback
|
||||
from warnings import warn
|
||||
|
||||
api_key = credentials.get("fmp_api_key") if credentials else ""
|
||||
|
||||
interval = get_interval(query.interval)
|
||||
@@ -111,17 +113,16 @@ class FMPCryptoHistoricalFetcher(
|
||||
|
||||
symbols = query.symbol.split(",")
|
||||
|
||||
results = []
|
||||
messages = []
|
||||
results: list = []
|
||||
messages: list = []
|
||||
|
||||
async def get_one(symbol):
|
||||
"""Get data for one symbol."""
|
||||
|
||||
url = get_url_params(symbol)
|
||||
data: list = []
|
||||
|
||||
data = []
|
||||
|
||||
response = await amake_request(url, **kwargs)
|
||||
response = await amake_request(url, response_callback=response_callback)
|
||||
|
||||
if isinstance(response, dict) and response.get("Error Message"):
|
||||
message = f"Error fetching data for {symbol}: {response.get('Error Message', '')}"
|
||||
@@ -161,13 +162,13 @@ class FMPCryptoHistoricalFetcher(
|
||||
|
||||
@staticmethod
|
||||
def transform_data(
|
||||
query: FMPCryptoHistoricalQueryParams, data: List[Dict], **kwargs: Any
|
||||
) -> List[FMPCryptoHistoricalData]:
|
||||
query: FMPCryptoHistoricalQueryParams, data: list[dict], **kwargs: Any
|
||||
) -> list[FMPCryptoHistoricalData]:
|
||||
"""Return the transformed data."""
|
||||
|
||||
# Get rid of duplicate fields.
|
||||
to_pop = ["label", "changePercent", "unadjustedVolume"]
|
||||
results: List[FMPCryptoHistoricalData] = []
|
||||
results: list[FMPCryptoHistoricalData] = []
|
||||
|
||||
for d in sorted(
|
||||
data,
|
||||
@@ -179,8 +180,8 @@ class FMPCryptoHistoricalFetcher(
|
||||
reverse=False,
|
||||
):
|
||||
_ = [d.pop(pop) for pop in to_pop if pop in d]
|
||||
if d.get("unadjusted_volume") == d.get("volume"):
|
||||
_ = d.pop("unadjusted_volume")
|
||||
if d.get("unadjusted_volume") and d["adjusted_volume"] == d.get("volume"):
|
||||
_ = d.pop("unadjusted_volume", None)
|
||||
results.append(FMPCryptoHistoricalData.model_validate(d))
|
||||
|
||||
return results
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
import asyncio
|
||||
from datetime import date as dateType
|
||||
from typing import Any, Dict, List, Optional
|
||||
from warnings import warn
|
||||
from typing import Any, Optional
|
||||
|
||||
from openbb_core.app.model.abstract.error import OpenBBError
|
||||
from openbb_core.provider.abstract.fetcher import Fetcher
|
||||
@@ -13,9 +11,6 @@ from openbb_core.provider.standard_models.forward_pe_estimates import (
|
||||
ForwardPeEstimatesData,
|
||||
ForwardPeEstimatesQueryParams,
|
||||
)
|
||||
from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError
|
||||
from openbb_core.provider.utils.helpers import amake_request
|
||||
from openbb_intrinio.utils.helpers import response_callback
|
||||
from pydantic import Field
|
||||
|
||||
|
||||
@@ -59,13 +54,13 @@ class IntrinioForwardPeEstimatesData(ForwardPeEstimatesData):
|
||||
|
||||
|
||||
class IntrinioForwardPeEstimatesFetcher(
|
||||
Fetcher[IntrinioForwardPeEstimatesQueryParams, List[IntrinioForwardPeEstimatesData]]
|
||||
Fetcher[IntrinioForwardPeEstimatesQueryParams, list[IntrinioForwardPeEstimatesData]]
|
||||
):
|
||||
"""Intrinio Forward PE Estimates Fetcher."""
|
||||
|
||||
@staticmethod
|
||||
def transform_query(
|
||||
params: Dict[str, Any]
|
||||
params: dict[str, Any],
|
||||
) -> IntrinioForwardPeEstimatesQueryParams:
|
||||
"""Transform the query params."""
|
||||
return IntrinioForwardPeEstimatesQueryParams(**params)
|
||||
@@ -73,14 +68,20 @@ class IntrinioForwardPeEstimatesFetcher(
|
||||
@staticmethod
|
||||
async def aextract_data(
|
||||
query: IntrinioForwardPeEstimatesQueryParams,
|
||||
credentials: Optional[Dict[str, str]],
|
||||
credentials: Optional[dict[str, str]],
|
||||
**kwargs: Any,
|
||||
) -> List[Dict]:
|
||||
) -> list[dict]:
|
||||
"""Return the raw data from the Intrinio endpoint."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import asyncio # noqa
|
||||
from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError
|
||||
from openbb_core.provider.utils.helpers import amake_request
|
||||
from openbb_intrinio.utils.helpers import response_callback
|
||||
|
||||
api_key = credentials.get("intrinio_api_key") if credentials else ""
|
||||
BASE_URL = "https://api-v2.intrinio.com/zacks/forward_pe"
|
||||
symbols = query.symbol.split(",") if query.symbol else None
|
||||
results: List[Dict] = []
|
||||
results: list[dict] = []
|
||||
|
||||
async def get_one(symbol):
|
||||
"""Get the data for one symbol."""
|
||||
@@ -90,33 +91,51 @@ class IntrinioForwardPeEstimatesFetcher(
|
||||
url, response_callback=response_callback, **kwargs
|
||||
)
|
||||
except Exception as e:
|
||||
warn(f"Symbol Error: {symbol} --> {e}")
|
||||
else:
|
||||
if data:
|
||||
results.append(data) # type: ignore
|
||||
raise OpenBBError(e) from e
|
||||
|
||||
if data:
|
||||
results.append(data) # type: ignore
|
||||
|
||||
if symbols:
|
||||
await asyncio.gather(*[get_one(symbol) for symbol in symbols])
|
||||
if not results:
|
||||
raise EmptyDataError(
|
||||
f"There were no results found for any of the given symbols. -> {symbols}"
|
||||
try:
|
||||
gather_results = await asyncio.gather(
|
||||
*[get_one(symbol) for symbol in symbols], return_exceptions=True
|
||||
)
|
||||
return results
|
||||
|
||||
for result in gather_results:
|
||||
if isinstance(result, UnauthorizedError):
|
||||
raise result
|
||||
if isinstance(result, OpenBBError):
|
||||
raise result
|
||||
|
||||
if not results:
|
||||
raise EmptyDataError(
|
||||
f"There were no results found for any of the given symbols. -> {symbols}"
|
||||
)
|
||||
return results
|
||||
except Exception as e:
|
||||
raise OpenBBError(
|
||||
f"Error in Intrinio request -> {e} -> {symbols}"
|
||||
) from e
|
||||
|
||||
async def fetch_callback(response, session):
|
||||
"""Use callback for pagination."""
|
||||
data = await response.json()
|
||||
error = data.get("error", None)
|
||||
|
||||
if error:
|
||||
message = data.get("message", "")
|
||||
if "api key" in message.lower():
|
||||
if "api key" in message.lower() or "view this data" in error.lower():
|
||||
raise UnauthorizedError(
|
||||
f"Unauthorized Intrinio request -> {message}"
|
||||
f"Unauthorized Intrinio request -> {message} -> {error}"
|
||||
)
|
||||
raise OpenBBError(f"Error: {error} -> {message}")
|
||||
|
||||
forward_pe = data.get("forward_pe")
|
||||
|
||||
if forward_pe and len(forward_pe) > 0: # type: ignore
|
||||
results.extend(forward_pe) # type: ignore
|
||||
|
||||
return results
|
||||
|
||||
url = f"{BASE_URL}?page_size=10000&api_key={api_key}"
|
||||
@@ -130,9 +149,9 @@ class IntrinioForwardPeEstimatesFetcher(
|
||||
@staticmethod
|
||||
def transform_data(
|
||||
query: IntrinioForwardPeEstimatesQueryParams,
|
||||
data: List[Dict],
|
||||
data: list[dict],
|
||||
**kwargs: Any,
|
||||
) -> List[IntrinioForwardPeEstimatesData]:
|
||||
) -> list[IntrinioForwardPeEstimatesData]:
|
||||
"""Transform the raw data into the standard format."""
|
||||
symbols = query.symbol.split(",") if query.symbol else []
|
||||
if symbols:
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Literal, Optional
|
||||
from warnings import warn
|
||||
from typing import Any, Literal, Optional
|
||||
|
||||
from openbb_core.provider.abstract.fetcher import Fetcher
|
||||
from openbb_core.provider.standard_models.index_historical import (
|
||||
@@ -95,13 +94,13 @@ class PolygonIndexHistoricalData(IndexHistoricalData):
|
||||
class PolygonIndexHistoricalFetcher(
|
||||
Fetcher[
|
||||
PolygonIndexHistoricalQueryParams,
|
||||
List[PolygonIndexHistoricalData],
|
||||
list[PolygonIndexHistoricalData],
|
||||
]
|
||||
):
|
||||
"""Polygon Index Historical Fetcher."""
|
||||
|
||||
@staticmethod
|
||||
def transform_query(params: Dict[str, Any]) -> PolygonIndexHistoricalQueryParams:
|
||||
def transform_query(params: dict[str, Any]) -> PolygonIndexHistoricalQueryParams:
|
||||
"""Transform the query params."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from dateutil.relativedelta import relativedelta
|
||||
@@ -119,18 +118,21 @@ class PolygonIndexHistoricalFetcher(
|
||||
@staticmethod
|
||||
async def aextract_data(
|
||||
query: PolygonIndexHistoricalQueryParams,
|
||||
credentials: Optional[Dict[str, str]],
|
||||
credentials: Optional[dict[str, str]],
|
||||
**kwargs: Any,
|
||||
) -> List[Dict]:
|
||||
) -> list[dict]:
|
||||
"""Extract raw data from the Polygon endpoint."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from openbb_core.provider.utils.helpers import ( # noqa
|
||||
from aiohttp import ClientResponseError # noqa
|
||||
from openbb_core.provider.utils.errors import OpenBBError, UnauthorizedError
|
||||
from openbb_core.provider.utils.helpers import (
|
||||
ClientResponse,
|
||||
ClientSession,
|
||||
amake_requests,
|
||||
safe_fromtimestamp,
|
||||
)
|
||||
from pytz import timezone # noqa
|
||||
from pytz import timezone
|
||||
from warnings import warn
|
||||
|
||||
api_key = credentials.get("polygon_api_key") if credentials else ""
|
||||
|
||||
@@ -146,9 +148,12 @@ class PolygonIndexHistoricalFetcher(
|
||||
|
||||
async def callback(
|
||||
response: ClientResponse, session: ClientSession
|
||||
) -> List[Dict]:
|
||||
) -> list[dict]:
|
||||
data = await response.json()
|
||||
|
||||
if isinstance(data, dict) and data.get("status") == "NOT_AUTHORIZED":
|
||||
raise UnauthorizedError(response.get("message", str(response)))
|
||||
|
||||
symbol = response.url.parts[4]
|
||||
next_url = data.get("next_url", None) # type: ignore[union-attr]
|
||||
results: list = data.get("results", []) # type: ignore[union-attr]
|
||||
@@ -178,14 +183,24 @@ class PolygonIndexHistoricalFetcher(
|
||||
|
||||
return results
|
||||
|
||||
return await amake_requests(urls, callback, **kwargs) # type: ignore
|
||||
try:
|
||||
return await amake_requests(urls, callback, raise_for_status=True) # type: ignore
|
||||
|
||||
except ClientResponseError as e:
|
||||
if e.status == 403:
|
||||
raise UnauthorizedError(
|
||||
f"Unauthorized Polygon request -> {e.message} -> {e.request_info.url}"
|
||||
) from e
|
||||
raise OpenBBError(
|
||||
f"Error in Polygon request -> {e} -> {e.request_info.url}"
|
||||
) from e
|
||||
|
||||
@staticmethod
|
||||
def transform_data(
|
||||
query: PolygonIndexHistoricalQueryParams,
|
||||
data: List[Dict],
|
||||
data: list[dict],
|
||||
**kwargs: Any,
|
||||
) -> List[PolygonIndexHistoricalData]:
|
||||
) -> list[PolygonIndexHistoricalData]:
|
||||
"""Transform the data."""
|
||||
if not data:
|
||||
raise EmptyDataError()
|
||||
|
||||
@@ -1,72 +1,31 @@
|
||||
"""Polygon Helpers Module."""
|
||||
|
||||
import json
|
||||
from io import StringIO
|
||||
from typing import Any, Dict, List, Optional, Tuple, TypeVar, Union
|
||||
from typing import Any, Optional, Tuple, Union
|
||||
|
||||
from openbb_core.app.model.abstract.error import OpenBBError
|
||||
from openbb_core.provider.utils.errors import EmptyDataError
|
||||
from openbb_core.provider.utils.errors import EmptyDataError, UnauthorizedError
|
||||
from openbb_core.provider.utils.helpers import (
|
||||
ClientResponse,
|
||||
ClientSession,
|
||||
amake_request,
|
||||
)
|
||||
from pydantic import BaseModel
|
||||
|
||||
T = TypeVar("T", bound=BaseModel)
|
||||
|
||||
|
||||
class BasicResponse:
|
||||
"""Basic Response class."""
|
||||
|
||||
def __init__(self, response: StringIO):
|
||||
"""Initialize the BasicResponse class."""
|
||||
# Find a way to get the status code
|
||||
self.status_code = 200
|
||||
response.seek(0)
|
||||
self.text = response.read()
|
||||
|
||||
def json(self) -> dict:
|
||||
"""Return the response as a dictionary."""
|
||||
return json.loads(self.text)
|
||||
|
||||
|
||||
def request(url: str) -> BasicResponse:
|
||||
"""Request function for PyScript.
|
||||
|
||||
Pass in Method and make sure to await.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
url: str
|
||||
URL to make request to
|
||||
|
||||
Return
|
||||
------
|
||||
response: BasicRequest
|
||||
BasicRequest object with status_code and text attributes
|
||||
"""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from pyodide.http import open_url # type: ignore
|
||||
|
||||
response = open_url(url)
|
||||
return BasicResponse(response)
|
||||
|
||||
|
||||
async def response_callback(
|
||||
response: ClientResponse, _: ClientSession
|
||||
) -> Union[dict, List[dict]]:
|
||||
) -> Union[dict, list]:
|
||||
"""Use callback for make_request."""
|
||||
data: Dict = await response.json() # type: ignore
|
||||
data = await response.json() # type: ignore
|
||||
|
||||
if response.status != 200:
|
||||
message = data.get("error") or data.get("message")
|
||||
raise OpenBBError(f"Error in Polygon request -> {message}")
|
||||
|
||||
keys_in_data = "results" in data or "tickers" in data
|
||||
if isinstance(data, dict) and data.get("status") == "NOT_AUTHORIZED":
|
||||
raise UnauthorizedError(response.get("message", str(response)))
|
||||
|
||||
if not keys_in_data or len(data) == 0:
|
||||
raise EmptyDataError()
|
||||
if not data:
|
||||
raise EmptyDataError("No data was returned from the Polygon endpoint")
|
||||
|
||||
return data
|
||||
|
||||
@@ -78,7 +37,7 @@ async def get_data(url: str, **kwargs: Any) -> Union[list, dict]:
|
||||
|
||||
async def get_data_many(
|
||||
url: str, sub_dict: Optional[str] = None, **kwargs: Any
|
||||
) -> List[dict]:
|
||||
) -> list[dict]:
|
||||
"""Get data from Polygon endpoint and convert to list of schemas.
|
||||
|
||||
Parameters
|
||||
|
||||
Reference in New Issue
Block a user