Merge pull request #5312 from OpenBB-finance/hotfix/macro-routines-to-hub

Fix routines creation from the Terminal to Hub
This commit is contained in:
James Maslek
2023-08-14 10:54:28 -04:00
committed by GitHub
26 changed files with 431 additions and 191 deletions

4
README.md vendored
View File

@@ -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)

View File

@@ -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:

View File

@@ -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,11 @@ 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

View File

@@ -1,11 +1,11 @@
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
@@ -211,7 +211,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 +219,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 +317,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

View File

@@ -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

View File

@@ -17,7 +17,9 @@ import plotly.graph_objects as go
from packaging import version
from reportlab.graphics import renderPDF
# pylint: disable=C0415
from openbb_terminal.core.session.constants import BackendEnvironment
# pylint: disable=C0411,C0412,C0415
try:
from pywry import PyWry
except ImportError as e:
@@ -441,8 +443,10 @@ class Backend(PyWry):
self.check_backend()
endpoint = {True: "login", False: "logout"}[login]
json_url = f"{BackendEnvironment.HUB_URL}{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,

View File

@@ -1,13 +1,16 @@
BASE_URL = "https://payments.openbb.co/"
# BASE_URL = "http://127.0.0.1:8000/"
class HubEnvironment:
# BASE_URL = "http://127.0.0.1:8000/"
BASE_URL = "https://payments.openbb.co/"
HUB_URL = "https://my.openbb.co/"
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"
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"
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
BackendEnvironment = HubEnvironment()
DEFAULT_ROUTINES_URL = "https://openbb-cms.directus.app/items/Routines"

View File

@@ -7,18 +7,22 @@ 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
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.
@@ -71,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.
@@ -108,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.
@@ -190,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)
@@ -209,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.
@@ -258,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.
@@ -307,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]:
@@ -365,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.
@@ -429,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.
@@ -467,7 +477,6 @@ def upload_routine(
"version": get_current_system().VERSION,
"public": public,
}
try:
response = requests.post(
headers={"Authorization": auth_header},
@@ -476,7 +485,21 @@ def upload_routine(
timeout=timeout,
)
if response.status_code == 200:
console.print("[green]Successfully uploaded your routine.[/green]")
username = get_current_user().profile.username
console.print("[green]Successfully uploaded your routine.[/]")
run_env = BackendEnvironment.HUB_URL.rstrip("/")
if public:
console.print(
f"\n[yellow]Share or edit it at {run_env}/u/{username}/routine/{name.replace(' ', '-')}[/]"
)
else:
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]"
@@ -496,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.
@@ -520,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:
@@ -542,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.
@@ -566,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:
@@ -592,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]:
@@ -683,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.
@@ -732,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.
@@ -777,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.

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -164,7 +164,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",

View File

@@ -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},

View File

@@ -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):

View File

@@ -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,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"{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"""

View File

@@ -29,8 +29,8 @@ from openbb_terminal.account.show_prompt import get_show_prompt
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
@@ -85,6 +85,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 +112,6 @@ class BaseController(metaclass=ABCMeta):
"reset",
"support",
"wiki",
"record",
"stop",
"screenshot",
"askobb",
@@ -892,8 +892,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 +902,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 +937,108 @@ 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 ""
# 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]Title '{title}' has invalid format. Please use only digits, characters and whitespaces.[/]"
)
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]"
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]"
)
RECORD_SESSION = True
@log_start_end(log=logger)
def call_stop(self, _) -> None:
@@ -956,57 +1048,102 @@ 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):
routine_file = os.path.join(
current_user.preferences.USER_ROUTINES_DIRECTORY,
datetime.now().strftime("%Y%m%d_%H%M%S_") + SESSION_RECORDED_NAME,
# 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"
)
# 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]])
routine_file = os.path.join(
current_user.preferences.USER_ROUTINES_DIRECTORY,
title_for_local_storage,
)
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:
i = console.input(
"A routine with the same name already exists, "
"do you want to replace it? (y/n): "
)
# 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("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" 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".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,
"base_url": Hub.BackendEnvironment.BASE_URL,
}
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

View File

@@ -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)}

View File

@@ -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 (
@@ -196,7 +196,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"
)

View File

@@ -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"

View File

@@ -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")

View File

@@ -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(

View File

@@ -20,7 +20,6 @@ import certifi
import pandas as pd
import requests
from prompt_toolkit import PromptSession
from prompt_toolkit.completion import NestedCompleter
from prompt_toolkit.formatted_text import HTML
from prompt_toolkit.styles import Style
@@ -34,9 +33,10 @@ from openbb_terminal.core.config.paths import (
SETTINGS_ENV_FILE,
)
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,
@@ -90,6 +90,7 @@ class TerminalController(BaseController):
"news",
"intro",
"askobb",
"record",
]
CHOICES_MENUS = [
"stocks",
@@ -142,45 +143,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
self.ROUTINE_CHOICES["--url"] = 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"]}
@@ -188,6 +154,56 @@ 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",
"--url": None,
}
choices["record"] = {
"--name": None,
"-n": "--name",
"--description": None,
"-d": "--description",
"--public": None,
"-p": "--public",
"--local": None,
"-l": "--local",
"--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)
def print_help(self):
@@ -1085,6 +1101,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,
@@ -1095,6 +1112,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
@@ -1114,6 +1133,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"):
@@ -1141,6 +1165,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.",
@@ -1212,6 +1243,7 @@ def parse_args_and_run():
main(
ns_parser.debug,
ns_parser.dev,
ns_parser.path,
ns_parser.routine_args,
module=ns_parser.module,

View File

@@ -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

View File

@@ -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__":

View File

@@ -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

View File

@@ -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)