diff --git a/.gitignore b/.gitignore index 1588864eb6f..80dcce7c017 100644 --- a/.gitignore +++ b/.gitignore @@ -8,14 +8,17 @@ logs/ *.ipynb env/ venv/ -!notebooks/reports/.gitkeep +!notebooks/jupyter/.gitkeep .python-version iframe_figures/ exports/* .idea .coverage htmlcov -gamestonk_terminal/reports/stored/* +gamestonk_terminal/jupyter/reports/stored/* +!gamestonk_terminal/jupyter/reports/stored/.gitkeep +!gamestonk_terminal/jupyter/dashboards/*.ipynb +!gamestonk_terminal/jupyter/reports/*.ipynb gamestonk_terminal/portfolio/portfolios/* .ipynb_checkpoints/* @@ -30,7 +33,6 @@ jupyterlab/*/.ipynb_checkpoints jupyterlab/*/*.tsbuildinfo jupyterlab/*/ui-tests/test-results/ jupyterlab/*/ui-tests/tests/*.ts-snapshots/ -!jupyterlab/dashboards/stocks_interactive.ipynb # Sphinx documentation build files docs/_build diff --git a/gamestonk_terminal/__init__.py b/gamestonk_terminal/__init__.py index 425680c12c6..4a522ac1f81 100644 --- a/gamestonk_terminal/__init__.py +++ b/gamestonk_terminal/__init__.py @@ -6,7 +6,7 @@ from . import ( etf, forex, portfolio, - reports, + jupyter, resources, stocks, ) diff --git a/gamestonk_terminal/reports/README.md b/gamestonk_terminal/jupyter/README.md similarity index 100% rename from gamestonk_terminal/reports/README.md rename to gamestonk_terminal/jupyter/README.md diff --git a/gamestonk_terminal/reports/__init__.py b/gamestonk_terminal/jupyter/__init__.py similarity index 100% rename from gamestonk_terminal/reports/__init__.py rename to gamestonk_terminal/jupyter/__init__.py diff --git a/gamestonk_terminal/jupyter/dashboards/dashboards_controller.py b/gamestonk_terminal/jupyter/dashboards/dashboards_controller.py new file mode 100644 index 00000000000..b021dfd5a45 --- /dev/null +++ b/gamestonk_terminal/jupyter/dashboards/dashboards_controller.py @@ -0,0 +1,269 @@ +"""Dashboards Module""" +__docformat__ = "numpy" + +import argparse +import difflib +import subprocess +from typing import List, Union + +from prompt_toolkit.completion import NestedCompleter + +from gamestonk_terminal import feature_flags as gtff +from gamestonk_terminal.helper_funcs import ( + EXPORT_ONLY_RAW_DATA_ALLOWED, + parse_known_args_and_warn, + get_flair, + system_clear, +) +from gamestonk_terminal.menu import session + +# pylint: disable=consider-using-with + + +class DashboardsController: + """Dashboards Controller class""" + + # Command choices + CHOICES = [ + "cls", + "home", + "h", + "?", + "help", + "q", + "quit", + "..", + "exit", + "r", + "reset", + ] + + CHOICES_COMMANDS = [ + "stocks", + ] + + CHOICES += CHOICES_COMMANDS + + def __init__(self, queue: List[str] = None): + """Constructor""" + self.rc_parser = argparse.ArgumentParser(add_help=False, prog="dashboards") + self.rc_parser.add_argument( + "cmd", + choices=self.CHOICES, + ) + self.queue = queue if queue else list() + self.completer: Union[None, NestedCompleter] = None + + if session and gtff.USE_PROMPT_TOOLKIT: + choices: dict = {c: {} for c in self.CHOICES} + + self.completer = NestedCompleter.from_nested_dict(choices) + + @staticmethod + def print_help(): + """Print help""" + help_str = """ + stocks interactive dashboard with ticker information + """ + print(help_str) + + def switch(self, an_input: str): + """Process and dispatch input + + Returns + ------- + List[str] + List of commands in the queue to execute + """ + # Empty command + if not an_input: + print("") + return self.queue + + # Navigation slash is being used + if "/" in an_input: + actions = an_input.split("/") + + # Absolute path is specified + if not actions[0]: + an_input = "home" + # Relative path so execute first instruction + else: + an_input = actions[0] + + # Add all instructions to the queue + for cmd in actions[1:][::-1]: + if cmd: + self.queue.insert(0, cmd) + + (known_args, other_args) = self.rc_parser.parse_known_args(an_input.split()) + + # Redirect commands to their correct functions + if known_args.cmd: + if known_args.cmd in ("..", "q"): + known_args.cmd = "quit" + elif known_args.cmd in ("?", "h"): + known_args.cmd = "help" + elif known_args.cmd == "r": + known_args.cmd = "reset" + + getattr( + self, + "call_" + known_args.cmd, + lambda _: "Command not recognized!", + )(other_args) + + return self.queue + + def call_cls(self, _): + """Process cls command""" + system_clear() + + def call_home(self, _): + """Process home command""" + self.queue.insert(0, "quit") + + def call_help(self, _): + """Process help command""" + self.print_help() + + def call_quit(self, _): + """Process quit menu command""" + print("") + self.queue.insert(0, "quit") + + def call_exit(self, _): + """Process exit terminal command""" + self.queue.insert(0, "quit") + self.queue.insert(0, "quit") + self.queue.insert(0, "quit") + + def call_reset(self, _): + """Process reset command""" + self.queue.insert(0, "dashboards") + self.queue.insert(0, "jupyter") + self.queue.insert(0, "reset") + self.queue.insert(0, "quit") + + def call_stocks(self, other_args: List[str]): + """Process stocks command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="stocks", + description="""Shows an interactive stock dashboard""", + ) + parser.add_argument( + "-j", + "--jupyter", + action="store_true", + default=False, + dest="jupyter", + help="Shows dashboard in jupyter-lab.", + ) + + ns_parser = parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if ns_parser: + cmd = "jupyter-lab" if ns_parser.jupyter else "voila" + file = "gamestonk_terminal/jupyter/dashboards/stocks.ipynb" + + print( + f"Warning: this command will open a port on your computer to run a {cmd} server." + ) + response = input("Would you like us to run the server for you? y/n\n") + if response.lower() == "y": + + subprocess.Popen( + f"{cmd} {file}", + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + shell=True, + ) + else: + print( + f"To run manually type: {cmd} {file}\ninto a terminal after" + " entering the environment you use to run the terminal." + ) + print("") + + +def menu(queue: List[str] = None): + """Jupyter Menu""" + dashboard_controller = DashboardsController(queue) + an_input = "HELP_ME" + + while True: + # There is a command in the queue + if dashboard_controller.queue and len(dashboard_controller.queue) > 0: + # If the command is quitting the menu we want to return in here + if dashboard_controller.queue[0] in ("q", "..", "quit"): + print("") + if len(dashboard_controller.queue) > 1: + return dashboard_controller.queue[1:] + return [] + + # Consume 1 element from the queue + an_input = dashboard_controller.queue[0] + dashboard_controller.queue = dashboard_controller.queue[1:] + + # Print the current location because this was an instruction and we want user to know what was the action + if ( + an_input + and an_input.split(" ")[0] in dashboard_controller.CHOICES_COMMANDS + ): + print(f"{get_flair()} /jupyter/dashboard/ $ {an_input}") + + # Get input command from user + else: + # Display help menu when entering on this menu from a level above + if an_input == "HELP_ME": + dashboard_controller.print_help() + + # Get input from user using auto-completion + if session and gtff.USE_PROMPT_TOOLKIT and dashboard_controller.completer: + an_input = session.prompt( + f"{get_flair()} /jupyter/dashboard/ $ ", + completer=dashboard_controller.completer, + search_ignore_case=True, + ) + + # Get input from user without auto-completion + else: + an_input = input(f"{get_flair()} /jupyter/dashboard/ $ ") + + try: + # Process the input command + dashboard_controller.queue = dashboard_controller.switch(an_input) + + except SystemExit: + print( + f"\nThe command '{an_input}' doesn't exist on the /jupyter menu.", + end="", + ) + similar_cmd = difflib.get_close_matches( + an_input.split(" ")[0] if " " in an_input else an_input, + dashboard_controller.CHOICES, + n=1, + cutoff=0.7, + ) + if similar_cmd: + if " " in an_input: + candidate_input = ( + f"{similar_cmd[0]} {' '.join(an_input.split(' ')[1:])}" + ) + if candidate_input == an_input: + an_input = "" + dashboard_controller.queue = [] + print("\n") + continue + an_input = candidate_input + else: + an_input = similar_cmd[0] + + print(f" Replacing by '{an_input}'.") + dashboard_controller.queue.insert(0, an_input) + else: + print("\n") diff --git a/jupyterlab/dashboards/stocks_interactive.ipynb b/gamestonk_terminal/jupyter/dashboards/stocks.ipynb similarity index 100% rename from jupyterlab/dashboards/stocks_interactive.ipynb rename to gamestonk_terminal/jupyter/dashboards/stocks.ipynb diff --git a/gamestonk_terminal/jupyter/jupyter_controller.py b/gamestonk_terminal/jupyter/jupyter_controller.py new file mode 100644 index 00000000000..71c5e918b7e --- /dev/null +++ b/gamestonk_terminal/jupyter/jupyter_controller.py @@ -0,0 +1,234 @@ +"""Jupyter Controller Module""" +__docformat__ = "numpy" + +import argparse +import difflib +from typing import List, Union + +from prompt_toolkit.completion import NestedCompleter + +from gamestonk_terminal import feature_flags as gtff +from gamestonk_terminal.helper_funcs import ( + get_flair, + system_clear, +) +from gamestonk_terminal.menu import session + +# pylint: disable=too-many-public-methods,import-outside-toplevel + + +class JupyterController: + """Resources Controller class""" + + # Command choices + CHOICES = [ + "cls", + "home", + "h", + "?", + "help", + "q", + "quit", + "..", + "exit", + "r", + "reset", + ] + + CHOICES_COMMANDS = [ + "reports", + "dashboards", + ] + + CHOICES += CHOICES_COMMANDS + + def __init__(self, queue: List[str] = None): + """Constructor""" + self.rc_parser = argparse.ArgumentParser(add_help=False, prog="jupyter") + self.rc_parser.add_argument( + "cmd", + choices=self.CHOICES, + ) + self.queue = queue if queue else list() + self.completer: Union[None, NestedCompleter] = None + + if session and gtff.USE_PROMPT_TOOLKIT: + choices: dict = {c: {} for c in self.CHOICES} + + self.completer = NestedCompleter.from_nested_dict(choices) + + @staticmethod + def print_help(): + """Print help""" + help_str = """ +> reports creates jupyter reports +> dashboards shows interactive jupyter dashboards + """ + print(help_str) + + def switch(self, an_input: str): + """Process and dispatch input + + Returns + ------- + List[str] + List of commands in the queue to execute + """ + # Empty command + if not an_input: + print("") + return self.queue + + # Navigation slash is being used + if "/" in an_input: + actions = an_input.split("/") + + # Absolute path is specified + if not actions[0]: + an_input = "home" + # Relative path so execute first instruction + else: + an_input = actions[0] + + # Add all instructions to the queue + for cmd in actions[1:][::-1]: + if cmd: + self.queue.insert(0, cmd) + + (known_args, other_args) = self.rc_parser.parse_known_args(an_input.split()) + + # Redirect commands to their correct functions + if known_args.cmd: + if known_args.cmd in ("..", "q"): + known_args.cmd = "quit" + elif known_args.cmd in ("?", "h"): + known_args.cmd = "help" + elif known_args.cmd == "r": + known_args.cmd = "reset" + + getattr( + self, + "call_" + known_args.cmd, + lambda _: "Command not recognized!", + )(other_args) + + return self.queue + + def call_cls(self, _): + """Process cls command""" + system_clear() + + def call_home(self, _): + """Process home command""" + self.queue.insert(0, "quit") + + def call_help(self, _): + """Process help command""" + self.print_help() + + def call_quit(self, _): + """Process quit menu command""" + print("") + self.queue.insert(0, "quit") + + def call_exit(self, _): + """Process exit terminal command""" + self.queue.insert(0, "quit") + self.queue.insert(0, "quit") + + def call_reset(self, _): + """Process reset command""" + self.queue.insert(0, "jupyter") + self.queue.insert(0, "reset") + self.queue.insert(0, "quit") + + def call_reports(self, _): + """Process reports command""" + from gamestonk_terminal.jupyter.reports import reports_controller + + self.queue = reports_controller.menu(self.queue) + + def call_dashboards(self, _): + """Process dashboards command""" + from gamestonk_terminal.jupyter.dashboards import dashboards_controller + + self.queue = dashboards_controller.menu(self.queue) + + +def menu(queue: List[str] = None): + """Jupyter Menu""" + jupyter_controller = JupyterController(queue) + an_input = "HELP_ME" + + while True: + # There is a command in the queue + if jupyter_controller.queue and len(jupyter_controller.queue) > 0: + # If the command is quitting the menu we want to return in here + if jupyter_controller.queue[0] in ("q", "..", "quit"): + print("") + if len(jupyter_controller.queue) > 1: + return jupyter_controller.queue[1:] + return [] + + # Consume 1 element from the queue + an_input = jupyter_controller.queue[0] + jupyter_controller.queue = jupyter_controller.queue[1:] + + # Print the current location because this was an instruction and we want user to know what was the action + if ( + an_input + and an_input.split(" ")[0] in jupyter_controller.CHOICES_COMMANDS + ): + print(f"{get_flair()} /jupyter/ $ {an_input}") + + # Get input command from user + else: + # Display help menu when entering on this menu from a level above + if an_input == "HELP_ME": + jupyter_controller.print_help() + + # Get input from user using auto-completion + if session and gtff.USE_PROMPT_TOOLKIT and jupyter_controller.completer: + an_input = session.prompt( + f"{get_flair()} /jupyter/ $ ", + completer=jupyter_controller.completer, + search_ignore_case=True, + ) + + # Get input from user without auto-completion + else: + an_input = input(f"{get_flair()} /jupyter/ $ ") + + try: + # Process the input command + jupyter_controller.queue = jupyter_controller.switch(an_input) + + except SystemExit: + print( + f"\nThe command '{an_input}' doesn't exist on the /jupyter menu.", + end="", + ) + similar_cmd = difflib.get_close_matches( + an_input.split(" ")[0] if " " in an_input else an_input, + jupyter_controller.CHOICES, + n=1, + cutoff=0.7, + ) + if similar_cmd: + if " " in an_input: + candidate_input = ( + f"{similar_cmd[0]} {' '.join(an_input.split(' ')[1:])}" + ) + if candidate_input == an_input: + an_input = "" + jupyter_controller.queue = [] + print("\n") + continue + an_input = candidate_input + else: + an_input = similar_cmd[0] + + print(f" Replacing by '{an_input}'.") + jupyter_controller.queue.insert(0, an_input) + else: + print("\n") diff --git a/gamestonk_terminal/reports/crypto_market.ipynb b/gamestonk_terminal/jupyter/reports/crypto_market.ipynb similarity index 100% rename from gamestonk_terminal/reports/crypto_market.ipynb rename to gamestonk_terminal/jupyter/reports/crypto_market.ipynb diff --git a/gamestonk_terminal/reports/dark_pool.ipynb b/gamestonk_terminal/jupyter/reports/dark_pool.ipynb similarity index 100% rename from gamestonk_terminal/reports/dark_pool.ipynb rename to gamestonk_terminal/jupyter/reports/dark_pool.ipynb diff --git a/gamestonk_terminal/reports/due_diligence.ipynb b/gamestonk_terminal/jupyter/reports/due_diligence.ipynb similarity index 100% rename from gamestonk_terminal/reports/due_diligence.ipynb rename to gamestonk_terminal/jupyter/reports/due_diligence.ipynb diff --git a/gamestonk_terminal/reports/econ_data.ipynb b/gamestonk_terminal/jupyter/reports/econ_data.ipynb similarity index 100% rename from gamestonk_terminal/reports/econ_data.ipynb rename to gamestonk_terminal/jupyter/reports/econ_data.ipynb diff --git a/gamestonk_terminal/reports/reports_controller.py b/gamestonk_terminal/jupyter/reports/reports_controller.py similarity index 95% rename from gamestonk_terminal/reports/reports_controller.py rename to gamestonk_terminal/jupyter/reports/reports_controller.py index 8c64852e7ca..7e0eddd1e58 100644 --- a/gamestonk_terminal/reports/reports_controller.py +++ b/gamestonk_terminal/jupyter/reports/reports_controller.py @@ -195,7 +195,7 @@ Select one of the following reports: print("") notebook_template = os.path.join( - "gamestonk_terminal", "reports", report_to_run + "gamestonk_terminal", "jupyter", "reports", report_to_run ) args_to_output = f"_{'_'.join(other_args)}" if "_".join(other_args) else "" report_output_name = ( @@ -205,6 +205,7 @@ Select one of the following reports: ) notebook_output = os.path.join( "gamestonk_terminal", + "jupyter", "reports", "stored", report_output_name, @@ -224,7 +225,7 @@ Select one of the following reports: if gtff.OPEN_REPORT_AS_HTML: report_output_path = os.path.join( - os.path.dirname(__file__), "..", "..", f"{notebook_output}.html" + os.path.abspath(os.path.join(".")), notebook_output + ".html" ) webbrowser.open(f"file://{report_output_path}") @@ -261,10 +262,12 @@ Select one of the following reports: print("") self.queue.insert(0, "quit") self.queue.insert(0, "quit") + self.queue.insert(0, "quit") def call_reset(self, _): """Process reset command.""" self.queue.insert(0, "reports") + self.queue.insert(0, "jupyter") self.queue.insert(0, "reset") self.queue.insert(0, "quit") @@ -291,7 +294,7 @@ def menu(queue: List[str] = None): # Print the current location because this was an instruction # and we want user to know what was the action if an_input and an_input.split(" ")[0] in report_controller.CHOICES: - print(f"{get_flair()} /reports/ $ {an_input}") + print(f"{get_flair()} /jupyter/reports/ $ {an_input}") # Get input command from user else: @@ -303,7 +306,7 @@ def menu(queue: List[str] = None): if session and gtff.USE_PROMPT_TOOLKIT and report_controller.completer: try: an_input = session.prompt( - f"{get_flair()} /reports/ $ ", + f"{get_flair()} /jupyter/reports/ $ ", completer=report_controller.completer, search_ignore_case=True, ) @@ -312,7 +315,7 @@ def menu(queue: List[str] = None): an_input = "exit" # Get input from user without auto-completion else: - an_input = input(f"{get_flair()} /reports/ $ ") + an_input = input(f"{get_flair()} /jupyter/reports/ $ ") try: # Process the input command diff --git a/gamestonk_terminal/reports/similar_analysis.ipynb b/gamestonk_terminal/jupyter/reports/similar_analysis.ipynb similarity index 100% rename from gamestonk_terminal/reports/similar_analysis.ipynb rename to gamestonk_terminal/jupyter/reports/similar_analysis.ipynb diff --git a/gamestonk_terminal/reports/stored/.gitkeep b/gamestonk_terminal/jupyter/reports/stored/.gitkeep similarity index 100% rename from gamestonk_terminal/reports/stored/.gitkeep rename to gamestonk_terminal/jupyter/reports/stored/.gitkeep diff --git a/poetry.lock b/poetry.lock index 602b6812462..c15e1cdf4c2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3636,6 +3636,25 @@ six = ">=1.9.0,<2" docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] +[[package]] +name = "voila" +version = "0.3.0" +description = "VoilĂ  turns Jupyter notebooks into standalone web applications" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +jupyter-client = ">=6.1.3,<8" +jupyter-server = ">=0.3.0,<2.0.0" +nbclient = ">=0.4.0,<0.6" +nbconvert = ">=6.0.0,<7" +websockets = ">=9.0" + +[package.extras] +dev = ["black", "bump2version", "jupyter-releaser (>=0.6,<1.0)"] +test = ["ipywidgets", "mock", "matplotlib", "pandas", "pytest", "pytest-tornasync"] + [[package]] name = "wcwidth" version = "0.2.5" @@ -3762,7 +3781,7 @@ prediction = ["tensorflow"] [metadata] lock-version = "1.1" python-versions = "^3.8,<3.10" -content-hash = "a3cf2a88480398985f7a1009d8e01d90cd8363597a7813b40a53b2f211f9087b" +content-hash = "41f378fda04d1f0d4cfb3259518b717279c16fd3f486a8b0ecc4652793257665" [metadata.files] absl-py = [ @@ -6300,6 +6319,10 @@ virtualenv = [ {file = "virtualenv-20.13.0-py2.py3-none-any.whl", hash = "sha256:339f16c4a86b44240ba7223d0f93a7887c3ca04b5f9c8129da7958447d079b09"}, {file = "virtualenv-20.13.0.tar.gz", hash = "sha256:d8458cf8d59d0ea495ad9b34c2599487f8a7772d796f9910858376d1600dd2dd"}, ] +voila = [ + {file = "voila-0.3.0-py3-none-any.whl", hash = "sha256:e843f51cf93997f712ad07d2491019a2afdf09fcda30db520985e1084e059017"}, + {file = "voila-0.3.0.tar.gz", hash = "sha256:97ae429ca4b16a7a3fcf553d795b052ebe92d5db2113553a00b13e68eb4b7528"}, +] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, diff --git a/pyproject.toml b/pyproject.toml index 9c403d19b5a..a5f3b74c089 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,16 +73,17 @@ pyrsistent = "^0.18.0" openpyxl = "^3.0.9" jsonschema = "3.2.0" pandas = "^1.3.4" +ipympl = "^0.8.2" +voila = "^0.3.0" +rich = "^10.16.1" +investpy = "^1.0.7" +dnspython = "^2.1.0" +numpy = "1.21.2" tensorflow = {version = "^2.7.0", optional = true} discord = {version = "^1.7.3", optional = true} discord-components = {version = "^2.1.2", optional = true} pyimgur = {version = "^0.6.0", optional = true} python-dotenv = {version = "^0.19.2", optional = true} -ipympl = "^0.8.2" -rich = "^10.16.1" -investpy = "^1.0.7" -dnspython = "^2.1.0" -numpy = "1.21.2" [tool.poetry.dev-dependencies] diff --git a/requirements-full.txt b/requirements-full.txt index 64e3110522c..11fd200b31f 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -287,10 +287,11 @@ vadersentiment==3.3.2 valinvest==0.0.2; python_version >= "3.6" vcrpy==4.1.1; python_version >= "3.5" virtualenv==20.13.0; python_full_version >= "3.6.1" -wcwidth==0.2.5; python_version >= "3.6" and python_full_version >= "3.6.2" +voila==0.3.0; python_version >= "3.6" +wcwidth==0.2.5; python_version >= "3.7" and python_full_version >= "3.6.2" webencodings==0.5.1; python_version >= "3.7" websocket-client==1.2.3; python_version >= "3.8" and python_version < "4.0" -websockets==9.1; python_full_version >= "3.6.1" +websockets==9.1; python_full_version >= "3.6.1" and python_version >= "3.6" werkzeug==2.0.2; python_version >= "3.6" widgetsnbextension==3.5.2 wrapt==1.13.3; python_full_version >= "3.7.1" and python_full_version < "4.0.0" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0") and (python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5") diff --git a/requirements.txt b/requirements.txt index 273a80771d4..9082860bd9e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -262,11 +262,12 @@ user-agent==0.1.10 vadersentiment==3.3.2 valinvest==0.0.2; python_version >= "3.6" vcrpy==4.1.1; python_version >= "3.5" +voila==0.3.0; python_version >= "3.6" +wcwidth==0.2.5; python_version >= "3.7" and python_full_version >= "3.6.2" virtualenv==20.13.0; python_full_version >= "3.6.1" -wcwidth==0.2.5; python_version >= "3.6" and python_full_version >= "3.6.2" webencodings==0.5.1; python_version >= "3.7" websocket-client==1.2.3; python_version >= "3.8" and python_version < "4.0" -websockets==9.1; python_full_version >= "3.6.1" +websockets==9.1; python_full_version >= "3.6.1" and python_version >= "3.6" widgetsnbextension==3.5.2 wrapt==1.13.3; python_full_version >= "3.7.1" and python_full_version < "4.0.0" and (python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5") yarl==1.7.2; python_version >= "3.6" diff --git a/scripts/test_reports_base.gst b/scripts/test_jupyter_base.gst similarity index 55% rename from scripts/test_reports_base.gst rename to scripts/test_jupyter_base.gst index 3c7538721f1..4f913cafb31 100644 --- a/scripts/test_reports_base.gst +++ b/scripts/test_jupyter_base.gst @@ -3,15 +3,15 @@ h help ? q -repors +jupter .. -repots +jupyer .. -reports +jupyter quit -reports +jupyter r reset home -reports +jupyter exit \ No newline at end of file diff --git a/scripts/test_reports.gst b/scripts/test_reports.gst index a19c77c71f7..1486e9e315e 100644 --- a/scripts/test_reports.gst +++ b/scripts/test_reports.gst @@ -1,3 +1,4 @@ +jupyter reports econ_dta econ_data diff --git a/terminal.py b/terminal.py index 1823694964b..604f1a18a0f 100644 --- a/terminal.py +++ b/terminal.py @@ -63,8 +63,8 @@ class TerminalController: "portfolio", "forex", "etf", - "reports", "resources", + "jupyter", "funds", ] CHOICES += CHOICES_COMMANDS @@ -131,7 +131,7 @@ Timezone: {get_user_timezone_or_invalid()} > forex > funds > portfolio -> reports +> jupyter > resources """ print(help_text) @@ -254,11 +254,11 @@ Timezone: {get_user_timezone_or_invalid()} self.queue = forex_controller.menu(self.queue) - def call_reports(self, _): - """Process reports command""" - from gamestonk_terminal.reports import reports_controller + def call_jupyter(self, _): + """Process jupyter command""" + from gamestonk_terminal.jupyter import jupyter_controller - self.queue = reports_controller.menu(self.queue) + self.queue = jupyter_controller.menu(self.queue) def call_resources(self, _): """Process resources command"""