From f822b0afa3e192fba052f73134f2e8b127a68a7e Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Sat, 12 Aug 2023 17:48:36 -0700 Subject: [PATCH 01/10] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 221332fb10d..8c9170ac86c 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,9 @@ Any of our social media platforms: [openbb.co/links](https://openbb.co/links) ## 6. Star History -This is a proxy of our growth and that we are just getting started. But for more metrics important to us check [openbb.co/open](https://openbb.co/open). +This is a proxy of our growth and that we are just getting started. + +But for more metrics important to us check [openbb.co/open](https://openbb.co/open). [![Star History Chart](https://api.star-history.com/svg?repos=openbb-finance/OpenBBTerminal&type=Date)](https://star-history.com/#openbb-finance/OpenBBTerminal&Date) From db746aa1a9a6850634ef1cedea2f9a46805f0e7e Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Sun, 13 Aug 2023 02:27:26 -0500 Subject: [PATCH 02/10] Silly (#5313) * check that routine title is valid * more updates * small fixes * override local routine * more improvements to routine logic --- openbb_terminal/core/session/hub_model.py | 6 + .../econometrics/econometrics_controller.py | 2 +- .../quantitative_analysis/qa_controller.py | 2 +- openbb_terminal/featflags_controller.py | 2 +- openbb_terminal/parent_classes.py | 210 +++++++++++++----- .../brokers/degiro/degiro_controller.py | 2 +- .../parameters/params_controller.py | 2 +- openbb_terminal/terminal_controller.py | 88 +++++--- 8 files changed, 216 insertions(+), 98 deletions(-) diff --git a/openbb_terminal/core/session/hub_model.py b/openbb_terminal/core/session/hub_model.py index f47412a46b0..5dea92f109b 100644 --- a/openbb_terminal/core/session/hub_model.py +++ b/openbb_terminal/core/session/hub_model.py @@ -14,6 +14,7 @@ from openbb_terminal.core.session.constants import ( TIMEOUT, ) from openbb_terminal.core.session.current_system import get_current_system +from openbb_terminal.core.session.current_user import get_current_user from openbb_terminal.rich_config import console @@ -476,7 +477,12 @@ def upload_routine( timeout=timeout, ) if response.status_code == 200: + username = get_current_user().profile.username console.print("[green]Successfully uploaded your routine.[/green]") + if public: + console.print(f"\n[yellow]Share or edit it at https://my.openbb.co/u/{username}/routine/{name.replace(' ', '-')}[/yellow]") + else: + console.print(f"\n[yellow]Edit it at https://my.openbb.co/u/{username}/routine/{name.replace(' ', '-')}[/yellow]") elif response.status_code != 409: # 409: routine already exists console.print( "[red]" + response.json().get("detail", "Unknown error.") + "[/red]" diff --git a/openbb_terminal/econometrics/econometrics_controller.py b/openbb_terminal/econometrics/econometrics_controller.py index 03b1a9a538d..db42dcfa3a6 100644 --- a/openbb_terminal/econometrics/econometrics_controller.py +++ b/openbb_terminal/econometrics/econometrics_controller.py @@ -165,7 +165,7 @@ class EconometricsController(BaseController): } if session and get_current_user().preferences.USE_PROMPT_TOOLKIT: - choices: dict = {c: {} for c in self.controller_choices} + choices: dict = self.choices_default choices["load"] = { "--file": {c: {} for c in self.DATA_FILES}, "-f": "--file", diff --git a/openbb_terminal/economy/quantitative_analysis/qa_controller.py b/openbb_terminal/economy/quantitative_analysis/qa_controller.py index a188b9b8e22..f35048f26e1 100644 --- a/openbb_terminal/economy/quantitative_analysis/qa_controller.py +++ b/openbb_terminal/economy/quantitative_analysis/qa_controller.py @@ -83,7 +83,7 @@ class QaController(StockBaseController): self.resolution = "" # For the views if session and get_current_user().preferences.USE_PROMPT_TOOLKIT: - choices: dict = {c: {} for c in self.controller_choices} + choices: dict = self.choices_default choices["pick"] = {c: {} for c in self.options} choices["unitroot"] = { "--fuller_reg": {c: {} for c in self.FULLER_REG}, diff --git a/openbb_terminal/featflags_controller.py b/openbb_terminal/featflags_controller.py index 43ef32893e6..b3d3374819d 100644 --- a/openbb_terminal/featflags_controller.py +++ b/openbb_terminal/featflags_controller.py @@ -66,7 +66,7 @@ class FeatureFlagsController(BaseController): super().__init__(queue) if session and get_current_user().preferences.USE_PROMPT_TOOLKIT: - choices: dict = {c: {} for c in self.controller_choices} + choices: dict = self.choices_default self.completer = NestedCompleter.from_nested_dict(choices) def print_help(self): diff --git a/openbb_terminal/parent_classes.py b/openbb_terminal/parent_classes.py index f3600597df5..b7427ec9f32 100644 --- a/openbb_terminal/parent_classes.py +++ b/openbb_terminal/parent_classes.py @@ -5,6 +5,7 @@ __docformat__ = "numpy" # IMPORTS STANDARD import argparse +import itertools import difflib import json import logging @@ -26,6 +27,7 @@ from rich.markdown import Markdown import openbb_terminal.core.session.local_model as Local from openbb_terminal import config_terminal from openbb_terminal.account.show_prompt import get_show_prompt +from openbb_terminal.core.session.constants import SCRIPT_TAGS from openbb_terminal.core.completer.choices import build_controller_choice_map from openbb_terminal.core.config.paths import HIST_FILE_PATH from openbb_terminal.core.session import hub_model as Hub @@ -85,6 +87,7 @@ SUPPORT_TYPE = ["bug", "suggestion", "question", "generic"] # TODO: We should try to avoid these global variables RECORD_SESSION = False +RECORD_SESSION_LOCAL_ONLY = False SESSION_RECORDED = list() SESSION_RECORDED_NAME = "" SESSION_RECORDED_DESCRIPTION = "" @@ -111,7 +114,6 @@ class BaseController(metaclass=ABCMeta): "reset", "support", "wiki", - "record", "stop", "screenshot", "askobb", @@ -892,8 +894,9 @@ class BaseController(metaclass=ABCMeta): action="store", dest="name", type=str, - default=datetime.now().strftime("%Y%m%d_%H%M%S_routine.openbb"), - help="Routine file name to be saved.", + default="", + help="Routine title name to be saved - only use characters, digits and whitespaces.", + nargs="+", ) parser.add_argument( "-d", @@ -901,15 +904,30 @@ class BaseController(metaclass=ABCMeta): type=str, dest="description", help="The description of the routine", + default=f"Routine recorded at {datetime.now().strftime('%H:%M')} from the OpenBB Terminal", + nargs="+", + ) + parser.add_argument( + "--tag1", + type=str, + dest="tag1", + help=f"The tag associated with the routine. Select from: {', '.join(SCRIPT_TAGS)}", default="", nargs="+", ) parser.add_argument( - "-t", - "--tags", + "--tag2", type=str, - dest="tags", - help="The tags of the routine", + dest="tag2", + help=f"The tag associated with the routine. Select from: {', '.join(SCRIPT_TAGS)}", + default="", + nargs="+", + ) + parser.add_argument( + "--tag3", + type=str, + dest="tag3", + help=f"The tag associated with the routine. Select from: {', '.join(SCRIPT_TAGS)}", default="", nargs="+", ) @@ -921,32 +939,72 @@ class BaseController(metaclass=ABCMeta): help="Whether the routine should be public or not", default=False, ) + parser.add_argument( + "-l", + "--local", + dest="local", + action="store_true", + help="Only save the routine locally - this is necessary if you are running terminal in guest mode.", + default=False, + ) if other_args and "-" not in other_args[0][0]: other_args.insert(0, "-n") + ns_parser = self.parse_simple_args(parser, other_args) if ns_parser: + + if not ns_parser.name: + console.print("[red]Set a routine title by using the '-n' flag. E.g. 'record -n Morning routine'[/red]") + return + + tag1 = " ".join(ns_parser.tag1) if isinstance(ns_parser.tag1, list) else ns_parser.tag1 + if tag1 and tag1 not in SCRIPT_TAGS: + console.print(f"[red]The parameter 'tag1' needs to be one of the following {', '.join(SCRIPT_TAGS)}[/red]") + return + + tag2 = " ".join(ns_parser.tag2) if isinstance(ns_parser.tag2, list) else ns_parser.tag2 + if tag2 and tag2 not in SCRIPT_TAGS: + console.print(f"[red]The parameter 'tag2' needs to be one of the following {', '.join(SCRIPT_TAGS)}[/red]") + return + + tag3 = " ".join(ns_parser.tag3) if isinstance(ns_parser.tag3, list) else ns_parser.tag3 + if tag3 and tag3 not in SCRIPT_TAGS: + console.print(f"[red]The parameter 'tag3' needs to be one of the following {', '.join(SCRIPT_TAGS)}[/red]") + return + + if is_local() and not ns_parser.local: + console.print("[red]Recording session to the OpenBB Hub is not supported in guest mode.[/red]") + console.print("\n[yellow]Sign to OpenBB Hub to register: http://openbb.co[/yellow]") + console.print("\n[yellow]Otherwise set the flag '-l' to save the file locally.[/yellow]") + return + + # Check if title has a valid format + title = " ".join(ns_parser.name) if ns_parser.name else "" + pattern = re.compile(r"^[a-zA-Z0-9\s]+(?:[-a-zA-Z0-9\s]+)*$") + if not pattern.match(title): + console.print(f"[red]The title '{title}' has invalid format. Please use only digits, characters and whitespaces.[/red]") + return + global RECORD_SESSION + global RECORD_SESSION_LOCAL_ONLY global SESSION_RECORDED_NAME global SESSION_RECORDED_DESCRIPTION global SESSION_RECORDED_TAGS global SESSION_RECORDED_PUBLIC - SESSION_RECORDED_NAME = ( - ns_parser.name - if ".openbb" in ns_parser.name - else ns_parser.name + ".openbb" - ) + RECORD_SESSION = True + RECORD_SESSION_LOCAL_ONLY = ns_parser.local + SESSION_RECORDED_NAME = title + SESSION_RECORDED_DESCRIPTION = " ".join(ns_parser.description) if isinstance(ns_parser.description, list) else ns_parser.description + SESSION_RECORDED_TAGS = tag1 if tag1 else "" + SESSION_RECORDED_TAGS += ',' + tag2 if tag2 else "" + SESSION_RECORDED_TAGS += ',' + tag3 if tag3 else "" - SESSION_RECORDED_DESCRIPTION = " ".join(ns_parser.description) - SESSION_RECORDED_TAGS = " ".join(ns_parser.tags) if ns_parser.tags else "" SESSION_RECORDED_PUBLIC = ns_parser.public - console.print( - "[green]The session is successfully being recorded." - + " Remember to 'stop' before exiting terminal!\n[/green]" - ) - RECORD_SESSION = True + console.print(f"[green]The routine '{title}' is successfully being recorded.[/green]") + console.print("\n[yellow]Remember to run 'stop' command when you are done!\n[/yellow]") @log_start_end(log=logger) def call_stop(self, _) -> None: @@ -956,57 +1014,95 @@ class BaseController(metaclass=ABCMeta): if not RECORD_SESSION: console.print( - "[red]There is no session being recorded. Start one using 'record'[/red]\n" + "[red]There is no session being recorded. Start one using the command 'record'[/red]\n" ) - elif not SESSION_RECORDED: + elif len(SESSION_RECORDED) < 5: console.print( - "[red]There is no session to be saved. Run at least 1 command after starting 'record'[/red]\n" + "[red]Run at least 4 commands before stopping recording a session.[/red]\n" ) else: current_user = get_current_user() - routine_file = os.path.join( - current_user.preferences.USER_ROUTINES_DIRECTORY, SESSION_RECORDED_NAME - ) - if os.path.isfile(routine_file): + # Check if the user just wants to store routine locally + # This works regardless of whether they are logged in or not + if RECORD_SESSION_LOCAL_ONLY: + # Whitespaces are replaced by underscores and an .openbb extension is added + title_for_local_storage = SESSION_RECORDED_NAME.replace(" ", "_") + ".openbb" + routine_file = os.path.join( current_user.preferences.USER_ROUTINES_DIRECTORY, - datetime.now().strftime("%Y%m%d_%H%M%S_") + SESSION_RECORDED_NAME, + title_for_local_storage ) - # Writing to file - with open(routine_file, "w") as file1: - # Writing data to a file - file1.writelines([c + "\n\n" for c in SESSION_RECORDED[:-1]]) - - console.print( - f"[green]Your routine has been recorded and saved here: {routine_file}[/green]\n" - ) - - if not is_local(): - routine = read_routine(file_name=routine_file) - if routine is not None: - name = SESSION_RECORDED_NAME.split(sep=".openbb", maxsplit=-1)[0] - kwargs = { - "auth_header": current_user.profile.get_auth_header(), - "name": name, - "description": SESSION_RECORDED_DESCRIPTION, - "routine": routine, - "tags": SESSION_RECORDED_TAGS, - "public": SESSION_RECORDED_PUBLIC, - } - response = Hub.upload_routine(**kwargs) # type: ignore - if response is not None and response.status_code == 409: + # If file already exists, add a timestamp to the name + if os.path.isfile(routine_file): + i = console.input( + "A local routine with the same name already exists, " + "do you want to override it? (y/n): " + ) + console.print("") + while i.lower() not in ["y", "yes", "n", "no"]: i = console.input( - "A routine with the same name already exists, " - "do you want to replace it? (y/n): " + "Select 'y' or 'n' to proceed: " ) console.print("") - if i.lower() in ["y", "yes"]: - kwargs["override"] = True # type: ignore - response = Hub.upload_routine(**kwargs) # type: ignore - else: - console.print("[info]Aborted.[/info]") + + if i.lower() in ["n", "no"]: + new_name = datetime.now().strftime("%Y%m%d_%H%M%S_") + title_for_local_storage + routine_file = os.path.join( + current_user.preferences.USER_ROUTINES_DIRECTORY, + new_name, + ) + console.print(f"[yellow]The routine name has been updated to '{new_name}'[/yellow]\n") + + # Writing to file + with open(routine_file, "w") as file1: + lines = ["# OpenBB Terminal - Routine", "\n"] + username = get_current_user().profile.username + lines += [f"# Author: {username}", "\n\n"] if username else ["\n"] + lines += [ + f"# Title: {SESSION_RECORDED_NAME}", + "\n", + f"# Tags: {SESSION_RECORDED_TAGS}", + "\n\n", + f"# Description: {SESSION_RECORDED_DESCRIPTION}", + "\n\n", + ] + lines += [c + "\n\n" for c in SESSION_RECORDED[:-1]] + # Writing data to a file + file1.writelines(lines) + + console.print( + f"[green]Your routine has been recorded and saved here: {routine_file}[/green]\n" + ) + + # If user doesn't specify they want to store routine locally + else: + # Confirm that the user is logged in + if not is_local(): + # routine = read_routine(file_name=routine_file) + routine = "\n\n".join(SESSION_RECORDED[:-1]) + if routine is not None: + kwargs = { + "auth_header": current_user.profile.get_auth_header(), + "name": SESSION_RECORDED_NAME, + "description": SESSION_RECORDED_DESCRIPTION, + "routine": routine, + "tags": SESSION_RECORDED_TAGS, + "public": SESSION_RECORDED_PUBLIC, + } + response = Hub.upload_routine(**kwargs) # type: ignore + if response is not None and response.status_code == 409: + i = console.input( + "A routine with the same name already exists, " + "do you want to replace it? (y/n): " + ) + console.print("") + if i.lower() in ["y", "yes"]: + kwargs["override"] = True # type: ignore + response = Hub.upload_routine(**kwargs) # type: ignore + else: + console.print("[info]Aborted.[/info]") # Clear session to be recorded again RECORD_SESSION = False diff --git a/openbb_terminal/portfolio/brokers/degiro/degiro_controller.py b/openbb_terminal/portfolio/brokers/degiro/degiro_controller.py index fdae00fab59..bae880cd568 100644 --- a/openbb_terminal/portfolio/brokers/degiro/degiro_controller.py +++ b/openbb_terminal/portfolio/brokers/degiro/degiro_controller.py @@ -43,7 +43,7 @@ class DegiroController(BaseController): self.__degiro_view = DegiroView() if session and get_current_user().preferences.USE_PROMPT_TOOLKIT: - choices: dict = {c: {} for c in self.controller_choices} + choices: dict = self.choices_default zero_to_hundred: dict = {str(c): {} for c in range(0, 100)} diff --git a/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py b/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py index 472f0d24bd4..8d92c0188ab 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py +++ b/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py @@ -78,7 +78,7 @@ class ParametersController(BaseController): self.DATA_FILES = params_helpers.load_data_files() if session and get_current_user().preferences.USE_PROMPT_TOOLKIT: - choices: dict = {c: {} for c in self.controller_choices} + choices: dict = self.choices_default choices["set"] = {c: None for c in self.models} choices["set"]["--model"] = {c: None for c in self.models} choices["set"]["-m"] = "--model" diff --git a/openbb_terminal/terminal_controller.py b/openbb_terminal/terminal_controller.py index 7e3df6be9f3..fd791f55612 100644 --- a/openbb_terminal/terminal_controller.py +++ b/openbb_terminal/terminal_controller.py @@ -20,7 +20,7 @@ import certifi import pandas as pd import requests from prompt_toolkit import PromptSession -from prompt_toolkit.completion import NestedCompleter +from openbb_terminal.custom_prompt_toolkit import NestedCompleter from prompt_toolkit.formatted_text import HTML from prompt_toolkit.styles import Style @@ -33,6 +33,7 @@ from openbb_terminal.core.config.paths import ( REPOSITORY_DIRECTORY, SETTINGS_ENV_FILE, ) +from openbb_terminal.core.session.constants import SCRIPT_TAGS from openbb_terminal.core.log.generation.custom_logger import log_terminal from openbb_terminal.core.session import session_controller from openbb_terminal.core.session.current_system import set_system_variable @@ -90,6 +91,7 @@ class TerminalController(BaseController): "news", "intro", "askobb", + "record", ] CHOICES_MENUS = [ "stocks", @@ -142,44 +144,10 @@ class TerminalController(BaseController): def update_runtime_choices(self): """Update runtime choices.""" - self.ROUTINE_FILES = { - filepath.name: filepath - for filepath in get_current_user().preferences.USER_ROUTINES_DIRECTORY.rglob( - "*.openbb" - ) - } - if get_current_user().profile.get_token(): - self.ROUTINE_DEFAULT_FILES = { - filepath.name: filepath - for filepath in Path( - get_current_user().preferences.USER_ROUTINES_DIRECTORY - / "hub" - / "default" - ).rglob("*.openbb") - } - self.ROUTINE_PERSONAL_FILES = { - filepath.name: filepath - for filepath in Path( - get_current_user().preferences.USER_ROUTINES_DIRECTORY - / "hub" - / "personal" - ).rglob("*.openbb") - } - - self.ROUTINE_CHOICES["--file"] = { - filename: None for filename in self.ROUTINE_FILES - } - self.ROUTINE_CHOICES["--example"] = None - self.ROUTINE_CHOICES["-e"] = None - self.ROUTINE_CHOICES["--input"] = None - self.ROUTINE_CHOICES["-i"] = None - self.ROUTINE_CHOICES["--help"] = None - self.ROUTINE_CHOICES["--h"] = None - if session and get_current_user().preferences.USE_PROMPT_TOOLKIT: + # choices: dict = self.choices_default choices: dict = {c: {} for c in self.controller_choices} # type: ignore choices["support"] = self.SUPPORT_CHOICES - choices["exe"] = self.ROUTINE_CHOICES choices["news"] = self.NEWS_CHOICES choices["news"]["--source"] = {c: {} for c in ["Biztoc", "Feedparser"]} choices["hold"] = {c: None for c in ["on", "off", "-s", "--sameaxis"]} @@ -187,6 +155,53 @@ class TerminalController(BaseController): if biztoc_model.BIZTOC_TAGS: choices["news"]["--tag"] = {c: {} for c in biztoc_model.BIZTOC_TAGS} + self.ROUTINE_FILES = { + filepath.name: filepath + for filepath in get_current_user().preferences.USER_ROUTINES_DIRECTORY.rglob( + "*.openbb" + ) + } + if get_current_user().profile.get_token(): + self.ROUTINE_DEFAULT_FILES = { + filepath.name: filepath + for filepath in Path( + get_current_user().preferences.USER_ROUTINES_DIRECTORY + / "hub" + / "default" + ).rglob("*.openbb") + } + self.ROUTINE_PERSONAL_FILES = { + filepath.name: filepath + for filepath in Path( + get_current_user().preferences.USER_ROUTINES_DIRECTORY + / "hub" + / "personal" + ).rglob("*.openbb") + } + + choices["exe"] = { + "--file": {filename: {} for filename in list(self.ROUTINE_FILES.keys())}, + "-f": "--file", + "--example": None, + "-e": "--example", + "--input": None, + "-i": "--input", + } + + choices["record"] = { + "--name": None, + "-n": "--name", + "--description": None, + "-d": "--description", + "--public": None, + "-p": "--public", + "--local": None, + "-l": "--local", + "--tag1": {c: None for c in SCRIPT_TAGS}, + "--tag2": {c: None for c in SCRIPT_TAGS}, + "--tag3": {c: None for c in SCRIPT_TAGS}, + } + self.completer = NestedCompleter.from_nested_dict(choices) def print_help(self): @@ -761,6 +776,7 @@ class TerminalController(BaseController): self.queue = self.queue[1:] + # pylint: disable=global-statement def terminal(jobs_cmds: Optional[List[str]] = None, test_mode=False): """Terminal Menu.""" From 01210120d8c9806d4e738ddfd6bd1bed48e13037 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Sun, 13 Aug 2023 19:18:14 -0500 Subject: [PATCH 03/10] --debug points to dev env (#5316) * check that routine title is valid * more updates * small fixes * override local routine * more improvements to routine logic * --debug runs .dev --- openbb_terminal/core/plots/backend.py | 7 ++++++- openbb_terminal/core/session/constants.py | 11 +++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/openbb_terminal/core/plots/backend.py b/openbb_terminal/core/plots/backend.py index ba82753ab6d..8955796855c 100644 --- a/openbb_terminal/core/plots/backend.py +++ b/openbb_terminal/core/plots/backend.py @@ -441,8 +441,13 @@ class Backend(PyWry): self.check_backend() endpoint = {True: "login", False: "logout"}[login] + if str(os.environ.get("DEBUG_MODE", "false")).lower() != "true": + json_url = f"https://my.openbb.dev/{endpoint}?pywry=true" + else: + json_url = f"https://my.openbb.co/{endpoint}?pywry=true" + outgoing = dict( - json_data=dict(url=f"https://my.openbb.co/{endpoint}?pywry=true"), + json_data=dict(url=json_url), **self.get_kwargs(endpoint.title()), width=900, height=800, diff --git a/openbb_terminal/core/session/constants.py b/openbb_terminal/core/session/constants.py index 252b362d165..21fdee6bee7 100644 --- a/openbb_terminal/core/session/constants.py +++ b/openbb_terminal/core/session/constants.py @@ -1,7 +1,14 @@ -BASE_URL = "https://payments.openbb.co/" +from os import environ + +if str(environ.get("DEBUG_MODE", "false")).lower() != "true": + BASE_URL = "https://payments.openbb.dev/" + HUB_URL = "https://my.openbb.dev/" +else: + BASE_URL = "https://payments.openbb.co/" + HUB_URL = "https://my.openbb.co/" + # BASE_URL = "http://127.0.0.1:8000/" -HUB_URL = "https://my.openbb.co/" REGISTER_URL = HUB_URL + "register" SUPPORT_URL = HUB_URL + "app/terminal/support" SOURCES_URL = HUB_URL + "app/terminal/data-sources" From 3d6ad59643a01debaff91c7dd9d8b67f29f41e48 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Sun, 13 Aug 2023 19:43:10 -0500 Subject: [PATCH 04/10] few more updates (#5317) * check that routine title is valid * more updates * small fixes * override local routine * more improvements to routine logic * --debug runs .dev * few more updates --- openbb_terminal/core/session/hub_model.py | 12 ++++++++---- openbb_terminal/parent_classes.py | 5 +++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/openbb_terminal/core/session/hub_model.py b/openbb_terminal/core/session/hub_model.py index 5dea92f109b..4fc99c5c582 100644 --- a/openbb_terminal/core/session/hub_model.py +++ b/openbb_terminal/core/session/hub_model.py @@ -2,7 +2,7 @@ import datetime import json from typing import Any, Dict, List, Literal, Optional from uuid import UUID - +from os import environ import requests from jose import jwt @@ -479,10 +479,14 @@ def upload_routine( if response.status_code == 200: username = get_current_user().profile.username console.print("[green]Successfully uploaded your routine.[/green]") - if public: - console.print(f"\n[yellow]Share or edit it at https://my.openbb.co/u/{username}/routine/{name.replace(' ', '-')}[/yellow]") + if str(environ.get("DEBUG_MODE", "false")).lower() != "true": + run_env = "dev" else: - console.print(f"\n[yellow]Edit it at https://my.openbb.co/u/{username}/routine/{name.replace(' ', '-')}[/yellow]") + run_env = "co" + if public: + console.print(f"\n[yellow]Share or edit it at https://my.openbb.{run_env}/u/{username}/routine/{name.replace(' ', '-')}[/yellow]") + else: + console.print(f"\n[yellow]Edit it at https://my.openbb.{run_env}/u/{username}/routine/{name.replace(' ', '-')}[/yellow]") elif response.status_code != 409: # 409: routine already exists console.print( "[red]" + response.json().get("detail", "Unknown error.") + "[/red]" diff --git a/openbb_terminal/parent_classes.py b/openbb_terminal/parent_classes.py index b7427ec9f32..e5849a019f6 100644 --- a/openbb_terminal/parent_classes.py +++ b/openbb_terminal/parent_classes.py @@ -1068,7 +1068,7 @@ class BaseController(metaclass=ABCMeta): f"# Description: {SESSION_RECORDED_DESCRIPTION}", "\n\n", ] - lines += [c + "\n\n" for c in SESSION_RECORDED[:-1]] + lines += [c + "\n" for c in SESSION_RECORDED[:-1]] # Writing data to a file file1.writelines(lines) @@ -1081,7 +1081,8 @@ class BaseController(metaclass=ABCMeta): # Confirm that the user is logged in if not is_local(): # routine = read_routine(file_name=routine_file) - routine = "\n\n".join(SESSION_RECORDED[:-1]) + routine = "\n".join(SESSION_RECORDED[:-1]) + if routine is not None: kwargs = { "auth_header": current_user.profile.get_auth_header(), From 3e48648487b1b072b3b434f80f0b4b744ea666eb Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Sun, 13 Aug 2023 20:16:35 -0500 Subject: [PATCH 05/10] small fixy (#5318) * check that routine title is valid * more updates * small fixes * override local routine * more improvements to routine logic * --debug runs .dev * few more updates * small fix --- openbb_terminal/core/plots/backend.py | 2 +- openbb_terminal/core/session/constants.py | 2 +- openbb_terminal/core/session/hub_model.py | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/openbb_terminal/core/plots/backend.py b/openbb_terminal/core/plots/backend.py index 8955796855c..e8433e98f2e 100644 --- a/openbb_terminal/core/plots/backend.py +++ b/openbb_terminal/core/plots/backend.py @@ -441,7 +441,7 @@ class Backend(PyWry): self.check_backend() endpoint = {True: "login", False: "logout"}[login] - if str(os.environ.get("DEBUG_MODE", "false")).lower() != "true": + if str(os.environ.get("DEBUG_MODE", "false")).lower() == "true": json_url = f"https://my.openbb.dev/{endpoint}?pywry=true" else: json_url = f"https://my.openbb.co/{endpoint}?pywry=true" diff --git a/openbb_terminal/core/session/constants.py b/openbb_terminal/core/session/constants.py index 21fdee6bee7..2d2fb992e0f 100644 --- a/openbb_terminal/core/session/constants.py +++ b/openbb_terminal/core/session/constants.py @@ -1,6 +1,6 @@ from os import environ -if str(environ.get("DEBUG_MODE", "false")).lower() != "true": +if str(environ.get("DEBUG_MODE", "false")).lower() == "true": BASE_URL = "https://payments.openbb.dev/" HUB_URL = "https://my.openbb.dev/" else: diff --git a/openbb_terminal/core/session/hub_model.py b/openbb_terminal/core/session/hub_model.py index 4fc99c5c582..1c112ed7ec2 100644 --- a/openbb_terminal/core/session/hub_model.py +++ b/openbb_terminal/core/session/hub_model.py @@ -479,10 +479,12 @@ def upload_routine( if response.status_code == 200: username = get_current_user().profile.username console.print("[green]Successfully uploaded your routine.[/green]") - if str(environ.get("DEBUG_MODE", "false")).lower() != "true": + + if str(environ.get("DEBUG_MODE", "false")).lower() == "true": run_env = "dev" else: run_env = "co" + if public: console.print(f"\n[yellow]Share or edit it at https://my.openbb.{run_env}/u/{username}/routine/{name.replace(' ', '-')}[/yellow]") else: From c40c3f7529a1ee9b577288db2aaa3be4e461363b Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Mon, 14 Aug 2023 01:20:07 -0500 Subject: [PATCH 06/10] Creates a "--dev" flag that points to dev backend for testing with hub (#5319) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * check that routine title is valid * more updates * small fixes * override local routine * more improvements to routine logic * --debug runs .dev * few more updates * small fix * rename BASE_URL from ultima to ULTIMA_BASE_URL * use debug from dataclasses instead of env since env doesn't get updated * create --dev flag that can point to .dev backend * merge conflits * few changes, made it actually work 🤣 --------- Co-authored-by: tehcoderer --- openbb_terminal/account/account_controller.py | 5 ++ .../common/ultima_newsmonitor_model.py | 14 ++-- openbb_terminal/core/completer/choices.py | 7 +- openbb_terminal/core/models/system_model.py | 1 + openbb_terminal/core/plots/backend.py | 7 +- openbb_terminal/core/session/constants.py | 22 +++--- openbb_terminal/core/session/hub_model.py | 72 ++++++++++++------- .../core/session/routines_handler.py | 1 + .../core/session/session_controller.py | 27 ++++--- openbb_terminal/core/session/session_model.py | 5 +- openbb_terminal/keys_controller.py | 4 +- openbb_terminal/parent_classes.py | 1 + openbb_terminal/portfolio/portfolio_engine.py | 3 +- openbb_terminal/settings_controller.py | 11 +-- openbb_terminal/sources_controller.py | 5 +- openbb_terminal/terminal_controller.py | 24 +++++-- openbb_terminal/terminal_helper.py | 8 ++- terminal.py | 3 +- .../openbb_terminal/session/test_hub_model.py | 36 +++++----- 19 files changed, 157 insertions(+), 99 deletions(-) diff --git a/openbb_terminal/account/account_controller.py b/openbb_terminal/account/account_controller.py index 12b26bb8869..c9f233b0600 100644 --- a/openbb_terminal/account/account_controller.py +++ b/openbb_terminal/account/account_controller.py @@ -255,6 +255,7 @@ class AccountController(BaseController): auth_header=get_current_user().profile.get_auth_header(), page=ns_parser.page, size=ns_parser.size, + base_url=Hub.BackendEnvironment.BASE_URL, ) df, page, pages = get_personal_routines_info(response) if not df.empty: @@ -356,6 +357,7 @@ class AccountController(BaseController): "routine": routine, "tags": tags, "public": ns_parser.public, + "base_url": Hub.BackendEnvironment.BASE_URL, } response = Hub.upload_routine(**kwargs) # type: ignore @@ -412,6 +414,7 @@ class AccountController(BaseController): response = Hub.download_routine( auth_header=get_current_user().profile.get_auth_header(), uuid=self.REMOTE_CHOICES[name], + base_url=Hub.BackendEnvironment.BASE_URL ) if response and response.status_code == 200: data = [response.json(), "personal"] @@ -499,6 +502,7 @@ class AccountController(BaseController): response = Hub.delete_routine( auth_header=get_current_user().profile.get_auth_header(), uuid=self.REMOTE_CHOICES[name], + base_url=Hub.BackendEnvironment.BASE_URL ) if ( response @@ -551,6 +555,7 @@ class AccountController(BaseController): response = Hub.generate_personal_access_token( auth_header=get_current_user().profile.get_auth_header(), + base_url=Hub.BackendEnvironment.BASE_URL, days=ns_parser.days, ) if response and response.status_code == 200: diff --git a/openbb_terminal/common/ultima_newsmonitor_model.py b/openbb_terminal/common/ultima_newsmonitor_model.py index b4e3782ac0d..e06226b7b10 100644 --- a/openbb_terminal/common/ultima_newsmonitor_model.py +++ b/openbb_terminal/common/ultima_newsmonitor_model.py @@ -18,7 +18,7 @@ from openbb_terminal.rich_config import console logger = logging.getLogger(__name__) -BASE_URL = "https://api.ultimainsights.ai/v1" +ULTIMA_BASE_URL = "https://api.ultimainsights.ai/v1" NO_API_KEY = "REPLACE_ME" @@ -69,10 +69,10 @@ def get_news(term: str = "", sort: str = "articlePublishedDate") -> pd.DataFrame if term in supported_terms(): if auth_header: data = request( - f"{BASE_URL}/getNewsArticles/{term}", headers=auth_header + f"{ULTIMA_BASE_URL}/getNewsArticles/{term}", headers=auth_header ) else: - data = request(f"{BASE_URL}/getNewsArticles/{term}") + data = request(f"{ULTIMA_BASE_URL}/getNewsArticles/{term}") else: console.print( "[red]Ticker not supported. Unable to retrieve data\n[/red]" @@ -150,7 +150,7 @@ def supported_terms() -> list: # https://stackoverflow.com/questions/27835619/urllib-and-ssl-certificate-verify-failed-error/73270162#73270162 os.environ["REQUESTS_CA_BUNDLE"] = certifi.where() os.environ["SSL_CERT_FILE"] = certifi.where() - data = request(f"{BASE_URL}/supportedTickers") + data = request(f"{ULTIMA_BASE_URL}/supportedTickers") return list(data.json()) @@ -176,7 +176,7 @@ def get_company_info(ticker: str) -> dict: os.environ["SSL_CERT_FILE"] = certifi.where() if ticker in supported_terms(): - data = request(f"{BASE_URL}/getCompanyInfo/{ticker}") + data = request(f"{ULTIMA_BASE_URL}/getCompanyInfo/{ticker}") return data.json() console.print("[red]Ticker not supported. Unable to retrieve data\n[/red]") return {} @@ -213,9 +213,9 @@ def get_top_headlines(ticker: str) -> dict: if ticker in supported_terms(): if auth_header: - data = request(f"{BASE_URL}/getTopHeadlines/{ticker}", headers=auth_header) + data = request(f"{ULTIMA_BASE_URL}/getTopHeadlines/{ticker}", headers=auth_header) else: - data = request(f"{BASE_URL}/getTopHeadlines/{ticker}") + data = request(f"{ULTIMA_BASE_URL}/getTopHeadlines/{ticker}") if ( hasattr(data, "status") and data.status_code == 429 ): # If data request failed diff --git a/openbb_terminal/core/completer/choices.py b/openbb_terminal/core/completer/choices.py index eff17a6f1fd..178006cdca4 100644 --- a/openbb_terminal/core/completer/choices.py +++ b/openbb_terminal/core/completer/choices.py @@ -8,6 +8,7 @@ from unittest.mock import patch from openbb_terminal.helper_funcs import check_file_type_saved, check_positive from openbb_terminal.rich_config import get_ordered_list_sources +from openbb_terminal.core.session.current_system import get_current_system def __mock_parse_known_args_and_warn( @@ -211,7 +212,7 @@ def __patch_controller_functions(controller): ), ] - if str(environ.get("DEBUG_MODE", "false")).lower() != "true": + if not get_current_system().DEBUG_MODE: rich.start() patched_function_list = [] for patcher in patcher_list: @@ -219,7 +220,7 @@ def __patch_controller_functions(controller): yield patched_function_list - if str(environ.get("DEBUG_MODE", "false")).lower() != "true": + if not get_current_system().DEBUG_MODE: rich.stop() for patcher in patcher_list: patcher.stop() @@ -317,7 +318,7 @@ def build_controller_choice_map(controller) -> dict: argument_parser=argument_parser ) except Exception as exception: - if str(environ.get("DEBUG_MODE", "false")).lower() == "true": + if get_current_system().DEBUG_MODE: raise Exception( f"On command : `{command}`.\n{str(exception)}" ) from exception diff --git a/openbb_terminal/core/models/system_model.py b/openbb_terminal/core/models/system_model.py index 85d61e7b1bf..55ba1868877 100644 --- a/openbb_terminal/core/models/system_model.py +++ b/openbb_terminal/core/models/system_model.py @@ -54,6 +54,7 @@ class SystemModel(BaseModel): # Others TEST_MODE: bool = False DEBUG_MODE: bool = False + DEV_BACKEND: bool = False ENABLE_AUTHENTICATION: bool = True HEADLESS: bool = False diff --git a/openbb_terminal/core/plots/backend.py b/openbb_terminal/core/plots/backend.py index e8433e98f2e..f32828bdeaa 100644 --- a/openbb_terminal/core/plots/backend.py +++ b/openbb_terminal/core/plots/backend.py @@ -17,6 +17,8 @@ import plotly.graph_objects as go from packaging import version from reportlab.graphics import renderPDF +from openbb_terminal.core.session.constants import BackendEnvironment + # pylint: disable=C0415 try: from pywry import PyWry @@ -441,10 +443,7 @@ class Backend(PyWry): self.check_backend() endpoint = {True: "login", False: "logout"}[login] - if str(os.environ.get("DEBUG_MODE", "false")).lower() == "true": - json_url = f"https://my.openbb.dev/{endpoint}?pywry=true" - else: - json_url = f"https://my.openbb.co/{endpoint}?pywry=true" + json_url = f"{BackendEnvironment.HUB_URL}{endpoint}?pywry=true" outgoing = dict( json_data=dict(url=json_url), diff --git a/openbb_terminal/core/session/constants.py b/openbb_terminal/core/session/constants.py index 2d2fb992e0f..83b9b854aac 100644 --- a/openbb_terminal/core/session/constants.py +++ b/openbb_terminal/core/session/constants.py @@ -1,20 +1,16 @@ -from os import environ - -if str(environ.get("DEBUG_MODE", "false")).lower() == "true": - BASE_URL = "https://payments.openbb.dev/" - HUB_URL = "https://my.openbb.dev/" -else: +class HubEnvironment: + # BASE_URL = "http://127.0.0.1:8000/" BASE_URL = "https://payments.openbb.co/" HUB_URL = "https://my.openbb.co/" -# BASE_URL = "http://127.0.0.1:8000/" + def __new__(cls, *args, **kwargs): # pylint: disable=W0613 + """Create a singleton instance of the backend.""" + if not hasattr(cls, "instance"): + cls.instance = super().__new__(cls) # pylint: disable=E1120 + return cls.instance -REGISTER_URL = HUB_URL + "register" -SUPPORT_URL = HUB_URL + "app/terminal/support" -SOURCES_URL = HUB_URL + "app/terminal/data-sources" -KEYS_URL = HUB_URL + "app/terminal/api-keys" -COLORS_URL = HUB_URL + "app/terminal/theme" -CHARTS_TABLES_URL = HUB_URL + "app/terminal/theme/charts-tables" + +BackendEnvironment = HubEnvironment() DEFAULT_ROUTINES_URL = "https://openbb-cms.directus.app/items/Routines" diff --git a/openbb_terminal/core/session/hub_model.py b/openbb_terminal/core/session/hub_model.py index 1c112ed7ec2..52f0005c645 100644 --- a/openbb_terminal/core/session/hub_model.py +++ b/openbb_terminal/core/session/hub_model.py @@ -2,16 +2,16 @@ import datetime import json from typing import Any, Dict, List, Literal, Optional from uuid import UUID -from os import environ + import requests from jose import jwt from openbb_terminal.core.session.constants import ( - BASE_URL, CONNECTION_ERROR_MSG, CONNECTION_TIMEOUT_MSG, DEFAULT_ROUTINES_URL, TIMEOUT, + BackendEnvironment, ) from openbb_terminal.core.session.current_system import get_current_system from openbb_terminal.core.session.current_user import get_current_user @@ -19,7 +19,10 @@ from openbb_terminal.rich_config import console def create_session( - email: str, password: str, base_url: str = BASE_URL, timeout: int = TIMEOUT + email: str, + password: str, + base_url: str = BackendEnvironment.BASE_URL, + timeout: int = TIMEOUT, ) -> Optional[requests.Response]: """Create a session. @@ -72,7 +75,7 @@ def check_token_expiration(token: str): def create_session_from_token( - token: str, base_url: str = BASE_URL, timeout: int = TIMEOUT + token: str, base_url: str = BackendEnvironment.BASE_URL, timeout: int = TIMEOUT ): """Create a session from token. @@ -109,7 +112,10 @@ def create_session_from_token( def delete_session( - auth_header: str, token: str, base_url: str = BASE_URL, timeout: int = TIMEOUT + auth_header: str, + token: str, + base_url: str = BackendEnvironment.BASE_URL, + timeout: int = TIMEOUT, ) -> Optional[requests.Response]: """Delete the session. @@ -191,7 +197,7 @@ def get_session(email: str, password: str) -> dict: dict The session info. """ - response = create_session(email, password) + response = create_session(email, password, base_url=BackendEnvironment.BASE_URL) if response is None: return {} return process_session_response(response) @@ -210,14 +216,14 @@ def get_session_from_token(token: str) -> dict: dict The session info. """ - response = create_session_from_token(token) + response = create_session_from_token(token, base_url=BackendEnvironment.BASE_URL) if response is None: return {} return process_session_response(response) def fetch_user_configs( - session: dict, base_url: str = BASE_URL, timeout: int = TIMEOUT + session: dict, base_url: str = BackendEnvironment.BASE_URL, timeout: int = TIMEOUT ) -> Optional[requests.Response]: """Fetch user configurations. @@ -259,7 +265,10 @@ def fetch_user_configs( def clear_user_configs( - config: str, auth_header: str, base_url: str = BASE_URL, timeout: int = TIMEOUT + config: str, + auth_header: str, + base_url: str = BackendEnvironment.BASE_URL, + timeout: int = TIMEOUT, ) -> Optional[requests.Response]: """Clear user configurations to the server. @@ -308,7 +317,7 @@ def upload_user_field( key: str, value: Any, auth_header: str, - base_url: str = BASE_URL, + base_url: str = BackendEnvironment.BASE_URL, timeout: int = TIMEOUT, silent: bool = False, ) -> Optional[requests.Response]: @@ -366,7 +375,7 @@ def upload_config( value: str, type_: Literal["settings", "terminal_style"], auth_header: str, - base_url: str = BASE_URL, + base_url: str = BackendEnvironment.BASE_URL, timeout: int = TIMEOUT, ) -> Optional[requests.Response]: """Patch user configurations to the server. @@ -430,7 +439,7 @@ def upload_routine( override: bool = False, tags: str = "", public: bool = False, - base_url: str = BASE_URL, + base_url: str = BackendEnvironment.BASE_URL, timeout: int = TIMEOUT, ) -> Optional[requests.Response]: """Send a routine to the server. @@ -468,7 +477,6 @@ def upload_routine( "version": get_current_system().VERSION, "public": public, } - try: response = requests.post( headers={"Authorization": auth_header}, @@ -478,17 +486,20 @@ def upload_routine( ) if response.status_code == 200: username = get_current_user().profile.username - console.print("[green]Successfully uploaded your routine.[/green]") + console.print("[green]Successfully uploaded your routine.[/]") + + run_env = BackendEnvironment.HUB_URL.rstrip("/") - if str(environ.get("DEBUG_MODE", "false")).lower() == "true": - run_env = "dev" - else: - run_env = "co" - if public: - console.print(f"\n[yellow]Share or edit it at https://my.openbb.{run_env}/u/{username}/routine/{name.replace(' ', '-')}[/yellow]") + console.print( + f"\n[yellow]Share or edit it at {run_env}/u/{username}/routine/{name.replace(' ', '-')}[/]" + ) else: - console.print(f"\n[yellow]Edit it at https://my.openbb.{run_env}/u/{username}/routine/{name.replace(' ', '-')}[/yellow]") + console.print(f"\n[yellow]Go to {run_env} to edit this script,[/]") + console.print( + f"[yellow]or even make it public so you can access it at " + f"{run_env}/u/{username}/routine/{name.replace(' ', '-')}[/]" + ) elif response.status_code != 409: # 409: routine already exists console.print( "[red]" + response.json().get("detail", "Unknown error.") + "[/red]" @@ -508,7 +519,7 @@ def upload_routine( def download_routine( auth_header: str, uuid: UUID, - base_url=BASE_URL, + base_url: str = BackendEnvironment.BASE_URL, timeout: int = TIMEOUT, ) -> Optional[requests.Response]: """Download a routine from the server. @@ -554,7 +565,7 @@ def download_routine( def delete_routine( auth_header: str, uuid: UUID, - base_url=BASE_URL, + base_url: str = BackendEnvironment.BASE_URL, timeout: int = TIMEOUT, ) -> Optional[requests.Response]: """Delete a routine from the server. @@ -604,7 +615,7 @@ def list_routines( fields: Optional[List[str]] = None, page: int = 1, size: int = 10, - base_url=BASE_URL, + base_url: str = BackendEnvironment.BASE_URL, timeout: int = TIMEOUT, silent: bool = False, ) -> Optional[requests.Response]: @@ -695,7 +706,10 @@ def get_default_routines( def generate_personal_access_token( - auth_header: str, base_url: str = BASE_URL, timeout: int = TIMEOUT, days: int = 30 + auth_header: str, + base_url: str = BackendEnvironment.BASE_URL, + timeout: int = TIMEOUT, + days: int = 30, ) -> Optional[requests.Response]: """ Generate an OpenBB Personal Access Token. @@ -744,7 +758,9 @@ def generate_personal_access_token( def get_personal_access_token( - auth_header: str, base_url: str = BASE_URL, timeout: int = TIMEOUT + auth_header: str, + base_url: str = BackendEnvironment.BASE_URL, + timeout: int = TIMEOUT, ) -> Optional[requests.Response]: """ Show the user's OpenBB Personal Access Token. @@ -789,7 +805,9 @@ def get_personal_access_token( def revoke_personal_access_token( - auth_header: str, base_url: str = BASE_URL, timeout: int = TIMEOUT + auth_header: str, + base_url: str = BackendEnvironment.BASE_URL, + timeout: int = TIMEOUT, ) -> Optional[requests.Response]: """ Delete the user's OpenBB Personal Access Token. diff --git a/openbb_terminal/core/session/routines_handler.py b/openbb_terminal/core/session/routines_handler.py index bef93b1e747..56f185aaf2d 100644 --- a/openbb_terminal/core/session/routines_handler.py +++ b/openbb_terminal/core/session/routines_handler.py @@ -51,6 +51,7 @@ def download_routines(auth_header: str, silent: bool = False) -> list: fields=["name", "script"], page=1, size=100, + base_url=Hub.BackendEnvironment.BASE_URL, silent=silent, ) if response and response.status_code == 200: diff --git a/openbb_terminal/core/session/session_controller.py b/openbb_terminal/core/session/session_controller.py index 4069106a971..6d26fb29784 100644 --- a/openbb_terminal/core/session/session_controller.py +++ b/openbb_terminal/core/session/session_controller.py @@ -5,11 +5,11 @@ from prompt_toolkit import PromptSession import openbb_terminal.core.session.local_model as Local from openbb_terminal.core.config.paths import PACKAGE_DIRECTORY from openbb_terminal.core.plots.backend import plots_backend -from openbb_terminal.core.session.constants import ( - REGISTER_URL, - SUPPORT_URL, +from openbb_terminal.core.session.constants import BackendEnvironment +from openbb_terminal.core.session.current_system import ( + get_current_system, + set_system_variable, ) -from openbb_terminal.core.session.current_system import get_current_system from openbb_terminal.core.session.session_model import ( LoginStatus, create_session, @@ -24,8 +24,12 @@ def display_welcome_message(links: bool = True) -> None: with open(PACKAGE_DIRECTORY / "core" / "session" / "banner.txt") as f: console.print(f"[menu]{f.read()}[/menu]\n") if links: - console.print(f"Register : [cmds]{REGISTER_URL}[/cmds]") - console.print(f"Support : [cmds]{SUPPORT_URL}[/cmds]") + console.print( + f"Register : [cmds]{BackendEnvironment.HUB_URL + 'register'}[/cmds]" + ) + console.print( + f"Support : [cmds]{BackendEnvironment.HUB_URL + 'app/terminal/support'}[/cmds]" + ) def get_user_input() -> Tuple[str, str, bool]: @@ -135,13 +139,15 @@ def prompt_cli(welcome: bool = True): # pylint: disable=inconsistent-return-statements -def launch_terminal(debug: bool = False, queue: Optional[List[str]] = None): +def launch_terminal( + debug: bool = False, dev: bool = False, queue: Optional[List[str]] = None +): """Launch terminal""" # pylint: disable=import-outside-toplevel from openbb_terminal import terminal_controller if queue: - return terminal_controller.main(debug, queue, module="") + return terminal_controller.main(debug, dev, queue, module="") terminal_controller.parse_args_and_run() @@ -170,8 +176,13 @@ def main( welcome: bool = True, prompt: bool = True, queue: Optional[List[str]] = None, + dev: bool = False, ): """Main function""" + if dev: + set_system_variable("DEV_BACKEND", True) + BackendEnvironment.BASE_URL = "https://payments.openbb.dev/" + BackendEnvironment.HUB_URL = "https://my.openbb.dev/" local_session = Local.get_session() if session is None else session diff --git a/openbb_terminal/core/session/session_model.py b/openbb_terminal/core/session/session_model.py index a0e9732e499..5140932fe8e 100644 --- a/openbb_terminal/core/session/session_model.py +++ b/openbb_terminal/core/session/session_model.py @@ -93,7 +93,7 @@ def login(session: Dict, remember: bool = False) -> LoginStatus: preferences=get_current_user().preferences, sources=SourcesModel(), ) - response = Hub.fetch_user_configs(session) + response = Hub.fetch_user_configs(session, Hub.BackendEnvironment.BASE_URL) if response is not None: if response.status_code == 200: configs = json.loads(response.content) @@ -159,6 +159,7 @@ def update_backend_sources(auth_header, configs, silent: bool = True): key="features_sources", value=updated_sources, auth_header=auth_header, + base_url=Hub.BackendEnvironment.BASE_URL, silent=silent, ) except Exception: @@ -190,7 +191,7 @@ def logout( success = True - r = Hub.delete_session(auth_header, token) + r = Hub.delete_session(auth_header, token, base_url=Hub.BackendEnvironment.BASE_URL) if not r or r.status_code != 200: success = False diff --git a/openbb_terminal/keys_controller.py b/openbb_terminal/keys_controller.py index 3a522f68b64..6c2ccd5f398 100644 --- a/openbb_terminal/keys_controller.py +++ b/openbb_terminal/keys_controller.py @@ -8,7 +8,7 @@ import logging from typing import Callable, Dict, List, Optional from openbb_terminal import keys_model, keys_view -from openbb_terminal.core.session.constants import KEYS_URL +from openbb_terminal.core.session.constants import BackendEnvironment from openbb_terminal.core.session.current_user import get_current_user, is_local from openbb_terminal.core.session.env_handler import get_reading_order from openbb_terminal.custom_prompt_toolkit import NestedCompleter @@ -75,7 +75,7 @@ class KeysController(BaseController): # pylint: disable=too-many-public-methods """ reading_order = get_reading_order() hierarchy = "\n ".join(list(map(str, reversed(reading_order)))) - return hierarchy if is_local() else f"{KEYS_URL}\n {hierarchy}" + return hierarchy if is_local() else f"{BackendEnvironment.HUB_URL + 'app/terminal/api-keys'}\n {hierarchy}" def print_help(self, update_status: bool = True, reevaluate: bool = True): """Print help""" diff --git a/openbb_terminal/parent_classes.py b/openbb_terminal/parent_classes.py index e5849a019f6..69c1710e32b 100644 --- a/openbb_terminal/parent_classes.py +++ b/openbb_terminal/parent_classes.py @@ -1091,6 +1091,7 @@ class BaseController(metaclass=ABCMeta): "routine": routine, "tags": SESSION_RECORDED_TAGS, "public": SESSION_RECORDED_PUBLIC, + "base_url": Hub.BackendEnvironment.BASE_URL, } response = Hub.upload_routine(**kwargs) # type: ignore if response is not None and response.status_code == 409: diff --git a/openbb_terminal/portfolio/portfolio_engine.py b/openbb_terminal/portfolio/portfolio_engine.py index 22adcd191e9..ce931d77d07 100644 --- a/openbb_terminal/portfolio/portfolio_engine.py +++ b/openbb_terminal/portfolio/portfolio_engine.py @@ -21,6 +21,7 @@ from openbb_terminal.portfolio.portfolio_helper import ( from openbb_terminal.rich_config import console from openbb_terminal.stocks.fundamental_analysis.yahoo_finance_model import get_splits from openbb_terminal.terminal_helper import suppress_stdout +from openbb_terminal.core.session.current_system import get_current_system # pylint: disable=E1136,W0201,R0902,C0302 # pylint: disable=unsupported-assignment-operation,redefined-outer-name @@ -196,7 +197,7 @@ class PortfolioEngine: # Load transactions from file if path.endswith(".xlsx"): - if str(environ.get("DEBUG_MODE", "false")).lower() != "true": + if not get_current_system().DEBUG_MODE: warnings.filterwarnings( "ignore", category=UserWarning, module="openpyxl" ) diff --git a/openbb_terminal/settings_controller.py b/openbb_terminal/settings_controller.py index 4d0b31e6007..4ba909c0021 100644 --- a/openbb_terminal/settings_controller.py +++ b/openbb_terminal/settings_controller.py @@ -21,7 +21,7 @@ from openbb_terminal.core.config.paths import ( SETTINGS_ENV_FILE, STYLES_DIRECTORY_REPO, ) -from openbb_terminal.core.session.constants import CHARTS_TABLES_URL, COLORS_URL +from openbb_terminal.core.session.constants import BackendEnvironment from openbb_terminal.core.session.current_user import ( get_current_user, is_local, @@ -231,7 +231,7 @@ class SettingsController(BaseController): " Then, place the downloaded file 'openbb_config.richstyle.json'" f" inside {get_current_user().preferences.USER_STYLES_DIRECTORY} or " f"{STYLES_DIRECTORY_REPO}. If you have a hub account you can change colors " - f"here {COLORS_URL}.", + f"here {BackendEnvironment.HUB_URL + 'app/terminal/theme'}.", ) if other_args and "-" not in other_args[0][0]: other_args.insert(0, "-s") @@ -246,6 +246,7 @@ class SettingsController(BaseController): value=ns_parser.style, type_="settings", auth_header=get_current_user().profile.get_auth_header(), + base_url=BackendEnvironment.HUB_URL, ) console.print("") console.print("Colors updated.") @@ -266,7 +267,7 @@ class SettingsController(BaseController): dest="style", choices=["dark", "light"], help="Choose chart style. If you have a hub account you can change theme " - f"here {CHARTS_TABLES_URL}.", + f"here {BackendEnvironment.HUB_URL + 'app/terminal/theme/charts-tables'}.", required="-h" not in other_args and "--help" not in other_args, ) if other_args and "-" not in other_args[0][0]: @@ -282,6 +283,7 @@ class SettingsController(BaseController): value=ns_parser.style, type_="terminal_style", auth_header=get_current_user().profile.get_auth_header(), + base_url=BackendEnvironment.HUB_URL, ) console.print("") theme.apply_style(ns_parser.style) @@ -303,7 +305,7 @@ class SettingsController(BaseController): dest="style", choices=["dark", "light"], help="Choose table style. If you have a hub account you can change theme " - f"here {CHARTS_TABLES_URL}.", + f"here {BackendEnvironment.HUB_URL + 'app/terminal/theme/charts-tables'}.", required="-h" not in other_args and "--help" not in other_args, ) if other_args and "-" not in other_args[0][0]: @@ -319,6 +321,7 @@ class SettingsController(BaseController): value=ns_parser.style, type_="terminal_style", auth_header=get_current_user().profile.get_auth_header(), + base_url=BackendEnvironment.HUB_URL, ) console.print("") console.print("Table theme updated.\n") diff --git a/openbb_terminal/sources_controller.py b/openbb_terminal/sources_controller.py index eebedbe7904..d6483057bbf 100644 --- a/openbb_terminal/sources_controller.py +++ b/openbb_terminal/sources_controller.py @@ -8,7 +8,7 @@ import os from pathlib import Path from typing import List, Optional -from openbb_terminal.core.session.constants import SOURCES_URL +from openbb_terminal.core.session.constants import BackendEnvironment # IMPORTATION THIRDPARTY # IMPORTATION INTERNAL @@ -54,7 +54,7 @@ class SourcesController(BaseController): if Path(sources_file).exists() and os.stat(sources_file).st_size > 0: self.source = sources_file else: - self.source = SOURCES_URL + self.source = BackendEnvironment.HUB_URL + "app/terminal/data-sources" def parse_input(self, an_input: str) -> List: """Parse controller input @@ -176,6 +176,7 @@ class SourcesController(BaseController): key="features_sources", value=choices, auth_header=get_current_user().profile.get_auth_header(), + base_url=BackendEnvironment.BASE_URL, ) console.print("") console.print( diff --git a/openbb_terminal/terminal_controller.py b/openbb_terminal/terminal_controller.py index fd791f55612..4afab50b1f3 100644 --- a/openbb_terminal/terminal_controller.py +++ b/openbb_terminal/terminal_controller.py @@ -33,7 +33,7 @@ from openbb_terminal.core.config.paths import ( REPOSITORY_DIRECTORY, SETTINGS_ENV_FILE, ) -from openbb_terminal.core.session.constants import SCRIPT_TAGS +from openbb_terminal.core.session import constants from openbb_terminal.core.log.generation.custom_logger import log_terminal from openbb_terminal.core.session import session_controller from openbb_terminal.core.session.current_system import set_system_variable @@ -197,9 +197,9 @@ class TerminalController(BaseController): "-p": "--public", "--local": None, "-l": "--local", - "--tag1": {c: None for c in SCRIPT_TAGS}, - "--tag2": {c: None for c in SCRIPT_TAGS}, - "--tag3": {c: None for c in SCRIPT_TAGS}, + "--tag1": {c: None for c in constants.SCRIPT_TAGS}, + "--tag2": {c: None for c in constants.SCRIPT_TAGS}, + "--tag3": {c: None for c in constants.SCRIPT_TAGS}, } self.completer = NestedCompleter.from_nested_dict(choices) @@ -1100,6 +1100,7 @@ def run_routine(file: str, routines_args=Optional[str]): def main( debug: bool, + dev: bool, path_list: List[str], routines_args: Optional[List[str]] = None, **kwargs, @@ -1110,6 +1111,8 @@ def main( ---------- debug : bool Whether to run the terminal in debug mode + dev: + Points backend towards development environment instead of production test : bool Whether to run the terminal in integrated test mode filtert : str @@ -1129,6 +1132,11 @@ def main( if debug: set_system_variable("DEBUG_MODE", True) + if dev: + set_system_variable("DEV_BACKEND", True) + constants.BackendEnvironment.BASE_URL = "https://payments.openbb.dev/" + constants.BackendEnvironment.HUB_URL = "https://my.openbb.dev/" + cfg.start_plot_backend() if isinstance(path_list, list) and path_list[0].endswith(".openbb"): @@ -1156,6 +1164,13 @@ def parse_args_and_run(): default=False, help="Runs the terminal in debug mode.", ) + parser.add_argument( + "--dev", + dest="dev", + action="store_true", + default=False, + help="Points backend towards development environment instead of production", + ) parser.add_argument( "--file", help="The path or .openbb file to run.", @@ -1227,6 +1242,7 @@ def parse_args_and_run(): main( ns_parser.debug, + ns_parser.dev, ns_parser.path, ns_parser.routine_args, module=ns_parser.module, diff --git a/openbb_terminal/terminal_helper.py b/openbb_terminal/terminal_helper.py index 81f3ff7e33e..63458b34186 100644 --- a/openbb_terminal/terminal_helper.py +++ b/openbb_terminal/terminal_helper.py @@ -23,7 +23,7 @@ from openbb_terminal import thought_of_the_day as thought from openbb_terminal.base_helpers import load_env_files from openbb_terminal.core.config.paths import HIST_FILE_PATH, SETTINGS_ENV_FILE from openbb_terminal.core.plots.backend import plots_backend -from openbb_terminal.core.session.constants import REGISTER_URL +from openbb_terminal.core.session.constants import BackendEnvironment from openbb_terminal.core.session.current_system import get_current_system from openbb_terminal.core.session.current_user import ( get_current_user, @@ -257,7 +257,8 @@ def print_guest_block_msg(): console.print( "[info]You are currently logged as a guest.[/info]\n" "[info]Login to use this feature.[/info]\n\n" - f"[info]If you don't have an account, you can create one here: [/info][cmds]{REGISTER_URL}\n[/cmds]" + "[info]If you don't have an account, you can create one here: [/info]" + f"[cmds]{BackendEnvironment.HUB_URL + 'register'}\n[/cmds]" ) @@ -369,6 +370,7 @@ def reset(queue: Optional[List[str]] = None): plots_backend().close(reset=True) load_env_files() debug = get_current_system().DEBUG_MODE + dev = get_current_system().DEV_BACKEND try: # save the current user @@ -399,7 +401,7 @@ def reset(queue: Optional[List[str]] = None): if is_local(): from openbb_terminal.terminal_controller import main - main(debug, queue_list, module="") # type: ignore + main(debug, dev, queue_list, module="") # type: ignore else: from openbb_terminal.core.session import session_controller diff --git a/terminal.py b/terminal.py index dd0977a5f62..f9d8d8e5248 100644 --- a/terminal.py +++ b/terminal.py @@ -34,8 +34,9 @@ def main(): and ("--login" in sys.argv[1:] or is_installer()) and sys.stdin.isatty() ) + dev = "--dev" in sys.argv[1:] - session_controller.main(prompt=prompt_login) + session_controller.main(prompt=prompt_login, dev=dev) if __name__ == "__main__": diff --git a/tests/openbb_terminal/session/test_hub_model.py b/tests/openbb_terminal/session/test_hub_model.py index 25f620deef9..489ccae660f 100644 --- a/tests/openbb_terminal/session/test_hub_model.py +++ b/tests/openbb_terminal/session/test_hub_model.py @@ -46,7 +46,7 @@ def test_create_session_success(email, password): assert response.json() == TEST_RESPONSE mock_post.assert_called_once_with( - url=hub_model.BASE_URL + "login", + url=hub_model.BackendEnvironment.BASE_URL + "login", json={"email": email, "password": password, "remember": True}, timeout=hub_model.TIMEOUT, ) @@ -113,7 +113,7 @@ def test_create_session_from_token_success(mocker, token): assert response.json() == TEST_RESPONSE mock_post.assert_called_once_with( - url=hub_model.BASE_URL + "sdk/login", + url=hub_model.BackendEnvironment.BASE_URL + "sdk/login", json={"token": token}, timeout=hub_model.TIMEOUT, ) @@ -151,7 +151,7 @@ def test_delete_session_success(auth_header, token): assert response.status_code == 200 mock_post.assert_called_once_with( - url=hub_model.BASE_URL + "logout", + url=hub_model.BackendEnvironment.BASE_URL + "logout", headers={"Authorization": "Bearer test_token"}, json={"token": "test_token"}, timeout=hub_model.TIMEOUT, @@ -336,7 +336,7 @@ def test_fetch_user_configs_success(token_type, access_token): assert result == mock_response requests_get_mock.assert_called_once() _, kwargs = requests_get_mock.call_args - assert kwargs["url"] == hub_model.BASE_URL + "terminal/user" + assert kwargs["url"] == hub_model.BackendEnvironment.BASE_URL + "terminal/user" assert kwargs["headers"] == { "Authorization": f"{token_type.title()} {access_token}" } @@ -352,7 +352,7 @@ def test_fetch_user_configs_failure(): result = hub_model.fetch_user_configs(session) assert isinstance(result, requests.Response) get_mock.assert_called_once_with( - url=hub_model.BASE_URL + "terminal/user", + url=hub_model.BackendEnvironment.BASE_URL + "terminal/user", headers={"Authorization": "Bearer abc123"}, timeout=hub_model.TIMEOUT, ) @@ -366,7 +366,7 @@ def test_fetch_user_configs_connection_error(): result = hub_model.fetch_user_configs(session) assert result is None get_mock.assert_called_once_with( - url=hub_model.BASE_URL + "terminal/user", + url=hub_model.BackendEnvironment.BASE_URL + "terminal/user", headers={"Authorization": "Bearer abc123"}, timeout=hub_model.TIMEOUT, ) @@ -378,7 +378,7 @@ def test_fetch_user_configs_timeout(): result = hub_model.fetch_user_configs(session) assert result is None get_mock.assert_called_once_with( - url=hub_model.BASE_URL + "terminal/user", + url=hub_model.BackendEnvironment.BASE_URL + "terminal/user", headers={"Authorization": "Bearer abc123"}, timeout=hub_model.TIMEOUT, ) @@ -390,7 +390,7 @@ def test_fetch_user_configs_exception(): result = hub_model.fetch_user_configs(session) assert result is None get_mock.assert_called_once_with( - url=hub_model.BASE_URL + "terminal/user", + url=hub_model.BackendEnvironment.BASE_URL + "terminal/user", headers={"Authorization": "Bearer abc123"}, timeout=hub_model.TIMEOUT, ) @@ -415,7 +415,7 @@ def test_upload_config_success(key, value, type_, auth_header): assert result.status_code == mock_response.status_code requests_patch_mock.assert_called_once() _, kwargs = requests_patch_mock.call_args - assert kwargs["url"] == hub_model.BASE_URL + "terminal/user" + assert kwargs["url"] == hub_model.BackendEnvironment.BASE_URL + "terminal/user" assert kwargs["headers"] == {"Authorization": f"{auth_header}"} assert kwargs["json"] == {"key": f"features_{type_}.{key}", "value": value} assert kwargs["timeout"] == hub_model.TIMEOUT @@ -434,7 +434,7 @@ def test_upload_config_failure(): assert result.status_code == mock_response.status_code requests_patch_mock.assert_called_once() _, kwargs = requests_patch_mock.call_args - assert kwargs["url"] == hub_model.BASE_URL + "terminal/user" + assert kwargs["url"] == hub_model.BackendEnvironment.BASE_URL + "terminal/user" assert kwargs["headers"] == {"Authorization": "auth_header"} assert kwargs["json"] == {"key": "features_settings.key", "value": "value"} assert kwargs["timeout"] == hub_model.TIMEOUT @@ -451,7 +451,7 @@ def test_upload_config_connection_error(): assert result is None requests_patch_mock.assert_called_once() _, kwargs = requests_patch_mock.call_args - assert kwargs["url"] == hub_model.BASE_URL + "terminal/user" + assert kwargs["url"] == hub_model.BackendEnvironment.BASE_URL + "terminal/user" assert kwargs["headers"] == {"Authorization": "auth_header"} assert kwargs["json"] == {"key": "features_settings.key", "value": "value"} assert kwargs["timeout"] == hub_model.TIMEOUT @@ -468,7 +468,7 @@ def test_upload_config_timeout(): assert result is None requests_patch_mock.assert_called_once() _, kwargs = requests_patch_mock.call_args - assert kwargs["url"] == hub_model.BASE_URL + "terminal/user" + assert kwargs["url"] == hub_model.BackendEnvironment.BASE_URL + "terminal/user" assert kwargs["headers"] == {"Authorization": "auth_header"} assert kwargs["json"] == {"key": "features_settings.key", "value": "value"} assert kwargs["timeout"] == hub_model.TIMEOUT @@ -485,7 +485,7 @@ def test_upload_config_exception(): assert result is None requests_patch_mock.assert_called_once() _, kwargs = requests_patch_mock.call_args - assert kwargs["url"] == hub_model.BASE_URL + "terminal/user" + assert kwargs["url"] == hub_model.BackendEnvironment.BASE_URL + "terminal/user" assert kwargs["headers"] == {"Authorization": "auth_header"} assert kwargs["json"] == {"key": "features_settings.key", "value": "value"} assert kwargs["timeout"] == hub_model.TIMEOUT @@ -504,7 +504,7 @@ def test_clear_user_configs_success(): assert result.status_code == mock_response.status_code requests_put_mock.assert_called_once() _, kwargs = requests_put_mock.call_args - assert kwargs["url"] == hub_model.BASE_URL + "user" + assert kwargs["url"] == hub_model.BackendEnvironment.BASE_URL + "user" assert kwargs["headers"] == {"Authorization": "auth_header"} assert kwargs["json"] == {"config": {}} assert kwargs["timeout"] == hub_model.TIMEOUT @@ -523,7 +523,7 @@ def test_clear_user_configs_failure(): assert result.status_code == mock_response.status_code requests_put_mock.assert_called_once() _, kwargs = requests_put_mock.call_args - assert kwargs["url"] == hub_model.BASE_URL + "user" + assert kwargs["url"] == hub_model.BackendEnvironment.BASE_URL + "user" assert kwargs["headers"] == {"Authorization": "auth_header"} assert kwargs["json"] == {"config": {}} assert kwargs["timeout"] == hub_model.TIMEOUT @@ -539,7 +539,7 @@ def test_clear_user_configs_timeout(): assert result is None requests_put_mock.assert_called_once() _, kwargs = requests_put_mock.call_args - assert kwargs["url"] == hub_model.BASE_URL + "user" + assert kwargs["url"] == hub_model.BackendEnvironment.BASE_URL + "user" assert kwargs["headers"] == {"Authorization": "auth_header"} assert kwargs["json"] == {"config": {}} assert kwargs["timeout"] == hub_model.TIMEOUT @@ -555,7 +555,7 @@ def test_clear_user_configs_connection_error(): assert result is None requests_put_mock.assert_called_once() _, kwargs = requests_put_mock.call_args - assert kwargs["url"] == hub_model.BASE_URL + "user" + assert kwargs["url"] == hub_model.BackendEnvironment.BASE_URL + "user" assert kwargs["headers"] == {"Authorization": "auth_header"} assert kwargs["json"] == {"config": {}} assert kwargs["timeout"] == hub_model.TIMEOUT @@ -570,7 +570,7 @@ def test_clear_user_configs_exception(): assert result is None requests_put_mock.assert_called_once() _, kwargs = requests_put_mock.call_args - assert kwargs["url"] == hub_model.BASE_URL + "user" + assert kwargs["url"] == hub_model.BackendEnvironment.BASE_URL + "user" assert kwargs["headers"] == {"Authorization": "auth_header"} assert kwargs["json"] == {"config": {}} assert kwargs["timeout"] == hub_model.TIMEOUT From 5ddeb8f35e01fdb90ace17299975111a850082bc Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Mon, 14 Aug 2023 05:20:25 -0500 Subject: [PATCH 07/10] Fix regex (#5320) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * check that routine title is valid * more updates * small fixes * override local routine * more improvements to routine logic * --debug runs .dev * few more updates * small fix * rename BASE_URL from ultima to ULTIMA_BASE_URL * use debug from dataclasses instead of env since env doesn't get updated * create --dev flag that can point to .dev backend * merge conflits * few changes, made it actually work 🤣 * fix regex --------- Co-authored-by: tehcoderer --- openbb_terminal/parent_classes.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openbb_terminal/parent_classes.py b/openbb_terminal/parent_classes.py index 69c1710e32b..d0bb293902b 100644 --- a/openbb_terminal/parent_classes.py +++ b/openbb_terminal/parent_classes.py @@ -981,7 +981,8 @@ class BaseController(metaclass=ABCMeta): # Check if title has a valid format title = " ".join(ns_parser.name) if ns_parser.name else "" - pattern = re.compile(r"^[a-zA-Z0-9\s]+(?:[-a-zA-Z0-9\s]+)*$") + # To this day, the reason why /^[a-zA-Z0-9\s]+$/ does not work is unknown + pattern = re.compile(r"^[a-zA-Z0-9\s]+(?:[a-zA-Z0-9\s]+)*$") if not pattern.match(title): console.print(f"[red]The title '{title}' has invalid format. Please use only digits, characters and whitespaces.[/red]") return From 2c44cae0e9bf002377fd1d9bf987da5b3dc006b8 Mon Sep 17 00:00:00 2001 From: James Maslek Date: Mon, 14 Aug 2023 09:57:41 -0400 Subject: [PATCH 08/10] add back --url auto complete --- openbb_terminal/account/account_controller.py | 4 +- .../common/ultima_newsmonitor_model.py | 4 +- openbb_terminal/core/completer/choices.py | 3 +- openbb_terminal/keys_controller.py | 6 +- openbb_terminal/parent_classes.py | 92 +++++++++++++------ openbb_terminal/portfolio/portfolio_engine.py | 3 +- openbb_terminal/terminal_controller.py | 11 ++- 7 files changed, 83 insertions(+), 40 deletions(-) diff --git a/openbb_terminal/account/account_controller.py b/openbb_terminal/account/account_controller.py index c9f233b0600..8db4d421c25 100644 --- a/openbb_terminal/account/account_controller.py +++ b/openbb_terminal/account/account_controller.py @@ -414,7 +414,7 @@ class AccountController(BaseController): response = Hub.download_routine( auth_header=get_current_user().profile.get_auth_header(), uuid=self.REMOTE_CHOICES[name], - base_url=Hub.BackendEnvironment.BASE_URL + base_url=Hub.BackendEnvironment.BASE_URL, ) if response and response.status_code == 200: data = [response.json(), "personal"] @@ -502,7 +502,7 @@ class AccountController(BaseController): response = Hub.delete_routine( auth_header=get_current_user().profile.get_auth_header(), uuid=self.REMOTE_CHOICES[name], - base_url=Hub.BackendEnvironment.BASE_URL + base_url=Hub.BackendEnvironment.BASE_URL, ) if ( response diff --git a/openbb_terminal/common/ultima_newsmonitor_model.py b/openbb_terminal/common/ultima_newsmonitor_model.py index e06226b7b10..656ba75c53f 100644 --- a/openbb_terminal/common/ultima_newsmonitor_model.py +++ b/openbb_terminal/common/ultima_newsmonitor_model.py @@ -213,7 +213,9 @@ def get_top_headlines(ticker: str) -> dict: if ticker in supported_terms(): if auth_header: - data = request(f"{ULTIMA_BASE_URL}/getTopHeadlines/{ticker}", headers=auth_header) + data = request( + f"{ULTIMA_BASE_URL}/getTopHeadlines/{ticker}", headers=auth_header + ) else: data = request(f"{ULTIMA_BASE_URL}/getTopHeadlines/{ticker}") if ( diff --git a/openbb_terminal/core/completer/choices.py b/openbb_terminal/core/completer/choices.py index 178006cdca4..fabfb46c384 100644 --- a/openbb_terminal/core/completer/choices.py +++ b/openbb_terminal/core/completer/choices.py @@ -1,14 +1,13 @@ from argparse import ArgumentParser from contextlib import contextmanager from inspect import isfunction, unwrap -from os import environ from types import MethodType from typing import Callable, List from unittest.mock import patch +from openbb_terminal.core.session.current_system import get_current_system from openbb_terminal.helper_funcs import check_file_type_saved, check_positive from openbb_terminal.rich_config import get_ordered_list_sources -from openbb_terminal.core.session.current_system import get_current_system def __mock_parse_known_args_and_warn( diff --git a/openbb_terminal/keys_controller.py b/openbb_terminal/keys_controller.py index 6c2ccd5f398..69c94595a53 100644 --- a/openbb_terminal/keys_controller.py +++ b/openbb_terminal/keys_controller.py @@ -75,7 +75,11 @@ class KeysController(BaseController): # pylint: disable=too-many-public-methods """ reading_order = get_reading_order() hierarchy = "\n ".join(list(map(str, reversed(reading_order)))) - return hierarchy if is_local() else f"{BackendEnvironment.HUB_URL + 'app/terminal/api-keys'}\n {hierarchy}" + return ( + hierarchy + if is_local() + else f"{BackendEnvironment.HUB_URL + 'app/terminal/api-keys'}\n {hierarchy}" + ) def print_help(self, update_status: bool = True, reevaluate: bool = True): """Print help""" diff --git a/openbb_terminal/parent_classes.py b/openbb_terminal/parent_classes.py index d0bb293902b..e5ec6945bc9 100644 --- a/openbb_terminal/parent_classes.py +++ b/openbb_terminal/parent_classes.py @@ -5,7 +5,6 @@ __docformat__ = "numpy" # IMPORTS STANDARD import argparse -import itertools import difflib import json import logging @@ -27,12 +26,11 @@ from rich.markdown import Markdown import openbb_terminal.core.session.local_model as Local from openbb_terminal import config_terminal from openbb_terminal.account.show_prompt import get_show_prompt -from openbb_terminal.core.session.constants import SCRIPT_TAGS from openbb_terminal.core.completer.choices import build_controller_choice_map from openbb_terminal.core.config.paths import HIST_FILE_PATH from openbb_terminal.core.session import hub_model as Hub +from openbb_terminal.core.session.constants import SCRIPT_TAGS from openbb_terminal.core.session.current_user import get_current_user, is_local -from openbb_terminal.core.session.routines_handler import read_routine from openbb_terminal.cryptocurrency import cryptocurrency_helpers from openbb_terminal.custom_prompt_toolkit import NestedCompleter from openbb_terminal.decorators import log_start_end @@ -953,30 +951,55 @@ class BaseController(metaclass=ABCMeta): ns_parser = self.parse_simple_args(parser, other_args) if ns_parser: - if not ns_parser.name: - console.print("[red]Set a routine title by using the '-n' flag. E.g. 'record -n Morning routine'[/red]") + console.print( + "[red]Set a routine title by using the '-n' flag. E.g. 'record -n Morning routine'[/red]" + ) return - tag1 = " ".join(ns_parser.tag1) if isinstance(ns_parser.tag1, list) else ns_parser.tag1 + tag1 = ( + " ".join(ns_parser.tag1) + if isinstance(ns_parser.tag1, list) + else ns_parser.tag1 + ) if tag1 and tag1 not in SCRIPT_TAGS: - console.print(f"[red]The parameter 'tag1' needs to be one of the following {', '.join(SCRIPT_TAGS)}[/red]") + console.print( + f"[red]The parameter 'tag1' needs to be one of the following {', '.join(SCRIPT_TAGS)}[/red]" + ) return - tag2 = " ".join(ns_parser.tag2) if isinstance(ns_parser.tag2, list) else ns_parser.tag2 + tag2 = ( + " ".join(ns_parser.tag2) + if isinstance(ns_parser.tag2, list) + else ns_parser.tag2 + ) if tag2 and tag2 not in SCRIPT_TAGS: - console.print(f"[red]The parameter 'tag2' needs to be one of the following {', '.join(SCRIPT_TAGS)}[/red]") + console.print( + f"[red]The parameter 'tag2' needs to be one of the following {', '.join(SCRIPT_TAGS)}[/red]" + ) return - tag3 = " ".join(ns_parser.tag3) if isinstance(ns_parser.tag3, list) else ns_parser.tag3 + tag3 = ( + " ".join(ns_parser.tag3) + if isinstance(ns_parser.tag3, list) + else ns_parser.tag3 + ) if tag3 and tag3 not in SCRIPT_TAGS: - console.print(f"[red]The parameter 'tag3' needs to be one of the following {', '.join(SCRIPT_TAGS)}[/red]") + console.print( + f"[red]The parameter 'tag3' needs to be one of the following {', '.join(SCRIPT_TAGS)}[/red]" + ) return if is_local() and not ns_parser.local: - console.print("[red]Recording session to the OpenBB Hub is not supported in guest mode.[/red]") - console.print("\n[yellow]Sign to OpenBB Hub to register: http://openbb.co[/yellow]") - console.print("\n[yellow]Otherwise set the flag '-l' to save the file locally.[/yellow]") + console.print( + "[red]Recording session to the OpenBB Hub is not supported in guest mode.[/red]" + ) + console.print( + "\n[yellow]Sign to OpenBB Hub to register: http://openbb.co[/yellow]" + ) + console.print( + "\n[yellow]Otherwise set the flag '-l' to save the file locally.[/yellow]" + ) return # Check if title has a valid format @@ -984,7 +1007,9 @@ class BaseController(metaclass=ABCMeta): # To this day, the reason why /^[a-zA-Z0-9\s]+$/ does not work is unknown pattern = re.compile(r"^[a-zA-Z0-9\s]+(?:[a-zA-Z0-9\s]+)*$") if not pattern.match(title): - console.print(f"[red]The title '{title}' has invalid format. Please use only digits, characters and whitespaces.[/red]") + console.print( + f"[red]Title '{title}' has invalid format. Please use only digits, characters and whitespaces.[/]" + ) return global RECORD_SESSION @@ -997,15 +1022,23 @@ class BaseController(metaclass=ABCMeta): RECORD_SESSION = True RECORD_SESSION_LOCAL_ONLY = ns_parser.local SESSION_RECORDED_NAME = title - SESSION_RECORDED_DESCRIPTION = " ".join(ns_parser.description) if isinstance(ns_parser.description, list) else ns_parser.description + SESSION_RECORDED_DESCRIPTION = ( + " ".join(ns_parser.description) + if isinstance(ns_parser.description, list) + else ns_parser.description + ) SESSION_RECORDED_TAGS = tag1 if tag1 else "" - SESSION_RECORDED_TAGS += ',' + tag2 if tag2 else "" - SESSION_RECORDED_TAGS += ',' + tag3 if tag3 else "" + SESSION_RECORDED_TAGS += "," + tag2 if tag2 else "" + SESSION_RECORDED_TAGS += "," + tag3 if tag3 else "" SESSION_RECORDED_PUBLIC = ns_parser.public - console.print(f"[green]The routine '{title}' is successfully being recorded.[/green]") - console.print("\n[yellow]Remember to run 'stop' command when you are done!\n[/yellow]") + console.print( + f"[green]The routine '{title}' is successfully being recorded.[/green]" + ) + console.print( + "\n[yellow]Remember to run 'stop' command when you are done!\n[/yellow]" + ) @log_start_end(log=logger) def call_stop(self, _) -> None: @@ -1028,11 +1061,13 @@ class BaseController(metaclass=ABCMeta): # This works regardless of whether they are logged in or not if RECORD_SESSION_LOCAL_ONLY: # Whitespaces are replaced by underscores and an .openbb extension is added - title_for_local_storage = SESSION_RECORDED_NAME.replace(" ", "_") + ".openbb" + title_for_local_storage = ( + SESSION_RECORDED_NAME.replace(" ", "_") + ".openbb" + ) routine_file = os.path.join( current_user.preferences.USER_ROUTINES_DIRECTORY, - title_for_local_storage + title_for_local_storage, ) # If file already exists, add a timestamp to the name @@ -1043,18 +1078,21 @@ class BaseController(metaclass=ABCMeta): ) console.print("") while i.lower() not in ["y", "yes", "n", "no"]: - i = console.input( - "Select 'y' or 'n' to proceed: " - ) + i = console.input("Select 'y' or 'n' to proceed: ") console.print("") if i.lower() in ["n", "no"]: - new_name = datetime.now().strftime("%Y%m%d_%H%M%S_") + title_for_local_storage + new_name = ( + datetime.now().strftime("%Y%m%d_%H%M%S_") + + title_for_local_storage + ) routine_file = os.path.join( current_user.preferences.USER_ROUTINES_DIRECTORY, new_name, ) - console.print(f"[yellow]The routine name has been updated to '{new_name}'[/yellow]\n") + console.print( + f"[yellow]The routine name has been updated to '{new_name}'[/yellow]\n" + ) # Writing to file with open(routine_file, "w") as file1: diff --git a/openbb_terminal/portfolio/portfolio_engine.py b/openbb_terminal/portfolio/portfolio_engine.py index ce931d77d07..2c945b661d5 100644 --- a/openbb_terminal/portfolio/portfolio_engine.py +++ b/openbb_terminal/portfolio/portfolio_engine.py @@ -4,7 +4,6 @@ __docformat__ = "numpy" import datetime import logging import warnings -from os import environ from typing import Any, Dict import numpy as np @@ -12,6 +11,7 @@ import pandas as pd import yfinance as yf from tqdm import tqdm +from openbb_terminal.core.session.current_system import get_current_system from openbb_terminal.decorators import log_start_end from openbb_terminal.portfolio.allocation_model import get_allocation from openbb_terminal.portfolio.portfolio_helper import ( @@ -21,7 +21,6 @@ from openbb_terminal.portfolio.portfolio_helper import ( from openbb_terminal.rich_config import console from openbb_terminal.stocks.fundamental_analysis.yahoo_finance_model import get_splits from openbb_terminal.terminal_helper import suppress_stdout -from openbb_terminal.core.session.current_system import get_current_system # pylint: disable=E1136,W0201,R0902,C0302 # pylint: disable=unsupported-assignment-operation,redefined-outer-name diff --git a/openbb_terminal/terminal_controller.py b/openbb_terminal/terminal_controller.py index 4afab50b1f3..84453250a20 100644 --- a/openbb_terminal/terminal_controller.py +++ b/openbb_terminal/terminal_controller.py @@ -20,7 +20,6 @@ import certifi import pandas as pd import requests from prompt_toolkit import PromptSession -from openbb_terminal.custom_prompt_toolkit import NestedCompleter from prompt_toolkit.formatted_text import HTML from prompt_toolkit.styles import Style @@ -33,11 +32,11 @@ from openbb_terminal.core.config.paths import ( REPOSITORY_DIRECTORY, SETTINGS_ENV_FILE, ) -from openbb_terminal.core.session import constants from openbb_terminal.core.log.generation.custom_logger import log_terminal -from openbb_terminal.core.session import session_controller +from openbb_terminal.core.session import constants, session_controller from openbb_terminal.core.session.current_system import set_system_variable from openbb_terminal.core.session.current_user import get_current_user, set_preference +from openbb_terminal.custom_prompt_toolkit import NestedCompleter from openbb_terminal.helper_funcs import ( EXPORT_ONLY_RAW_DATA_ALLOWED, check_positive, @@ -180,12 +179,15 @@ class TerminalController(BaseController): } choices["exe"] = { - "--file": {filename: {} for filename in list(self.ROUTINE_FILES.keys())}, + "--file": { + filename: {} for filename in list(self.ROUTINE_FILES.keys()) + }, "-f": "--file", "--example": None, "-e": "--example", "--input": None, "-i": "--input", + "--url": None, } choices["record"] = { @@ -776,7 +778,6 @@ class TerminalController(BaseController): self.queue = self.queue[1:] - # pylint: disable=global-statement def terminal(jobs_cmds: Optional[List[str]] = None, test_mode=False): """Terminal Menu.""" From 99a5459dc0cd4c81b836d64a6a1573d899a45403 Mon Sep 17 00:00:00 2001 From: James Maslek Date: Mon, 14 Aug 2023 10:03:41 -0400 Subject: [PATCH 09/10] mypy --- openbb_terminal/core/session/hub_model.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openbb_terminal/core/session/hub_model.py b/openbb_terminal/core/session/hub_model.py index 52f0005c645..8c711b10d07 100644 --- a/openbb_terminal/core/session/hub_model.py +++ b/openbb_terminal/core/session/hub_model.py @@ -543,7 +543,7 @@ def download_routine( try: response = requests.get( headers={"Authorization": auth_header}, - url=base_url + "terminal/script/" + uuid, + url=base_url + "terminal/script/" + uuid, # type: ignore timeout=timeout, ) if response.status_code == 404: @@ -589,7 +589,7 @@ def delete_routine( try: response = requests.delete( headers={"Authorization": auth_header}, - url=base_url + "terminal/script/" + uuid, + url=base_url + "terminal/script/" + uuid, # type: ignore timeout=timeout, ) if response.status_code == 200: From 889a986b072938231a8511d8f3c04932fefd003e Mon Sep 17 00:00:00 2001 From: James Maslek Date: Mon, 14 Aug 2023 10:47:29 -0400 Subject: [PATCH 10/10] pylint + test --- openbb_terminal/core/plots/backend.py | 2 +- tests/openbb_terminal/test_terminal_controller.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openbb_terminal/core/plots/backend.py b/openbb_terminal/core/plots/backend.py index f32828bdeaa..af6a29e2947 100644 --- a/openbb_terminal/core/plots/backend.py +++ b/openbb_terminal/core/plots/backend.py @@ -19,7 +19,7 @@ from reportlab.graphics import renderPDF from openbb_terminal.core.session.constants import BackendEnvironment -# pylint: disable=C0415 +# pylint: disable=C0411,C0412,C0415 try: from pywry import PyWry except ImportError as e: diff --git a/tests/openbb_terminal/test_terminal_controller.py b/tests/openbb_terminal/test_terminal_controller.py index 7abdbadde20..5ff5f757236 100644 --- a/tests/openbb_terminal/test_terminal_controller.py +++ b/tests/openbb_terminal/test_terminal_controller.py @@ -68,10 +68,10 @@ def no_suppress(): @pytest.mark.vcr(record_mode="none") @pytest.mark.record_stdout @pytest.mark.parametrize( - "debug, path", - [(True, None), (False, ["scripts/test_alt_covid.openbb"])], + "debug, dev, path", + [(True, False, None), (False, False, ["scripts/test_alt_covid.openbb"])], ) -def test_menu(mocker, debug, path): +def test_menu(mocker, debug, dev, path): mocker.patch(target="terminal_controller.terminal") mocker.patch(target="terminal_controller.suppress_stdout", side_effect=no_suppress) - terminal_controller.main(debug, path) + terminal_controller.main(debug, dev, path)