From bea21dff28759402b2317059e32afd6039d91123 Mon Sep 17 00:00:00 2001 From: montezdesousa <79287829+montezdesousa@users.noreply.github.com> Date: Fri, 10 Mar 2023 23:07:40 +0000 Subject: [PATCH] Handle pydantic ValidationError reading .env (#4456) * move tradier to data providers * handle env load errors * improve message * detail model in message --- .../core/models/credentials_model.py | 2 +- .../core/session/credentials_handler.py | 1 - openbb_terminal/core/session/current_user.py | 8 ++-- openbb_terminal/core/session/env_handler.py | 40 ++++++++++++++++++- 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/openbb_terminal/core/models/credentials_model.py b/openbb_terminal/core/models/credentials_model.py index 310e661bc87..a63f0662ebf 100644 --- a/openbb_terminal/core/models/credentials_model.py +++ b/openbb_terminal/core/models/credentials_model.py @@ -36,6 +36,7 @@ class CredentialsModel: API_TOKEN_TERMINAL_KEY: str = "REPLACE_ME" API_STOCKSERA_KEY: str = "REPLACE_ME" API_INTRINIO_KEY: str = "REPLACE_ME" + API_TRADIER_TOKEN: str = "REPLACE_ME" # Socials API_GITHUB_KEY: str = "REPLACE_ME" @@ -57,7 +58,6 @@ class CredentialsModel: OANDA_ACCOUNT_TYPE: str = "REPLACE_ME" OANDA_ACCOUNT: str = "REPLACE_ME" OANDA_TOKEN: str = "REPLACE_ME" - API_TRADIER_TOKEN: str = "REPLACE_ME" API_BINANCE_KEY: str = "REPLACE_ME" API_BINANCE_SECRET: str = "REPLACE_ME" API_COINBASE_KEY: str = "REPLACE_ME" diff --git a/openbb_terminal/core/session/credentials_handler.py b/openbb_terminal/core/session/credentials_handler.py index fc2f432c8fb..1f9448fb07d 100644 --- a/openbb_terminal/core/session/credentials_handler.py +++ b/openbb_terminal/core/session/credentials_handler.py @@ -22,7 +22,6 @@ LOCAL_KEYS = [ "OANDA_ACCOUNT_TYPE", "OANDA_ACCOUNT", "OANDA_TOKEN", - "API_TRADIER_TOKEN", "API_BINANCE_KEY", "API_BINANCE_SECRET", "API_COINBASE_KEY", diff --git a/openbb_terminal/core/session/current_user.py b/openbb_terminal/core/session/current_user.py index 340197f8f8d..9798963d1b2 100644 --- a/openbb_terminal/core/session/current_user.py +++ b/openbb_terminal/core/session/current_user.py @@ -9,11 +9,13 @@ from openbb_terminal.core.models import ( ProfileModel, UserModel, ) -from openbb_terminal.core.session.env_handler import reading_env +from openbb_terminal.core.session.env_handler import load_env_to_model, reading_env __env_dict = reading_env() -__credentials = CredentialsModel(**__env_dict) -__preferences = PreferencesModel(**__env_dict) +__credentials = load_env_to_model(__env_dict, CredentialsModel) +__preferences = load_env_to_model(__env_dict, PreferencesModel) + + __profile = ProfileModel() __local_user = UserModel( # type: ignore credentials=__credentials, diff --git a/openbb_terminal/core/session/env_handler.py b/openbb_terminal/core/session/env_handler.py index 97548e4f2db..35fec6c478c 100644 --- a/openbb_terminal/core/session/env_handler.py +++ b/openbb_terminal/core/session/env_handler.py @@ -1,8 +1,9 @@ # IMPORTS STANDARD -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Type, Union # IMPORTS THIRDPARTY from dotenv import dotenv_values +from pydantic import ValidationError # IMPORTS INTERNAL from openbb_terminal.core.config.paths import ( @@ -10,6 +11,8 @@ from openbb_terminal.core.config.paths import ( REPOSITORY_ENV_FILE, SETTINGS_ENV_FILE, ) +from openbb_terminal.core.models.credentials_model import CredentialsModel +from openbb_terminal.core.models.preferences_model import PreferencesModel def reading_env() -> Dict[str, Any]: @@ -31,3 +34,38 @@ def reading_env() -> Dict[str, Any]: } return __env_dict_filtered + + +def load_env_to_model( + env_dict: dict, model: Union[Type[CredentialsModel], Type[PreferencesModel]] +) -> Union[Type[CredentialsModel], Type[PreferencesModel]]: + """Load environment variables to model. + + Parameters + ---------- + env_dict : dict + Environment variables dictionary. + model : Union[Type[CredentialsModel], Type[PreferencesModel]] + Model to validate. + + Returns + ------- + Union[Type[CredentialsModel], Type[PreferencesModel]] + Model with environment variables. + """ + try: + return model(**env_dict) # type: ignore + except ValidationError as error: + model_name = model.__name__.strip("Model").lower() + print(f"Error loading {model_name}:") + for err in error.errors(): + loc = err.get("loc", None) + var_name = str(loc[0]) if loc else "" + msg = err.get("msg", "") + var = env_dict.pop(var_name, None) + fields = model.__dataclass_fields__ # type: ignore + if var and var_name in fields: + default = fields[var_name].default + print(f" {var_name}: {msg}, using default -> {default}") + + return model(**env_dict) # type: ignore