[Feature] - Update credential filters to v4 (#5949)

* update cred filters to v4

* ignore v3 key if v4 is there already

* add comment + unit test

* update hub state instead of replacing

* remove unused file

* fix unittests

* ruff

* add comment

* remove lc

* black

* comment

* comment

* comment

* comment

* send warning if v3 keys found

* tradier v3

* keep v3 intact

* better

* unit test + minor fixes

* cleaner

* comment

* sorted

* remove unecessary class

* remove ultima from v3tov4 map

* unit test v3tov4 map

* unit test v3tov4 map

* unit test v3tov4 map

* providers.json

* ^

---------

Co-authored-by: Igor Radovanovic <74266147+IgorWounds@users.noreply.github.com>
This commit is contained in:
montezdesousa
2024-04-15 16:09:18 +01:00
committed by GitHub
parent 40ce132109
commit 2c1e409e9c
8 changed files with 248 additions and 139 deletions

58
openbb_platform/assets/providers.json vendored Normal file
View File

@@ -0,0 +1,58 @@
[
{
"name": "Alpha Vantage",
"credentials": ["alpha_vantage_api_key"],
"v3_credentials": ["API_KEY_ALPHAVANTAGE"],
"link": "https://www.alphavantage.co/support/#api-key",
"instructions": "Go to: https://www.alphavantage.co/support/#api-key\n\n![AlphaVantage](https://user-images.githubusercontent.com/46355364/207820936-46c2ba00-81ff-4cd3-98a4-4fa44412996f.png)\n\nFill out the form, pass Captcha, and click on, \"GET FREE API KEY\"."
},
{
"name": "BizToc",
"credentials": ["biztoc_api_key"],
"v3_credentials": ["API_BIZTOC_TOKEN"],
"link": "https://biztoc.com",
"instructions": "The BizToc API is hosted on RapidAPI. To set up, go to: https://rapidapi.com/thma/api/biztoc.\n\n![biztoc0](https://github.com/marban/OpenBBTerminal/assets/18151143/04cdd423-f65e-4ad8-ad5a-4a59b0f5ddda)\n\nIn the top right, select 'Sign Up'. After answering some questions, you will be prompted to select one of their plans.\n\n![biztoc1](https://github.com/marban/OpenBBTerminal/assets/18151143/9f3b72ea-ded7-48c5-aa33-bec5c0de8422)\n\nAfter signing up, navigate back to https://rapidapi.com/thma/api/biztoc. If you are logged in, you will see a header called X-RapidAPI-Key.\n\n![biztoc2](https://github.com/marban/OpenBBTerminal/assets/18151143/0f3b6c91-07e0-447a-90cd-a9e23522929f)"
},
{
"name": "FRED",
"credentials": ["fred_api_key"],
"v3_credentials": ["API_FRED_KEY"],
"link": "https://fred.stlouisfed.org/docs/api/api_key.html",
"instructions": "Go to: https://fred.stlouisfed.org\n\n![FRED](https://user-images.githubusercontent.com/46355364/207827137-d143ba4c-72cb-467d-a7f4-5cc27c597aec.png)\n\nClick on, \"My Account\", create a new account or sign in with Google:\n\n![FRED](https://user-images.githubusercontent.com/46355364/207827011-65cdd501-27e3-436f-bd9d-b0d8381d46a7.png)\n\nAfter completing the sign-up, go to \"My Account\", and select \"API Keys\". Then, click on, \"Request API Key\".\n\n![FRED](https://user-images.githubusercontent.com/46355364/207827577-c869f989-4ef4-4949-ab57-6f3931f2ae9d.png)\n\nFill in the box for information about the use-case for FRED, and by clicking, \"Request API key\", at the bottom of the page, the API key will be issued.\n\n![FRED](https://user-images.githubusercontent.com/46355364/207828032-0a32d3b8-1378-4db2-9064-aa1eb2111632.png)"
},
{
"name": "Financial Modeling Prep",
"credentials": ["fmp_api_key"],
"v3_credentials": ["API_KEY_FINANCIALMODELINGPREP"],
"link": "https://financialmodelingprep.com/developer",
"instructions": "Go to: https://site.financialmodelingprep.com/developer/docs\n\n![FinancialModelingPrep](https://user-images.githubusercontent.com/46355364/207821920-64553d05-d461-4984-b0fe-be0368c71186.png)\n\nClick on, \"Get my API KEY here\", and sign up for a free account.\n\n![FinancialModelingPrep](https://user-images.githubusercontent.com/46355364/207822184-a723092e-ef42-4f87-8c55-db150f09741b.png)\n\nWith an account created, sign in and navigate to the Dashboard, which shows the assigned token. by pressing the \"Dashboard\" button which will show the API key.\n\n![FinancialModelingPrep](https://user-images.githubusercontent.com/46355364/207823170-dd8191db-e125-44e5-b4f3-2df0e115c91d.png)"
},
{
"name": "Intrinio",
"credentials": ["intrinio_api_key"],
"v3_credentials": ["API_INTRINIO_KEY"],
"link": "https://intrinio.com/",
"instructions": "Go to: https://intrinio.com/starter-plan\n\n![Intrinio](https://user-images.githubusercontent.com/85772166/219207556-fcfee614-59f1-46ae-bff4-c63dd2f6991d.png)\n\nAn API key will be issued with a subscription. Find the token value within the account dashboard."
},
{
"name": "Polygon",
"credentials": ["polygon_api_key"],
"v3_credentials": ["API_POLYGON_KEY"],
"link": "https://polygon.io",
"instructions": "Go to: https://polygon.io\n\n![Polygon](https://user-images.githubusercontent.com/46355364/207825623-fcd7f0a3-131a-4294-808c-754c13e38e2a.png)\n\nClick on, \"Get your Free API Key\".\n\n![Polygon](https://user-images.githubusercontent.com/46355364/207825952-ca5540ec-6ed2-4cef-a0ed-bb50b813932c.png)\n\nAfter signing up, the API Key is found at the bottom of the account dashboard page.\n\n![Polygon](https://user-images.githubusercontent.com/46355364/207826258-b1f318fa-fd9c-41d9-bf5c-fe16722e6601.png)"
},
{
"name": "Nasdaq",
"credentials": ["nasdaq_api_key"],
"v3_credentials": ["API_KEY_QUANDL"],
"link": "https://www.quandl.com/tools/api",
"instructions": "Go to: https://www.quandl.com\n\n![Quandl](https://user-images.githubusercontent.com/46355364/207823899-208a3952-f557-4b73-aee6-64ac00faedb7.png)\n\nClick on, \"Sign Up\", and register a new account.\n\n![Quandl](https://user-images.githubusercontent.com/46355364/207824214-4b6b2b74-e709-4ed4-adf2-14803e6f3568.png)\n\nFollow the sign-up instructions, and upon completion the API key will be assigned.\n\n![Quandl](https://user-images.githubusercontent.com/46355364/207824664-3c82befb-9c69-42df-8a82-510d85c19a97.png)"
},
{
"name": "Tradier",
"credentials": ["tradier_api_key"],
"v3_credentials": ["API_TRADIER_TOKEN"],
"link": "https://tradier.com/products/market-data-api",
"instructions": "Go to: https://documentation.tradier.com\n\n![Tradier](https://user-images.githubusercontent.com/46355364/207829178-a8bba770-f2ea-4480-b28e-efd81cf30980.png)\n\nClick on, \"Open Account\", to start the sign-up process. After the account has been setup, navigate to [Tradier Broker Dash](https://dash.tradier.com/login?redirect=settings.api) and create the application. Request a sandbox access token."
}
]

View File

@@ -1,41 +0,0 @@
"""Model for API keys for various providers."""
from typing import Optional
from pydantic import BaseModel, Field
class FeaturesKeys(BaseModel):
"""API keys for various providers."""
API_BITQUERY_KEY: Optional[str] = Field(default=None)
API_BIZTOC_TOKEN: Optional[str] = Field(default=None)
API_CMC_KEY: Optional[str] = Field(default=None)
API_COINGLASS_KEY: Optional[str] = Field(default=None)
API_CRYPTO_PANIC_KEY: Optional[str] = Field(default=None)
API_DAPPRADAR_KEY: Optional[str] = Field(default=None)
API_DATABENTO_KEY: Optional[str] = Field(default=None)
API_EODHD_KEY: Optional[str] = Field(default=None)
API_ETHPLORER_KEY: Optional[str] = Field(default=None)
API_FINNHUB_KEY: Optional[str] = Field(default=None)
API_FRED_KEY: Optional[str] = Field(default=None)
API_GITHUB_KEY: Optional[str] = Field(default=None)
API_GLASSNODE_KEY: Optional[str] = Field(default=None)
API_INTRINIO_KEY: Optional[str] = Field(default=None)
API_KEY_ALPHAVANTAGE: Optional[str] = Field(default=None)
API_KEY_FINANCIALMODELINGPREP: Optional[str] = Field(default=None)
API_KEY_QUANDL: Optional[str] = Field(default=None)
API_MESSARI_KEY: Optional[str] = Field(default=None)
API_NEWS_TOKEN: Optional[str] = Field(default=None)
API_POLYGON_KEY: Optional[str] = Field(default=None)
API_REDDIT_CLIENT_ID: Optional[str] = Field(default=None)
API_REDDIT_CLIENT_SECRET: Optional[str] = Field(default=None)
API_REDDIT_PASSWORD: Optional[str] = Field(default=None)
API_REDDIT_USERNAME: Optional[str] = Field(default=None)
API_REDDIT_USER_AGENT: Optional[str] = Field(default=None)
API_SANTIMENT_KEY: Optional[str] = Field(default=None)
API_SHROOM_KEY: Optional[str] = Field(default=None)
API_SMARTSTAKE_KEY: Optional[str] = Field(default=None)
API_SMARTSTAKE_TOKEN: Optional[str] = Field(default=None)
API_TOKEN_TERMINAL_KEY: Optional[str] = Field(default=None)
API_WHALE_ALERT_KEY: Optional[str] = Field(default=None)

View File

@@ -1,16 +1,15 @@
"""Hub user settings model."""
# from typing import Dict, List, Union
from typing import Dict, Optional
from openbb_core.app.model.hub.features_keys import FeaturesKeys
from pydantic import BaseModel, ConfigDict, Field
class HubUserSettings(BaseModel):
"""User settings for the Hub."""
"""Hub user settings model."""
# features_settings: Dict[str, str]
features_keys: FeaturesKeys = Field(default_factory=FeaturesKeys)
features_keys: Dict[str, Optional[str]] = Field(default_factory=dict)
# features_sources: Dict[str, List[str]]
# features_terminal_style: Dict[str, Union[str, Dict[str, str]]]

View File

@@ -1,6 +1,7 @@
"""Hub manager class."""
from typing import Optional
from warnings import warn
from fastapi import HTTPException
from jose import JWTError
@@ -8,13 +9,11 @@ from jose.exceptions import ExpiredSignatureError
from jose.jwt import decode, get_unverified_header
from openbb_core.app.model.abstract.error import OpenBBError
from openbb_core.app.model.credentials import Credentials
from openbb_core.app.model.hub.features_keys import FeaturesKeys
from openbb_core.app.model.hub.hub_session import HubSession
from openbb_core.app.model.hub.hub_user_settings import HubUserSettings
from openbb_core.app.model.profile import Profile
from openbb_core.app.model.user_settings import UserSettings
from openbb_core.env import Env
from pydantic import SecretStr
from requests import get, post, put
@@ -22,6 +21,18 @@ class HubService:
"""Hub service class."""
TIMEOUT = 10
# Mapping of V3 keys to V4 keys for backward compatibility
V3TOV4 = {
"API_KEY_ALPHAVANTAGE": "alpha_vantage_api_key",
"API_BIZTOC_TOKEN": "biztoc_api_key",
"API_FRED_KEY": "fred_api_key",
"API_KEY_FINANCIALMODELINGPREP": "fmp_api_key",
"API_INTRINIO_KEY": "intrinio_api_key",
"API_POLYGON_KEY": "polygon_api_key",
"API_KEY_QUANDL": "nasdaq_api_key",
"API_TRADIER_TOKEN": "tradier_api_key",
}
V4TOV3 = {v: k for k, v in V3TOV4.items()}
def __init__(
self,
@@ -31,6 +42,7 @@ class HubService:
"""Initialize Hub service."""
self._base_url = base_url or Env().HUB_BACKEND
self._session = session
self._hub_user_settings: Optional[HubUserSettings] = None
@property
def base_url(self) -> str:
@@ -81,13 +93,10 @@ class HubService:
def pull(self) -> UserSettings:
"""Pull user settings from Hub."""
if self._session:
hub_user_settings = self._get_user_settings(self._session)
if hub_user_settings:
profile = Profile(
hub_session=self._session,
)
credentials = self.hub2platform(hub_user_settings)
return UserSettings(profile=profile, credentials=credentials)
self._hub_user_settings = self._get_user_settings(self._session)
profile = Profile(hub_session=self._session)
credentials = self.hub2platform(self._hub_user_settings)
return UserSettings(profile=profile, credentials=credentials)
raise OpenBBError(
"No session found. Login or provide a 'HubSession' on initialization."
)
@@ -216,42 +225,38 @@ class HubService:
detail = response.json().get("detail", None)
raise HTTPException(status_code, detail)
@classmethod
def hub2platform(cls, settings: HubUserSettings) -> Credentials:
def hub2platform(self, settings: HubUserSettings) -> Credentials:
"""Convert Hub user settings to Platform models."""
# TODO: Hub is getting credentials from `all_api_keys.json`, which uses
# the terminal names conventions. We need to update it to use a file that
# lives here in the platform and maps the credential names between the two.
credentials = Credentials(
alpha_vantage_api_key=settings.features_keys.API_KEY_ALPHAVANTAGE,
biztoc_api_key=settings.features_keys.API_BIZTOC_TOKEN,
fred_api_key=settings.features_keys.API_FRED_KEY,
fmp_api_key=settings.features_keys.API_KEY_FINANCIALMODELINGPREP,
intrinio_api_key=settings.features_keys.API_INTRINIO_KEY,
polygon_api_key=settings.features_keys.API_POLYGON_KEY,
nasdaq_api_key=settings.features_keys.API_KEY_QUANDL,
)
return credentials
if any(k in settings.features_keys for k in self.V3TOV4):
deprecated = {
k: v for k, v in self.V3TOV4.items() if k in settings.features_keys
}
msg = ""
for k, v in deprecated.items():
msg += f"\n'{k}' -> '{v}', "
msg = msg.strip(", ")
warn(
message=f"\nDeprecated v3 credentials found.\n{msg}"
"\n\nYou can update them at https://my.openbb.co/app/platform/credentials.",
)
# We give priority to v4 keys over v3 keys if both are present
hub_credentials = {
self.V3TOV4.get(k, k): settings.features_keys.get(self.V3TOV4.get(k, k), v)
for k, v in settings.features_keys.items()
}
return Credentials(**hub_credentials)
@classmethod
def platform2hub(cls, credentials: Credentials) -> HubUserSettings:
def platform2hub(self, credentials: Credentials) -> HubUserSettings:
"""Convert Platform models to Hub user settings."""
def get_cred(cred: str) -> Optional[str]:
secret_str: Optional[SecretStr] = getattr(credentials, cred, None)
return secret_str.get_secret_value() if secret_str else None
features_keys = FeaturesKeys(
API_BIZTOC_TOKEN=get_cred("biztoc_api_key"),
API_FRED_KEY=get_cred("fred_api_key"),
API_INTRINIO_KEY=get_cred("intrinio_api_key"),
API_KEY_ALPHAVANTAGE=get_cred("alpha_vantage_api_key"),
API_KEY_FINANCIALMODELINGPREP=get_cred("fmp_api_key"),
API_POLYGON_KEY=get_cred("polygon_api_key"),
API_KEY_QUANDL=get_cred("nasdaq_api_key"),
)
hub_user_settings = HubUserSettings(features_keys=features_keys)
return hub_user_settings
# Dump mode json ensures SecretStr values are serialized as strings
credentials = credentials.model_dump(mode="json", exclude_none=True)
settings = self._hub_user_settings or HubUserSettings()
for v4_k, v in sorted(credentials.items()):
v3_k = self.V4TOV3.get(v4_k, None)
# If v3 key was there, we keep it
k = v3_k if v3_k in settings.features_keys else v4_k
settings.features_keys[k] = v
return settings
@staticmethod
def check_token_expiration(token: str) -> None:

View File

@@ -34,6 +34,7 @@ class Account:
self._openbb_directory = (
base_app._command_runner.system_settings.openbb_directory
)
self._hub_service: Optional[HubService] = None
def __repr__(self) -> str:
"""Human readable representation of the object."""
@@ -120,18 +121,20 @@ class Account:
Optional[UserSettings]
User settings: profile, credentials, preferences
"""
hs = self._create_hub_service(email, password, pat)
incoming = hs.pull()
self._hub_service = self._create_hub_service(email, password, pat)
incoming = self._hub_service.pull()
updated: UserSettings = UserService.update_default(incoming)
self._base_app._command_runner.user_settings = updated
if remember_me:
Path(self._openbb_directory).mkdir(parents=False, exist_ok=True)
session_file = Path(self._openbb_directory, self.SESSION_FILE)
with open(session_file, "w") as f:
if not hs.session:
if not self._hub_service.session:
raise OpenBBError("Not connected to hub.")
json.dump(hs.session.model_dump(mode="json"), f, indent=4)
json.dump(
self._hub_service.session.model_dump(mode="json"), f, indent=4
)
if return_settings:
return self._base_app._command_runner.user_settings
@@ -151,14 +154,12 @@ class Account:
Optional[UserSettings]
User settings: profile, credentials, preferences
"""
hub_session = self._base_app._command_runner.user_settings.profile.hub_session
if not hub_session:
if not self._hub_service:
UserService.write_default_user_settings(
self._base_app._command_runner.user_settings
)
else:
hs = HubService(hub_session)
hs.push(self._base_app._command_runner.user_settings)
self._hub_service.push(self._base_app._command_runner.user_settings)
if return_settings:
return self._base_app._command_runner.user_settings
@@ -178,14 +179,12 @@ class Account:
Optional[UserSettings]
User settings: profile, credentials, preferences
"""
hub_session = self._base_app._command_runner.user_settings.profile.hub_session
if not hub_session:
if not self._hub_service:
self._base_app._command_runner.user_settings = (
UserService.read_default_user_settings()
)
else:
hs = HubService(hub_session)
incoming = hs.pull()
incoming = self._hub_service.pull()
updated: UserSettings = UserService.update_default(incoming)
updated.id = self._base_app._command_runner.user_settings.id
self._base_app._command_runner.user_settings = updated
@@ -208,12 +207,10 @@ class Account:
Optional[UserSettings]
User settings: profile, credentials, preferences
"""
hub_session = self._base_app._command_runner.user_settings.profile.hub_session
if not hub_session:
if not self._hub_service:
raise OpenBBError("Not connected to hub.")
hs = HubService(hub_session)
hs.disconnect()
self._hub_service.disconnect()
session_file = Path(self._openbb_directory, self.SESSION_FILE)
if session_file.exists():

View File

@@ -62,10 +62,7 @@ class BaseApp:
def create_app(extensions: Optional[E] = None) -> Type[BaseApp]:
"""Create the app."""
class EmptyClass:
pass
class App(BaseApp, extensions or EmptyClass): # type: ignore
class App(BaseApp, extensions or object): # type: ignore[misc]
def __repr__(self) -> str:
# pylint: disable=E1101
ext_doc = extensions.__doc__ if extensions else ""

View File

@@ -1,13 +0,0 @@
"""Test the FeaturesKeys class."""
from openbb_core.app.model.hub.features_keys import FeaturesKeys
# ruff: noqa: S105 S106
def test_features_keys():
"""Test the FeaturesKeys class."""
fk = FeaturesKeys(API_BITQUERY_KEY="test", API_BIZTOC_TOKEN="test2")
assert fk.API_BITQUERY_KEY == "test"
assert fk.API_BIZTOC_TOKEN == "test2"

View File

@@ -4,10 +4,10 @@
# ruff: noqa: S105 S106
from pathlib import Path
from unittest.mock import MagicMock, patch
import pytest
from openbb_core.app.model.hub.features_keys import FeaturesKeys
from openbb_core.app.service.hub_service import (
Credentials,
HubService,
@@ -25,6 +25,66 @@ def mocker():
yield mock
def test_v3tov4_map():
"""Test v3 to v4 map."""
v3_keys = {
"databento": "API_DATABENTO_KEY",
"alpha_vantage": "API_KEY_ALPHAVANTAGE",
"fmp": "API_KEY_FINANCIALMODELINGPREP",
"nasdaq": "API_KEY_QUANDL",
"polygon": "API_POLYGON_KEY",
"fred": "API_FRED_KEY",
"news_api": "API_NEWS_TOKEN",
"biztoc": "API_BIZTOC_TOKEN",
"cmc": "API_CMC_KEY",
"finnhub": "API_FINNHUB_KEY",
"whale_alert": "API_WHALE_ALERT_KEY",
"glassnode": "API_GLASSNODE_KEY",
"coinglass": "API_COINGLASS_KEY",
"ethplorer": "API_ETHPLORER_KEY",
"cryptopanic": "API_CRYPTO_PANIC_KEY",
"crypto_panic": "API_CRYPTO_PANIC_KEY", # If dev choses to use this name
"bitquery": "API_BITQUERY_KEY",
"smartstake": ["API_SMARTSTAKE_KEY", "API_SMARTSTAKE_TOKEN"],
"messari": "API_MESSARI_KEY",
"shroom": "API_SHROOM_KEY",
"santiment": "API_SANTIMENT_KEY",
"eodhd": "API_EODHD_KEY",
"tokenterminal": "API_TOKEN_TERMINAL_KEY",
"token_terminal": "API_TOKEN_TERMINAL_KEY", # If dev choses to use this name
"intrinio": "API_INTRINIO_KEY",
"github": "API_GITHUB_KEY",
"reddit": [
"API_REDDIT_CLIENT_ID",
"API_REDDIT_CLIENT_SECRET",
"API_REDDIT_USERNAME",
"API_REDDIT_USER_AGENT",
"API_REDDIT_PASSWORD",
],
"companies_house": "API_COMPANIESHOUSE_KEY",
"companieshouse": "API_COMPANIESHOUSE_KEY", # If dev choses to use this name
"dappradar": "API_DAPPRADAR_KEY",
"nixtla": "API_KEY_NIXTLA",
}
providers = sorted(
[
p.stem
for p in Path("openbb_platform", "providers").glob("*")
if p.is_dir() and p.name not in ("__pycache__", "tests")
]
)
for provider in providers:
if provider in v3_keys:
keys = v3_keys[provider]
if not isinstance(keys, list):
keys = [keys]
for k in keys:
assert k in HubService.V3TOV4
def test_connect_with_email_password():
"""Test connect with email and password."""
mock_hub_session = MagicMock(spec=HubSession)
@@ -173,31 +233,78 @@ def test_put_user_settings():
)
def test_hub2platform():
def test_hub2platform_v4_only():
"""Test hub2platform."""
mock_user_settings = MagicMock(spec=HubUserSettings)
mock_user_settings.features_keys = FeaturesKeys(
API_KEY_FINANCIALMODELINGPREP="fmp",
API_POLYGON_KEY="polygon",
API_FRED_KEY="fred",
)
mock_user_settings.features_keys = {
"fmp_api_key": "abc",
"polygon_api_key": "def",
"fred_api_key": "ghi",
}
credentials = HubService.hub2platform(mock_user_settings)
credentials = HubService().hub2platform(mock_user_settings)
assert isinstance(credentials, Credentials)
assert credentials.fmp_api_key.get_secret_value() == "fmp"
assert credentials.polygon_api_key.get_secret_value() == "polygon"
assert credentials.fred_api_key.get_secret_value() == "fred"
assert credentials.fmp_api_key.get_secret_value() == "abc"
assert credentials.polygon_api_key.get_secret_value() == "def"
assert credentials.fred_api_key.get_secret_value() == "ghi"
def test_hub2platform_v3_only():
"""Test hub2platform."""
mock_user_settings = MagicMock(spec=HubUserSettings)
mock_user_settings.features_keys = {
"API_KEY_FINANCIALMODELINGPREP": "abc",
"API_POLYGON_KEY": "def",
"API_FRED_KEY": "ghi",
}
credentials = HubService().hub2platform(mock_user_settings)
assert isinstance(credentials, Credentials)
assert credentials.fmp_api_key.get_secret_value() == "abc"
assert credentials.polygon_api_key.get_secret_value() == "def"
assert credentials.fred_api_key.get_secret_value() == "ghi"
def test_hub2platform_v3v4():
"""Test hub2platform."""
mock_user_settings = MagicMock(spec=HubUserSettings)
mock_user_settings.features_keys = {
"API_KEY_FINANCIALMODELINGPREP": "abc",
"fmp_api_key": "other_key",
"API_POLYGON_KEY": "def",
"API_FRED_KEY": "ghi",
}
credentials = HubService().hub2platform(mock_user_settings)
assert isinstance(credentials, Credentials)
assert credentials.fmp_api_key.get_secret_value() == "other_key"
assert credentials.polygon_api_key.get_secret_value() == "def"
assert credentials.fred_api_key.get_secret_value() == "ghi"
def test_platform2hub():
"""Test platform2hub."""
mock_credentials = MagicMock(spec=Credentials)
mock_credentials.fmp_api_key = SecretStr("fmp")
mock_credentials.polygon_api_key = SecretStr("polygon")
mock_credentials.fred_api_key = SecretStr("fred")
mock_user_settings = MagicMock(spec=HubUserSettings)
mock_user_settings.features_keys = { # Received from Hub
"API_KEY_FINANCIALMODELINGPREP": "abc",
"fmp_api_key": "other_key",
"API_FRED_KEY": "ghi",
}
mock_hub_service = HubService()
mock_hub_service._hub_user_settings = mock_user_settings
mock_credentials = Credentials( # Current credentials
fmp_api_key=SecretStr("fmp"),
polygon_api_key=SecretStr("polygon"),
fred_api_key=SecretStr("fred"),
benzinga_api_key=SecretStr("benzinga"),
some_api_key=SecretStr("some"),
)
user_settings = mock_hub_service.platform2hub(mock_credentials)
user_settings = HubService.platform2hub(mock_credentials)
assert isinstance(user_settings, HubUserSettings)
assert user_settings.features_keys.API_KEY_FINANCIALMODELINGPREP == "fmp"
assert user_settings.features_keys.API_POLYGON_KEY == "polygon"
assert user_settings.features_keys.API_FRED_KEY == "fred"
assert user_settings.features_keys["API_KEY_FINANCIALMODELINGPREP"] == "fmp"
assert user_settings.features_keys["fmp_api_key"] == "other_key"
assert user_settings.features_keys["polygon_api_key"] == "polygon"
assert user_settings.features_keys["API_FRED_KEY"] == "fred"
assert user_settings.features_keys["benzinga_api_key"] == "benzinga"
assert "some_api_key" not in user_settings.features_keys