diff --git a/fsl/utils/path.py b/fsl/utils/path.py index 7f7f80cf0b3ad541ac3206ee84630320eaad58cd..0a0859528945a7b944482442b0ffc658d0dc05f9 100644 --- a/fsl/utils/path.py +++ b/fsl/utils/path.py @@ -23,6 +23,8 @@ paths. removeDuplicates uniquePrefix commonBase + wslpath + winpath """ @@ -30,10 +32,11 @@ import os.path as op import os import glob import operator -import re +import re from fsl.utils.platform import platform + class PathError(Exception): """``Exception`` class raised by the functions defined in this module when something goes wrong. @@ -527,17 +530,18 @@ def commonBase(paths): raise PathError('No common base') + def wslpath(winpath): """ - Convert Windows path (or a command line argument containing a Windows path) + Convert Windows path (or a command line argument containing a Windows path) to the equivalent WSL path (e.g. ``c:\\Users`` -> ``/mnt/c/Users``). Also supports paths in the form ``\\wsl$\\(distro)\\users\\...`` - :param winpath: Command line argument which may (or may not) contain a Windows path. It is assumed to be - either of the form <windows path> or --<arg>=<windows path>. Note that we don't need to - handle --arg <windows path> or -a <windows path> since in these cases the argument - and the path will be parsed as separate entities. - :return: If ``winpath`` matches a Windows path, the converted argument (including the --<arg>= portion). + :param winpath: Command line argument which may (or may not) contain a Windows path. It is assumed to be + either of the form <windows path> or --<arg>=<windows path>. Note that we don't need to + handle --arg <windows path> or -a <windows path> since in these cases the argument + and the path will be parsed as separate entities. + :return: If ``winpath`` matches a Windows path, the converted argument (including the --<arg>= portion). Otherwise returns ``winpath`` unchanged. """ match = re.match(r"^(--[\w-]+=)?\\\\wsl\$[\\\/][^\\^\/]+(.*)$", winpath) @@ -552,10 +556,11 @@ def wslpath(winpath): arg, drive, path = match.group(1, 2, 3) if arg is None: arg = "" - return arg + "/mnt/" + drive.lower() + path.replace("\\", "/") + return arg + "/mnt/" + drive.lower() + path.replace("\\", "/") return winpath + def winpath(wslpath): """ Convert a WSL-local filepath (for example ``/usr/local/fsl/``) into a path that can be used from diff --git a/fsl/utils/platform.py b/fsl/utils/platform.py index 73d0937d264a1a88396d25deb837d34ba6130d56..ebd9478cb79f3d11d5cda0d4bf8a3eeb00c534f7 100644 --- a/fsl/utils/platform.py +++ b/fsl/utils/platform.py @@ -285,16 +285,19 @@ class Platform(notifier.Notifier): """ return os.environ.get('FSLDIR', None) + @property def fsldevdir(self): """The FSL development directory location. """ return os.environ.get('FSLDEVDIR', None) + @property def fslwsl(self): """Boolean flag indicating whether FSL is installed in Windows Subsystem for Linux """ return self.fsldir is not None and self.fsldir.startswith("\\\\wsl$") + @fsldir.setter def fsldir(self, value): """Changes the value of the :attr:`fsldir` property, and notifies any @@ -404,6 +407,7 @@ class Platform(notifier.Notifier): """ return self.__glIsSoftware + platform = Platform() """An instance of the :class:`Platform` class. Feel free to create your own instance, but be aware that if you do so you will not be updated of changes diff --git a/fsl/utils/run.py b/fsl/utils/run.py index acb77c741e2bb1f329d67833de7e53459bff4697..e2adbeb8de7d39006b28eac3497573fd281cd8d9 100644 --- a/fsl/utils/run.py +++ b/fsl/utils/run.py @@ -20,17 +20,17 @@ """ -import sys -import shlex -import logging -import threading -import contextlib -import collections -import subprocess as sp -import os.path as op -import os - -import six +import sys +import shlex +import logging +import threading +import contextlib +import collections.abc as abc +import subprocess as sp +import os.path as op +import os + +import six from fsl.utils.platform import platform as fslplatform import fsl.utils.fslsub as fslsub @@ -203,7 +203,7 @@ def run(*args, **kwargs): if submit is True: submit = dict() - if submit is not None and not isinstance(submit, collections.Mapping): + if submit is not None and not isinstance(submit, abc.Mapping): raise ValueError('submit must be a mapping containing ' 'options for fsl.utils.fslsub.submit') @@ -377,16 +377,17 @@ def runfsl(*args, **kwargs): return run(*args, **kwargs) + def wslcmd(cmdpath, *args): """ Convert a command + arguments into an equivalent set of arguments that will run the command under Windows Subsystem for Linux - + :param cmdpath: Fully qualified path to the command. This is essentially a WSL path not a Windows one since FSLDIR is specified as a WSL path, however it may have backslashes as path separators due to previous use of ``os.path.join`` :param args: Sequence of command arguments (the first of which is the unqualified command name) - + :return: If ``cmdpath`` exists and is executable in WSL, return a sequence of command arguments which when executed will run the command in WSL. Windows paths in the argument list will be converted to WSL paths. If ``cmdpath`` was not executable in WSL, returns None @@ -423,6 +424,7 @@ def wslcmd(cmdpath, *args): # Command was not found in WSL with this path return None + def wait(job_ids): """Proxy for :func:`.fslsub.wait`. """ return fslsub.wait(job_ids)