20
20
from copy import deepcopy
21
21
from datetime import datetime as dt
22
22
import os
23
- import re
24
23
import platform
25
24
import subprocess as sp
26
25
import shlex
27
26
import sys
28
- from textwrap import wrap
29
27
import simplejson as json
30
28
from dateutil .parser import parse as parseutc
29
+ from future import standard_library
31
30
32
31
from ... import config , logging , LooseVersion
33
32
from ...utils .provenance import write_provenance
34
- from ...utils .misc import trim , str2bool , rgetcwd
33
+ from ...utils .misc import str2bool , rgetcwd
35
34
from ...utils .filemanip import (FileNotFoundError , split_filename ,
36
35
which , get_dependencies )
37
36
from ...utils .subprocess import run_command
42
41
from .specs import (BaseInterfaceInputSpec , CommandLineInputSpec ,
43
42
StdOutCommandLineInputSpec , MpiCommandLineInputSpec ,
44
43
get_filecopy_info )
45
- from .support import (Bunch , InterfaceResult , NipypeInterfaceError )
44
+ from .support import (Bunch , InterfaceResult , NipypeInterfaceError ,
45
+ format_help )
46
46
47
- from future import standard_library
48
47
standard_library .install_aliases ()
49
48
50
49
iflogger = logging .getLogger ('nipype.interface' )
@@ -68,47 +67,42 @@ class Interface(object):
68
67
69
68
input_spec = None # A traited input specification
70
69
output_spec = None # A traited output specification
71
-
72
- # defines if the interface can reuse partial results after interruption
73
- _can_resume = False
70
+ _can_resume = False # See property below
71
+ _always_run = False # See property below
74
72
75
73
@property
76
74
def can_resume (self ):
75
+ """Defines if the interface can reuse partial results after interruption.
76
+ Only applies to interfaces being run within a workflow context."""
77
77
return self ._can_resume
78
78
79
- # should the interface be always run even if the inputs were not changed?
80
- _always_run = False
81
-
82
79
@property
83
80
def always_run (self ):
81
+ """Should the interface be always run even if the inputs were not changed?
82
+ Only applies to interfaces being run within a workflow context."""
84
83
return self ._always_run
85
84
86
- def __init__ (self , ** inputs ):
87
- """Initialize command with given args and inputs."""
88
- raise NotImplementedError
89
-
90
- @classmethod
91
- def help (cls ):
92
- """ Prints class help"""
93
- raise NotImplementedError
94
-
95
- @classmethod
96
- def _inputs_help (cls ):
97
- """ Prints inputs help"""
98
- raise NotImplementedError
99
-
100
- @classmethod
101
- def _outputs_help (cls ):
102
- """ Prints outputs help"""
85
+ @property
86
+ def version (self ):
87
+ """interfaces should implement a version property"""
103
88
raise NotImplementedError
104
89
105
90
@classmethod
106
91
def _outputs (cls ):
107
92
""" Initializes outputs"""
108
93
raise NotImplementedError
109
94
110
- @property
111
- def version (self ):
95
+ @classmethod
96
+ def help (cls , returnhelp = False ):
97
+ """ Prints class help """
98
+ allhelp = format_help (cls )
99
+ if returnhelp :
100
+ return allhelp
101
+ print (allhelp )
102
+ return None # R1710
103
+
104
+ def __init__ (self ):
105
+ """Subclasses must implement __init__"""
112
106
raise NotImplementedError
113
107
114
108
def run (self ):
@@ -190,142 +184,6 @@ def __init__(self, from_file=None, resource_monitor=None,
190
184
for name , value in list (inputs .items ()):
191
185
setattr (self .inputs , name , value )
192
186
193
- @classmethod
194
- def help (cls , returnhelp = False ):
195
- """ Prints class help
196
- """
197
-
198
- if cls .__doc__ :
199
- # docstring = cls.__doc__.split('\n')
200
- # docstring = [trim(line, '') for line in docstring]
201
- docstring = trim (cls .__doc__ ).split ('\n ' ) + ['' ]
202
- else :
203
- docstring = ['' ]
204
-
205
- allhelp = '\n ' .join (docstring + cls ._inputs_help (
206
- ) + ['' ] + cls ._outputs_help () + ['' ] + cls ._refs_help () + ['' ])
207
- if returnhelp :
208
- return allhelp
209
- else :
210
- print (allhelp )
211
-
212
- @classmethod
213
- def _refs_help (cls ):
214
- """ Prints interface references.
215
- """
216
- if not cls .references_ :
217
- return []
218
-
219
- helpstr = ['References::' ]
220
-
221
- for r in cls .references_ :
222
- helpstr += ['{}' .format (r ['entry' ])]
223
-
224
- return helpstr
225
-
226
- @classmethod
227
- def _get_trait_desc (self , inputs , name , spec ):
228
- desc = spec .desc
229
- xor = spec .xor
230
- requires = spec .requires
231
- argstr = spec .argstr
232
-
233
- manhelpstr = ['\t %s' % name ]
234
-
235
- type_info = spec .full_info (inputs , name , None )
236
-
237
- default = ''
238
- if spec .usedefault :
239
- default = ', nipype default value: %s' % str (
240
- spec .default_value ()[1 ])
241
- line = "(%s%s)" % (type_info , default )
242
-
243
- manhelpstr = wrap (
244
- line ,
245
- 70 ,
246
- initial_indent = manhelpstr [0 ] + ': ' ,
247
- subsequent_indent = '\t \t ' )
248
-
249
- if desc :
250
- for line in desc .split ('\n ' ):
251
- line = re .sub ("\s+" , " " , line )
252
- manhelpstr += wrap (
253
- line , 70 , initial_indent = '\t \t ' , subsequent_indent = '\t \t ' )
254
-
255
- if argstr :
256
- pos = spec .position
257
- if pos is not None :
258
- manhelpstr += wrap (
259
- 'flag: %s, position: %s' % (argstr , pos ),
260
- 70 ,
261
- initial_indent = '\t \t ' ,
262
- subsequent_indent = '\t \t ' )
263
- else :
264
- manhelpstr += wrap (
265
- 'flag: %s' % argstr ,
266
- 70 ,
267
- initial_indent = '\t \t ' ,
268
- subsequent_indent = '\t \t ' )
269
-
270
- if xor :
271
- line = '%s' % ', ' .join (xor )
272
- manhelpstr += wrap (
273
- line ,
274
- 70 ,
275
- initial_indent = '\t \t mutually_exclusive: ' ,
276
- subsequent_indent = '\t \t ' )
277
-
278
- if requires :
279
- others = [field for field in requires if field != name ]
280
- line = '%s' % ', ' .join (others )
281
- manhelpstr += wrap (
282
- line ,
283
- 70 ,
284
- initial_indent = '\t \t requires: ' ,
285
- subsequent_indent = '\t \t ' )
286
- return manhelpstr
287
-
288
- @classmethod
289
- def _inputs_help (cls ):
290
- """ Prints description for input parameters
291
- """
292
- helpstr = ['Inputs::' ]
293
-
294
- inputs = cls .input_spec ()
295
- if len (list (inputs .traits (transient = None ).items ())) == 0 :
296
- helpstr += ['' , '\t None' ]
297
- return helpstr
298
-
299
- manhelpstr = ['' , '\t [Mandatory]' ]
300
- mandatory_items = inputs .traits (mandatory = True )
301
- for name , spec in sorted (mandatory_items .items ()):
302
- manhelpstr += cls ._get_trait_desc (inputs , name , spec )
303
-
304
- opthelpstr = ['' , '\t [Optional]' ]
305
- for name , spec in sorted (inputs .traits (transient = None ).items ()):
306
- if name in mandatory_items :
307
- continue
308
- opthelpstr += cls ._get_trait_desc (inputs , name , spec )
309
-
310
- if manhelpstr :
311
- helpstr += manhelpstr
312
- if opthelpstr :
313
- helpstr += opthelpstr
314
- return helpstr
315
-
316
- @classmethod
317
- def _outputs_help (cls ):
318
- """ Prints description for output parameters
319
- """
320
- helpstr = ['Outputs::' , '' ]
321
- if cls .output_spec :
322
- outputs = cls .output_spec ()
323
- for name , spec in sorted (outputs .traits (transient = None ).items ()):
324
- helpstr += cls ._get_trait_desc (outputs , name , spec )
325
- if len (helpstr ) == 2 :
326
- helpstr += ['\t None' ]
327
- return helpstr
328
-
329
187
def _outputs (self ):
330
188
""" Returns a bunch containing output fields for the class
331
189
"""
@@ -645,7 +503,7 @@ def save_inputs_to_json(self, json_file):
645
503
A convenient way to save current inputs to a JSON file.
646
504
"""
647
505
inputs = self .inputs .get_traitsfree ()
648
- iflogger .debug ('saving inputs {} ' , inputs )
506
+ iflogger .debug ('saving inputs %s ' , inputs )
649
507
with open (json_file , 'w' if PY3 else 'wb' ) as fhandle :
650
508
json .dump (inputs , fhandle , indent = 4 , ensure_ascii = False )
651
509
@@ -777,14 +635,6 @@ def set_default_terminal_output(cls, output_type):
777
635
raise AttributeError (
778
636
'Invalid terminal output_type: %s' % output_type )
779
637
780
- @classmethod
781
- def help (cls , returnhelp = False ):
782
- allhelp = 'Wraps command **{cmd}**\n \n {help}' .format (
783
- cmd = cls ._cmd , help = super (CommandLine , cls ).help (returnhelp = True ))
784
- if returnhelp :
785
- return allhelp
786
- print (allhelp )
787
-
788
638
def __init__ (self , command = None , terminal_output = None , ** inputs ):
789
639
super (CommandLine , self ).__init__ (** inputs )
790
640
self ._environ = None
@@ -804,6 +654,10 @@ def __init__(self, command=None, terminal_output=None, **inputs):
804
654
@property
805
655
def cmd (self ):
806
656
"""sets base command, immutable"""
657
+ if not self ._cmd :
658
+ raise NotImplementedError (
659
+ 'CommandLineInterface should wrap an executable, but '
660
+ 'none has been set.' )
807
661
return self ._cmd
808
662
809
663
@property
0 commit comments