@@ -1804,8 +1804,9 @@ def _get_ssh_client(self):
18041804
18051805
18061806class JSONFileGrabberInputSpec (DynamicTraitedSpec , BaseInterfaceInputSpec ):
1807- in_file = File (exists = True , mandatory = True ,
1808- desc = 'JSON source file' )
1807+ in_file = File (exists = True , desc = 'JSON source file' )
1808+ defaults = traits .Dict (desc = ('JSON dictionary that sets default output'
1809+ 'values, overridden by values found in in_file' ))
18091810
18101811
18111812class JSONFileGrabber (IOBase ):
@@ -1819,12 +1820,15 @@ class JSONFileGrabber(IOBase):
18191820
18201821 >>> from nipype.interfaces.io import JSONFileGrabber
18211822 >>> jsonSource = JSONFileGrabber()
1823+ >>> jsonSource.inputs.defaults = {'param1': u'overrideMe', 'param3': 1.0}
1824+ >>> res = jsonSource.run()
1825+ >>> res.outputs.get()
1826+ {'param3': 1.0, 'param1': u'overrideMe'}
18221827 >>> jsonSource.inputs.in_file = 'jsongrabber.txt'
18231828 >>> res = jsonSource.run()
1824- >>> print res.outputs.param1
1825- exampleStr
1826- >>> print res.outputs.param2
1827- 4
1829+ >>> res.outputs.get()
1830+ {'param3': 1.0, 'param2': 4, 'param1': u'exampleStr'}
1831+
18281832
18291833 """
18301834 input_spec = JSONFileGrabberInputSpec
@@ -1834,22 +1838,41 @@ class JSONFileGrabber(IOBase):
18341838 def _list_outputs (self ):
18351839 import json
18361840
1837- with open (self .inputs .in_file , 'r' ) as f :
1838- data = json .load (f )
1841+ outputs = {}
1842+ if isdefined (self .inputs .in_file ):
1843+ with open (self .inputs .in_file , 'r' ) as f :
1844+ data = json .load (f )
18391845
1840- if not isinstance (data , dict ):
1841- raise RuntimeError ('JSON input has no dictionary structure' )
1846+ if not isinstance (data , dict ):
1847+ raise RuntimeError ('JSON input has no dictionary structure' )
18421848
1843- outputs = {}
1844- for key , value in data .iteritems ():
1845- outputs [key ] = value
1849+ for key , value in data .iteritems ():
1850+ outputs [key ] = value
1851+
1852+ if isdefined (self .inputs .defaults ):
1853+ defaults = self .inputs .defaults
1854+ for key , value in defaults .iteritems ():
1855+ if key not in outputs .keys ():
1856+ outputs [key ] = value
18461857
18471858 return outputs
18481859
18491860
18501861class JSONFileSinkInputSpec (DynamicTraitedSpec , BaseInterfaceInputSpec ):
18511862 out_file = File (desc = 'JSON sink file' )
1852- in_dict = traits .Dict (desc = 'input JSON dictionary' )
1863+ in_dict = traits .Dict (value = {}, usedefault = True ,
1864+ desc = 'input JSON dictionary' )
1865+ _outputs = traits .Dict (value = {}, usedefault = True )
1866+
1867+ def __setattr__ (self , key , value ):
1868+ if key not in self .copyable_trait_names ():
1869+ if not isdefined (value ):
1870+ super (JSONFileSinkInputSpec , self ).__setattr__ (key , value )
1871+ self ._outputs [key ] = value
1872+ else :
1873+ if key in self ._outputs :
1874+ self ._outputs [key ] = value
1875+ super (JSONFileSinkInputSpec , self ).__setattr__ (key , value )
18531876
18541877
18551878class JSONFileSinkOutputSpec (TraitedSpec ):
@@ -1858,7 +1881,10 @@ class JSONFileSinkOutputSpec(TraitedSpec):
18581881
18591882class JSONFileSink (IOBase ):
18601883
1861- """ Very simple frontend for storing values into a JSON file.
1884+ """
1885+ Very simple frontend for storing values into a JSON file.
1886+ Entries already existing in in_dict will be overridden by matching
1887+ entries dynamically added as inputs.
18621888
18631889 .. warning::
18641890
@@ -1885,34 +1911,52 @@ class JSONFileSink(IOBase):
18851911 input_spec = JSONFileSinkInputSpec
18861912 output_spec = JSONFileSinkOutputSpec
18871913
1888- def __init__ (self , input_names = [], ** inputs ):
1914+ def __init__ (self , infields = [], force_run = True , ** inputs ):
18891915 super (JSONFileSink , self ).__init__ (** inputs )
1890- self ._input_names = filename_to_list (input_names )
1891- add_traits (self .inputs , [name for name in self ._input_names ])
1916+ self ._input_names = infields
1917+
1918+ undefined_traits = {}
1919+ for key in infields :
1920+ self .inputs .add_trait (key , traits .Any )
1921+ self .inputs ._outputs [key ] = Undefined
1922+ undefined_traits [key ] = Undefined
1923+ self .inputs .trait_set (trait_change_notify = False , ** undefined_traits )
1924+
1925+ if force_run :
1926+ self ._always_run = True
1927+
1928+ def _process_name (self , name , val ):
1929+ if '.' in name :
1930+ newkeys = name .split ('.' )
1931+ name = newkeys .pop (0 )
1932+ nested_dict = {newkeys .pop (): val }
1933+
1934+ for nk in reversed (newkeys ):
1935+ nested_dict = {nk : nested_dict }
1936+ val = nested_dict
1937+
1938+ return name , val
18921939
18931940 def _list_outputs (self ):
18941941 import json
18951942 import os .path as op
1943+
18961944 if not isdefined (self .inputs .out_file ):
18971945 out_file = op .abspath ('datasink.json' )
18981946 else :
18991947 out_file = self .inputs .out_file
19001948
1901- out_dict = dict ()
1949+ out_dict = self . inputs . in_dict
19021950
1903- if isdefined (self .inputs .in_dict ):
1904- if isinstance (self .inputs .in_dict , dict ):
1905- out_dict = self .inputs .in_dict
1906- else :
1907- for name in self ._input_names :
1908- val = getattr (self .inputs , name )
1909- val = val if isdefined (val ) else 'undefined'
1910- out_dict [name ] = val
1951+ # Overwrite in_dict entries automatically
1952+ for key , val in self .inputs ._outputs .items ():
1953+ if not isdefined (val ) or key == 'trait_added' :
1954+ continue
1955+ key , val = self ._process_name (key , val )
1956+ out_dict [key ] = val
19111957
19121958 with open (out_file , 'w' ) as f :
19131959 json .dump (out_dict , f )
19141960 outputs = self .output_spec ().get ()
19151961 outputs ['out_file' ] = out_file
19161962 return outputs
1917-
1918-
0 commit comments