Source code for seamm_installer.datastore

# -*- coding: utf-8 -*-

"""Handle the datastore for SEAMM."""

import importlib.metadata as implib
from pathlib import Path
import platform
import subprocess

from . import my


system = platform.system()
if system in ("Darwin",):
    from .mac import ServiceManager

    mgr = ServiceManager(prefix="org.molssi.seamm.")
elif system in ("Linux",):
    from .linux import ServiceManager

    mgr = ServiceManager(prefix="org.molssi.seamm.")
else:
    raise NotImplementedError(f"SEAMM does not support services on {system} yet.")


[docs] def setup(parser): """Define the command-line interface for handling services. Parameters ---------- parser : argparse.ArgumentParser The main parser for the application. """ services_parser = parser.add_parser("datastore") subparser = services_parser.add_subparsers() # Show tmp_parser = subparser.add_parser("show") tmp_parser.set_defaults(func=show) # Update tmp_parser = subparser.add_parser("update") tmp_parser.set_defaults(func=update)
[docs] def latest_version(): """Show information about the datastore.""" path = _find_path() version = None if path is not None: cmd = "alembic heads" result = subprocess.run( cmd, cwd=path, shell=True, text=True, capture_output=True ) if result.returncode == 0: version = result.stdout.strip() else: my.logger.warning(f"Running '{cmd}' was not successful:") my.logger.warning(result.stderr) return version
[docs] def db_version(): """Return the version of the database.""" db_path = Path(my.options.root) / "Jobs" / "seamm.db" if not db_path.expanduser().exists(): version = "not installed" else: path = _find_path() version = "unknown" if path is not None: uri = f"sqlite:///{str(db_path.expanduser())}" cmd = f'alembic -x uri="{uri}" current' result = subprocess.run( cmd, cwd=path, shell=True, text=True, capture_output=True ) if result.returncode == 0: version = result.stdout.strip() if version == "": version = "--none--" else: my.logger.warning(f"Running '{cmd}' was not successful:") my.logger.warning(result.stderr) return version
[docs] def update(): """Update the database to the latest version.""" db_path = Path(my.options.root) / "Jobs" / "seamm.db" if not db_path.expanduser().exists(): print(f"The database file '{db_path}' does not exist.") else: version = db_version() latest = latest_version() if version == latest: print(f"The database at '{db_path}' is already up-to-date.") else: service_name = "dev_dashboard" if my.development else "dashboard" restart = mgr.is_running(service_name) if restart: print(f"Stopping the service {service_name}") mgr.stop_service(service_name) print("Updating the database.") update_db() if restart: print(f"Restarting the service {service_name}") mgr.start_service(service_name) version = db_version() if version == latest: print( f"The database at '{db_path}' has been updated to version {version}" ) else: raise RuntimeError( f"The database at '{db_path}' was updated to version {version},\n" f"but it should be {latest}. Something went wrong!" )
[docs] def update_db(): """Update the database to the latest version.""" db_path = Path(my.options.root) / "Jobs" / "seamm.db" if not db_path.expanduser().exists(): raise RuntimeError(f"The database '{db_path}' does not exist.") path = _find_path() if path is None: raise RuntimeError( "Cannot find the path to the installed version of seamm-datastore.\n" "Is it installed?" ) uri = f"sqlite:///{str(db_path.expanduser())}" cmd = f'alembic -x uri="{uri}" upgrade head' result = subprocess.run(cmd, cwd=path, shell=True, text=True, capture_output=True) if result.returncode != 0: raise RuntimeError(f"Running '{cmd}' was not successful:\n\n{result.stderr}")
[docs] def show(): """Show information about the datastore.""" db_path = Path(my.options.root) / "Jobs" / "seamm.db" latest = latest_version() if not db_path.expanduser().exists(): print(f"The database file '{db_path}' does not exist.") else: version = db_version() if version == latest: print(f"The database at '{db_path}' (version {version}) is up-to-date.") else: print( f"The database at '{db_path}' (version {version}) should be upgraded " f"to {latest} by running" "\n\n" " seamm-installer datastore update" )
def _find_path(): """Return the path for alembic in the datastore installation. Returns ------- pathlib.Path The path to the alembic installation, or None if not present. """ files = [p for p in implib.files("seamm-datastore") if "alembic.ini" in str(p)] if len(files) == 0: path = None else: path = files[0].locate().parent return path