@@ -1804,8 +1804,9 @@ def _get_ssh_client(self):
1804
1804
1805
1805
1806
1806
class 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' ))
1809
1810
1810
1811
1811
1812
class JSONFileGrabber (IOBase ):
@@ -1819,12 +1820,15 @@ class JSONFileGrabber(IOBase):
1819
1820
1820
1821
>>> from nipype.interfaces.io import JSONFileGrabber
1821
1822
>>> 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'}
1822
1827
>>> jsonSource.inputs.in_file = 'jsongrabber.txt'
1823
1828
>>> 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
+
1828
1832
1829
1833
"""
1830
1834
input_spec = JSONFileGrabberInputSpec
@@ -1834,22 +1838,41 @@ class JSONFileGrabber(IOBase):
1834
1838
def _list_outputs (self ):
1835
1839
import json
1836
1840
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 )
1839
1845
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' )
1842
1848
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
1846
1857
1847
1858
return outputs
1848
1859
1849
1860
1850
1861
class JSONFileSinkInputSpec (DynamicTraitedSpec , BaseInterfaceInputSpec ):
1851
1862
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 )
1853
1876
1854
1877
1855
1878
class JSONFileSinkOutputSpec (TraitedSpec ):
@@ -1858,7 +1881,10 @@ class JSONFileSinkOutputSpec(TraitedSpec):
1858
1881
1859
1882
class JSONFileSink (IOBase ):
1860
1883
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.
1862
1888
1863
1889
.. warning::
1864
1890
@@ -1885,34 +1911,52 @@ class JSONFileSink(IOBase):
1885
1911
input_spec = JSONFileSinkInputSpec
1886
1912
output_spec = JSONFileSinkOutputSpec
1887
1913
1888
- def __init__ (self , input_names = [], ** inputs ):
1914
+ def __init__ (self , infields = [], force_run = True , ** inputs ):
1889
1915
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
1892
1939
1893
1940
def _list_outputs (self ):
1894
1941
import json
1895
1942
import os .path as op
1943
+
1896
1944
if not isdefined (self .inputs .out_file ):
1897
1945
out_file = op .abspath ('datasink.json' )
1898
1946
else :
1899
1947
out_file = self .inputs .out_file
1900
1948
1901
- out_dict = dict ()
1949
+ out_dict = self . inputs . in_dict
1902
1950
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
1911
1957
1912
1958
with open (out_file , 'w' ) as f :
1913
1959
json .dump (out_dict , f )
1914
1960
outputs = self .output_spec ().get ()
1915
1961
outputs ['out_file' ] = out_file
1916
1962
return outputs
1917
-
1918
-
0 commit comments