From e28bf11ed91a5d84adce0df033978394439d8d29 Mon Sep 17 00:00:00 2001 From: Yoan Mollard Date: Fri, 26 Jun 2020 00:58:29 +0200 Subject: [PATCH] Added service to download the Snap app if needed --- pypot/creatures/services_launcher.py | 23 ++++++---- pypot/vpl/__init__.py | 0 pypot/vpl/download.py | 67 ++++++++++++++++++++++++++++ pypot/vpl/snap.py | 13 ++++++ setup.py | 1 + 5 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 pypot/vpl/__init__.py create mode 100644 pypot/vpl/download.py create mode 100644 pypot/vpl/snap.py diff --git a/pypot/creatures/services_launcher.py b/pypot/creatures/services_launcher.py index 2a38be1d..e35b3ef7 100644 --- a/pypot/creatures/services_launcher.py +++ b/pypot/creatures/services_launcher.py @@ -185,15 +185,20 @@ def main(): snap_static_port = 8888 snap_static_server = HTTPServer(("0.0.0.0", snap_static_port), SimpleHTTPRequestHandler) - os.chdir(os.path.join(os.path.dirname(__file__), "..", "snap")) - snap_static_server_process = Process(target=snap_static_server.serve_forever, args=()) - static_server_started = True - snap_static_server_process.start() - - snap_url = 'http://127.0.0.1:{}/snap.html'.format(snap_static_port) - block_url = 'http://{}:{}/snap-blocks.xml'.format( - find_local_ip(), args.snap_port) - url = '{}#open:{}'.format(snap_url, block_url) + from pypot.vpl.snap import download_snap_interactively + static_app = download_snap_interactively() + if static_app is None: + print("The static server was not started because the VPL app has not been downloaded") + else: + os.chdir(static_app) + snap_static_server_process = Process(target=snap_static_server.serve_forever, args=()) + static_server_started = True + snap_static_server_process.start() + + snap_url = 'http://127.0.0.1:{}/snap.html'.format(snap_static_port) + block_url = 'http://{}:{}/snap-blocks.xml'.format( + find_local_ip(), args.snap_port) + url = '{}#open:{}'.format(snap_url, block_url) with closing(start_poppy_with_services(args)): diff --git a/pypot/vpl/__init__.py b/pypot/vpl/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pypot/vpl/download.py b/pypot/vpl/download.py new file mode 100644 index 00000000..3f444ab5 --- /dev/null +++ b/pypot/vpl/download.py @@ -0,0 +1,67 @@ +import sys +import tempfile +from wget import download +from urllib.error import URLError +from zipfile import ZipFile +from pathlib import Path + +def get_pypot_datadir(app_name="pypot"): + """ + Returns pypot's directory for peristent data. + Attempt creation if create==True. + + # linux: ~/.local/share + # macOS: ~/Library/Application Support + # windows: C:/Users//AppData/Roaming + """ + home = Path.home() + + if sys.platform == "win32": + data_dir = home / "AppData/Roaming" + elif sys.platform == "linux": + data_dir = home / ".local/share" + elif sys.platform == "darwin": + data_dir = home / "Library/Application Support" + else: + raise ValueError("Can't find the user data directory of your platform '{}'".format(sys.platform)) + + #app_name = app_name if version is None else app_name + "-" + str(version) + pypot_dir = data_dir / app_name + return pypot_dir + + +def download_vpl_interactively(vpl_app_name, vpl_app_url, extract=False): + """ + Download the specified Visual Programming langage web app and returns its path. + If it couldn't be downloaded, return None + """ + pypot_datadir = get_pypot_datadir() + vpl_dir = pypot_datadir / vpl_app_name + actual_vpl_dir = vpl_dir / vpl_app_name if extract else vpl_dir + + if vpl_dir.is_dir(): + return actual_vpl_dir + else: + while True: + response = input("This is the first time you are launching {}, it needs to be downloaded first. Proceed? [Y/n] ".format(vpl_app_name)) + if response.lower() in ["y", ""]: + try: + vpl_dir.mkdir(parents=True) + except FileExistsError: + pass + print("Downloading...") + try: + downloaded_app = download(vpl_app_url, tempfile.gettempdir()) + except URLError as e: + print("Cannot download the {] app from {}: {}".format(vpl_app_name, vpl_app_url, str(e)), file=sys.stderr) + else: + try: + with ZipFile(downloaded_app, 'r') as archive: + archive.extractall(vpl_dir) + except FileNotFoundError: + print("Couldn't extract {} from zipfile".format(vpl_app_name)) + else: + return actual_vpl_dir + else: + print("Download aborted by user", file=sys.stderr) + return None diff --git a/pypot/vpl/snap.py b/pypot/vpl/snap.py new file mode 100644 index 00000000..02171dc2 --- /dev/null +++ b/pypot/vpl/snap.py @@ -0,0 +1,13 @@ +from .download import download_vpl_interactively + +# Snap 5.4.5 application download to local data directory in userspace +VPL_APP_URL = "https://codeload.github.com/jmoenig/Snap/zip/v5.4.5" +VPL_APP_NAME = "Snap-5.4.5" +VPL_EXTRACT_ZIP_ROOT = True + +def download_snap_interactively(): + """ + Download the Snap 5.4.5 Programming langage web app and returns its path. + If it couldn't be downloaded, return None + """ + return download_vpl_interactively(VPL_APP_NAME, VPL_APP_URL, VPL_EXTRACT_ZIP_ROOT) diff --git a/setup.py b/setup.py index 1aa7e9a9..fb396f0f 100644 --- a/setup.py +++ b/setup.py @@ -20,6 +20,7 @@ def version(): 'bottle', 'requests', 'opencv-contrib-python', + 'wget', ] if sys.version_info < (3, 5):