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
41
40
from .traits_extension import traits , isdefined , TraitError
42
41
from .specs import (BaseInterfaceInputSpec , CommandLineInputSpec ,
43
42
StdOutCommandLineInputSpec , MpiCommandLineInputSpec )
44
- from .support import (Bunch , InterfaceResult , NipypeInterfaceError )
43
+ from .support import (Bunch , InterfaceResult , NipypeInterfaceError ,
44
+ format_help )
45
45
46
- from future import standard_library
47
46
standard_library .install_aliases ()
48
47
49
48
iflogger = logging .getLogger ('nipype.interface' )
@@ -67,48 +66,37 @@ class Interface(object):
67
66
68
67
input_spec = None # A traited input specification
69
68
output_spec = None # A traited output specification
70
-
71
- # defines if the interface can reuse partial results after interruption
72
- _can_resume = False
69
+ _can_resume = False # See property below
70
+ _always_run = False # See property below
73
71
74
72
@property
75
73
def can_resume (self ):
74
+ """defines if the interface can reuse partial results after interruption"""
76
75
return self ._can_resume
77
76
78
- # should the interface be always run even if the inputs were not changed?
79
- _always_run = False
80
-
81
77
@property
82
78
def always_run (self ):
79
+ """should the interface be always run even if the inputs were not changed?"""
83
80
return self ._always_run
84
81
85
- def __init__ (self , ** inputs ):
86
- """Initialize command with given args and inputs."""
87
- raise NotImplementedError
88
-
89
- @classmethod
90
- def help (cls ):
91
- """ Prints class help"""
92
- raise NotImplementedError
93
-
94
- @classmethod
95
- def _inputs_help (cls ):
96
- """ Prints inputs help"""
97
- raise NotImplementedError
98
-
99
- @classmethod
100
- def _outputs_help (cls ):
101
- """ Prints outputs help"""
82
+ @property
83
+ def version (self ):
84
+ """interfaces should implement a version property"""
102
85
raise NotImplementedError
103
86
104
87
@classmethod
105
88
def _outputs (cls ):
106
89
""" Initializes outputs"""
107
90
raise NotImplementedError
108
91
109
- @property
110
- def version (self ):
111
- raise NotImplementedError
92
+ @classmethod
93
+ def help (cls , returnhelp = False ):
94
+ """ Prints class help """
95
+ allhelp = format_help (cls )
96
+ if returnhelp :
97
+ return allhelp
98
+ print (allhelp )
99
+ return None # R1710
112
100
113
101
def run (self ):
114
102
"""Execute the command."""
@@ -185,142 +173,6 @@ def __init__(self, from_file=None, resource_monitor=None,
185
173
for name , value in list (inputs .items ()):
186
174
setattr (self .inputs , name , value )
187
175
188
- @classmethod
189
- def help (cls , returnhelp = False ):
190
- """ Prints class help
191
- """
192
-
193
- if cls .__doc__ :
194
- # docstring = cls.__doc__.split('\n')
195
- # docstring = [trim(line, '') for line in docstring]
196
- docstring = trim (cls .__doc__ ).split ('\n ' ) + ['' ]
197
- else :
198
- docstring = ['' ]
199
-
200
- allhelp = '\n ' .join (docstring + cls ._inputs_help (
201
- ) + ['' ] + cls ._outputs_help () + ['' ] + cls ._refs_help () + ['' ])
202
- if returnhelp :
203
- return allhelp
204
- else :
205
- print (allhelp )
206
-
207
- @classmethod
208
- def _refs_help (cls ):
209
- """ Prints interface references.
210
- """
211
- if not cls .references_ :
212
- return []
213
-
214
- helpstr = ['References::' ]
215
-
216
- for r in cls .references_ :
217
- helpstr += ['{}' .format (r ['entry' ])]
218
-
219
- return helpstr
220
-
221
- @classmethod
222
- def _get_trait_desc (self , inputs , name , spec ):
223
- desc = spec .desc
224
- xor = spec .xor
225
- requires = spec .requires
226
- argstr = spec .argstr
227
-
228
- manhelpstr = ['\t %s' % name ]
229
-
230
- type_info = spec .full_info (inputs , name , None )
231
-
232
- default = ''
233
- if spec .usedefault :
234
- default = ', nipype default value: %s' % str (
235
- spec .default_value ()[1 ])
236
- line = "(%s%s)" % (type_info , default )
237
-
238
- manhelpstr = wrap (
239
- line ,
240
- 70 ,
241
- initial_indent = manhelpstr [0 ] + ': ' ,
242
- subsequent_indent = '\t \t ' )
243
-
244
- if desc :
245
- for line in desc .split ('\n ' ):
246
- line = re .sub ("\s+" , " " , line )
247
- manhelpstr += wrap (
248
- line , 70 , initial_indent = '\t \t ' , subsequent_indent = '\t \t ' )
249
-
250
- if argstr :
251
- pos = spec .position
252
- if pos is not None :
253
- manhelpstr += wrap (
254
- 'flag: %s, position: %s' % (argstr , pos ),
255
- 70 ,
256
- initial_indent = '\t \t ' ,
257
- subsequent_indent = '\t \t ' )
258
- else :
259
- manhelpstr += wrap (
260
- 'flag: %s' % argstr ,
261
- 70 ,
262
- initial_indent = '\t \t ' ,
263
- subsequent_indent = '\t \t ' )
264
-
265
- if xor :
266
- line = '%s' % ', ' .join (xor )
267
- manhelpstr += wrap (
268
- line ,
269
- 70 ,
270
- initial_indent = '\t \t mutually_exclusive: ' ,
271
- subsequent_indent = '\t \t ' )
272
-
273
- if requires :
274
- others = [field for field in requires if field != name ]
275
- line = '%s' % ', ' .join (others )
276
- manhelpstr += wrap (
277
- line ,
278
- 70 ,
279
- initial_indent = '\t \t requires: ' ,
280
- subsequent_indent = '\t \t ' )
281
- return manhelpstr
282
-
283
- @classmethod
284
- def _inputs_help (cls ):
285
- """ Prints description for input parameters
286
- """
287
- helpstr = ['Inputs::' ]
288
-
289
- inputs = cls .input_spec ()
290
- if len (list (inputs .traits (transient = None ).items ())) == 0 :
291
- helpstr += ['' , '\t None' ]
292
- return helpstr
293
-
294
- manhelpstr = ['' , '\t [Mandatory]' ]
295
- mandatory_items = inputs .traits (mandatory = True )
296
- for name , spec in sorted (mandatory_items .items ()):
297
- manhelpstr += cls ._get_trait_desc (inputs , name , spec )
298
-
299
- opthelpstr = ['' , '\t [Optional]' ]
300
- for name , spec in sorted (inputs .traits (transient = None ).items ()):
301
- if name in mandatory_items :
302
- continue
303
- opthelpstr += cls ._get_trait_desc (inputs , name , spec )
304
-
305
- if manhelpstr :
306
- helpstr += manhelpstr
307
- if opthelpstr :
308
- helpstr += opthelpstr
309
- return helpstr
310
-
311
- @classmethod
312
- def _outputs_help (cls ):
313
- """ Prints description for output parameters
314
- """
315
- helpstr = ['Outputs::' , '' ]
316
- if cls .output_spec :
317
- outputs = cls .output_spec ()
318
- for name , spec in sorted (outputs .traits (transient = None ).items ()):
319
- helpstr += cls ._get_trait_desc (outputs , name , spec )
320
- if len (helpstr ) == 2 :
321
- helpstr += ['\t None' ]
322
- return helpstr
323
-
324
176
def _outputs (self ):
325
177
""" Returns a bunch containing output fields for the class
326
178
"""
@@ -653,7 +505,7 @@ def save_inputs_to_json(self, json_file):
653
505
A convenient way to save current inputs to a JSON file.
654
506
"""
655
507
inputs = self .inputs .get_traitsfree ()
656
- iflogger .debug ('saving inputs {} ' , inputs )
508
+ iflogger .debug ('saving inputs %s ' , inputs )
657
509
with open (json_file , 'w' if PY3 else 'wb' ) as fhandle :
658
510
json .dump (inputs , fhandle , indent = 4 , ensure_ascii = False )
659
511
@@ -785,14 +637,6 @@ def set_default_terminal_output(cls, output_type):
785
637
raise AttributeError (
786
638
'Invalid terminal output_type: %s' % output_type )
787
639
788
- @classmethod
789
- def help (cls , returnhelp = False ):
790
- allhelp = 'Wraps command **{cmd}**\n \n {help}' .format (
791
- cmd = cls ._cmd , help = super (CommandLine , cls ).help (returnhelp = True ))
792
- if returnhelp :
793
- return allhelp
794
- print (allhelp )
795
-
796
640
def __init__ (self , command = None , terminal_output = None , ** inputs ):
797
641
super (CommandLine , self ).__init__ (** inputs )
798
642
self ._environ = None
@@ -812,6 +656,10 @@ def __init__(self, command=None, terminal_output=None, **inputs):
812
656
@property
813
657
def cmd (self ):
814
658
"""sets base command, immutable"""
659
+ if not self ._cmd :
660
+ raise NotImplementedError (
661
+ 'CommandLineInterface should wrap an executable, but '
662
+ 'none has been set.' )
815
663
return self ._cmd
816
664
817
665
@property
0 commit comments