From 1ba3b318aebc6adf469af1e4aa840d4fa575fa99 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 10 Nov 2017 13:14:32 -0800 Subject: [PATCH 1/4] RF: Add PackageInfo class to standardize version parsing --- nipype/interfaces/afni/base.py | 31 +++++-------------------- nipype/interfaces/ants/base.py | 41 +++++++++++++--------------------- nipype/interfaces/base.py | 22 ++++++++++++++++++ 3 files changed, 43 insertions(+), 51 deletions(-) diff --git a/nipype/interfaces/afni/base.py b/nipype/interfaces/afni/base.py index 3405f96cfa..1097a28d46 100644 --- a/nipype/interfaces/afni/base.py +++ b/nipype/interfaces/afni/base.py @@ -14,45 +14,26 @@ from ...utils.filemanip import split_filename, fname_presuffix from ..base import ( - CommandLine, traits, CommandLineInputSpec, isdefined, File, TraitedSpec) + CommandLine, traits, CommandLineInputSpec, isdefined, File, TraitedSpec, + PackageInfo) from ...external.due import BibTeX # Use nipype's logging system IFLOGGER = logging.getLogger('interface') -class Info(object): +class Info(PackageInfo): """Handle afni output type and version information. """ __outputtype = 'AFNI' ftypes = {'NIFTI': '.nii', 'AFNI': '', 'NIFTI_GZ': '.nii.gz'} + version_cmd = 'afni --version' @staticmethod - def version(): - """Check for afni version on system - - Parameters - ---------- - None - - Returns - ------- - version : str - Version number as string or None if AFNI not found - - """ - try: - clout = CommandLine(command='afni --version', - resource_monitor=False, - terminal_output='allatonce').run() - except IOError: - # If afni_vcheck is not present, return None - IFLOGGER.warn('afni executable not found.') - return None - - version_stamp = clout.runtime.stdout.split('\n')[0].split('Version ')[1] + def parse_version(raw_info): + version_stamp = raw_info.split('\n')[0].split('Version ')[1] if version_stamp.startswith('AFNI'): version_stamp = version_stamp.split('AFNI_')[1] elif version_stamp.startswith('Debian'): diff --git a/nipype/interfaces/ants/base.py b/nipype/interfaces/ants/base.py index 3ab50a24f5..0baabf4968 100644 --- a/nipype/interfaces/ants/base.py +++ b/nipype/interfaces/ants/base.py @@ -6,11 +6,11 @@ from builtins import str import os -import subprocess # Local imports from ... import logging, LooseVersion -from ..base import CommandLine, CommandLineInputSpec, traits, isdefined +from ..base import (CommandLine, CommandLineInputSpec, traits, isdefined, + PackageInfo) logger = logging.getLogger('interface') # -Using -1 gives primary responsibilty to ITKv4 to do the correct @@ -29,32 +29,21 @@ ALT_ITKv4_THREAD_LIMIT_VARIABLE = 'ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS' -class Info(object): - _version = None +class Info(PackageInfo): + version_cmd = os.path.join(os.getenv('ANTSPATH', ''), + 'antsRegistration') + ' --version' - @property - def version(self): - if self._version is None: - try: - basedir = os.environ['ANTSPATH'] - except KeyError: - return None - - cmd = os.path.join(basedir, 'antsRegistration') - try: - res = subprocess.check_output([cmd, '--version']).decode('utf-8') - except OSError: - return None - - for line in res.splitlines(): - if line.startswith('ANTs Version: '): - self._version = line.split()[2] - break - else: - return None + @staticmethod + def parse_version(raw_info): + for line in raw_info.splitlines(): + if line.startswith('ANTs Version: '): + v_string = line.split()[2] + break + else: + return None # -githash may or may not be appended - v_string = self._version.split('-')[0] + v_string = v_string.split('-')[0] # 2.2.0-equivalent version string if 'post' in v_string and LooseVersion(v_string) >= LooseVersion('2.1.0.post789'): @@ -125,4 +114,4 @@ def set_default_num_threads(cls, num_threads): @property def version(self): - return Info().version + return Info.version() diff --git a/nipype/interfaces/base.py b/nipype/interfaces/base.py index 0fa9559718..c608fdff7e 100644 --- a/nipype/interfaces/base.py +++ b/nipype/interfaces/base.py @@ -1924,6 +1924,28 @@ def _format_arg(self, name, spec, value): return super(SEMLikeCommandLine, self)._format_arg(name, spec, value) +class PackageInfo(object): + _version = None + version_cmd = None + + @classmethod + def version(klass): + if klass._version is None: + try: + clout = CommandLine(command=klass.version_cmd, + resource_monitor=False, + terminal_output='allatonce').run() + except OSError: + return None + + klass._version = klass.parse_version(raw_info) + return klass._version + + @staticmethod + def parse_version(raw_info): + raise NotImplementedError + + class MultiPath(traits.List): """ Abstract class - shared functionality of input and output MultiPath """ From 1a65959e9b237fdbf0fe0a9790d8b2bc1344daf7 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 10 Nov 2017 13:34:22 -0800 Subject: [PATCH 2/4] ENH: Get version from file (e.g. FreeSurfer) --- nipype/interfaces/base.py | 22 ++++++++++++++---- nipype/interfaces/freesurfer/base.py | 34 +++++++--------------------- 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/nipype/interfaces/base.py b/nipype/interfaces/base.py index c608fdff7e..aadb9c333d 100644 --- a/nipype/interfaces/base.py +++ b/nipype/interfaces/base.py @@ -1927,15 +1927,27 @@ def _format_arg(self, name, spec, value): class PackageInfo(object): _version = None version_cmd = None + version_file = None @classmethod def version(klass): if klass._version is None: - try: - clout = CommandLine(command=klass.version_cmd, - resource_monitor=False, - terminal_output='allatonce').run() - except OSError: + if klass.version_cmd is not None: + try: + clout = CommandLine(command=klass.version_cmd, + resource_monitor=False, + terminal_output='allatonce').run() + except OSError: + return None + + raw_info = clout.runtime.stdout + elif klass.version_file is not None: + try: + with open(klass.version_file, 'rt') as fobj: + raw_info = fobj.read() + except OSError: + return None + else: return None klass._version = klass.parse_version(raw_info) diff --git a/nipype/interfaces/freesurfer/base.py b/nipype/interfaces/freesurfer/base.py index 4d87cdf9e7..56a4d5df77 100644 --- a/nipype/interfaces/freesurfer/base.py +++ b/nipype/interfaces/freesurfer/base.py @@ -23,12 +23,13 @@ from ...utils.filemanip import fname_presuffix from ..base import (CommandLine, Directory, CommandLineInputSpec, isdefined, - traits, TraitedSpec, File) + traits, TraitedSpec, File, + PackageInfo) __docformat__ = 'restructuredtext' -class Info(object): +class Info(PackageInfo): """ Freesurfer subject directory and version information. Examples @@ -39,32 +40,13 @@ class Info(object): >>> Info.subjectsdir() # doctest: +SKIP """ + if os.getenv('FREESURFER_HOME'): + version_file = os.path.join(os.getenv('FREESURFER_HOME'), + 'build-stamp.txt') @staticmethod - def version(): - """Check for freesurfer version on system - - Find which freesurfer is being used....and get version from - /path/to/freesurfer/build-stamp.txt - - Returns - ------- - - version : string - version number as string - or None if freesurfer version not found - - """ - fs_home = os.getenv('FREESURFER_HOME') - if fs_home is None: - return None - versionfile = os.path.join(fs_home, 'build-stamp.txt') - if not os.path.exists(versionfile): - return None - fid = open(versionfile, 'rt') - version = fid.readline() - fid.close() - return version + def parse_version(raw_info): + return raw_info.splitlines()[0] @classmethod def looseversion(cls): From ca1b0044ced7f6425a5d89cc3e4f5dedb54205aa Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 10 Nov 2017 13:39:56 -0800 Subject: [PATCH 3/4] FIX: CommandLine generates IOError, not OSError --- nipype/interfaces/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/interfaces/base.py b/nipype/interfaces/base.py index aadb9c333d..ee058df18f 100644 --- a/nipype/interfaces/base.py +++ b/nipype/interfaces/base.py @@ -1937,7 +1937,7 @@ def version(klass): clout = CommandLine(command=klass.version_cmd, resource_monitor=False, terminal_output='allatonce').run() - except OSError: + except IOError: return None raw_info = clout.runtime.stdout From adf5a353f765d7f20f20291f0aeb7d57f4f95690 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 10 Nov 2017 15:15:11 -0800 Subject: [PATCH 4/4] FIX: Indentation --- nipype/interfaces/base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nipype/interfaces/base.py b/nipype/interfaces/base.py index ee058df18f..facafa5fc9 100644 --- a/nipype/interfaces/base.py +++ b/nipype/interfaces/base.py @@ -1950,7 +1950,8 @@ def version(klass): else: return None - klass._version = klass.parse_version(raw_info) + klass._version = klass.parse_version(raw_info) + return klass._version @staticmethod