diff --git a/setup.cfg b/setup.cfg index 3a4310a..1eeaa09 100644 --- a/setup.cfg +++ b/setup.cfg @@ -40,7 +40,7 @@ zip_safe = False setup_requires=setuptools>=42; wheel; setuptools_scm[toml]>=3.4 install_requires= argopt - miutil[nii,web]>=0.7.2 + miutil[nii,web]>=0.8.0 setuptools # pkg_resources numpy scipy diff --git a/spm12/cli.py b/spm12/cli.py index 8f005b3..195fab4 100644 --- a/spm12/cli.py +++ b/spm12/cli.py @@ -1,15 +1,21 @@ """Usage: - spm12 [options] + spm12 [options] [...] Options: -c DIR, --cache DIR : directory to use for installation [default: ~/.spm12]. -s VER, --spm-version : version [default: 12]. + -r, --runtime : use runtime (not full MATLAB). + +Arguments: + : Runtime command [default: quit]|gui|help|... """ import logging from argopt import argopt -from .utils import ensure_spm +from .utils import ensure_spm, mcr_run + +log = logging.getLogger(__name__) def main(argv=None): @@ -17,6 +23,14 @@ def main(argv=None): level=logging.DEBUG, format="%(levelname)s:%(funcName)s:%(message)s" ) args = argopt(__doc__).parse_args(argv) - ensure_spm(cache=args.cache, version=args.spm_version) + log.info(args) + if isinstance(args.command, str): + args.command = [args.command] + if len(args.command) == 1 and args.command[0] == "gui": + args.command = [] + if args.runtime: + log.debug(mcr_run(*args.command, cache=args.cache, version=args.spm_version)) + else: + ensure_spm(cache=args.cache, version=args.spm_version) print("SPM{v} is successfully installed".format(v=args.spm_version)) return 0 diff --git a/spm12/utils.py b/spm12/utils.py index da67894..5b88b11 100644 --- a/spm12/utils.py +++ b/spm12/utils.py @@ -1,10 +1,12 @@ import logging +import os from functools import wraps from os import path +from subprocess import CalledProcessError, check_output from textwrap import dedent -from miutil.fdio import extractall -from miutil.mlab import get_engine +from miutil.fdio import Path, extractall, fspath +from miutil.mlab import get_engine, get_runtime from miutil.web import urlopen_cached from pkg_resources import resource_filename @@ -16,6 +18,44 @@ __all__ = ["get_matlab", "ensure_spm"] PATH_M = resource_filename(__name__, "") log = logging.getLogger(__name__) +SPM12_ZIP = "https://www.fil.ion.ucl.ac.uk/spm/download/restricted/eldorado/spm12.zip" +MCR_ZIP = "https://www.fil.ion.ucl.ac.uk/spm/download/restricted/utopia/spm12_r7771.zip" + + +def env_prefix(key, dir): + os.environ[key] = "%s%s%s" % (os.environ[key], os.pathsep, fspath(dir)) + + +def spm_runtime(cache="~/.spm12", version=12): + cache = Path(cache).expanduser() + if str(version) != "12": + raise NotImplementedError + runtime = cache / "runtime" + if not runtime.is_dir(): + log.info("Downloading to %s", cache) + with urlopen_cached(MCR_ZIP, cache) as fd: + extractall(fd, runtime) + + runner = runtime / "spm12" / "run_spm12.sh" + runner.chmod(0o755) + return fspath(runner) + + +def mcr_run(*cmd, cache="~/.spm12", version=12, mcr_version=713): + mcr_root = fspath(get_runtime(version=mcr_version)) + runner = spm_runtime(cache=cache, version=version) + try: + return check_output((runner, mcr_root) + cmd).decode("U8").strip() + except CalledProcessError as err: + raise RuntimeError( + dedent( + """\ + {} + + See https://en.wikibooks.org/wiki/SPM/Standalone#Trouble-shooting + """ + ).format(err) + ) @lru_cache() @@ -40,11 +80,7 @@ def ensure_spm(name=None, cache="~/.spm12", version=12): log.warning("MATLAB could not find SPM.") try: log.info("Downloading to %s", cache) - with urlopen_cached( - "https://www.fil.ion.ucl.ac.uk/" - "spm/download/restricted/eldorado/spm12.zip", - cache, - ) as fd: + with urlopen_cached(SPM12_ZIP, cache) as fd: extractall(fd, cache) eng.addpath(addpath) if not eng.exist("spm_jobman"):