Skip to content

Commit

Permalink
Desktop manager (#57)
Browse files Browse the repository at this point in the history
* create desktop manager startups

* update path

* desktop manager

* write bash equivalent

* refactor w/ tests

* get version information in real-time, since packages may be updated
  • Loading branch information
shapiromatron authored Aug 14, 2024
1 parent 116a741 commit e27978a
Show file tree
Hide file tree
Showing 9 changed files with 300 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
.ruff_cache/
.tox/
.vscode/
/bmds-desktop/
bmds_ui/static/bundles/
build/
/data/
Expand Down
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
recursive-include bmds_ui/ *css *.js *.json *.html *.md *.py
recursive-include bmds_ui/static *
recursive-include bmds_ui/templates *
recursive-include bmds_ui/desktop/templates *
global-exclude .DS_Store .gitkeep __pycache__ *.pyc
3 changes: 3 additions & 0 deletions bmds_ui/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .desktop.cli import main

main()
72 changes: 72 additions & 0 deletions bmds_ui/desktop/actions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import json
import os
import platform
import subprocess
import sys
from contextlib import redirect_stderr, redirect_stdout
from datetime import datetime
from pathlib import Path
from threading import Thread
from urllib.error import URLError
from urllib.parse import urlparse
Expand All @@ -11,14 +16,19 @@
import django
from django.conf import settings
from django.core.management import call_command
from django.template import Context, Template
from django.template.engine import Engine
from packaging.version import Version, parse
from rich.console import Console
from whitenoise import WhiteNoise

from .. import __version__
from ..main.settings import desktop
from .config import Database, DesktopConfig, get_app_home, get_version_path
from .log import log, stream

PRERELEASE_URL = "https://gitlab.epa.gov/api/v4/projects/1508/packages/pypi/simple"


def sync_persistent_data():
"""Sync persistent data to database and static file path. We do this every time a database
Expand Down Expand Up @@ -149,3 +159,65 @@ def get_version_message(current: Version, latest: Version, latest_date: datetime
elif current > latest:
return f"You have a newer version than what's currently available, {latest} (released {latest_date:%b %d, %Y})."
raise ValueError("Cannot compare versions")


def show_version():
"""Show the version for BMDS Desktop"""
console = Console()
console.print(__version__)


def render_template(template_text: str, context: dict) -> str:
template = Template(template_text, engine=Engine())
return template.render(Context(context))


def write_startup_script(template: str) -> str:
python_path = Path(sys.executable)
show_prerelease = get_installed_version().is_prerelease
return render_template(
template,
{
"prerelease_url": PRERELEASE_URL,
"show_prerelease": show_prerelease,
"python_path": python_path,
},
)


def create_shortcut(no_input: bool = False):
shortcut_path = Path(os.curdir).resolve() / "bmds-desktop"
shortcut_path.mkdir(exist_ok=True)
system = platform.system()
match system:
case "Windows":
shortcut = shortcut_path / "bmds-desktop-manager.bat"
template = (Path(__file__).parent / "templates/manager-bat.txt").read_text()
script = write_startup_script(template)
shortcut.write_text(script)
case "Darwin" | "Linux" | _:
shortcut = shortcut_path / "bmds-desktop-manager.sh"
template = (Path(__file__).parent / "templates/manager-sh.txt").read_text()
script = write_startup_script(template)
shortcut.touch(mode=0o755, exist_ok=True)
shortcut.write_text(script)

console = Console()
console.print("BMDS Desktop Manger Created:", style="magenta")
console.print("----------------------------", style="magenta")
console.print(shortcut, style="cyan")
console.print("\nOpening this file will start BMDS Desktop.")
console.print("You can move this file or create a shortcut to it.\n")

if not no_input: # pragma: no cover
resp = console.input(
f'Would you like to open the folder to view "{shortcut.name}"? ([cyan]y/n[/cyan]) '
)
if resp.lower()[0] == "y":
match system:
case "Windows":
os.startfile(str(shortcut_path)) # noqa: S606
case "Darwin":
subprocess.run(["open", str(shortcut_path)]) # noqa: S603, S607
case "Linux" | _:
console.print("Sorry, you'll have to open the folder manually.")
13 changes: 8 additions & 5 deletions bmds_ui/desktop/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from pathlib import Path

from .. import __version__
from .actions import create_shortcut, show_version
from .app import BmdsDesktopTui
from .config import Config, get_default_config_path
from .exceptions import DesktopException
Expand All @@ -20,14 +21,14 @@ def get_app(config: str | None = None) -> BmdsDesktopTui:
return BmdsDesktopTui()


def show_version():
"""Show the version for BMDS Desktop"""
print(__version__) # noqa: T201


def main():
parser = argparse.ArgumentParser(description=f"BMDS Desktop ({__version__})")
parser.add_argument("--version", "-V", action="store_true", help="Show version")
parser.add_argument(
"--create-shortcut",
action="store_true",
help="Create a shortcut to the BMDS Desktop Manager",
)
parser.add_argument(
"--config",
metavar="config",
Expand All @@ -38,6 +39,8 @@ def main():
args = parser.parse_args()
if args.version:
return show_version()
if args.create_shortcut:
return create_shortcut()
try:
get_app(config=args.config).run()
except DesktopException as err:
Expand Down
85 changes: 85 additions & 0 deletions bmds_ui/desktop/templates/manager-bat.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
@echo off

:beginning
echo:
echo --------------------------------
echo BMDS Desktop Manager
echo --------------------------------
echo:
echo 1) Start BMDS Desktop
echo 2) Update BMDS Desktop
{% if show_prerelease %}echo 2p) Update BMDS Desktop (prerelease - EPA VPN required){% endif %}
echo 3) Show diagnostic information
echo:

:loop
set /p "id=Enter a number above, or q to quit: "
if %id% == 1 goto :start
if %id% == 2 goto :update
{% if show_prerelease %}if %id% == 2p goto :update-prerelease{% endif %}
if %id% == 3 goto :diagnostics
if %id% == help goto :beginning
if %id% == q goto :quit
if %id% == Q goto :quit
goto :loop

:start
"{{ python_path }}" -m bmds_ui
goto :beginning

:update
echo Updating BMDS Desktop
"{{ python_path }}" -m ensurepip > nul 2>&1
"{{ python_path }}" -m pip install -U -q pip
echo:
echo Current version:
"{{ python_path }}" -m pip show bmds-ui pybmds
echo:
echo This may take a while, wait until you see "Update complete!"
echo Updating ...
"{{ python_path }}" -m pip install -U -q bmds-ui
"{{ python_path }}" -m pip show bmds-ui pybmds
echo:
echo Update complete!
pause
goto :beginning

{% if show_prerelease %}
:update-prerelease
echo Updating BMDS Desktop (prerelease - EPA VPN required)
echo:
"{{ python_path }}" -m ensurepip > nul 2>&1
"{{ python_path }}" -m pip install -U -q pip
echo:
echo Current version:
"{{ python_path }}" -m pip show bmds-ui pybmds
echo:
echo This may take a while, wait until you see "Update complete!"
echo Updating ...
"{{ python_path }}" -m pip install -q -U bmds-ui --index-url {{prerelease_url}}
"{{ python_path }}" -m pip show bmds-ui pybmds
echo:
echo Update complete!
pause
goto :beginning
{% endif %}

:diagnostics
echo:
echo Diagnostic Installation Information:
echo ------------------------------------
echo:
echo Python Version:
"{{ python_path }}" --version -VV
echo:
echo Python Path:
echo {{ python_path }}
echo:
echo BMDS UI + pybmds Version:
"{{ python_path }}" -m pip show bmds-ui pybmds
echo:
pause
goto :beginning

:quit
pause
107 changes: 107 additions & 0 deletions bmds_ui/desktop/templates/manager-sh.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/bin/bash

set -e

write_instructions(){
echo
echo "--------------------------------"
echo " BMDS Desktop Manager"
echo "--------------------------------"
echo
echo "1) Start BMDS Desktop"
echo "2) Update BMDS Desktop"
{% if show_prerelease %}echo "2p) Update BMDS Desktop (prerelease - EPA VPN required)"{% endif %}
echo "3) Show diagnostic information"
echo
}

pause(){
read -n 1 -p "Press any key to continue..."
}

start(){
"{{ python_path }}" -m bmds_ui
write_instructions
}

update(){
echo "Updating BMDS Desktop"
echo "---------------------"
"{{ python_path }}" -m ensurepip &> /dev/null
"{{ python_path }}" -m pip install -U -q pip
echo
echo Current version:
"{{ python_path }}" -m pip show bmds-ui pybmds
echo
echo "This may take a while, wait until you see \"Update complete!\""
echo "Updating ..."
"{{ python_path }}" -m pip install -U -q bmds-ui
"{{ python_path }}" -m pip show bmds-ui pybmds
echo
echo "Update complete!"
pause
write_instructions
}

{% if show_prerelease %}update_pre(){
echo "Updating BMDS Desktop (prerelease - EPA VPN required)"
echo "-----------------------------------------------------"
echo
"{{ python_path }}" -m ensurepip &> /dev/null
"{{ python_path }}" -m pip install -U -q pip
echo
echo "Current version:"
"{{ python_path }}" -m pip show bmds-ui pybmds
echo
echo "This may take a while, wait until you see \"Update complete!\""
echo "Updating ..."
"{{ python_path }}" -m pip install -q -U bmds-ui --index-url {{prerelease_url}}
"{{ python_path }}" -m pip show bmds-ui pybmds
echo
echo "Update complete!"
pause
write_instructions
}{% endif %}

diagnostic(){
echo
echo "Diagnostic Installation Information:"
echo "------------------------------------"
echo
echo "Python Version:"
"{{ python_path }}" --version -VV
echo
echo "Python Path:"
echo "{{ python_path }}"
echo
echo "BMDS UI + pybmds Version:"
"{{ python_path }}" -m pip show bmds-ui pybmds
echo
pause
write_instructions
}

valid_input=0
write_instructions
while [ $valid_input -eq 0 ]; do
read -p "Enter a number above, or q to quit: " user_input
if [[ $user_input == "q" || $user_input == "Q" || $user_input == "quit" || $user_input == "exit" ]]; then
valid_input=1
fi
if [[ $user_input == "help" ]]; then
write_instructions
fi
if [[ $user_input == "1" ]]; then
start
fi
if [[ $user_input == "2" ]]; then
update
fi
{% if show_prerelease %}if [[ $user_input == "2p" ]]; then
update_pre
fi{%endif%}
if [[ $user_input == "3" ]]; then
diagnostic
fi
done
pause
14 changes: 14 additions & 0 deletions tests/desktop/test_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,17 @@ def test_get_version_message():
latest = Version("1.0.0")
resp = actions.get_version_message(current, latest, latest_date)
assert "You have a newer version than what's currently available" in resp


def test_render_template():
assert actions.render_template("Hello {{name}}!", context={"name": "world"}) == "Hello world!"


def test_write_startup_script():
assert actions.write_startup_script("test") == "test"


def test_create_shortcut(capsys):
actions.create_shortcut(no_input=True)
captured = capsys.readouterr()
assert "BMDS Desktop Manger Created" in captured.out
10 changes: 9 additions & 1 deletion tests/desktop/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import shlex
import subprocess
import sys

from bmds_ui import __version__
from bmds_ui.desktop.cli import main


def test_version(capsys):
sys.argv = ["bmds", "--version"]
sys.argv = ["bmds-server", "--version"]
main()
captured = capsys.readouterr()
assert __version__ in captured.out


def test_main():
commands = [shlex.quote(sys.executable), "-m", "bmds_ui", "--version"]
resp = subprocess.run(commands, capture_output=True) # noqa: S603
assert __version__ in resp.stdout.decode()

0 comments on commit e27978a

Please sign in to comment.