diff --git a/nipype/interfaces/base/core.py b/nipype/interfaces/base/core.py index 3aa84b9b3f..62063309e3 100644 --- a/nipype/interfaces/base/core.py +++ b/nipype/interfaces/base/core.py @@ -411,8 +411,12 @@ def _check_version_requirements(self, trait_object, raise_exception=True): raise Exception( 'Trait %s (%s) (version %s < required %s)' % (name, self.__class__.__name__, version, min_ver)) - check = dict(max_ver=lambda t: t is not None) - names = trait_object.trait_names(**check) + + # check maximum version + check = dict(max_ver=lambda t: t is not None) + names = trait_object.trait_names(**check) + if names and self.version: + version = LooseVersion(str(self.version)) for name in names: max_ver = LooseVersion( str(trait_object.traits()[name].max_ver)) diff --git a/nipype/interfaces/base/specs.py b/nipype/interfaces/base/specs.py index 0bc0544b9a..3f7676c191 100644 --- a/nipype/interfaces/base/specs.py +++ b/nipype/interfaces/base/specs.py @@ -119,20 +119,6 @@ def _xor_warn(self, obj, name, old, new): 'which is already set') % (name, trait_name) raise IOError(msg) - def _requires_warn(self, obj, name, old, new): - """Part of the xor behavior - """ - if isdefined(new): - trait_spec = self.traits()[name] - msg = None - for trait_name in trait_spec.requires: - if not isdefined(getattr(self, trait_name)): - if not msg: - msg = 'Input %s requires inputs: %s' \ - % (name, ', '.join(trait_spec.requires)) - if msg: # only one requires warning at a time. - warn(msg) - def _deprecated_warn(self, obj, name, old, new): """Checks if a user assigns a value to a deprecated trait """ @@ -165,29 +151,6 @@ def _deprecated_warn(self, obj, name, old, new): '%s' % trait_spec.new_name: new }) - def _hash_infile(self, adict, key): - """ Inject file hashes into adict[key]""" - stuff = adict[key] - if not is_container(stuff): - stuff = [stuff] - file_list = [] - for afile in stuff: - if is_container(afile): - hashlist = self._hash_infile({'infiles': afile}, 'infiles') - hash = [val[1] for val in hashlist] - else: - if config.get('execution', - 'hash_method').lower() == 'timestamp': - hash = hash_timestamp(afile) - elif config.get('execution', - 'hash_method').lower() == 'content': - hash = hash_infile(afile) - else: - raise Exception("Unknown hash method: %s" % config.get( - 'execution', 'hash_method')) - file_list.append((afile, hash)) - return file_list - def get(self, **kwargs): """ Returns traited class as a dict diff --git a/nipype/interfaces/base/support.py b/nipype/interfaces/base/support.py index 88fdf761a5..2aa1d7162a 100644 --- a/nipype/interfaces/base/support.py +++ b/nipype/interfaces/base/support.py @@ -168,10 +168,8 @@ def _get_bunch_hash(self): sorted_dict = to_str(sorted(dict_nofilename.items())) return dict_withhash, md5(sorted_dict.encode()).hexdigest() - def __pretty__(self, p, cycle): - """Support for the pretty module - - pretty is included in ipython.externals for ipython > 0.10""" + def _repr_pretty_(self, p, cycle): + """Support for the pretty module from ipython.externals""" if cycle: p.text('Bunch(...)') else: diff --git a/nipype/interfaces/base/tests/test_core.py b/nipype/interfaces/base/tests/test_core.py index 05a9f02b47..12d5c78e58 100644 --- a/nipype/interfaces/base/tests/test_core.py +++ b/nipype/interfaces/base/tests/test_core.py @@ -177,74 +177,76 @@ def __init__(self, **inputs): assert 'ec5755e07287e04a4b409e03b77a517c' == hashvalue -def test_input_version(): - class InputSpec(nib.TraitedSpec): - foo = nib.traits.Int(desc='a random int', min_ver='0.9') +class MinVerInputSpec(nib.TraitedSpec): + foo = nib.traits.Int(desc='a random int', min_ver='0.9') + +class MaxVerInputSpec(nib.TraitedSpec): + foo = nib.traits.Int(desc='a random int', max_ver='0.7') + +def test_input_version_1(): class DerivedInterface1(nib.BaseInterface): - input_spec = InputSpec + input_spec = MinVerInputSpec obj = DerivedInterface1() obj._check_version_requirements(obj.inputs) config.set('execution', 'stop_on_unknown_version', True) - with pytest.raises(Exception): + with pytest.raises(ValueError) as excinfo: obj._check_version_requirements(obj.inputs) + assert "no version information" in str(excinfo.value) config.set_default_config() - class InputSpec(nib.TraitedSpec): - foo = nib.traits.Int(desc='a random int', min_ver='0.9') +def test_input_version_2(): class DerivedInterface1(nib.BaseInterface): - input_spec = InputSpec + input_spec = MinVerInputSpec _version = '0.8' obj = DerivedInterface1() obj.inputs.foo = 1 - with pytest.raises(Exception): - obj._check_version_requirements() + with pytest.raises(Exception) as excinfo: + obj._check_version_requirements(obj.inputs) + assert "version 0.8 < required 0.9" in str(excinfo.value) - class InputSpec(nib.TraitedSpec): - foo = nib.traits.Int(desc='a random int', min_ver='0.9') +def test_input_version_3(): class DerivedInterface1(nib.BaseInterface): - input_spec = InputSpec + input_spec = MinVerInputSpec _version = '0.10' obj = DerivedInterface1() obj._check_version_requirements(obj.inputs) - class InputSpec(nib.TraitedSpec): - foo = nib.traits.Int(desc='a random int', min_ver='0.9') +def test_input_version_4(): class DerivedInterface1(nib.BaseInterface): - input_spec = InputSpec + input_spec = MinVerInputSpec _version = '0.9' obj = DerivedInterface1() obj.inputs.foo = 1 obj._check_version_requirements(obj.inputs) - class InputSpec(nib.TraitedSpec): - foo = nib.traits.Int(desc='a random int', max_ver='0.7') +def test_input_version_5(): class DerivedInterface2(nib.BaseInterface): - input_spec = InputSpec + input_spec = MaxVerInputSpec _version = '0.8' obj = DerivedInterface2() obj.inputs.foo = 1 - with pytest.raises(Exception): - obj._check_version_requirements() + with pytest.raises(Exception) as excinfo: + obj._check_version_requirements(obj.inputs) + assert "version 0.8 > required 0.7" in str(excinfo.value) - class InputSpec(nib.TraitedSpec): - foo = nib.traits.Int(desc='a random int', max_ver='0.9') +def test_input_version_6(): class DerivedInterface1(nib.BaseInterface): - input_spec = InputSpec - _version = '0.9' + input_spec = MaxVerInputSpec + _version = '0.7' obj = DerivedInterface1() obj.inputs.foo = 1 diff --git a/nipype/interfaces/base/traits_extension.py b/nipype/interfaces/base/traits_extension.py index 78b68a5601..5b3e9f94d7 100644 --- a/nipype/interfaces/base/traits_extension.py +++ b/nipype/interfaces/base/traits_extension.py @@ -54,7 +54,7 @@ class Str(Unicode): traits.DictStrStr = DictStrStr -class BaseFile(BaseUnicode): +class File(BaseUnicode): """ Defines a trait whose value must be the name of a file. """ @@ -96,14 +96,11 @@ def __init__(self, if exists: self.info_text = 'an existing file name' - super(BaseFile, self).__init__(value, **metadata) + super(File, self).__init__(value, **metadata) def validate(self, object, name, value): - """ Validates that a specified value is valid for this trait. - - Note: The 'fast validator' version performs this check in C. - """ - validated_value = super(BaseFile, self).validate(object, name, value) + """ Validates that a specified value is valid for this trait.""" + validated_value = super(File, self).validate(object, name, value) if not self.exists: return validated_value elif os.path.isfile(value): @@ -117,53 +114,12 @@ def validate(self, object, name, value): self.error(object, name, value) -class File(BaseFile): - """ - Defines a trait whose value must be the name of a file. - Disables the default C-level fast validator. - """ - - def __init__(self, - value='', - filter=None, - auto_set=False, - entries=0, - exists=False, - **metadata): - """ Creates a File trait. - - Parameters - ---------- - value : string - The default value for the trait - filter : string - A wildcard string to filter filenames in the file dialog box used by - the attribute trait editor. - auto_set : boolean - Indicates whether the file editor updates the trait value after - every key stroke. - exists : boolean - Indicates whether the trait value must be an existing file or - not. - - Default Value - ------------- - *value* or '' - """ - # if not exists: - # # Define the C-level fast validator to use: - # fast_validate = (11, str) - - super(File, self).__init__(value, filter, auto_set, entries, exists, - **metadata) - - # ------------------------------------------------------------------------------- -# 'BaseDirectory' and 'Directory' traits: +# 'Directory' trait # ------------------------------------------------------------------------------- -class BaseDirectory(BaseUnicode): +class Directory(BaseUnicode): """ Defines a trait whose value must be the name of a directory. """ @@ -177,7 +133,7 @@ def __init__(self, entries=0, exists=False, **metadata): - """ Creates a BaseDirectory trait. + """ Creates a Directory trait. Parameters ---------- @@ -201,13 +157,10 @@ def __init__(self, if exists: self.info_text = 'an existing directory name' - super(BaseDirectory, self).__init__(value, **metadata) + super(Directory, self).__init__(value, **metadata) def validate(self, object, name, value): - """ Validates that a specified value is valid for this trait. - - Note: The 'fast validator' version performs this check in C. - """ + """ Validates that a specified value is valid for this trait.""" if isinstance(value, (str, bytes)): if not self.exists: return value @@ -222,44 +175,6 @@ def validate(self, object, name, value): self.error(object, name, value) -class Directory(BaseDirectory): - """ - Defines a trait whose value must be the name of a directory. - Disables the default C-level fast validator. - """ - - def __init__(self, - value='', - auto_set=False, - entries=0, - exists=False, - **metadata): - """ Creates a Directory trait. - - Parameters - ---------- - value : string - The default value for the trait - auto_set : boolean - Indicates whether the directory editor updates the trait value - after every key stroke. - exists : boolean - Indicates whether the trait value must be an existing directory or - not. - - Default Value - ------------- - *value* or '' - """ - # Define the C-level fast validator to use if the directory existence - # test is not required: - # if not exists: - # self.fast_validate = (11, str) - - super(Directory, self).__init__(value, auto_set, entries, exists, - **metadata) - - # lists of tuples # each element consists of : # - uncompressed (tuple[0]) extension diff --git a/nipype/pipeline/engine/utils.py b/nipype/pipeline/engine/utils.py index d34e2523fe..9082722b6c 100644 --- a/nipype/pipeline/engine/utils.py +++ b/nipype/pipeline/engine/utils.py @@ -1158,9 +1158,6 @@ def _standardize_iterables(node): iterables = node.iterables # The candidate iterable fields fields = set(node.inputs.copyable_trait_names()) - # Flag indicating whether the iterables are in the alternate - # synchronize form and are not converted to a standard format. - # synchronize = False # OE: commented out since it is not used # A synchronize iterables node without an itersource can be in # [fields, value tuples] format rather than # [(field, value list), (field, value list), ...] diff --git a/nipype/utils/misc.py b/nipype/utils/misc.py index a7487539d6..6b7629e32a 100644 --- a/nipype/utils/misc.py +++ b/nipype/utils/misc.py @@ -285,7 +285,6 @@ def dict_diff(dold, dnew, indent=0): # Values in common keys would differ quite often, # so we need to join the messages together for k in new_keys.intersection(old_keys): - same = False try: new, old = dnew[k], dold[k] same = new == old