Skip to content

Commit

Permalink
Merge pull request #642 from debrief/viewer-mode
Browse files Browse the repository at this point in the history
Add Viewer mode
  • Loading branch information
IanMayo authored Dec 1, 2020
2 parents 8295409 + f6ec0f5 commit 88cb344
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 23 deletions.
6 changes: 5 additions & 1 deletion bin/install_pepys.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,13 @@ try {
# Create Pepys folder in Start Menu
New-Item -Path $startmenu_location -Name "Pepys" -ItemType "directory"

# Pepys Admin shortcuts
Make-Shortcut -ShortcutLocation ($startmenu_location + "Pepys\Pepys Admin.lnk") -TargetPath ".\pepys_admin.bat" -Icon $icon_string

Make-Shortcut -ShortcutLocation ($startmenu_location + "Pepys\Pepys Admin (training mode).lnk") -TargetPath ".\pepys_admin_training.bat" -Icon $icon_string

# Pepys Viewer shortcuts
Make-Shortcut -ShortcutLocation ($startmenu_location + "Pepys\Pepys Viewer.lnk") -TargetPath ".\pepys_viewer.bat" -Icon $icon_string
Make-Shortcut -ShortcutLocation ($startmenu_location + "Pepys\Pepys Viewer (training mode).lnk") -TargetPath ".\pepys_viewer_training.bat" -Icon $icon_string
}
catch {
Write-Output $_
Expand Down
14 changes: 14 additions & 0 deletions bin/pepys_viewer.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@echo off
CALL set_paths.bat
REM If error returned from set_paths.bat then don't continue with running python
IF ERRORLEVEL 1 GOTO :ERROR

python -m pepys_admin.cli --viewer %1 %2 %3 %4 %5 %6 %7 %8 %9
PAUSE

REM Go to the end of the file, skipping the :ERROR label below
GOTO :eof

REM PAUSE so that the user can see the error
:ERROR
PAUSE
14 changes: 14 additions & 0 deletions bin/pepys_viewer_training.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@echo off
CALL set_paths.bat
REM If error returned from set_paths.bat then don't continue with running python
IF ERRORLEVEL 1 GOTO :ERROR

python -m pepys_admin.cli --viewer --training %1 %2 %3 %4 %5 %6 %7 %8 %9
PAUSE

REM Go to the end of the file, skipping the :ERROR label below
GOTO :eof

REM PAUSE so that the user can see the error
:ERROR
PAUSE
2 changes: 1 addition & 1 deletion create_deployment.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ catch {

try {
# Do a standard pip install of the requirements and dev requirements, not warning us that scripts will be unavailable
.\python\python.exe -m pip install -r requirements.txt -r requirements_dev.txt --no-warn-script-location --no-cache-dir
.\python\python.exe -m pip install -r requirements.txt -r requirements_dev.txt --no-warn-script-location --no-cache-dir --use-deprecated=legacy-resolver

if ($LastExitCode -ne 0)
{
Expand Down
31 changes: 23 additions & 8 deletions pepys_admin/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@

import config
from pepys_admin.admin_cli import AdminShell
from pepys_admin.view_data_cli import ViewDataShell
from pepys_import.cli import set_up_training_mode
from pepys_import.core.store.data_store import DataStore
from pepys_import.utils.data_store_utils import is_schema_created
from pepys_import.utils.error_handling import handle_database_errors
from pepys_import.utils.text_formatting_utils import format_command

Expand All @@ -25,7 +27,9 @@ def main(): # pragma: no cover
"Uses training mode, where all interactions take place with a training database located "
"in the user's home folder. No actions will affect the database configured in the Pepys config file."
)
viewer_help = "Start Pepys Admin in Viewer mode, where the only actions available are those under the 'View Data' menu"
parser = argparse.ArgumentParser(description="Pepys Admin CLI")
parser.add_argument("--viewer", help=viewer_help, action="store_true", default=False)
parser.add_argument("--path", type=str, help="CSV files path")

group = parser.add_mutually_exclusive_group()
Expand All @@ -36,12 +40,11 @@ def main(): # pragma: no cover

args = parser.parse_args()

run_admin_shell(db=args.db, path=args.path, training=args.training)
run_shell(db=args.db, path=args.path, training=args.training, viewer=args.viewer)


def run_admin_shell(path, training=False, data_store=None, db=None):
"""Runs the admin shell.
def run_shell(path, training=False, data_store=None, db=None, viewer=False):
"""Runs the shell.
Arguments allow specification of individual args from command-line
(db, path, training) or specification of a data_store instead of a db name,
to allow for advanced use in unit tests.
Expand All @@ -56,6 +59,11 @@ def run_admin_shell(path, training=False, data_store=None, db=None):
# the config file details have changed since the last test
reload(config)

if viewer:
welcome_text = "Pepys_viewer"
else:
welcome_text = "Pepys_admin"

if data_store is None:
if db is None:
data_store = DataStore(
Expand All @@ -65,7 +73,7 @@ def run_admin_shell(path, training=False, data_store=None, db=None):
db_port=config.DB_PORT,
db_name=config.DB_NAME,
db_type=config.DB_TYPE,
welcome_text="Pepys_admin",
welcome_text=welcome_text,
)
else:
data_store = DataStore(
Expand All @@ -75,12 +83,19 @@ def run_admin_shell(path, training=False, data_store=None, db=None):
db_port=0,
db_name=db,
db_type="sqlite",
welcome_text="Pepys_admin",
welcome_text=welcome_text,
)

try:
with handle_database_errors():
AdminShell(data_store, path).cmdloop()
if viewer:
with handle_database_errors():
if is_schema_created(data_store.engine, data_store.db_type) is False:
print("Database schema does not exist: tables cannot be viewed")
return
ViewDataShell(data_store, viewer=True).cmdloop()
else:
with handle_database_errors():
AdminShell(data_store, path).cmdloop()
except SystemExit:
# This makes sure that calling exit() from within our code doesn't actually exit immediately,
# instead it drops out to here, where we can still ask the final training mode question
Expand Down
19 changes: 14 additions & 5 deletions pepys_admin/view_data_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ class ViewDataShell(BaseShell):
(4) Output SQL Results to CSV
(.) Back
"""
prompt = "(pepys-admin) (view) "

def __init__(self, data_store):
def __init__(self, data_store, viewer=False):
super(ViewDataShell, self).__init__()
self.data_store = data_store
self.aliases = {
Expand All @@ -46,10 +45,20 @@ def __init__(self, data_store):
"4": self.do_output_sql_to_csv,
}

@staticmethod
def do_cancel():
self.viewer = viewer

if viewer:
self.prompt = "(pepys-viewer) "
self.intro = self.intro.replace("(.) Back", "(.) Exit")
else:
self.prompt = "(pepys-admin) (view) "

def do_cancel(self):
"""Returns to the previous menu"""
print("Returning to the previous menu...")
if self.viewer:
print("Thank you for using Pepys Viewer")
else:
print("Returning to the previous menu...")

def _get_table_names(self):
"""Gets the table names using SQL Alchemy's inspect db functionality."""
Expand Down
57 changes: 49 additions & 8 deletions tests/test_admin_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
from datetime import datetime
from io import StringIO
from sqlite3 import OperationalError
from unittest.mock import patch
from unittest.mock import ANY, patch

import pg8000
import pytest
from testing.postgresql import Postgresql

from paths import MIGRATIONS_DIRECTORY
from pepys_admin.admin_cli import AdminShell
from pepys_admin.cli import run_admin_shell
from pepys_admin.cli import run_shell
from pepys_admin.export_cli import ExportByPlatformNameShell, ExportShell
from pepys_admin.initialise_cli import InitialiseShell
from pepys_admin.snapshot_cli import SnapshotShell
Expand Down Expand Up @@ -705,7 +705,7 @@ def test_missing_db_column_sqlite(self, patched_input, patched_iterfzf):
temp_output = StringIO()
with redirect_stdout(temp_output):
data_store = DataStore("", "", "", 0, "cli_import_test.db", db_type="sqlite")
run_admin_shell(data_store=data_store, path=".")
run_shell(data_store=data_store, path=".")
output = temp_output.getvalue()

assert "ERROR: SQL error when communicating with database" in output
Expand Down Expand Up @@ -740,7 +740,7 @@ def test_missing_db_column_sqlite_2(self, patched_input):
temp_output = StringIO()
with redirect_stdout(temp_output):
data_store = DataStore("", "", "", 0, "cli_import_test.db", db_type="sqlite")
run_admin_shell(data_store=data_store, path=".")
run_shell(data_store=data_store, path=".")
output = temp_output.getvalue()

assert "ERROR: Table summaries couldn't be printed." in output
Expand Down Expand Up @@ -803,7 +803,7 @@ def test_missing_db_column_postgres(self, patched_input, patched_iterfzf):
db_port=55527,
db_type="postgres",
)
run_admin_shell(data_store=data_store, path=".")
run_shell(data_store=data_store, path=".")
output = temp_output.getvalue()

assert "ERROR: SQL error when communicating with database" in output
Expand All @@ -829,7 +829,7 @@ def test_missing_db_column_postgres_2(self, patched_input):
db_port=55527,
db_type="postgres",
)
run_admin_shell(data_store=data_store, path=".")
run_shell(data_store=data_store, path=".")
output = temp_output.getvalue()

assert "ERROR: Table summaries couldn't be printed." in output
Expand Down Expand Up @@ -1595,7 +1595,7 @@ def test_training_mode_message(patched_prompt1, patched_prompt2, patched_input):
temp_output = StringIO()
with redirect_stdout(temp_output):
try:
run_admin_shell(db=None, training=True, path=".")
run_shell(db=None, training=True, path=".")
except SystemExit:
pass
output = temp_output.getvalue()
Expand Down Expand Up @@ -1628,7 +1628,7 @@ def test_training_mode_setup(patched_prompt1, patched_prompt2, patched_input, pa
db_name = os.path.expanduser(os.path.join("~", "pepys_training_database.db"))

try:
run_admin_shell(db=None, training=True, path=".")
run_shell(db=None, training=True, path=".")
except SystemExit:
pass

Expand All @@ -1650,5 +1650,46 @@ def test_training_mode_setup(patched_prompt1, patched_prompt2, patched_input, pa
os.environ["PEPYS_CONFIG_FILE"] = orig_pepys_config_file


@patch("pepys_admin.cli.DataStore")
def test_viewer_mode_datastore(patched_ds):
run_shell(path=".", db=None, training=False, viewer=True)

patched_ds.assert_called_with(
db_username=ANY,
db_password=ANY,
db_host=ANY,
db_port=ANY,
db_name=ANY,
db_type=ANY,
welcome_text="Pepys_viewer",
)


def test_viewer_mode_blank_db():
temp_output = StringIO()
with redirect_stdout(temp_output):
try:
run_shell(path=".", db=":memory:", training=False, viewer=True)
except SystemExit:
pass
output = temp_output.getvalue()
print(output)

assert "Database schema does not exist: tables cannot be viewed" in output


@patch("pepys_admin.cli.ViewDataShell")
def test_viewer_mode_valid_db(patched_vds):
if os.path.exists("created_db.db"):
os.remove("created_db.db")

store = DataStore("", "", "", 0, "created_db.db", db_type="sqlite")
store.initialise()

run_shell(path=".", db="created_db.db", training=False, viewer=True)

patched_vds.assert_called_with(ANY, viewer=True)


if __name__ == "__main__":
unittest.main()

0 comments on commit 88cb344

Please sign in to comment.