Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into feature/integratio…
Browse files Browse the repository at this point in the history
…n-test-coverage
  • Loading branch information
IgorWounds committed May 7, 2023
2 parents 04e0eab + 1f0c3ff commit 1163357
Show file tree
Hide file tree
Showing 10 changed files with 351 additions and 96 deletions.
45 changes: 23 additions & 22 deletions openbb_terminal/account/account_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,8 @@ def call_upload(self, other_args: List[str]):
self.REMOTE_CHOICES.append(name)
self.update_runtime_choices()

# store data in list with "personal/default" to identify data's routine type
# and for save_routine
@log_start_end(log=logger)
def call_download(self, other_args: List[str]):
"""Download"""
Expand Down Expand Up @@ -398,37 +400,36 @@ def call_download(self, other_args: List[str]):
print_guest_block_msg()
else:
if ns_parser:
data = None

# Default routine
data = []
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
)
# Personal routines
response = Hub.download_routine(
auth_header=get_current_user().profile.get_auth_header(),
name=name,
)
if response and response.status_code == 200:
data = [response.json(), "personal"]
# Default routine
elif name in self.DEFAULT_CHOICES:
data = [
next(
(r for r in self.DEFAULT_ROUTINES if r["name"] == name),
None,
),
"default",
]

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

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

script = data.get("script", "")
script = [data[0].get("script", ""), data[1]]
if script:
file_name = f"{name}.openbb"
file_path = save_routine(
Expand Down
41 changes: 28 additions & 13 deletions openbb_terminal/core/session/routines_handler.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
from os import walk
from pathlib import Path
from typing import Dict, List, Optional, Tuple, Union

Expand All @@ -10,7 +11,10 @@
from openbb_terminal.rich_config import console


def download_routines(auth_header: str, silent: bool = False) -> Dict[str, str]:
# created dictionaries for personal and default routines with the structure
# {"file_name" :["script","personal/default"]}
# and stored dictionaries in list
def download_routines(auth_header: str, silent: bool = False) -> list:
"""Download default and personal routines.
Parameters
Expand All @@ -25,7 +29,8 @@ def download_routines(auth_header: str, silent: bool = False) -> Dict[str, str]:
Dict[str, str]
The routines.
"""
routines_dict = {}
personal_routines_dict = {}
default_routines_dict = {}

try:
response = Hub.get_default_routines(silent=silent)
Expand All @@ -35,7 +40,7 @@ def download_routines(auth_header: str, silent: bool = False) -> Dict[str, str]:
for routine in data:
name = routine.get("name", "")
if name:
routines_dict[name] = routine.get("script", "")
default_routines_dict[name] = [routine.get("script", ""), "default"]
except Exception:
console.print("[red]\nFailed to download default routines.[/red]")

Expand All @@ -54,13 +59,17 @@ def download_routines(auth_header: str, silent: bool = False) -> Dict[str, str]:
for routine in items:
name = routine.get("name", "")
if name:
routines_dict[name] = routine.get("script", "")
personal_routines_dict[name] = [
routine.get("script", ""),
"personal",
]
except Exception:
console.print("[red]\nFailed to download personal routines.[/red]")

return routines_dict
return [personal_routines_dict, default_routines_dict]


# use os.walk to search subdirectories and then construct file path
def read_routine(file_name: str, folder: Optional[Path] = None) -> Optional[str]:
"""Read the routine.
Expand All @@ -85,12 +94,12 @@ def read_routine(file_name: str, folder: Optional[Path] = None) -> Optional[str]

try:
user_folder = folder / "hub"
file_path = (
user_folder / file_name
if os.path.exists(user_folder / file_name)
else folder / file_name
)

for path, _, files in walk(user_folder):
file_path = (
folder / os.path.relpath(path, folder) / file_name
if file_name in files
else folder / file_name
)
with open(file_path) as f:
routine = "".join(f.readlines())
return routine
Expand All @@ -99,9 +108,10 @@ def read_routine(file_name: str, folder: Optional[Path] = None) -> Optional[str]
return None


# created new directory structure to account for personal and default routines
def save_routine(
file_name: str,
routine: str,
routine: list,
folder: Optional[Path] = None,
force: bool = False,
silent: bool = False,
Expand Down Expand Up @@ -134,14 +144,19 @@ def save_routine(

try:
user_folder = folder / "hub"
if routine[1] == "default":
user_folder = folder / "hub" / "default"
elif routine[1] == "personal":
user_folder = folder / "hub" / "personal"

if not os.path.exists(user_folder):
os.makedirs(user_folder)

file_path = user_folder / file_name
if os.path.exists(file_path) and not force:
return "File already exists"
with open(file_path, "w") as f:
f.write(routine)
f.write(routine[0])
return user_folder / file_name
except Exception:
console_print("[red]\nFailed to save routine.[/red]")
Expand Down
6 changes: 5 additions & 1 deletion openbb_terminal/core/session/session_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,12 @@ def download_and_save_routines(auth_header: str):
The authorization header, e.g. "Bearer <token>".
"""
routines = download_routines(auth_header=auth_header)
personal_routines_dict = routines[0]
default_routines_dict = routines[1]
try:
for name, content in routines.items():
for name, content in personal_routines_dict.items():
save_routine(file_name=f"{name}.openbb", routine=content, force=True)
for name, content in default_routines_dict.items():
save_routine(file_name=f"{name}.openbb", routine=content, force=True)
except Exception:
console.print("[red]\nFailed to save routines.[/red]")
Expand Down
19 changes: 7 additions & 12 deletions openbb_terminal/stocks/stocks_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,7 @@ def call_search(self, other_args: List[str]):
help="Search by sector to find stocks matching the criteria",
)
parser.add_argument(
"-g",
"--industry-group",
"--industrygroup",
default="",
choices=stocks_helper.format_parse_choices(self.industry_group),
type=str.lower,
Expand Down Expand Up @@ -227,8 +226,7 @@ def call_search(self, other_args: List[str]):
help="Search by a specific exchange to find stocks matching the criteria",
)
parser.add_argument(
"-m",
"--exchange-country",
"--exchangecountry",
default="",
choices=stocks_helper.format_parse_choices(
list(stocks_helper.market_coverage_suffix.keys())
Expand All @@ -248,13 +246,12 @@ def call_search(self, other_args: List[str]):
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-q")
ns_parser = self.parse_known_args_and_warn(
if ns_parser := self.parse_known_args_and_warn(
parser,
other_args,
EXPORT_ONLY_RAW_DATA_ALLOWED,
limit=10,
)
if ns_parser:
):
# Mapping
sector = stocks_helper.map_parse_choices(self.sector)[ns_parser.sector]
industry = stocks_helper.map_parse_choices(self.industry)[
Expand Down Expand Up @@ -296,7 +293,7 @@ def call_tob(self, other_args: List[str]):
"--ticker",
action="store",
dest="s_ticker",
required=not any(x in other_args for x in ["-h", "--help"])
required=all(x not in other_args for x in ["-h", "--help"])
and not self.ticker,
help="Ticker to get data for",
)
Expand All @@ -311,10 +308,8 @@ def call_tob(self, other_args: List[str]):

if not self.ticker and other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-t")
ns_parser = self.parse_known_args_and_warn(parser, other_args)

if ns_parser:
ticker = ns_parser.s_ticker if ns_parser.s_ticker else self.ticker
if ns_parser := self.parse_known_args_and_warn(parser, other_args):
ticker = ns_parser.s_ticker or self.ticker
cboe_view.display_top_of_book(ticker, ns_parser.exchange)

@log_start_end(log=logger)
Expand Down
15 changes: 10 additions & 5 deletions openbb_terminal/stocks/stocks_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,11 @@ def search(
exchange: str
Search by exchange to find stock matching the criteria
exchange_country: str
Search by exchange country to find stock matching
Search by exchange country to find stock matching the criteria
all_exchanges: bool
Whether to search all exchanges, without this option only the United States market is searched
limit : int
The limit of companies shown.
The limit of results shown, where 0 means all the results
Returns
-------
Expand All @@ -166,7 +166,9 @@ def search(
kwargs["industry_group"] = industry_group
if exchange:
kwargs["exchange"] = exchange
kwargs["exclude_exchanges"] = False if exchange_country else not all_exchanges
kwargs["exclude_exchanges"] = (
False if (exchange_country or exchange) else not all_exchanges
)

try:
equities_database = fd.Equities()
Expand All @@ -187,7 +189,7 @@ def search(
" capabilities. This tends to be due to access restrictions for GitHub.com,"
" please check if you can access this website without a VPN.[/red]\n"
)
data = {}
data = pd.DataFrame()
except ValueError:
console.print(
"[red]No companies were found that match the given criteria.[/red]\n"
Expand Down Expand Up @@ -223,6 +225,8 @@ def search(
exchange_suffix[x] = k

df = df[["name", "country", "sector", "industry_group", "industry", "exchange"]]
# To automate renaming columns
headers = [col.replace("_", " ") for col in df.columns.tolist()]

title = "Companies found"
if query:
Expand Down Expand Up @@ -252,7 +256,8 @@ def search(
print_rich_table(
df,
show_index=True,
headers=["Name", "Country", "Sector", "Industry Group", "Industry", "Exchange"],
headers=headers,
index_name="Symbol",
title=title,
limit=limit,
)
Expand Down
48 changes: 42 additions & 6 deletions openbb_terminal/terminal_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import webbrowser
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Optional
from typing import Any, Dict, List, Optional

import certifi
import pandas as pd
Expand Down Expand Up @@ -126,6 +126,11 @@ class TerminalController(BaseController):

def __init__(self, jobs_cmds: Optional[List[str]] = None):
"""Construct terminal controller."""
self.ROUTINE_FILES: Dict[str, str] = dict()
self.ROUTINE_DEFAULT_FILES: Dict[str, str] = dict()
self.ROUTINE_PERSONAL_FILES: Dict[str, str] = dict()
self.ROUTINE_CHOICES: Dict[str, Any] = dict()

super().__init__(jobs_cmds)

self.queue: List[str] = list()
Expand All @@ -147,8 +152,24 @@ def update_runtime_choices(self):
"*.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 = {}
self.ROUTINE_CHOICES["--file"] = {
filename: None for filename in self.ROUTINE_FILES
}
Expand Down Expand Up @@ -564,19 +585,34 @@ def call_exe(self, other_args: List[str]):

if ns_parser:
if ns_parser.example:
path = MISCELLANEOUS_DIRECTORY / "routines" / "routine_example.openbb"
routine_path = (
MISCELLANEOUS_DIRECTORY / "routines" / "routine_example.openbb"
)
console.print(
"[info]Executing an example, please type `about exe` "
"to learn how to create your own script.[/info]\n"
)
time.sleep(3)
elif ns_parser.file:
# if string is not in this format "default/file.openbb" then check for files in ROUTINE_FILES
file_path = " ".join(ns_parser.file)
path = self.ROUTINE_FILES.get(file_path, Path(file_path))
full_path = file_path
hub_routine = file_path.split("/")
if hub_routine[0] == "default":
routine_path = Path(
self.ROUTINE_DEFAULT_FILES.get(hub_routine[1], full_path)
)
elif hub_routine[0] == "personal":
routine_path = Path(
self.ROUTINE_PERSONAL_FILES.get(hub_routine[1], full_path)
)
else:
routine_path = Path(self.ROUTINE_FILES.get(file_path, full_path))

else:
return

with open(path) as fp:
with open(routine_path) as fp:
raw_lines = [
x for x in fp if (not is_reset(x)) and ("#" not in x) and x
]
Expand Down Expand Up @@ -955,7 +991,7 @@ def replace_dynamic(match: re.Match, special_arguments: Dict[str, str]) -> str:
return default


def run_routine(file: str, routines_args=List[str]):
def run_routine(file: str, routines_args=Optional[str]):
"""Execute command routine from .openbb file."""
user_routine_path = (
get_current_user().preferences.USER_DATA_DIRECTORY / "routines" / file
Expand Down
Loading

0 comments on commit 1163357

Please sign in to comment.