Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make default routines available & download personal routines on login #4737

Merged
merged 29 commits into from
Apr 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
bbaad2b
make default routines available
montezdesousa Apr 11, 2023
b4a4560
remove unecessary change
montezdesousa Apr 11, 2023
2886ba5
Merge branch 'develop' into feature/default_routines
montezdesousa Apr 11, 2023
bfae685
user to personal
montezdesousa Apr 11, 2023
d915e6f
rename some funcs
montezdesousa Apr 11, 2023
55194bb
add last update to tables
montezdesousa Apr 11, 2023
26d448e
add routines download on login
montezdesousa Apr 11, 2023
e0f9818
move some routines funcs to controller
montezdesousa Apr 11, 2023
6db14b3
fix tests
montezdesousa Apr 11, 2023
1af2142
add space
montezdesousa Apr 11, 2023
36dee3f
wrap some funcs inside try, except
montezdesousa Apr 12, 2023
08cd157
fix account test
montezdesousa Apr 12, 2023
daca4a4
suppress outputs
montezdesousa Apr 12, 2023
dc62a4b
rewrite docstring
montezdesousa Apr 12, 2023
977a98c
remove circular import
montezdesousa Apr 12, 2023
db357d8
reverse order
montezdesousa Apr 12, 2023
c08f9d6
update docstring
montezdesousa Apr 12, 2023
e93addf
allow exe with spaces in file name
montezdesousa Apr 12, 2023
fdbf5c5
fix exe with input
montezdesousa Apr 12, 2023
16c011b
Update terminal_controller.py
montezdesousa Apr 12, 2023
a465bae
fix regex for file extensions
montezdesousa Apr 12, 2023
74238ec
pylint
montezdesousa Apr 12, 2023
d84c36f
Merge branch 'develop' into feature/default_routines
montezdesousa Apr 12, 2023
f22183e
Merge branch 'develop' into feature/default_routines
montezdesousa Apr 12, 2023
6420111
Merge branch 'develop' into feature/default_routines
JerBouma Apr 12, 2023
e45b48c
Merge branch 'develop' into feature/default_routines
montezdesousa Apr 12, 2023
9b60f7c
Merge branch 'develop' into feature/default_routines
montezdesousa Apr 12, 2023
399db99
put default routines url inside constants
montezdesousa Apr 12, 2023
f989237
Merge branch 'develop' into feature/default_routines
jmaslek Apr 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
180 changes: 126 additions & 54 deletions openbb_terminal/account/account_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@
from pathlib import Path
from typing import Dict, List, Optional

from openbb_terminal.account.account_model import (
get_routines_info,
read_routine,
save_routine,
set_login_called,
from openbb_terminal.account.account_view import (
display_default_routines,
display_personal_routines,
)
from openbb_terminal.account.account_view import display_routines_list
from openbb_terminal.core.session import hub_model as Hub
from openbb_terminal.core.session.current_user import (
get_current_user,
is_local,
)
from openbb_terminal.core.session.routines_handler import (
get_default_routines_info,
get_personal_routines_info,
read_routine,
save_routine,
)
from openbb_terminal.core.session.session_model import logout
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
from openbb_terminal.decorators import log_start_end
Expand All @@ -27,6 +30,32 @@
logger = logging.getLogger(__name__)


__login_called = False


def get_login_called():
"""Get the login/logout called flag.

Returns
-------
bool
The login/logout called flag.
"""
return __login_called


def set_login_called(value: bool):
"""Set the login/logout called flag.

Parameters
----------
value : bool
The login/logout called flag.
"""
global __login_called # pylint: disable=global-statement
__login_called = value


class AccountController(BaseController):
"""Account Controller Class"""

Expand All @@ -49,27 +78,41 @@ class AccountController(BaseController):
def __init__(self, queue: Optional[List[str]] = None):
"""Constructor"""
super().__init__(queue)
self.ROUTINE_FILES: Dict[str, Path] = {}
self.LOCAL_ROUTINES: Dict[str, Path] = {}
self.REMOTE_CHOICES: List[str] = []

self.DEFAULT_ROUTINES: List[Dict[str, str]] = self.fetch_default_routines()
self.DEFAULT_CHOICES: List[str] = [
r["name"] for r in self.DEFAULT_ROUTINES if "name" in r
]

if session and get_current_user().preferences.USE_PROMPT_TOOLKIT:
self.choices: dict = self.choices_default
self.completer = NestedCompleter.from_nested_dict(self.choices)

def update_runtime_choices(self):
"""Update runtime choices"""
self.ROUTINE_FILES = self.get_routines()
self.LOCAL_ROUTINES = self.get_local_routines()
if session and get_current_user().preferences.USE_PROMPT_TOOLKIT:
self.choices["upload"]["--file"].update({c: {} for c in self.ROUTINE_FILES})
self.choices["upload"]["--file"].update(
{c: {} for c in self.LOCAL_ROUTINES}
)
self.choices["download"]["--name"].update(
{c: {} for c in self.REMOTE_CHOICES}
{c: {} for c in self.DEFAULT_CHOICES + self.REMOTE_CHOICES}
)
self.choices["delete"]["--name"].update(
{c: {} for c in self.REMOTE_CHOICES}
)
self.completer = NestedCompleter.from_nested_dict(self.choices)

def get_routines(self):
"""Get routines"""
def get_local_routines(self) -> Dict[str, Path]:
"""Get local routines

Returns
-------
Dict[str, Path]
The local routines
"""
current_user = get_current_user()
return {
filepath.name: filepath
Expand All @@ -78,6 +121,20 @@ def get_routines(self):
)
}

def fetch_default_routines(self) -> List[Dict[str, str]]:
"""Fetch default routines

Returns
-------
List[Dict[str, str]]
The default routines
"""
response = Hub.get_default_routines()
if response and response.status_code == 200:
d = response.json()
return d.get("data", [])
return []

def print_help(self):
"""Print help"""
mt = MenuText("account/", 100)
Expand Down Expand Up @@ -201,13 +258,16 @@ def call_list(self, other_args: List[str]):
page=ns_parser.page,
size=ns_parser.size,
)
df, page, pages = get_routines_info(response)
df, page, pages = get_personal_routines_info(response)
if not df.empty:
self.REMOTE_CHOICES += list(df["name"])
self.update_runtime_choices()
display_routines_list(df, page, pages)
display_personal_routines(df, page, pages)
else:
console.print("[red]No routines found.[/red]")
console.print("")
df = get_default_routines_info(self.DEFAULT_ROUTINES)
display_default_routines(df)

@log_start_end(log=logger)
def call_upload(self, other_args: List[str]):
Expand Down Expand Up @@ -320,49 +380,61 @@ def call_download(self, other_args: List[str]):
print_guest_block_msg()
else:
if ns_parser:
response = Hub.download_routine(
auth_header=get_current_user().profile.get_auth_header(),
name=" ".join(ns_parser.name),
)
data = None

if response and response.status_code == 200:
data = response.json()
if data:
name = data.get("name", "")
if name:
console.print(f"[info]Name:[/info] {name}")

description = data.get("description", "")
if description:
console.print(f"[info]Description:[/info] {description}")

script = data.get("script", "")
if script:
file_name = f"{name}.openbb"
file_path = save_routine(
file_name=file_name,
routine=script,
# Default routine
name = " ".join(ns_parser.name)
if name in self.DEFAULT_CHOICES:
data = next(
(r for r in self.DEFAULT_ROUTINES if r["name"] == name), None
)
else:
# User routine
response = Hub.download_routine(
auth_header=get_current_user().profile.get_auth_header(),
name=name,
)
data = (
response.json()
if response and response.status_code == 200
else None
)

# Save routine
if data:
name = data.get("name", "")
if name:
console.print(f"[info]Name:[/info] {name}")

description = data.get("description", "")
if description:
console.print(f"[info]Description:[/info] {description}")

script = data.get("script", "")
if script:
file_name = f"{name}.openbb"
file_path = save_routine(
file_name=file_name,
routine=script,
)
if file_path == "File already exists":
i = console.input(
"\nA file with the same name already exists, "
"do you want to replace it? (y/n): "
)
if file_path == "File already exists":
i = console.input(
"\nA file with the same name already exists, "
"do you want to replace it? (y/n): "
console.print("")
if i.lower() in ["y", "yes"]:
file_path = save_routine(
file_name=file_name,
routine=script,
force=True,
)
console.print("")
if i.lower() in ["y", "yes"]:
file_path = save_routine(
file_name=file_name,
routine=script,
force=True,
)
if file_path:
console.print(
f"[info]Location:[/info] {file_path}"
)
else:
console.print("[info]Aborted.[/info]")
elif file_path:
console.print(f"[info]Location:[/info] {file_path}")
if file_path:
console.print(f"[info]Location:[/info] {file_path}")
else:
console.print("[info]Aborted.[/info]")
elif file_path:
console.print(f"[info]Location:[/info] {file_path}")

@log_start_end(log=logger)
def call_delete(self, other_args: List[str]):
Expand Down
56 changes: 43 additions & 13 deletions openbb_terminal/account/account_view.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import pandas as pd

from openbb_terminal.helper_funcs import print_rich_table
from openbb_terminal.rich_config import console


def display_routines_list(df: pd.DataFrame, page: int, pages: int):
"""Display the routines list.
def display_personal_routines(df: pd.DataFrame, page: int, pages: int):
"""Display the routines.

Parameters
----------
Expand All @@ -15,14 +16,43 @@ def display_routines_list(df: pd.DataFrame, page: int, pages: int):
pages : int
The total number of pages.
"""
title = f"Available routines - page {page}"
if pages:
title += f" of {pages}"

print_rich_table(
df=df,
title=title,
headers=["Name", "Description"],
show_index=True,
index_name="#",
)
try:
title = f"Personal routines - page {page}"
if pages:
title += f" of {pages}"

df["updated_date"] = pd.to_datetime(df["updated_date"])
df["updated_date"] = df["updated_date"].dt.strftime("%Y-%m-%d %H:%M:%S")
df.replace(to_replace=[None], value="-", inplace=True)
print_rich_table(
df=df,
title=title,
headers=["Name", "Description", "Version", "Last update"],
show_index=True,
index_name="#",
)
except Exception:
console.print("Failed to display personal routines.")


def display_default_routines(df: pd.DataFrame):
"""Display the default routines.

Parameters
----------
df : pd.DataFrame
The default routines list.
"""
try:
df["date_updated"] = pd.to_datetime(df["date_updated"])
df["date_updated"] = df["date_updated"].dt.strftime("%Y-%m-%d %H:%M:%S")
df.replace(to_replace=[None], value="-", inplace=True)
print_rich_table(
df=df,
title="Default routines",
headers=["Name", "Description", "Version", "Last update"],
show_index=True,
index_name="#",
)
except Exception:
console.print("Failed to display default routines.")
Empty file.
3 changes: 2 additions & 1 deletion openbb_terminal/core/session/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
COLORS_URL = HUB_URL + "app/terminal/theme"
CHARTS_TABLES_URL = HUB_URL + "app/terminal/theme/charts-tables"

TIMEOUT = 15
DEFAULT_ROUTINES_URL = "https://tffo1zc1.directus.app/items/Routines"

TIMEOUT = 15
CONNECTION_ERROR_MSG = "[red]Connection error.[/red]"
CONNECTION_TIMEOUT_MSG = "[red]Connection timeout.[/red]"
Loading